Solar self-consumption coach for Dutch households.
The Netherlands ends net-metering (salderingsregeling) on January 1, 2027. After that date, exporting solar to the grid pays ~€ 0.04/kWh while importing costs ~€ 0.32/kWh — an 8× gap. Sunwise tells you which hours today to run your washing machine, dishwasher, EV charger, or dryer so you use your own panels' power instead of the grid's.
Live: https://sunwise-kappa.vercel.app
- Energy clock — a 24-hour timeline showing today's solar production, grid price, and carbon intensity side-by-side.
- Best windows — highlights the top hours where solar is high, prices are low, and carbon is clean.
- Appliance advice — per-appliance cards with the best run window, solar coverage %, and estimated savings in €.
- Saldering framing — the UI explains what the 2027 deadline means for your specific situation.
| Layer | Choice |
|---|---|
| Build | Vite 5 + TypeScript (strict) |
| UI | React 18 + Tailwind CSS 3 + Framer Motion 11 |
| Solar + weather | Open-Meteo (hourly solar irradiance + cloud cover, free, no key) |
| Prices | EnergyZero (NL day-ahead, free, no key) |
| Carbon | Static NL diurnal profile (all real-time sources require keys) |
| Address | PDOK Locatieserver (NL geocoding, free, no key) |
| PWA | vite-plugin-pwa + Workbox (offline-capable, installable) |
| Deploy | Vercel free tier |
$0 operating cost. Every data source is free and keyless.
All scoring logic lives in src/lib/evaluate.ts as pure functions — no API calls, no React, fully unit-tested.
computeSolarFromIrradiance— converts Open-Meteo's hourly GHI (W/m²) to estimated panel output (Wh) for the configured system (kWp, tilt, azimuth, losses).computeBestWindows— normalizes solar, price, and carbon per hour; scores each with weights (solar 50%, price 30%, carbon 20%); finds top-3 non-overlapping windows via sliding window.computeAdvice— for each selected appliance, finds its best contiguous run window, computes solar coverage (Wh overlap with solar curve), saving in € vs grid, and a saldering-aware note.
npm install
npm run dev # dev server
npm run build # type-check + production build
npm run test # 25 unit tests (Vitest)All external market data is behind a MarketDataSource interface (src/lib/market.ts):
interface MarketDataSource {
readonly market: string;
fetchPrices(): Promise<HourlyValue[]>; // hourly €/MWh
fetchCarbon(): Promise<HourlyValue[]>; // hourly gCO₂/kWh
}Adding Germany (ENTSO-E) or Belgium is one new adapter file + one line change in useSolarDay.ts. Open-Meteo is pan-European.
- v1.x — dynamic-tariff households (Tibber, Eneco); battery dispatch scheduling.
- v2 — ENTSO-E adapter → all EU markets via
MarketDataSource. - v3 — B2B carbon-aware scheduling for businesses with solar assets.