{"slug": "how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim", "title": "How I Built a Carbon Footprint Tracker with Django + NVIDIA NIM", "summary": "A developer built Carbon.Ledger, a full-stack Django web app that logs user activities, computes CO₂ impact using database-stored emission factors, and provides AI-powered reduction tips via NVIDIA NIM's Mistral Large model. The app features a hallucination guard that checks LLM-generated numbers against provided context to prevent misinformation, and uses htmx for dynamic dropdowns without custom JavaScript. Deployed on Render, the project highlights the importance of separating LLM text generation from data calculations.", "body_md": "I wanted to build something that mattered. Climate change is one of those topics where awareness is the first barrier — most people don't know their actual footprint. So I built **Carbon.Ledger**: a full-stack web app that lets you log activities, see your CO₂ impact, and get AI-powered tips to cut back.\n\nHere's how I built it, what went wrong, and the one engineering decision I'm most proud of.\n\n`mistralai/mistral-large-3-675b-instruct-2512`\n\nThe app is built around one simple loop:\n\n**Understand → Track → Reduce**\n\nUsers can read lesson articles, browse a glossary (CO₂e, Scope 1/2/3, Net Zero), and ask free-text climate questions via an LLM-powered Q&A — rate limited to 10 questions/day.\n\nAn activity logging form lets users log transport, energy, food, and goods. CO₂ is auto-computed on save using emission factors stored in the database — no LLM involved here. The dashboard shows a 30-day breakdown with a Chart.js donut chart and progress against a monthly goal.\n\nRule-based insights compare the user's totals against national average benchmarks. The top emission category drives filtered recommendations. And once per day, the LLM generates a personalized tip — cached 24h per user.\n\nThis is the part I'm most proud of.\n\nLLMs make up numbers. That's a real problem when you're talking about emissions data — if the model says \"beef produces 5 kg CO₂ per kg\" when the real figure is 27, that's actively harmful misinformation.\n\nMy solution in `services/llm.py`\n\n:\n\n``` php\ndef _contains_hallucinated_numbers(response: str, context: str) -> bool:\n    \"\"\"\n    Extract all numbers from the LLM response.\n    Check every one of them exists in the context we provided.\n    If not → hallucination detected.\n    \"\"\"\n    import re\n    response_numbers = set(re.findall(r'\\d+\\.?\\d*', response))\n    context_numbers = set(re.findall(r'\\d+\\.?\\d*', context))\n    return not response_numbers.issubset(context_numbers)\n```\n\nThe flow:\n\n`timeout=10.0`\n\nand `max_retries=1`\n\nare explicitly set to prevent hung Gunicorn worker threads on slow LLM responses.**Key principle: the LLM is never used for calculations. All math is Python/DB.**\n\nThe activity log form has a dependent dropdown — selecting a category dynamically loads the relevant emission factors. I used htmx for this instead of writing custom JavaScript:\n\n```\n<select name=\"category\" \n        hx-get=\"/factors/\"\n        hx-target=\"#factor-select\"\n        hx-trigger=\"change\">\n```\n\nOne attribute. No JS file. The server returns a partial HTML snippet with the filtered factors. This is exactly what htmx is built for.\n\nRender makes Django deployment straightforward. A few Django-specific things worth noting:\n\n```\n# settings.py\nSECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')\nSECURE_SSL_REDIRECT = not DEBUG\nSESSION_COOKIE_SECURE = not DEBUG\nCSRF_COOKIE_SECURE = not DEBUG\n```\n\nRender terminates TLS at the proxy level, so `SECURE_PROXY_SSL_HEADER`\n\nis essential — without it Django won't recognize HTTPS requests and will redirect loop forever.\n\nAlso: randomize your admin URL via env var:\n\n```\nADMIN_URL = env('ADMIN_URL', default='admin/')\n```\n\nStops bots from hammering the default `/admin/`\n\nendpoint.\n\n**Async LLM calls.** Right now the LLM calls are synchronous — a slow NVIDIA NIM response blocks a Gunicorn worker. The fix is Celery + Redis for background tasks. I skipped it for the MVP but it's the first thing I'd add.\n\n**Audited emission factors.** The 22 factors I seeded are approximations from public sources, not peer-reviewed figures. For a production app, you'd want to integrate a verified dataset like the UK Government GHG conversion factors.\n\n**Email verification.** Currently anyone can sign up with any email. Not a problem for an MVP, but a real gap.\n\nIf you're building something with Django + LLMs, the hallucination guard pattern is worth stealing. And if you have thoughts on better emission factor datasets, I'd love to hear them in the comments.", "url": "https://wpnews.pro/news/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim", "canonical_source": "https://dev.to/divyansh0208/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim-4jp3", "published_at": "2026-06-24 16:01:00+00:00", "updated_at": "2026-06-24 16:09:23.563234+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools", "large-language-models", "ai-products"], "entities": ["Django", "NVIDIA NIM", "Mistral Large", "Carbon.Ledger", "Render", "htmx", "Chart.js", "Celery"], "alternates": {"html": "https://wpnews.pro/news/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim", "markdown": "https://wpnews.pro/news/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim.md", "text": "https://wpnews.pro/news/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim.txt", "jsonld": "https://wpnews.pro/news/how-i-built-a-carbon-footprint-tracker-with-django-nvidia-nim.jsonld"}}