01 Local-first IES simulation

Light, before
the room exists.

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 / Plan Atelier · 6.00 × 4.00 × 3.00 m · as new
LuxLab plan view: a 6 by 4 metre room with a false-colour work-plane heatmap, six downlights and a 105 to 741 lux legend.
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.

01 What 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.

Prompt DeepSeek parse Local solve
Try the Ask bar

02 How it works

From .ies to lux in three moves.

A short loop: edit, debounce, calculate. The worker keeps the interface responsive while the grid runs.

01 Parse

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

02 Model

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

03 Read

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

03 Local-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 preview Projects stay in the browser
LuxLab 3D preview: a transparent room shell containing six luminaires above a false-colour work-plane heatmap.
6 luminaires 450 patches 467 lx mean as new
Fig. 02 — Work-plane illuminance in the read-only 3D preview. Same 450 patches; rendered locally.

04 The plan

Credible studies, at browser speed.

v0.14.1 is tagged and in use. Press Select in the luminaire list to show a checkmark on every row and choose several lights explicitly, then move them together or delete them with one confirmation. Export a full A4 PDF report 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 scene and results panels resize. Geometry is here too: rooms are polygons on a shared floor, walls block light, and a stepped outline is something you draw.

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.

05 Method

A short, inspectable pipeline.

Parse, interpolate, integrate, display. Every result is reproducible from the inputs, in the browser.

  1. 01LM-63
  2. 02Bilinear
  3. 03Worker
  4. 04Typed arrays
  5. 05Canvas
  6. 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

Direct E = I(γ, C) · cos ε / r² Up to four bounces Bᵢ¹ = ρᵢ · Eᵢ Bᵢk+1 = ρᵢ · Σⱼ Bⱼk Aⱼ cos θⱼ cos θᵢ / (π rᵢⱼ²) Eref(p) = Σₖ Σᵢ Bᵢk Aᵢ cos θᵢ cos θₚ / (π rᵢ²) Maintained Em = 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

06 Changelog

What shipped, in order.

Generated from the project changelog on every deploy, so the page cannot fall behind the release.

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.

v0.14.0

Added

  • Marquee selection and group movement. A new BoxSelect tool on the plan draws a selection rectangle; Shift-drag also starts an additive marquee. Dragging any selected light moves the whole selection by the same delta, preserving the arrangement and stopping at the first room boundary. Arrow keys nudge the group (Shift for 0.5 m); Cmd/Ctrl + A selects the active room.
  • Safe bulk delete. A floating selection bar shows the count, Delete and Clear. Deleting two or more lights goes through one accessible confirmation and one project update, so the autosave and calculation run once. The single-light inline confirmation is unchanged.
  • PDF project report. A Report button in the header generates a downloadable A4 PDF entirely in the browser: a print-friendly 2D plan of every room with a common heatmap scale and isolines, a 3D view of the active room, the project summary, environment settings, per-room and floor results, fixture and luminaire schedules, connected/operating loads and the engine's limitations.

Changed

  • The plan toolbar and hint now explain marquee and Shift-drag selection; the Luminaire section labels the multi-selection primary light and routes bulk delete through the shared confirmation.
  • Project report images use a print palette and a hidden deterministic 3D render, so the report never includes selection handles, hover tooltips, app chrome or the live camera.
  • Added jspdf as a dynamically imported client dependency for the PDF build; the main bundle is unchanged until a report is generated.

Notes

  • The report requires a ready current calculation; the button is disabled while the simulation is queued, running or failed. The PDF is generated locally and nothing is uploaded.
  • The 2D plan covers every room; the 3D view is the active room, matching the app's 3D view. The report is an engineering summary, not a compliance certificate.
  • No database, API or environment change; the report chunk is part of the normal PWA build.

v0.13.0

Added

  • Project-aware assistant. On an open project the prompt bar now reads the project before it answers. Ask why a result looks the way it does — uniformity, average, minimum and maximum, compliance, light spacing, mounting height, surfaces or maintenance — and get an answer that cites the engine's own numbers, the darkest and brightest cells and a coarse 5 × 5 lux sample.
  • Small project edits. Ask for a room resize, a ceiling or work-plane change, a new target, a surface reflectance, a light move or dimming change, a bulk dim, added lights or named removals. The assistant returns a small validated action batch; LuxLab applies it atomically, recalculates, and shows the exact changes plus before/after metrics. One-step Undo restores the previous version.
  • Two assistant modes. This project reads and edits the open project; New study keeps the original brief-to-project flow. A newly created study stays in study mode for its follow-ups; opening an existing project starts in project mode. Each mode keeps its own short history.
  • Project edit safety. Action names must resolve to real rooms and lights, the batch is atomic, every number is clamped, the final project is validated against the project schema, and a project that changed while the assistant was thinking is never overwritten.

Changed

  • The assistant transcript can be taller, renders project answers and edits as a dedicated card, and names the active project and the edited room. Project mode also identifies the exact project summary that is sent to the configured provider.
  • The assistant answers are plain text with preserved paragraphs; the model still never calculates illuminance, spacing or compliance.

Notes

  • The project snapshot includes the project name, room names and sizes, luminaire names/positions, fixture metadata and calculated metrics. IES text, full photometry, project ids and user data are never sent. The project assistant applies the same rate limits and admin-managed provider.
  • No database or environment change. Fixture replacement, room creation and polygon editing are not available through project mode in this release.

v0.12.0

Added

  • Resizable workspace panels. Drag the divider beside the scene panel or the results panel to give the plan and 3D view more room, or widen the calculation panel. The centre viewport re-fits live; the plan, the heatmap and the 3D canvas stay sharp at any width.
  • Keyboard resizing and reset. Focus a divider and use the arrow keys (Shift for larger steps, Home/End for the limits); double-click it or use Settings → Layout → Reset panel widths to restore the defaults. Each divider reports its position to assistive technology.
  • Per-browser layout memory. Panel widths are stored in this browser, survive reloads and are clamped on smaller windows. The preferred width returns when the window grows again.

Changed

  • The fixed scene/results panel borders are replaced by slim draggable dividers with the same hairline look. The scene panel defaults to 280 px at every breakpoint and the results panel to 320 px; both are adjustable.
  • Arrow keys on a focused divider stop at the divider, so they no longer nudge a selected luminaire.

v0.11.0

Added

  • Admin-managed AI provider settings. Administrators can choose the assistant's provider from either Settings surface — the admin dashboard's Settings tab or the in-app Settings modal (shown only to admins) — between DeepSeek and OpenCode Go. They can set the model, enter or replace the API key, test the connection and revert to the server environment. The choice is stored on the server and applies to every account; there is no per-user provider, model or key configuration.
  • Encrypted key storage. Provider keys entered in the dashboard are encrypted with AES-256-GCM using a key derived from LUXLAB_APP_SECRET and stored in the SQLite settings table. The API never returns a key, only a masked last-four hint, and save/clear actions are written to the audit log.
  • Environment fallback and safe failure. With no saved override the existing environment configuration keeps working exactly as before. A saved override wins; a key that can no longer be decrypted or a corrupt settings row fails closed instead of silently switching provider. Reverting deletes the override and restores the environment.

Changed

  • The assistant client is built per request from the resolved provider settings rather than at service start, so an administrator's change applies immediately.
  • The in-app Assistant toggle is now clearly a per-browser privacy choice ("Ask LuxLab in this browser"); the provider, model and key are administrator-owned.

Notes

  • Rotating LUXLAB_APP_SECRET invalidates saved provider keys; the admin panel says so and asks for the key again. Backups of the database now contain a ciphertext that needs the same secret.
  • The current live deployment keeps its environment OpenCode Go key until an administrator saves an override; no migration is required.

07 Ready 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.

Open LuxLab See what's next

v0.14.1 Local-first Metric

LM-63 Type C Direct + up to 4 bounces Metres · lux IndexedDB Ask LuxLab Offline PWA