How This Site Was Built
ShinyQ HQ was built in the open by AI coding agents working from written specs and plans. Kurniadi reviewed the changes and approved each merge. This page follows the build from its blueprint to the checks required before release.
As of Nov 2, 2026, commit a403821
The Blueprint
The whole system on one map: who writes the code, where it ships, and what runs when a visitor opens the site.
How it runs
- 1
Every page is pre-rendered as static HTML. The Classic site needs neither WebGL nor a Next.js server runtime; Cloudflare Pages hosts the files.
- 2
The 3D tower mounts on the client on top of those pages and never replaces their content.
- 3
Pages Functions handle the Ask Rover Assistant, performance and visit beacons, and public stats requests.
- 4
A Cron Worker aggregates visit statistics into KV every two hours. The public stats show counts and topics, not raw logs or visitor-entered questions.
- 5
The Agent Office runs live. Hooks in GitHub Copilot, Claude Code and Codex call a relay on the owner's Mac, which sends only each session's state and activity type; code, prompts and file paths never leave the machine.
- 6
The hq-office Worker has no public route: Pages Functions reach it through a service binding. Its Durable Object keeps the ten desks, the CI lanes reported by the GitHub webhook and an eight-day replay.
- 7
Ask reads its knowledge pack from Workers KV, checked by its hash, with a small bundled fallback. Gemma 4 on Workers AI answers first; Mistral Small 3.1 and two free Groq tiers take over when a tier fails.
- 8
The certification study guides live as PDFs in a private R2 bucket. A Pages Function serves them in byte ranges, so the in-site reader opens a guide without downloading all of it.
The Build Timeline
Rounds of merged pull requests, from the first foundation to this page. The counts and dates come from the repository history.
Pull request numbers open on GitHub in a new tab.
Foundation and the Five Floors
The content dataset, missions, launch infrastructure, the tower shell, the rover and the first five floors took shape.
15 merged pull requests
Game-First Load, Classic Site and Ask the HQ
The Classic site was revamped, the 3D boot cover and CI fast pipeline arrived, client work moved to sector labels and the Ask the HQ assistant launched, with the first walkable floors, the CV viewer and a performance pass.
30 merged pull requests


The Classic site home page, from the design mockup to the built page. Title Case, Call Pads and the Writing Floor
Titles moved to Title Case with one project order, elevator call pads and a new landing hero arrived, and the Writing floor and roof deck were built.
6 merged pull requests


The landing hero, from the design mockup to the built page. Point-and-Go, Onboarding and the Highlights Hall
Perspectives, live-site links and ticketing projects were added to the content, alongside point-and-go movement, paper PDFs, Rover dialog, onboarding and the Highlights Hall.
7 merged pull requests
Performance, Camera and Spectacle
Share cards and SEO landed, the elevator and camera became smoother and freer, a GPU, CPU and memory pass set the performance gates, and the Motion setting and floating signs arrived.
20 merged pull requests
Visit Stats, Ops Room, Data and ML, Security
Public visit stats, the Tech Reactor, the Ops Control Room, the Data and ML pods and the Topic Constellation were built, followed by a security audit, Ask answers about how the site was built and a README redesign.
43 merged pull requests
Uptime, CSP and Floor Chunks
Hourly uptime alerts and per-page CSP hashes arrived, packages were upgraded, floors loaded as separate chunks and the Labs floor was split into three separate project boards.
22 merged pull requests


The Labs floor before and after the three separate boards. Diagrams, Music, Day and Night
Architecture diagrams, ambient music, shareable Classic links and smart CI were added, with a day and night sky, a Corners HUD with a minimap and L3-style arrivals on every floor.
11 merged pull requests
Rover Menu, Ambience and the Engine Room
Ask gained 100 curated question pills, multi-turn memory and free Groq backup tiers; Rover got a menu and idle animations, and every floor its own ambience. Deploys now start on merge and roll back on a red main CI. The intro got its fly-in, and this build story arrived with the secret B1 Engine Room, unlocked by visiting all five floors.
21 merged pull requests
Faster CI, a Living Sky and a New Intro
A CI speed-up series: main runs only the complement of its pull request's green run, perf gates follow shared imports, budget sweeps moved to the nightly, Lighthouse checks only the affected pages and e2e shards are packed by worker time. The sun and moon now rise and set on a four-minute cycle, Rover wakes up before a reveal orbit of the Lobby, and every owner decision became its own file.
14 merged pull requests
Agent Office, Study Guides and the Rover Voice
The Agent Office backend arrived: a Worker with a Durable Object, and a relay with hooks for Copilot, Claude Code and Codex. Certification study guides moved to R2 with an in-site reader and the L4 Study Vault. The Classic site got quick performance wins and a design refinement, public stats refresh every two hours, Rover answers in its own voice and the Ask knowledge pack moved to Workers KV.
16 merged pull requests
A Roomier Lobby, Faster 3D and the 3D Office
The Lobby slab grew to 54 u with every obstacle 6 u apart, and the Agent Office opened in its own L1 wing, with a Live Agent Office card on the Classic home. Performance passes C to E moved floor layouts out of the Classic site, served 3D data as static JSON, built one logo atlas, slowed the frame rate when nothing moves and mounted the 3D chunk about 250 ms sooner. Nightly Ask evals moved to Groq models production never uses.
16 merged pull requests
The Office Revamp, Upgrades and the Living B1
The office revamp seated a living Rover crew at ten desks in two rows, with helper drones, a Needs Kurniadi beacon, the ship-it pipeline from CI to production and a day replay. Visit stats became accurate (automated visits skipped), Node, Bun, Next.js and other packages were upgraded, and the public-safety blocklist was removed: client names stay out by review. B1 grew into a living machine: this detailed story with Rover's Brain and Rejected Designs as stations, and a reactor hall whose core runs on live CI runs, deploys, awake agents and visits.
17 merged pull requests
Leaner CI, the B1 Hologram Pass and Honest Visit Stats
Pull requests got fewer perf shards and leaner caches, and verified dead code and duplicated tests were cleared. Every B1 bay gained a hologram drawn from its own data, with a Stack Halo over the reactor. Elevator rides moved to a 35 degree diagonal, every L2 and L4 room and every L3 project got its own floating icon or sculpture, and visit counting became first-party with an hourly update.
15 merged pull requests
Smarter Ask, One PDF Reader, Time Travel and the Recruiter Pass
Ask moved to hybrid semantic retrieval with five turns of memory, answers civic, learning and team questions, and can outline how Kurniadi approached a problem like the visitor's. Every PDF now opens in the shared study guide reader, the journey became a Time Travel skyline with a slider and Play, the Classic site got its recruiter pass, and the B1 walls their gunmetal panels with lit seams.
12 merged pull requests
Reader Tracks, Phone-First 3D and the Hallmark Redesign
L4 traded its post timeline for one bookshelf per reader track. Phones got a boot card docked at the bottom, a Lobby landing view and a short docked tour. The Classic site was redesigned page by page, Indonesian copy was rewritten to read naturally, and 24 stack names gained logos.
13 merged pull requests
Phone-First Parts 2 and 3, Certifications and a Ten-Book Vault
Every floor title now reads on a phone, a phone held sideways gets its own camera, and the joystick floats. GH-300 was earned, the AB-100 study guide joined a Study Vault that now holds ten books as two tiers, and the profile was aligned with LinkedIn.
37 merged pull requests
Working with AI Agents
Agents write the code; the human owns the decisions. A coordinator splits the work across parallel sessions, and every change follows the same loop, with its spec and plan committed to the repository.
Every change, step by step
- 1
Coordinator
A coordinator chat holds the owner's requests and decisions. It splits the work into features and starts one project session per feature, each in its own git worktree and branch, so parallel work never collides, and it keeps at most two CI runs in flight.
- 2
Spec
A brainstorm with the agent ends in a written design spec that states what to build and why, with the owner's content decisions as the final word.
- 3
Plan
The spec becomes a step-by-step plan in the repository: small tasks, exact files, tests written first and the commands that prove each step.
- 4
Agent Tasks
Inside a session, the superpowers workflow runs the plan as subagent-driven tasks: one fresh agent per task, each returning a report with test evidence. Smaller sub-agents explore the code, run long commands and review diffs in their own context.
- 5
Review
Each task is reviewed before the next begins. Changes to the look of a floor also pass a local look-preserving visual gate (scripts/visual-gate.ts) that compares screenshots across devices and camera poses.
- 6
Owner Gates
The owner reviews at fixed gates: the spec, any list that needs approval (the Rejected Designs on this floor went through one), screenshots across phone, tablet and desktop for a visual change, and finally the merge.
- 7
Gates and Release
The pull request then has to pass the Gates, and the merge the owner approves is what ships it.
Agents used
- GitHub Copilot
- Claude Code
- Codex
### Task 5: Bundle gate with per-floor chunk caps
**Files:**
- Modify: `e2e/budgets.ts` (`BYTES_3D_BUDGET.floors`)
- Modify: `e2e/perf/bytes-3d.spec.ts`
- Modify: `scripts/perf-report.ts` (`bytes3d` entry `floors?`, summary line)
- Test: `tests/unit/perf-report.test.ts`
**Interfaces:**
- Consumes: `window.__hq.floorChunks.load(id)` and `?prefetch=off` (Tasks 1 and 4).
- Produces: `BYTES_3D_BUDGET.floors: { L3: 20 * 1024, L4: 16 * 1024, RF: 8 * 1024 }`; perf entry `{ kind: "bytes3d"; tier; js; other; floors?: Partial<Record<"L3" | "L4" | "RF", number>> }`.The Gates
Automated checks that decide whether a change may merge. Each one states what it checks and the number it enforces.
| Gate | What it checks and its budget |
|---|---|
| Types, Lint and Unit TestsBlocks merge | Strict TypeScript, ESLint and the Vitest suite, including the content and docs tests: Title Case, both languages, no em dash. Zero type errors, lint errors and failing tests |
| Secret ScanBlocks merge | Scans the repository history for committed credentials, because the repository is public. Zero secrets found |
| Per-Page CSP HashesBlocks merge | The build hashes every inline script of every page, and the export scan fails when a page carries a script its own policy does not allow. No inline script without a hash |
| Selective Pull Request RunsBlocks merge | Reads a pull request's changed paths and runs only the e2e specs, perf tests and Lighthouse pages they affect, plus a smoke set. Any planner error runs everything. Docs-only and test-only pull requests run no heavy job |
| Main Runs, Deploy and RollbackBlocks merge | A push to main runs only what its merged pull request's green run on the same tree skipped, so main still covers everything once per merge. Production deploys after that green run (or after full CI on main), and a red main run rolls production back to the last good deployment. Every check once per merge; no deploy without a green run on the same tree |
| End-to-End ShardsBlocks merge | Playwright tests the exported site in shards packed by measured worker time, so they finish together. Actions wait for the required application state, never for fixed delays. Every spec passes in every shard |
| 3D Download SizeBlocks merge | Measures the gzip JavaScript the 3D experience downloads before its first frame, for the lite and full tiers, and each floor chunk on its own. A cap rises only to the measured size plus about 0.6 KB, and only with the owner's approval. Under 466.4 KB gzip on the first-frame path |
| 3D Render and MemoryBlocks merge | Counts draw calls and triangles on every floor. Elevator round trips then check GPU object counts and JS heap growth against the memory budgets. Under 150 scene draw calls and 30k triangles; zero GPU object growth and under 2 MB heap growth |
| Classic Site SpeedBlocks merge | Lighthouse CI loads the affected Classic pages plus the home page and fails the check on slow paint, layout shift, blocking time or heavy scripts. LCP 2 s, CLS 0.01, TBT 200 ms and JS 240 KB on Classic pages |
| Look-Preserving Visual GateReports only | Compares screenshots of a change against its base on 3 devices and 8 camera poses. It needs a real GPU, which hosted runners lack, so it runs locally before a visual change merges. Strict profile: at most 0.1% of pixels differ |
| Nightly Full RunReports only | Every night the whole suite runs on 8 e2e and 4 perf shards, including the slow budget sweeps kept out of pull requests. A failure opens an issue, which closes once a later night is green. Everything, every night |
The Dashboard
A repository snapshot of commits, merged pull requests, tests, specs and plans. The performance budgets live with the Gates.
315
Merged pull requests
329
Commits since Oct 9, 2026
506
Unit test files
725
End-to-end tests
30
Spec documents
126
Written plans
5
Floors in the 3D tower
Hourly
Uptime check on the live site
Rover's Brain
How Ask Rover Assistant finds, grounds and checks its answers, from the question to the streamed reply.
How it answers
- 1
Gatekeeper
Each question passes a Turnstile check (or a signed 30-minute cookie), rate limits of 8 a minute and 40 a day per visitor, and a scrub of personal data. Earlier turns arrive signed; a turn whose signature fails is dropped.
- 2
Scope Routing
Rules, not a model, decide what Rover answers. Private topics, opinions about other people and general-assistant requests are declined; lifestyle questions are answered only from Kurniadi's written perspectives, and questions about this site always get the site-build note.
- 3
Retrieval
BM25 with title and intent boosts, fused with multilingual bge-m3 embeddings (one call per question, BM25 alone when it fails), picks the top 6 chunks, at most 6,000 characters, from the knowledge pack. The pack lives in Workers KV, checked by its hash, with a small bundled fallback.
- 4
Model Chain
Gemma 4 on Workers AI answers first, through AI Gateway. After an error, a timeout or an empty answer the next tier takes over: Mistral Small 3.1, then Qwen 3.8 27B and gpt-oss-120b on Groq. Every tier gets the same context, rules and checks.
- 5
Output Checks
Every answer is checked before it reaches the visitor: no secrets or prompt leaks, numbers grounded in the retrieved context, links only to pages it retrieved, and an opinion only when a written source exists.
- 6
Rover's Voice
Rover speaks as the guide ("I found") and always of Kurniadi in the third person. A factual answer opens with its content; a touch of personality fits only a greeting or a decline.
- 7
Memory and Follow-Ups
The last 5 turns travel with each question, signed with HMAC so they cannot be forged. The answer streams in, and its follow-up questions are picked in the browser from the answer's tags, not by the model.
- 8
Nightly Evals
Every night a 21-question smoke test runs on Gemma 4, and rotating slices of the golden set, the curated questions and the red team run on a Groq model production never uses; a fidelity set checks the first backup. A question that never reached a model counts as not run, not as a wrong answer, and a red-team failure opens an issue.
Rejected Designs
Ideas that were tried or proposed and then dropped, each with the reason.
Iframe Previews of Certificates
Showing certificate and paper pages from their issuers inside the site, in an iframe.
The issuers' pages refuse to be framed (X-Frame-Options and frame-ancestors), and the site only frames itself; in-site preview cards and viewers took their place.
A Public Route for the Office Worker
Giving the hq-office Worker its own public workers.dev route.
A workers.dev address contains the account's subdomain, which stays out of the public repository, so every route is a Pages Function that reaches the Worker through a service binding.
The Safety Blocklist
A build-time list of names to block in the content, the built site and Ask answers.
It had to carry the very names it guarded; the owner removed it, and client names stay out by review.
Pull request #288
Memory Gate Split in Three
Splitting the full-tier memory test into three parallel CI parts to shorten main's wall time.
On hold: uneven e2e shards set main's wall time, not the memory test, and the split cost 11 more worker-minutes; worker-aware shard packing went in instead.
A Second, English-Only Perspectives Pack
Keeping the Ask pack small by moving Kurniadi's written perspectives into a second pack loaded on demand, or storing them in English only.
Pages Functions bundle every imported JSON into one Worker script, so a second pack saved nothing; English only would break Indonesian retrieval, since BM25 matches the question's words, and the written-source check.
Oxlint and Knip
Moving most lint rules to oxlint and adding knip to find unused files, dependencies and exports.
Skipped by owner decision; the existing ESLint setup stays.
A Phone View Down the B1 Aisle
Arriving on B1 on a phone with the camera looking straight down the aisle.
In portrait it cut every station sign at the edges and showed mostly floor, so the phone camera turns across the aisle to two whole signs.
A Lazy 3D Mount
Mounting the 3D scene as a lazy React component behind Suspense.
A lazy component suspends once even when its chunk is already loaded, and React holds the retry, so the first frame came about 250 ms later.
The Postprocessing Wrapper
Building the glow pass with the @react-three/postprocessing wrapper.
It bundled an ambient occlusion library the site never used, about 8 KB gzip, so the chain now uses postprocessing directly.
A Per-View Idle Check
Dropping to 30 fps only on the quiet parts of each floor's view when Rover is parked.
It added 2.0 KB gzip to the 3D session and broke both caps; one idle frame rate per floor does the job.
A Blank-Box Intro
An intro that opened on plain boxes before cutting to Rover.
The owner found it looked bad; Rover now wakes up first, then a reveal orbit circles the Lobby.
Guided Floor Walks
Guided walks that drove Rover past each floor's stations.
Removed at the owner's request: one first-visit line per floor and point-and-go took their place.
A Generated Web CV
Generating the CV from the site's data as a web export in both languages.
The owner preferred his own PDF, shown byte for byte in an in-site viewer.