What it is
A sales site for Warmline Home Energy, a fictional installer of air-source heat pumps, solar panels, home batteries and car chargers, of the kind a regional installer would commission. It opens on an ordinary two-storey house, takes the gable off to show it in section, and then follows one cold spring day of energy through it: at 07:00 the outdoor unit pulls heat out of 2 °C air and the refrigerant carries it to warm water in the floors and radiators; at 13:00 the roof runs the house, tops up the hot-water cylinder and fills the battery; at 18:30 the battery covers the peak-rate hours; at 02:00 the car and the battery charge on the cheap night rate. A live readout shows the time, tariff, outdoor temperature, solar, home use, heat pump input and output with its COP, battery level, grid and car. The day ends on a 24-hour chart with an hour slider. Below it, a savings estimate (floor area, insulation, current heating, solar and battery) shows yearly cost and CO₂ before and after, the cost after a grant and the payback, with counters and a monthly chart; then a demo survey form that sends nothing. The installer, the house, the energy model and every price, tariff, saving, grant and carbon figure are invented and labelled as illustrative on the page.
Engineering decisions
- Plain Three.js without React Three Fiber, like Aster Bay: one imperative scene module (
world.ts) with a frame(input) call; React renders only the HTML around it. - Everything is modelled in code, no model files or image downloads (
model.ts): walls are extruded shapes with real window and door openings, a gable roof with tile courses, rafters, ridge, fascia, gutters and downpipes; an insulated loft; a stair with treads and handrail; a furnished living room, kitchen, bedroom and shower room; the outdoor unit with its coil grille, fan guard and turning blades; indoor unit, hot-water cylinder, wall battery, inverter, meter box, consumer unit and car charger; a carport with a car, bins and a bike; garden, fences, shed, trees, street, lamps, a grid pole with overhead wires and neighbouring houses. Parts are collected per material and merged, so a few hundred props become a few dozen draw calls. - The cut: the front gable is its own group with transparent copies of the materials, so it can slide and fade away; dark section caps (poché) and an orange section line then mark where the cut passes through walls, slabs and roof.
- One small, pure simulation (
sim.ts, unit-tested) drives the scene, the readout and the chart: outdoor temperature, solar, appliances, space and water heating, a COP that depends on air temperature and flow temperature, a car charging window, and a battery that fills on the night rate and covers the day and peak. It runs in 15-minute steps and balances energy at every step; the day is run twice so the battery starts where the previous day ended. - Flows are routes of straight runs with rounded corners (
flows.ts). Pipes and cables are tubes along the same routes; particles move along them at a speed and opacity set by the simulated kW, and run backwards when the battery discharges or the house exports. Heating water fades from warm orange to cool blue along the loop. Particles are nudged a few centimetres towards the camera in the vertex shader so the pipe they ride on does not hide them. - Story chapters are data in
sim.ts (camera pose, hour, cut, heat and power weights); one scrubbed GSAP tween moves a progress value, and the last chapter takes its hour from the day slider, so the story ends where the chart starts. - The savings estimate (
savings.ts, unit-tested) works month by month with heating and solar spread over the year, so the yearly totals equal the monthly chart exactly. Counters are tweened straight into the DOM; a hidden live region and a hidden table give screen readers the final numbers. - Labels on the model and the readout are HTML positioned from projected 3D points and written directly by the render loop, so scrolling never re-renders React.
Performance notes
Three.js loads only on this page. The scene renders continuously while it is on screen and the tab is visible (particles and the fan move); under reduced motion it renders only when something changes. The low tier (phones, 4 cores or fewer, or ?quality=low) drops shadows, antialiasing and room lights, caps the pixel ratio at 1.25, halves the particles and leaves out some trees, hedge and fence detail. ?debug shows the frame rate. Everything created is disposed on unmount.
Reduced motion
Chapters cut to their pose behind a 0.15 s fade instead of flying; flows are drawn as still arrows in their colours instead of moving particles; the fan stands still; the savings counters show their values at once and the monthly bars do not grow; Play the day is off.