A local-first IES lighting simulator for the browser: import real photometry, model a room, aim your
luminaires, or just describe the space — and read the work plane as a heatmap with engineering metrics.
Direct light plus up to four diffuse bounces, calculated on your machine.
Free account · No project uploads · Installable offline PWA
LM-63 · Type C
TILT=NONE photometry
Direct + up to 4
Diffuse bounces
Local-first
IndexedDB · offline PWA
Plate 01 / PlanAtelier · 6.00 × 4.00 × 3.00 m · as new
Average
467 lx
Uniformity
23%
Target
79% ≥ 300 lx
Fig. 01 — Demo atelier: six 2,400 lm downlights, a 64 × 43 grid and 450 surface patches.
Mean 467 lx as new. At the default 0.80 maintenance factor the same
room reads 373 lx maintained.
01What it does
A lighting study, not a render.
Photometry, geometry and result stay visible and editable. No hidden defaults, no black-box solver.
01 / Input
Import real photometry
Drop in an LM-63 Type C file. The parser reads the angle tables, symmetry and candela, draws a polar
distribution, and surfaces the lumens, watts and maximum candela behind it.
LM-63 · Type C · TILT=NONE
02 / Model
Build the room, aim the light
Set a rectangular room, work-plane height and surface reflectances. Place luminaires by hand, or stamp a
block of them with grid placement, then tune mounting height, aim, tilt and dimming in the inspector.
X/Y · Mount · Aim · Tilt · Dim
03 / Result
Read the work plane
Switch between total, direct and reflected illuminance. Track average, minimum, maximum and uniformity,
check a target-lux threshold, and hover the grid for a point reading. Up to three labelled isolux
contours trace the levels that matter, and a maintenance factor turns as-new figures into the
maintained values you specify against.
Average · Min · Max · U0 · Target
04 / Ask
Describe it, then calculate it
Type the room and the light you want — "20 × 15 m office, 500 lx" — and LuxLab builds the
scene, sizes the layout by simulation and reports the result. With a project open, ask
why the result looks the way it does or request a small change; LuxLab applies it,
recalculates and shows before and after. The provider reads the brief or project summary;
geometry, photometry and every lux value stay in the engine. Administrators choose
DeepSeek or OpenCode Go and manage the encrypted key in Settings; each person can still
hide the bar in their own browser. Select several lights to move them together, and
export the whole study as a PDF plan, 3D view and results report.
A short loop: edit, debounce, calculate. The worker keeps the interface responsive while the grid runs.
01Parse
Import and validate
Open the IES library and load a Type C file. LuxLab checks the header and angle tables, expands symmetry,
and builds a bilinear candela sampler.
Rejects TILT=INCLUDE · Type A/B
02Model
Place and aim
Set the room and work plane, then place luminaires in plan. Use the inspector for mounting height, aim,
tilt and dimming. The 3D view is read-only.
Walls block light · No shadows yet
03Read
Calculate and inspect
Recompute and read the false-colour map. Compare total, direct and reflected views, then check the
metrics and the target threshold.
Direct + up to four bounces
03Local-first
The calculation never leaves the tab.
No project uploads and no server-side render. An account gates the tool; the geometry, photometry
and results stay in the tab. If you use Ask LuxLab, the sentence and a list of fixture names go to
the configured AI provider; turning the assistant off in Settings sends nothing. Projects and IES source text live in
IndexedDB, and the service worker keeps the tool available offline. Close the lid and the room is
still there.
Private by default
No project uploads and no tracking cookies. Your project stays browser state, not a
server record; page views are counted anonymously. The assistant is the one network
feature, and it is opt-out.
Instant feedback
The engine runs in a Web Worker. Edits debounce for 360 ms; only the latest calculation survives.
Install it and unplug
An offline PWA. The app shell, fonts and the lazy 3D preview are precached after one visit.
Portable projects
Exports are self-contained .luxlab.json files with every referenced IES profile embedded.
IES→Parser→Worker→Canvas→IndexedDB
Plate 02 / 3D previewProjects stay in the browser
6 luminaires450 patches467 lx mean as new
Fig. 02 — Work-plane illuminance in the read-only 3D preview. Same 450 patches; rendered locally.
04The plan
Credible studies, at browser speed.
v0.15.2 is tagged and in use. Deleting a room asks first and tells you how many lights go
with it. Draw a room with a rectangle drag or an orthogonal outline,
edit corners and walls with snapping, type exact wall lengths, move a room with its lights,
and undo room edits without touching the rest of the study. The Projects lobby remains an
OrbitX portfolio. Press Select in the luminaire list to choose lights explicitly, then move
or delete them together. Export a full A4 PDF with a 2D plan of every room, a 3D view, all
results and the schedules. Describe a space in the Ask bar and LuxLab builds, solves and
calculates it; with a project open, ask why the result looks the way it does or request a
small edit, with Undo behind it.
The goal
Make a credible IES illumination study as quick as opening a tab: fast enough to iterate, private enough
for client work, and accessible enough that photometry isn't locked inside desktop software.
Shipped now
Shipped
One or more rooms on a shared floor plan, each with its own ceiling
Polygon room outlines, with walls that block light
Stepped and L-shaped rooms you can draw and reshape
Two workspaces: warm paper, or the OrbitX dark palette
A floor summary, area-weighted across every room
Type C, TILT=NONE IES import with polar preview
OrbitX catalogue: 97 IES profiles across 20 families
Direct illuminance plus up to four diffuse bounces
Multi-select on the plan, to move or delete a group at once
2D plan editor and read-only 3D preview
Average, min, max, U0 and target compliance
Up to three labelled isolux contours
Maintenance factor: fixed, or the CIE 97 four-factor method
Grid placement for blocks of luminaires
Accounts with roles, an admin dashboard and first-run password change
IndexedDB projects with self-contained JSON export
Installable, fully offline PWA
Next
Unscheduled
→Freeform outlines at any angle, and rooms that share a doorway
→Openings, furniture and shadow rays
→CSV and PDF report export
→Glare metrics, including UGR
→Type A/B photometry and TILT data
→Multi-bounce or path-traced verification
No dates. Scope follows what the method can support honestly.
05Method
A short, inspectable pipeline.
Parse, interpolate, integrate, display. Every result is reproducible from the inputs, in the browser.
01LM-63
02Bilinear
03Worker
04Typed arrays
05Canvas
06IndexedDB
01
LM-63 parser
Type C, TILT=NONE, header variants and symmetry expansion. Unsupported photometry is rejected, not approximated.
02
Bilinear candela
Vertical and horizontal interpolation with 360° wrap-around. Dimming and the maintenance factor scale candela linearly, per luminaire.
03
Web Worker
The pure engine runs off the main thread. Edits debounce for 360 ms and the latest request wins.
04
Deterministic heatmaps
The inferno scale is driven by the data's min and max. No random dithering, no per-frame noise.
05
Local IndexedDB
Projects and IES source text persist in the browser. Exports embed every referenced profile.
06
Offline PWA
The app shell, fonts and lazy 3D chunk are precached after the first visit. No CDN in the path.
Calculation
DirectE = I(γ, C) · cos ε / r²Up to four bouncesBᵢ¹ = ρᵢ · EᵢBᵢk+1 = ρᵢ · Σⱼ Bⱼk Aⱼ cos θⱼ cos θᵢ / (π rᵢⱼ²)Eref(p) = Σₖ Σᵢ Bᵢk Aᵢ cos θᵢ cos θₚ / (π rᵢ²)MaintainedEm = MF · (Ed + Eref), MF = LLMF · LSF · LMF · RSMF
Bilinear candela in γ and C. One bounce by default and up to four; still an estimate, not a full
radiosity solve.
Fixture check
750 lm declared→748 lm integrated
A public Cooper Lighting MRZ Type C profile was integrated at 1°. The check exercises angle handling and
flux integration — it is not a certification.
Third-party fixture · Not a compliance claim
06Changelog
What shipped, in order.
Generated from the project changelog on every deploy, so the page cannot fall behind the release.
v0.15.2
Fixed
Deleting a room asks first. The Room panel's delete was a single click that also removed every luminaire in the room. It now opens a confirmation that names the room, reports how many lights go with it, and says the study recalculates. Cancel leaves the room and its luminaires untouched. The dialog is bound to the room that was clicked, not to whichever room is active, so a change of selection cannot retarget it.
Notes
No schema, database, API or environment change.
Room-scoped Undo still restores a confirmed delete until a non-room edit clears the history, so the dialog says that instead of claiming the deletion is permanent.
scripts/smoke-room.mjs now covers the prompt, its Cancel path, the empty-room copy and Undo after a confirmed delete.
v0.15.1
Fixed
Fast room drags are reliable. The rectangle draft now lives in a ref while the pointer is down, so a quick press-move-release cannot finish against a stale zero-size draft. This is the same guard the outline draft already needed for rapid pointer events.
v0.15.0
Added
A room editor built around explicit tools. Select, Marquee, Draw rectangle, Draw outline and Pan live in a plan tool rail. A room is now drawn with a drag or a click-by-click orthogonal outline, with live width, depth and area, a ghost preview, Escape-to-cancel and Backspace to remove the last outline point.
A separate Edit outline mode. Select mode no longer covers a room with permanent handles. A room chip shows its name, area and dimensions; Edit outline exposes corner handles, wall handles, exact wall-length labels and a Done action. Corner and wall drags snap to the grid and neighbouring rooms, and wall plus buttons add a step.
Whole-room movement. Dragging a room body moves the room and its luminaires together; a room can be snapped to existing walls and corners.
Room-scoped Undo/Redo. Draw, add, duplicate, delete, move, reshape and dimension changes are undoable from the tool rail or Cmd/Ctrl+Z. Non-room edits clear the room history so Undo cannot silently revert unrelated work.
Validation. Rooms may share walls and corners but may not overlap; invalid previews and attempts are rejected with a reason. Imported non-rectilinear outlines remain calculated and displayable but are read-only for corner editing.
Changed
The Room panel now offers Draw room, Edit outline, Quick add, and clear shape metadata instead of the old blind Add room and remove-step controls.
Pointer-cancel and Escape restore the pre-gesture shape instead of committing the last preview.
The plan reports the active drawing/editing state through an aria-live status and uses larger touch targets for room handles.
Room history is intentionally scoped: a light, environment, AI or import edit clears it. A project-wide undo stack remains a separate feature.
Notes
No schema, database, API or environment change. Room and Project records are unchanged.
The orthogonal editor remains the boundary: arbitrary angled/curved outlines, wall thickness, doors and windows are out of scope.
New smoke: scripts/smoke-room.mjs.
v0.14.2
Added
Redesigned Projects lobby. The first screen after sign-in is now a portfolio workspace: a Studio index with a real, data-derived blueprint of the latest study, total rooms, luminaires and floor area, a quick Open latest action, a three-column grid of project cards with blueprints and live room/light/area metadata, a dedicated New project tile, and a designed empty state.
Import from the lobby. A project bundle can now be imported before opening a project, using the same validation and notices as the workspace header.
OrbitX blueprint plates. Project previews use the deep blue-black plate, electric-blue room outline and technical grid in both themes; the surrounding card and index surfaces still follow the selected app theme.
Fixed
List-row selection test IDs no longer collide with the plan's luminaire markers, which had made the AI smoke count both rows and plan markers.
v0.14.1
Changed
Explicit Select mode in the luminaire list. A Select button with a checkmark icon in the Luminaire section reveals a checkmark box on every row. Click a checkmark or a row to toggle that light in the selection; leaving Select hides the boxes but keeps the selection. Every selected row is highlighted, not just the primary light, and the existing bulk-delete and floating selection bar work with the same set.
The single-light Shift/Meta/Ctrl-click, plan marquee and group drag remain available; Select mode is an easier alternative for choosing lights from the list.
07Ready when you are
Start with a room. Leave with a number.
One click from the project list: 6 × 4 × 3 m, six 2,400 lm downlights, 373 lx maintained at the default
0.80 factor. A free account keeps it yours; nothing you draw is uploaded.