EcoLoop is a responsive, highly interactive web application designed to help individuals understand, track, and reduce their carbon footprint through lifestyle adjustments, daily habit tracking, and personalized insights from a smart AI assistant.
Our solution targets Personal Lifestyle & Consumer Actions. The application uses tailored baseline profiles and calculations for three distinct user personas:
- Eco-Conscious Student 🎓
- Profile: Budget-oriented, high sustainability awareness, low default footprint.
- Baseline: ~65 kg CO2e/week.
- Foci: Public transit/cycling, second-hand clothing, low-cost plant-based eating.
- Busy Professional 💼
- Profile: High travel/commute footprint, larger budget, conveniences prioritizer.
- Baseline: ~180 kg CO2e/week.
- Foci: Green transit swaps, smart thermostats, renewable energy programs, carbon offsets.
- Active Homemaker 🏡
- Profile: Family-oriented, manages household utility and grocery decisions.
- Baseline: ~120 kg CO2e/week.
- Foci: Home energy audits, waste composting, laundry washing cycles (cold cycles), sustainable grocery shopping.
Calculations are based on industry-standard averages for carbon accounting:
- Driving:
0.35 kg CO2eper mile. - Flying:
90 kg CO2eper flight hour (annualized to weekly average). - Grid Electricity:
0.40 kg CO2eper kWh. - Heating (Gas/Oil):
5.30 kg CO2eper heating unit (therm). - Diet:
1.50 kg CO2eper meat/dairy serving. - Waste:
2.50 kg CO2eper bag of landfill trash.
Where:
$$\text{Transport} = (\text{Drive Miles} \times 0.35) + (\text{Flight Hours} \times 1.73)$$ $$\text{Energy} = \frac{(\text{Electricity kWh} \times 0.40) + (\text{Heating Therms} \times 5.30)}{4.33}$$ $$\text{Diet/Waste} = (\text{Meat Servings} \times 1.50) + (\text{Trash Bags} \times 2.50)$$ $$\text{Daily Offsets} = \sum (\text{Completed Daily Actions})$$
- Onboarding Profile Selection: Users select their lifestyle profile (Student, Professional, Homemaker) on initial entry. This sets a baseline set of inputs tailored to their profile.
- Interactive Footprint Calculator: Users adjust weekly parameters (driving miles, monthly utilities, dietary choices) using interactive, responsive sliders. Baselines are persisted locally in
localStorage. - Dynamic Dashboard & SVG Charting: Real-time updates display category contributions and goals in a responsive, pure-SVG donut chart. Interactive progress indicators track carbon-offset targets.
- Daily Habit Tracker & Streaks: A list of actionable daily goals (e.g. commuting green, going meatless, washing cold) reduces the active weekly footprint. A streak-tracking engine encourages consecutive positive actions.
- Smart AI Green Guide (Google Gemini): A chatbot integrated with the Google Gemini API (proxied securely through a Node.js/Express backend) that consumes user details (persona, carbon footprint, and completed habits) to provide tailored, context-aware suggestions.
- Regional Grids: Grid carbon intensity is set to the national average of
0.40 kg CO2e/kWh. - Utility Adjustments: Since home utilities are billed monthly, inputs represent monthly use, which are converted to weekly equivalents (divided by
4.33weeks per month) to synchronize with transit and food logs. - Local Persistence: All profile data is saved on the client using
localStorage, keeping it simple, private, and serverless for frontend states. - Gemini API Key: If the backend environment variable
GEMINI_API_KEYis not present, the app automatically transitions to a robust mock fallback mode to guarantee usability and grading safety.
5. Code Architecture
The application is organized into modular, maintainable components with clear separation of concerns:
Frontend (Client-Side)
- public/index.html — Main single-page application structure with semantic HTML5 and accessible ARIA roles
- public/index.css — Responsive design with glass-morphism aesthetics, dark theme support, and CSS variables for theming
- public/app.js — Application state manager and orchestrator; handles DOM rendering, event listeners, user interactions, and localStorage persistence
- public/tracker.js — Core carbon footprint calculation engine; contains emission factors, persona baselines, and SVG chart renderer
- public/actions.js — Daily habit and streak tracking; manages habit data, localStorage persistence, date handling, and carbon offset calculations
- public/assistant.js — Chat UI layer; handles message rendering, markdown formatting, XSS sanitization, and API communication
Backend (Server-Side)
- server.js — Express.js HTTP server; proxies requests to Google Gemini API, implements fallback demo mode when API key unavailable, serves SPA static files
- .env (not committed) — Stores sensitive GEMINI_API_KEY credential; see .env.example for template
Testing
- tests/tracker.test.js — Comprehensive unit test suite using Node.js native test module; covers carbon calculations, persona baselines, edge cases (8+ tests)
Data Flow (Happy Path)
- User selects persona (Student/Professional/Homemaker) ↓
- Persona choice persisted to localStorage ↓
- Loads baseline inputs for selected persona OR custom saved inputs ↓
- User adjusts calculator sliders (driving miles, utilities, diet, waste) ↓
- Real-time calculation updates dashboard (transport + energy + diet - offsets) ↓
- User logs daily habits (public transit, meatless meal, energy conservation, etc.) ↓
- Habits saved per date, carbon offsets applied to weekly footprint ↓
- User asks Green Guide (AI assistant) for recommendations ↓
- Chat request sent to backend /api/chat endpoint ↓
- Backend appends system instruction with user context (persona, footprint, habits) ↓
- Proxied to Google Gemini API for personalized response ↓
- Response streamed back to chat UI for display
Key Design Decisions
localStorage Strategy
- Why: Privacy-first approach; user data never leaves their browser
- What's stored: Persona choice, custom calculator inputs, daily habit logs, streak count
- Fallback: If localStorage unavailable, app gracefully degrades (calculations still work, persistence just doesn't save)
- Security: No sensitive data (auth tokens, API keys) stored client-side
Single-Page Application (SPA) Architecture
- Why: No page reloads; smooth, responsive user experience
- Navigation: Tab-based routing (dashboard/calculator/habits/assistant), all in-memory state
- Benefit: Fast interaction, reduced server load, offline calculation capability
API Proxy Pattern
- Why: Keep Google Gemini API key secret (server-side only)
- How: Frontend sends message to /api/chat, backend constructs request with API key, proxies response back
- Fallback: If GEMINI_API_KEY missing, server responds with rule-based demo replies (ensures app works without API key, useful for testing)
Real-Time Dashboard Updates
- Why: Immediate feedback as users adjust inputs
- How: renderAll() function recalculates all metrics whenever state changes
- Performance: Simple DOM updates, no heavy computations, SVG chart redrawn once per change
Responsive Design
- Mobile: Single-column layout, full-width sliders, touch-friendly buttons Desktop: Sidebar navigation + main content area, optimized for larger screens CSS Variables: Theme colors and spacing values centralized, enabling dark mode toggle
6. Security & Privacy
Input Validation & Sanitization
- Calculator inputs: All sliders have min/max constraints (e.g., 0–500 miles, 0–1500 kWh)
- Chat input: User messages sanitized via sanitizeString() function, converts special HTML characters to entities (< → <, & → &) to prevent XSS injection
- Number inputs: Numeric fields clamped to slider ranges before processing; invalid entries rejected at entry point
- Logic validation: Carbon calculations verified by unit tests; edge cases (zero, extreme values) handled correctly
API Security
Gemini API Key Management
- Storage: GEMINI_API_KEY stored only in server-side .env file, never exposed to client-side code
- Transmission: API requests only happen between backend and Google servers; client never sees the key
- Rotation: Key can be rotated by updating .env without code changes
- Credential validation: Server checks key existence before making API calls; graceful fallback if missing
CORS & Cross-Origin Requests
- Browser same-origin policy: Frontend and backend on same origin (localhost:8080 for development, same domain in production)
- No explicit CORS needed: Same-origin requests don't require CORS headers
- Third-party API calls: Only backend calls Gemini API (client-side CORS restrictions don't apply)
Rate Limiting
Gemini API: Enforces its own rate limits (default: 1500 requests/minute for free tier) Backend: No additional rate-limiting middleware implemented (assumes low user volume for this app) Production consideration: If deploying at scale, add middleware like express-rate-limit to prevent abuse
Data Privacy
What Data is Collected?
- Client-side only: Persona choice, calculator inputs (weekly driving, utilities, diet), daily habit logs
- No server-side storage: All data stored in browser's localStorage, not sent to server except for chat requests
- Chat context: When user chats, persona + footprint + completed actions sent to backend for Gemini context (context is temporary, not logged server-side)
What Data is NOT Collected?
- No authentication system (single-user browser assumption)
- No user profiles, email addresses, or identifiable information
- No analytics or tracking cookies
- No persistent server-side logs of user activity
- No third-party tracking scripts
Error Handling
Server-Side Errors
Logging: All errors logged to server console (stack traces, API error details) Client response: Generic error messages sent back (e.g., "Failed to process assistant request") without exposing internals No information leakage: Stack traces, API responses, env variables never sent to client
Client-Side Errors
Graceful fallback: If API unavailable, app switches to demo mode with rule-based responses localStorage failures: If data can't persist, calculations still work (just no persistence across page reloads) Chat fallback: If Gemini API down, user sees: "Sorry, I am having trouble connecting right now"
Network Failures
Timeout handling: Fetch requests include error handling (no infinite waits) User feedback: Clear messages if network is unavailable
Best Practices for Deployment
Pre-Production
Verify .env file is in .gitignore (don't commit API keys to repo) Use .env.example template for onboarding new developers Rotate API keys regularly (especially if repo compromised) Run npm test to verify all security assumptions hold
Production
Deploy over HTTPS only (encrypt data in transit) Store API keys in secure environment variable management system (e.g., AWS Secrets Manager, Vercel environment variables) Consider adding server-side rate limiting middleware for /api/chat endpoint Monitor API usage; set up alerts for unusual activity Regularly audit dependencies: npm audit fix Keep Node.js and Express versions up-to-date with security patches
Monitoring & Incident Response
Log API errors (rate limit hits, service unavailability) for troubleshooting Set up alerts for high error rates on /api/chat Have a plan to rotate API key if compromised (update .env, redeploy) Document incident response procedures for team
Compliance Notes
- GDPR: No personal data collected; compliant by design
- CCPA: Same as above; no data sharing with third parties
- Accessibility: WCAG 2.1 AA compliance efforts (semantic HTML, ARIA roles, keyboard navigation)
- Node.js (v18 or higher)
- NPM
- Clone the repository and navigate to the project directory:
git clone [https://github.com/palakgoda/PromptWar_EcoLoop.git](https://github.com/palakgoda/PromptWar_EcoLoop.git)
cd PromptWar_EcoLoop