Roadmap for building silicon·eras as a Dioxus (Rust → WASM) app and embedding it in
dhilipsiva.dev. Derived from prompt.md, re-expressed for Dioxus (the prompt's
Vite + TS + D3 stack is superseded), plus new embedding + "edit data" requirements.
- Source-of-truth ordering (see
CLAUDE.md): the prototypeSilicon Eras.dc.htmlwins on any conflict → thenHANDOFF.md→ thenREADME.md.silicon-data.jsdocuments the data shapes; port the logic class nearly verbatim, re-express the template as Dioxusrsx!. - Log every forced deviation in
DESIGN_DIVERGENCE.mdwith rationale — never silently improvise. - Encoding law (do not break): color = entity · geometry = tier (envelope-vs-3-lines; heavy
typical vs thin entry/top) · texture = confidence (solid = documented, dashed +
≈= estimate). Never encode tier or confidence with color. - Stack: Dioxus 0.7 web, built with
dxv0.7.9 → copied intodhilipsiva.devstatic/silicon-eras/,--base-path silicon-eras, served at/silicon-eras/. App lives in its own repogithub.com/dhilipsiva/silicon-eras. - Theme: inherit dark/light from the host site's
data-themeon<html>— the app renders no theme toggle of its own. QUINE tokens (--ember-500,--phosphor-500,--quanta-500,--sky-500,--amber-500,--surface-card,--font-mono/sans/display,--space-*,--radius-*,--dur-*,--ease-*) come from the hostquine.css; portquine-viz.css's--viz-*extension into the app. - Milestone gate: stop after each milestone — each must build clean, pass tests, and match the handout before starting the next.
-
git initthis folder as the app repo (github.com/dhilipsiva/silicon-eras); keep the design bundle in-repo. Commit the dataset asdataset.csv(currentlysilicon-eras.txt). - Dioxus 0.7 web crate:
Cargo.toml,Dioxus.toml,.cargo/config.toml(wasm32 target;getrandomwasm_jsif pulled in). Release profilewasm-opt = false(Windowsdx/wasm-opt hang, matching the site'sslm-wasmnote). - Build-time CSV → typed data: an
xtask(orbuild.rs) readsdataset.csv, parses to typed structs (emit a generated Rust module orinclude_str!-ed JSON baked into the WASM), and writes a warnings report for every cell it cannot fully parse (honorsprompt.md's build-time contract). - Data contract — implement exactly (
prompt.md§Data contract):- Range cells (
16-48 KB,1.6-3.4 GHz) →{min, max, mid}; single values → all three equal. 6 cores / 12 threads→ cores primary, threads secondary.- Normalize to bytes / Hz, decimal multipliers; keep raw strings for tooltips.
- Sentinels (
none,shared,n/a, empty) → null-with-reason, never coerce to zero. - Sparsity: each series starts at its first non-null era — no zero-fill, no back-fill.
- Indexed mode: divide each series by its own first non-null era value (per device+metric base).
- Range cells (
- Parser unit tests — cover the real dataset edge cases (a superset of
prompt.md's fixtures; several prompt fixtures liketoggles, paper tapeand0.5-1 GBdon't occur verbatim):- Unit-crossing ranges:
256 bytes-1 KB,512 KB-1 MB,512 MB-1 GB(parse each side with its own unit). - Cores:
1 core; 2 threads (HT)(semicolon + parenthetical),8-16 cores / 16-32 threads(double range),6-8 cores(cores only),1 core; 2 threads (P4 HT 2002). sharedas a lower bound:shared-32 MB,shared-2 GB; also~8 KB shared,shared / 8 GB.- Type/qualifier suffixes to strip:
768 MB GDDR3,64-128 GB DDR5,32 GB GDDR7 (512-bit, 1792 GB/s),16 GB (Copilot+ floor),up to 1 MB. - Bare sentinels:
shared,n/a, empty cell; real front-panel stringswitches/LEDs; paper tape. - CSV: RFC-4180 quoting (fields embed commas/semicolons);
source_urlssplit on;not,(URLs contain commas), trim trailing spaces.
- Unit-crossing ranges:
- Known data-vs-contract exceptions — triage as accepted warnings, not bugs:
- laptop covers only 10 eras (missing the first two); desktop/gpu cover 12.
- gpu rows: empty
cores_threads, and no prices (even typical); gpuclockblank until 1995-99. - Two laptop entry rows carry prices (contract said typical-only).
vramis populated across all three tables (not gpu-only); early desktop vram is empty, early laptop vram isn/a.- Columns
era_label+graphics_displayexist in the file but aren't inprompt.md's column list.
- Era-band chart; envelope / typical / 3-line modes; log ↔ linear; abs ↔ indexed (multi-select only in indexed); plateau guides; pins with clustering; tooltips.
- Solid = documented, dashed + badge = estimate everywhere.
- Empty states:
∅ no metrics selected(indexed, none picked);∅ no data in this era range(brush before the lineage exists — name the first shipping year). - Gate: parse pipeline + parser tests green, Trajectories/RAM matches the handout.
- Band click → inspector drawer (slide-in, scrim); two era cards + diff panel with per-metric
multiples (
b ÷ aon typical; crimson on regression,÷; em-dash where a lineage is absent).
- 5 swimlanes on the shared era axis, full-height; segment edges follow real years, piecewise-linear within each unit band so decade/epoch schemes keep exact boundaries; ghost segments dashed; hover cards (mid-era snapshot).
- Hand-author swimlane + annotation-pin seed data (
src/data/seed.rs) fromprompt.md's Seed-data block + thegraphics_displayprose — do not regex the prose cells.
- 4 series: desktop/laptop typical, gpu mainstream (typical, heavy) + gpu flagship (top, thin,
same hue — tier = geometry). Nominal ↔ 2026-USD toggle; tooltip rows;
n/a — not yet shipping. - Budget time machine:
$input (clamp 0–999,999) + era scrubber → per-lineage tier card (top / typical / entry /⊥ below entry/∅ not yet shipping) vs REAL (2026) aggregated prices.
- Lollipops:
top ÷ entryper metric per era, always log, ×1 baseline; dashed stem when either endpoint is an estimate; estimates-off hides affected lollipops. - Polish: Lighthouse a11y ≥ 95; reduced-motion respected; warnings report empty or every warning triaged; zero silent design deviations.
- Three era schemes (named 12 / decades 6 / epochs 4) as segmentations of one atomic 12-era timeline. Aggregation: entry = min of members, top = max, typical = last non-null member's typical. All era indices are scheme-unit indices, clamped at read time (scheme switches shrink the index space). Indexed-mode base computed on FINE data so multiples stay scheme-invariant.
- URL state (shareable): round-trip all state to the URL hash/query (schema in HANDOFF §7);
history.replaceStateon change; malformed params silently dropped; parsed once on mount. - Keyboard:
← →scrub era within brush ·1–5switch view ·Ltoggle log ·Enteropen drawer ·Escclose popover→drawer. Ignored while typing in inputs. - Export:
⧉ share url(copy URL) ·⤓ csv(current-view slice) ·⤓ png(spec'd affordance → toast; production renders SVG→canvas at 2×). - Theme: read
document.documentElement.dataset.theme(lightvs absent = dark) + aMutationObserveron that attribute to re-render; no in-app toggle. Colors come fromvar(--…)tokens so light/dark re-colors automatically. - Responsive: ≥880px = full explorable; <880px = read-only card fallback (no charts, no drawer).
- Add an
⤓ edit dataaffordance in the app header row (next to share / png / csv) linking to the dataset on GitHub:https://github.com/dhilipsiva/silicon-eras/blob/main/dataset.csv. Read-only handoff to GitHub for community data edits.
-
scripts/build_silicon_eras.sh— clone ofscripts/build_voksa.sh: clone the silicon-eras repo,dx build --release --platform web --base-path silicon-eras, copy web output →static/silicon-eras/. - Register
silicon-erasinscripts/inject_nav.pyAPPS(dir / title / active-nav / extra-css) so the shared site header is grafted post-build. - Add a nav link in
templates/partials/nav.html(mirror the/voksa/live link). - Add
bash scripts/build_silicon_eras.shto.github/workflows/deploy.yml(dx v0.7.9 already installed); optionalsilicon-eras-updatedrepository_dispatchtrigger so data pushes redeploy. -
.gitignore→/static/silicon-eras. Optionalcontent/things-i-built/silicon-eras.mdproject card (live = "/silicon-eras/",repo = "…"), mirroringcontent/things-i-built/voksa.md.
rustup target add wasm32-unknown-unknowndx(dioxus-cli) v0.7.9 —cargo install dioxus-cli --version 0.7.9(or the site's pinned installer)- Build:
dx build --release --platform web --base-path silicon-eras· Test:cargo test