Inspiration
Most utility apps only show energy usage after the fact. We wanted to flip that -- give homeowners a forward-looking tool that answers "when should I run my dishwasher?" instead of "here's what you already spent." The idea clicked when we realized that hourly electricity prices, grid carbon intensity, and weather data could be combined into a single optimization problem, and that a chat assistant could make the results feel personal rather than robotic.
What it does
EnerGenius recommends optimal times to run household appliances (dishwasher, washer, dryer, EV charger, water heater) and schedules HVAC, minimizing both cost and carbon emissions while respecting the user's comfort and availability. Users see a visual daily timeline, choose from three schedule options per appliance, and chat with an AI assistant (Gemma 4) that remembers their preferences across sessions.
How we built it
The frontend is React + TypeScript with Vite, TanStack Query, Zustand, and shadcn/ui. The backend is FastAPI (Python), with Supabase handling auth and Postgres.
The scheduling engine is the core. We formulated it as a Mixed-Integer Linear Program using PuLP with the CBC solver. For each appliance $a$ with power $P_a$ and duration $D_a$ slots, we define binary decision variables $x_{a,t}$ indicating whether appliance $a$ starts at slot $t$. The objective minimizes:
$$\min \sum_{a} \sum_{t} x_{a,t} \left( w_c \cdot C_{a,t} + w_e \cdot E_{a,t} + w_s \cdot (1 - S_{a,t}) \right)$$
where $C_{a,t}$, $E_{a,t}$, and $S_{a,t}$ are the normalized cost, emissions, and user satisfaction for running appliance $a$ starting at slot $t$, and $(w_c, w_e, w_s)$ are user-tunable weights that sum to 1.
Key constraints include exactly one start per appliance, scheduling windows, quiet-hour restrictions for noisy appliances, and a circuit power limit $\sum_a P_a \cdot r_{a,t} \leq L$ for every slot $t$, where $r_{a,t}$ indicates whether appliance $a$ is running during slot $t$.
We solve three times with different weight vectors to produce cost-optimized, balanced, and convenience-optimized options. User feedback drives an exponential moving average that adapts the weights over time.
The AI chat integrates Backboard.io with Gemma 4, maintaining a persistent thread per user with memory and web search capabilities.
Challenges we ran into
- Solver feasibility -- Getting the MILP constraints right so the solver doesn't return infeasible when quiet hours and availability windows are tight. We added fallback logic that relaxes constraints incrementally.
- Backboard.io cold starts -- Gemma 4 responses through Backboard can take 2-4 seconds on cold starts. We built a pulsing "thinking" indicator and a 30-second timeout with a graceful fallback message so the UI never hangs.
- Keeping scope tight -- The biggest challenge of an 8-hour build is saying no. We mocked external market data (prices, carbon, weather) with realistic hardcoded curves rather than integrating three separate APIs, which let us focus on the optimization and chat experience.
What we learned
- PuLP and CBC are surprisingly fast for household-scale MILP problems -- solving across five appliances and 48 time slots completes in under a second.
- Adaptive weights from a simple feedback loop (click "Use this time") create a meaningful personalization signal with almost no user friction.
- A live AI chat demo is worth ten slides. Having Gemma 4 answer "Why is 2 PM the best time today?" with a real, contextual response was the strongest moment in our presentation.
What's next for EnerGenius
- Replace mocked data with live APIs (OpenEI for prices, Electricity Maps for carbon, OpenWeatherMap for weather)
- Upgrade the HVAC model to account for indoor thermal mass and occupancy
- Add real Google Calendar integration for availability
- Explore multi-home aggregation for community-level demand response
Built With
- 4
- backboard.io
- css
- fastapi
- gemma
- postgresql
- pulp
- python
- query
- react
- recharts
- shadcn/ui
- supabase
- tailwind
- tanstack
- typescript
- vite
- zustand
Log in or sign up for Devpost to join the conversation.