DEV Community

pulkitgovrani
pulkitgovrani Subscriber

Posted on

Personal Earth Assistant: Weekend Challenge - Earth Day Edition

DEV Weekend Challenge: Earth Day

This is a submission for Weekend Challenge: Earth Day Edition

What I Built

Personal Earth Assistant is a small full-stack app that helps people think about lower-impact everyday choices—commute, home size, diet, flights, and energy habits—without pretending to be a full carbon calculator.

Goals:

  • Give users a simple “Private Earth Score” (0–100) from a transparent rubric, not a black box.
  • Offer a chat coach that reads their saved profile and can update habits via server-side tools (so the model never needs API keys in the browser).
  • Keep identity and data scoped per user with Auth0 and a SQLite store keyed by Auth0 sub.

Stack: React (Vite) + Express (TypeScript), Auth0 SPA login + API audience, Gemini or Groq on the server only, SQLite for profile + chat history + score snapshots, streaks, and lightweight badges.


Demo

Video walkthrough:

Watch on YouTube


Code

Personal Earth Assistant

Vite + React SPA with an Express API: Auth0 login (JWT + audience), Gemini on the server only, SQLite profile + chat history keyed by Auth0 sub. Built for the DEV Weekend Challenge: Earth Day Edition.

Quick start (local)

  1. Auth0

    • Create a Single Page Application client.
    • Create an API with an identifier (e.g. https://personal-earth-api) — this value is your audience.
    • Under the API, authorize the SPA client if required by your tenant defaults.
    • Application URLs (dev): Callback, Logout, and Allowed Web Origins → http://localhost:5173.
  2. Google AI Studio

    • Create an API key for the Gemini API (server-side only).
  3. Env files

  4. Run

    npm install
    npm run dev
    Enter fullscreen mode Exit fullscreen mode

Production build (single Node process)

Highlights to skim in the repo:


How I Built It

Frontend is a Vite + React SPA. Users sign in with Auth0; the client requests access tokens with an API audience that matches a Custom API in Auth0 (not the Management API). All /api/* calls send Authorization: Bearer <token>.

Backend is Express. I verify JWTs with jose against Auth0’s JWKS (AUTH0_DOMAIN + AUTH0_AUDIENCE). Every row in SQLite is tied to sub, so users only ever see their own profile and chat.

Onboarding collects coarse lifestyle fields; the server computes a deterministic score from a documented rubric (server/src/score.ts) and stores snapshots over time for charts on the dashboard.

Chat runs only on the server:

  • Google Gemini (default) or Groq (LLM_PROVIDER=groq + GROQ_API_KEY) via a small provider switch.
  • The model can call tools to merge partial profile updates, set a weekly goal, or log a “win”—then the server persists to SQLite and recomputes the score when needed.
  • Streaming: SSE from POST /api/chat/stream so the UI shows tokens incrementally (Groq path completes the turn server-side, then chunks the reply for a smooth SSE experience).

Env loading: server/src/loadEnv.ts always loads server/.env relative to the package so npm run dev from the repo root still picks up keys (avoids the common “wrong cwd” issue with dotenv).

Interesting tradeoff: I kept the rubric simple and inspectable on purpose—good for a weekend build and for explaining “what the score means” in the UI. The value is in auth + safe LLM integration + durable user state, not in claiming scientific carbon accuracy.

Auth0 for Agents (angle)

This MVP is built around trusted human identity (Auth0 SPA JWT), server-held secrets (Gemini / Groq keys), and tool execution that mutates user state scoped by sub—the same building blocks you need when wiring agents or MCP-style flows: identity, policy, and side effects on the server. A natural next step would be to add Auth0’s agent-specific flows or delegated credentials per their docs and describe that in a follow-up post.

Google Gemini (angle)

I use @google/generative-ai on the Node server only, with function calling so the model can persist structured updates instead of only chatting. The client never sees GOOGLE_API_KEY. Streaming uses the SDK’s stream API for Gemini so tokens can flow to the browser over SSE while tool rounds stay on the server.


Prize Categories

I’m submitting for:

  • Best use of Auth0 for Agents — Auth0-backed SPA + API audience, JWT validation on every route, per-user SQLite isolation, and a server-side tool loop suitable for agent-style extensions (identity + secrets + durable actions).
  • Best use of Google Gemini — Server-only Gemini with tools, streaming responses over SSE, and profile/habit persistence driven by model tool calls.

Top comments (0)