← Back to work

2026 · Product, engineering

Solarscandinavia — Solar Investment Tooling

Two connected tools for the Swedish solar market — an investment calculator (NPV, IRR, LCOE, elcertifikat) and a map-driven proposal studio that designs arrays on satellite imagery and prints the quote.

Context

Two tools, one workflow. An installer needs to answer two questions for every lead: is it worth it? and what does the array actually look like on this roof? SolcellsKalkyl answers the first — a full Swedish investment case with NPV, IRR, LCOE, and payback. SolOffert answers the second — panel layout drawn on satellite imagery, sized against Google's Solar API, exported as a proposal.

They share a domain (Swedish PV economics, elcertifikat, tariff structure) and a reading order: design the array in SolOffert, run the numbers in SolcellsKalkyl, hand the customer the quote.

SolcellsKalkyl — the investment case

SolcellsKalkyl results and KPI tab
Resultat & KPI — NPV, payback, LCOE, IRR, and the present-value revenue split.

A single-file, browser-based financial model. One HTML file (~117 KB), no build step, no backend — open it and the full calculator is live. Vanilla JS, state lives in the DOM, calc() re-runs the model on every input change.

Five tabs, one document

SolcellsKalkyl diagram tab with four Chart.js visualisations
Diagram — cumulative cash flow, revenue stack, monthly production, cost breakdown. Charts destroy and rebuild on every recalc.

Financial model

Domain modelling

Configuration is JSON-driven: price scenarios and example projects live in sibling files (elpris_scenarier.json, exempel_a1.json, exempel_b1.json) and reload without touching code.

SolOffert — the proposal studio

SolOffert interactive solar proposal studio on Google satellite imagery
SolOffert — address search, roof polygons, obstacles, auto-filled panels, and Solar API flux overlays on one map.

React 18 + TypeScript on Vite 5. An installer types an address, draws the roof, drops obstacles, and the app places the panels and produces the quote.

The flow

  1. Google Places autocomplete → zoom to address.
  2. Draw one or more roof polygons on satellite imagery.
  3. Drop obstacles and keepout lines that block placement.
  4. Define panel zones — the geometry engine auto-fills them with panel rectangles under real constraints.
  5. Overlay Google Solar API data — annual flux, monthly flux, hourly shade — rendered from GeoTIFF into the map.
  6. Read off system size, annual production, payback, LCOE from the economics module.
  7. Export a printable quote with customer info and the technical/economic numbers.

Engineering highlights

Module layout

ModuleRole
src/App.tsxState reducer, async orchestration, UI composition
src/lib/mapManager.tsGoogle Maps integration, drawing, panel fill, undo
src/lib/solarApi.tsTyped clients for buildingInsights and dataLayers
src/lib/tiffRenderer.tsGeoTIFF fetch / cache / render pipeline
src/lib/economics.tsProduction distribution and financial model
src/lib/sunCalc.tsSun altitude/azimuth, direction labels

Stack

SolcellsKalkyl — HTML5, CSS custom-property design system, vanilla ES2020+, Chart.js 4.4, OpenAI Chat Completions, JSON config. SolOffert — React 18, TypeScript 5 (strict), Vite 5, Google Maps JS API, Google Places, Google Solar API, geotiff 2.1.

Takeaways

The interesting part wasn't any single component — it was the fit. SolcellsKalkyl proves out the economics on its own page; SolOffert proves out the design on the roof. Share the domain model (Swedish tariffs, elcertifikat phase-out, subsidy caps) and the two tools compose into the sales workflow an installer actually runs.

The calculator is deliberately zero-build: one HTML file opens in any browser and prints a six-page PDF. The proposal studio is the opposite extreme — a typed, geometry-heavy Vite app on top of three Google APIs. Same domain, different tool shape for different jobs.