Periodic Lens
A periodic table that builds its own shape on screen and maps Indonesia's share of world mineral production

- elements, each with cited properties
- 118
- Indonesian minerals tracked for world production
- 7
- commodities checked to tell zero from unknown
- 77
On this page
The problem
Students meet the periodic table as a chart to memorise. Clickable versions with element details already exist, and ptable.com does that well. Almost none explain the shape itself: why the first row has two elements, why the lanthanides sit in a footnote, why the blocks are 2, 6, 10 and 14 columns wide. The answer is the order in which electrons fill orbitals.
There was a second gap. No periodic table shows which elements Indonesia produces and at what share of world output, even though nickel, tin, copper and gold are a national story students already hear on the news.
I built Periodic Lens for students and chemistry-curious readers. It is English-first with a full Indonesian translation, because chemistry vocabulary is international.
What I built
The table builds itself from the rule
The build page states the filling rule, works the arithmetic on screen, and animates the table assembling from it. Then it lights up the roughly 20 elements, such as chromium, copper and gold, where the rule predicts the wrong electron arrangement. It shows the prediction next to the published value. A switch changes the filling order to a naive one, and the row lengths turn from 2, 8, 8, 18, 18, 32, 32 into a wrong shape. That difference is why the rule matters.
I store published data and use the rule to test it
Electron arrangements come from published data and are never generated. I use the rule only for the animation and to check the dataset. The tests assert that the rule disagrees with the published values on exactly the documented list of exceptions, in both directions. Generating the data from the rule was the biggest risk, because the rule fails on exactly the interesting elements. So those exceptions were the first thing I tested.
Unknown values look unknown
Many properties are not known for the heaviest elements. I made it impossible to store a property as a bare number: each value is either known, with a unit and source, or marked unknown. A missing value can't quietly show up as the bottom of a colour scale. Unknown has one look, a hatch pattern, and one lens maps nothing but where human knowledge runs out.
One lens at a time, with colours that pass tests
Most flashy periodic tables put five competing encodings on 118 cells. Here colour shows one property at a time, across eleven lenses, and switching re-colours every cell in one move. I set palettes by brightness targets. Tests check that colour scales rise steadily, that categories stay distinct in greyscale and for colour-blind readers, and that text keeps readable contrast.
Every number carries its source
Each property comes from a source file with a citation per field. A validator checks licences, citations, survey edition years and completeness, and a property without a source doesn't ship. Indonesia's production figures come from the US Geological Survey, checked against 77 tracked commodities so "not produced" and "unknown" are never confused. Each figure carries its edition year and whether it counts mined or refined output. Not produced is kept distinct from produced in small amounts, and there is no policy commentary either way.
Result
Periodic Lens is live and public in English and Indonesian. It covers 118 elements, 11 lenses, three table layouts with cells travelling between them, and three views, including a relief that shows properties as height. The Indonesian lens covers nickel, tin, cobalt, bauxite, copper, gold and silver.
I did a separate accessibility pass after the features were built: one tab stop with arrow-key navigation, plus a sortable text table with the same data. On phones the grid scrolls sideways at full size, because the shape is the subject. The site makes no network requests after the page loads. I built the first version in seven days in August 2026, then kept working into late September on mobile navigation, a layout picker and the Indonesia page's headline chart.
Under the hoodTechnical detail for engineers
- All chemistry lives in a pure library (
lib/elements/) that runs in plain Node; components only render. - Property values are typed as
{known, value, unit, source}or{unknown}. The hatch pattern is defined once inlib/elements/unknown.ts. lib/elements/aufbau.tsdrives the animation and the bidirectional exception assertion. The anomalies were the first thing tested (bf818d2).- Palettes are authored as luminance targets in
lib/design/palette.ts. Tests assert monotonic continuous ramps, categorical values at least 0.03 luminance apart, and AA contrast against the text on each value. - Pipeline: TSV sources with per-field citations, validate, merge and mark unknowns, one generated JSON. Zod validates the schema. The validator and all four test suites gate every deploy.
- A copy scan bans policy commentary and safety guidance in shipped copy in both locales. It flagged its own test file at first and was scoped to shipped code (
4c1090c). - Layouts: standard, Janet left-step and Benfey spiral. Views: grid, topography relief and discovery timeline. The unmeasured lens and the counterfactual toggle grew beyond the PRD.
- Sixteen consecutive accessibility fixes: native list semantics in place of invalid grid ARIA, a single tab stop, two-tone focus rings, rem-based type metrics, locale-aware landmark names, screen-reader announcements for lens changes.
- Builds are byte-identical for the same datasets, including build-time OG image generation.
- Next.js 14 static export on GitHub Pages. Four runtime dependencies (next, react, react-dom, zod). No charting, chemistry, animation or component library.
- The table, build animation, three layouts, three views, Indonesia page and method page are all built and live in two locales. Emission spectra from NIST data were cut (
04458f4). - A later pass added a serif display voice to what was originally a single sans-serif type family, alongside one accent colour and softer surfaces.
- 183 tests in 6 files. About 7,522 lines of TypeScript and TSX across the app, components and lib folders. 93 commits between 20 August and 29 September 2026.
Screenshots
Hiring, or building something similar?
I'm open to full-time roles and select freelance work.