Inspiration
Every year, billions of dollars in federal solar incentives go unclaimed in the communities that need them most. We saw a disconnect: rooftop solar tools exist for individual homeowners, but city planners and policymakers have no way to see which neighborhoods should be prioritized, why they're underserved, or what to do about it. We wanted to build something that doesn't just tell you "your roof gets 5.2 peak sun hours" — it tells a city council "Block Group 3204 has a median income of $28K, 62% renters, zero solar installations, and the highest energy burden in the county — here are the grants they qualify for and a deployment roadmap that respects your grid constraints." We also wanted to challenge ourselves technically: could we build a polyglot microservice architecture at a hackathon, with a financial engine written in Smalltalk running alongside a Python AI pipeline?
What it does
Radiance is an AI-powered solar intelligence platform that operates at both the individual rooftop and city-wide scale:
Rooftop Analysis — Draw a polygon on the map or drop a pin on any address. Radiance fetches satellite imagery, runs a SegFormer-B0 computer vision model to detect usable roof area and obstacles, pulls NASA POWER irradiance data, and produces a comprehensive solar score (0–100), energy generation forecast, carbon offset estimate, and grant eligibility report.
25-Year Financial Modeling — A Pharo Smalltalk microservice computes installation cost (net of the 30% federal ITC), year-by-year savings accounting for 0.5%/yr panel degradation and 2.5%/yr electricity inflation, payback period, net profit, and ROI — returned as both a summary and a full 25-row yearly breakdown.
WattsUp Equity Score — A 0–100 composite index per Census block group, built from live Census Bureau data: median income, renter percentage, energy burden, and existing solar adoption. The score surfaces why a neighborhood is underserved with human-readable barrier descriptions.
City-Scale Scanning & Heatmaps — Submit a bounding box and Radiance queries OpenStreetMap for every building, runs lightweight solar analysis on each, and renders a Deck.gl WebGL heatmap showing raw solar potential or unrealized capacity across the city.
Autonomous Deployment Roadmap — A planner that scores candidate buildings on equity (35%), grid impact (25%), financial viability (25%), and environmental impact (15%), allocates them to yearly deployment phases respecting budget and interconnection constraints, and generates an AI-written executive narrative for city council briefings.
Automation Engine — Rule-based triggers that fire after every analysis: equity alerts draft policy briefs for city council, grant matchers cross-reference DSIRE and SAM.gov, and contractor dispatchers notify installers — every action logged to an audit trail.
8 Financial Calculators — Battery optimizer, EV savings, net metering, PACE financing, investment comparator, bill spike analyzer, incentive navigator, and property portfolio dashboard.
How we built it
Radiance is a three-layer system: a React 18 + TypeScript frontend, an async FastAPI backend, and a Pharo Smalltalk 13 financial microservice.
Frontend: React 18 with Vite, TypeScript strict mode, Tailwind CSS, and shadcn/ui components. Google Maps (@react-google-maps/api) handles the base map and drawing tools; Deck.gl renders city-scale WebGL heatmaps with 100K+ data points at 60fps. Zustand manages 5 global stores, TanStack Query handles 15 custom hooks for server state, Recharts powers financial charts, and Framer Motion drives page transitions.
Backend: FastAPI with 10 routers, 12 service modules, and 7 Pydantic v2 model packages — fully async (httpx, not requests). The core is an 11-step solar analysis pipeline that orchestrates Google Maps Static API, SegFormer-B0 inference, NASA POWER irradiance, Census Bureau demographics, DSIRE incentive matching, and Gemini 2.5 Flash for AI-generated insights (with OpenRouter as automatic fallback). Redis provides tiered caching (NASA 24h, Census 7d, imagery 30d). 238 pytest tests cover the backend.
The Smalltalk Layer: The 25-year financial model is implemented as two Pharo Smalltalk classes — SolarFinancialModel (a pure computation object with zero I/O, where each financial concept is a message send) and SolarFinancialService (an HTTP wrapper using only built-in Pharo 13 classes: ZnServer, ZnDispatcherDelegate, and STONJSON). The Python backend calls Pharo via pharo_bridge.py, an async httpx client. If Pharo is unreachable, it silently falls back to an identical Python implementation — the app works with or without Pharo running, and 9 cross-language parity tests assert numeric equality within $1 tolerance. We chose Smalltalk because the 25-year simulation is a natural fit for message-passing semantics, and Pharo's live object inspector let us interactively debug financial edge cases during development.
ML/CV: SegFormer-B0 (transformer-based semantic segmentation) deployed on Modal with T4 GPU and scale-to-zero, with a CPU-only PIL+scipy fallback for development. Building polygon detection uses Google Geocoding v4beta with Sutherland-Hodgman polygon clipping for enclosure filtering.
Challenges we ran into
Pharo integration at a hackathon — Getting a headless Pharo 13 image to run as a production HTTP microservice with zero external package dependencies was non-trivial. We had to use only built-in Zinc HTTP and STONJSON classes, write a CodeImporter startup script, and design the bridge so failures are completely silent to the user.
Cross-language numeric parity — Ensuring the Smalltalk financial model and Python fallback produce identical results required careful handling of floating-point rounding, degradation compounding, and inflation sequences across 25 years. We wrote 9 dedicated parity tests with per-year and cumulative tolerances.
Census API complexity — Translating a lat/lng coordinate into a Census block group requires a multi-step FIPS geocode (state → county → tract → block group) before you can query ACS5 demographic data. Rate limits and inconsistent coverage added friction.
City-scale performance — Running even a lightweight solar analysis on hundreds of buildings in a bounding box required careful batching, synthetic fallbacks when OSM data is sparse, and single-fetch irradiance sharing across the scan.
LLM reliability — Gemini 2.5 Flash rate-limits aggressively during peak hours, so we built an automatic fallback chain (Gemini → OpenRouter → graceful None) so the pipeline never blocks on AI insights.
Accomplishments that we're proud of
A working polyglot microservice at a hackathon — Pharo Smalltalk computing real financial projections, called live from Python, with transparent fallback and cross-language parity tests. We believe this is genuinely unusual for a hackathon project.
238 backend tests passing — including 9 Pharo ↔ Python parity tests that validate numeric equality across languages.
Progressive degradation everywhere — every external dependency (Pharo, NASA, Census, OSM, Gemini, Modal) has a fallback path. The app never crashes due to an unavailable service.
The WattsUp Equity Score — turning raw Census demographics into an actionable, explainable 0–100 score with human-readable barrier descriptions that a city planner can actually use.
Autonomous deployment roadmaps — a planner that doesn't just rank buildings but allocates them to yearly deployment phases respecting real-world budget, grid penetration, and interconnection constraints, then writes an executive summary via LLM.
15 custom hooks, 5 Zustand stores, 10 API routers — a production-grade frontend/backend architecture built in a hackathon weekend.
What we learned
Smalltalk is alive and powerful — Pharo 13's built-in HTTP server and JSON support made it genuinely viable as a microservice runtime, not just an academic curiosity. The message-passing model maps beautifully to financial simulations where each concept (cost, degradation, payback year) becomes a method.
The bridge pattern is underrated — designing the Pharo integration as "preferred provider with silent fallback" meant we could develop Python-only 90% of the time and bring Pharo online when we needed it, with zero config changes.
Equity data is hard — Census Bureau APIs are powerful but deeply nested (state/county/tract/block group hierarchies), inconsistently documented, and rate-limited. Energy burden data from DOE's LEAD tool isn't freely available via API, so we had to build a regression estimator.
Hackathon scope is real — we scoped 3 parallel tracks of features (data/viz, financial tools, AI/civic) and had to ruthlessly prioritize. The todo-list-driven development approach kept us shipping incrementally.
What's next for Radiance
Live SegFormer-B0 on Modal — fully deployed GPU inference for production-quality roof segmentation, replacing the development CPU fallback.
Real-time WebSocket city scans — streaming progress updates as Celery workers process thousands of buildings, with a live-updating Deck.gl heatmap.
Redlining overlay — historical HOLC redlining maps layered with modern equity scores to visualize how historical disinvestment correlates with today's solar access gap.
Multilingual reports — LLM-generated solar analyses and policy briefs in Spanish, Mandarin, and other languages for the communities that need them most.
Expanded Pharo services — moving more computation into Smalltalk (battery storage optimization, grid impact modeling) to build out the polyglot architecture.
Open API — a public REST API so municipalities, nonprofits, and researchers can query solar + equity data programmatically for their own planning tools.
Mobile-first redesign — responsive layouts and offline-capable PWA so field teams can run assessments on-site.
Built With
- deck.gl
- dsire
- framermotion
- gemini
- google-maps
- javascript
- nasa
- pharo
- python
- react18
- rechart
- smalltalk
- sql
- tailwindcss
- tanstack
- typescript
- vite
- zustand
Log in or sign up for Devpost to join the conversation.