Fred de Ruiter's portfolio site. Most of the work on it runs in your browser, so you can try it instead of reading about it.
deruiter.dev · Architecture · Decision records · Docs · Contributing · Releases
Design a case report form, then follow one fictional study from protocol to analysis tables with every number traced back to where it came from. Build a logic proof one step at a time. Rotate a brain. Then, when you've earned it, play twelve games, several of which are about clinical data and one of which is about setting up a wedding mostly bought at Costco.
- What's inside
- The clinical data journey
- The arcade
- Built with
- Run it locally
- How it's checked
- How it ships
- Accessibility
- Documentation
- Contributing
- License
The site is grouped the way the top bar is: Clinical, Labs, Arcade, Writing and About (ADR 0058).
| Area | What you can do | Start here |
|---|---|---|
| Clinical | Design forms in CRF Studio, feel a protocol amendment land in Protocol Drift, run the Study Data Pipeline in your browser, and govern eight fictional studies on the Clinical Data Platform: dashboards, a metrics explorer, a SQL workbench and a data catalog. | /clinical |
| Labs | The Proof Workspace for step-by-step logic, NeuroRecon Studio for 3D MRI brain viewing, the Incident Simulator for outage triage, and Patrol Shift, a Midwest ski-patrol judgment simulator. | /labs |
| Arcade | Twelve cabinets: Study Director, Trial & Error: Biostat Ops, Clinical Trial Chaos, Protocol Drift, Laser Loon, Patty's Drive-Thru, For Better or Bulk, Working With Duck, Monkey C Mayhem, Retro Labyrinth, Quasi-Perfect Puzzler and Meme Vault. | /arcade |
| Writing | A blog on what's being built and what it taught, and case studies on the decisions behind each project and where it stops. | /blog · /case-studies |
| About | Background, office hours, how the site itself works, and credits for the open-source projects it stands on. | /stack · /acknowledgments |
![]() |
![]() |
|---|---|
| Proof Workspace | NeuroRecon Studio |
The Clinical section is one path through one fictional study, DEMO-301, from the form a site fills in to the portfolio a sponsor governs. The data is synthetic and the vendors are invented: no real patients were involved, and nothing here is a validated system.
flowchart LR
A["CRF Studio<br/>collect"] --> B["Protocol Drift<br/>feel the consequences"]
B --> C["Study Data Pipeline<br/>tabulate and analyse"]
C --> D["Clinical Data Platform<br/>govern the portfolio"]
D --> E["Case study<br/>read the decisions"]
classDef step fill:#13151a,stroke:#f59e0b,stroke-width:1.5px,color:#f4f4f6
classDef last fill:#13151a,stroke:#10b981,stroke-width:1.5px,color:#f4f4f6
class A,B,C,D step
class E last
- CRF Studio designs case report forms with edit checks, a visit schedule and controlled terminology, and exports a study the pipeline can run.
- Study Data Pipeline takes DEMO-301 from a USDM v4 definition through SDTM and ADaM to demographics, adverse event and change-from-baseline tables and a Kaplan-Meier figure, with Define-XML 2.1, Dataset-JSON and XPT exports and generated reviewer guides. Its own conformance gate checks every run, and "Inject an issue" lets you break the data on purpose and watch where the gate catches it.
- Clinical Data Platform puts DEMO-301 beside seven other fictional studies, with governed metrics compiled to SQL, a read-only SQL workbench running DuckDB in the browser, data contracts, lineage and a data quality scorecard.
![]() |
![]() |
![]() |
|---|---|---|
| CRF Studio | Study Data Pipeline | Portfolio dashboard |
A separate workflow also runs CDISC's open-source CORE rules engine over the SDTM, Define-XML and USDM outputs of the default study and of every injected-issue scenario, then commits the findings and fails when they drift (how to refresh them). Using CORE implies no endorsement by CDISC. The design is in ADR 0065 and ADR 0066.
Twelve cabinets, all captured from the current build. Each picture opens its game.
- App: Next.js 16 (App Router), React 19, TypeScript 7 (the Go compiler; ADR 0072), Tailwind CSS v4
- Rendering: Canvas 2D and Three.js for the studios and games,
@chenglou/pretextfor DOM-free text layout, Framer Motion for transitions - Data: Prisma 7 on Neon serverless Postgres, Upstash Redis for caching and rate limits, DuckDB-WASM for in-browser SQL, and Zod contracts for every API route (
openapi.json) - Services: Clerk (admin auth), Resend (email), Sentry (errors and tracing), Vercel (hosting)
Everything runs inside free-tier provider limits, and ADR 0036 explains how. Public pages are statically generated and refreshed daily, so a visit doesn't wake the database.
You need Node.js 22, 23 or 24 (CI and Vercel use Node 24; engines.node
stops before the next major) and npm 10 or newer. npm is the only supported
package manager. Dependency install scripts are allowlisted in
scripts/install-script-allowlist.json.
From a fresh clone, run the setup wizard. It checks your toolchain against
package.json, installs dependencies with npm ci, creates .env.local
for the profile you pick, offers each optional integration, and asks before
it applies the schema or loads sample data:
./scripts/setup.sh
npm run devAgents and CI use the same command without prompts, for example
./scripts/setup.sh --non-interactive --skip-db --json. The
setup reference lists every flag, profile and
safeguard.
To set it up by hand instead:
npm install
cp .env.example .env.local # then set DATABASE_URL to a Postgres connection string
npx prisma db push # create the schema
npx prisma db seed # load sample case studies
npm run dev # http://localhost:3000GITHUB_TOKEN is optional and only avoids GitHub API rate limits. Clerk,
Resend, Upstash and Sentry are optional for local work; npm run env:check
reports what is missing. Without them the site uses local stand-ins, so it
still runs. The full walkthrough is in the
onboarding tutorial.
Handy commands once you're in:
| Command | What it does |
|---|---|
npm run dev |
Dev server with a type checker running alongside |
npm run typecheck |
Type-checks the whole project with TypeScript 7 (about 25 seconds cold) |
npm test |
The unit, component and property suites (Vitest) |
npm run doctor |
The architecture linter: every repository invariant, with a fix hint each |
npm run quality |
Everything CI's quality gate runs, locally |
npm run scaffold <type> |
A new game, API route, ADR or case study, wired in everywhere it belongs |
Every pull request has to pass these before it merges:
- Vitest unit, component and fast-check property tests: more than 17,000 of them.
- Playwright end-to-end, visual and accessibility (axe-core) suites, plus synthetic probes that walk the critical journeys on production daily.
- Stryker mutation testing on the core engines, weekly.
- DX Doctor (
npm run doctor), which checks the repository's own rules: module boundaries, route registration, documentation drift, bundle budgets and more. - A cold TypeScript 7 type check of the whole program, which fails if the compiler goes over its memory budget.
- Secret, licence and dependency audits, and zero ESLint warnings.
CONTRIBUTING.md maps each local command to the CI job
that runs it.
Merging to main never deploys. Once a week, Sunday at 7 PM Central, the
weekly train checks that main is green and has no destructive migration,
browser-tests the exact release candidate, cuts a versioned
GitHub Release with
notes written from the commit messages, and asks Vercel to build that commit
(ADR 0063).
v1.0.0, the first release it cut, shipped on 2026-10-27. Anything that
misses a Sunday goes out the next one.
flowchart LR
M["Merged to main<br/>no deploy"] --> T{"Sunday 7 PM<br/>main green?"}
T -- yes --> B["Browser-test<br/>the candidate"]
B --> R["Draft release,<br/>fire deploy hook"]
R --> S{"Live site<br/>smoke test"}
S -- passes --> P["Publish<br/>the release"]
S -- fails --> H["release:hold<br/>issue"]
T -- no --> W["Wait for<br/>next Sunday"]
classDef step fill:#13151a,stroke:#3f3f46,color:#f4f4f6
classDef gate fill:#13151a,stroke:#f59e0b,stroke-width:1.5px,color:#f4f4f6
classDef good fill:#13151a,stroke:#10b981,stroke-width:1.5px,color:#f4f4f6
classDef bad fill:#13151a,stroke:#ef4444,stroke-width:1.5px,color:#f4f4f6
class M,B,R,W step
class T,S gate
class P good
class H bad
Rollback is Vercel's Instant Rollback. The runbook is
DEPLOYMENT.md, and schema changes follow
docs/how-to/write-a-database-migration.md.
The site aims for WCAG 2.1 AA on every public page, and CI runs axe-core against them. You'll find a skip link, focus trapping in every dialog and drawer, 44px touch targets on touch screens, honoured reduced-motion settings, a dyslexia-friendly reading mode under Preferences, and text alternatives and keyboard controls for the canvas-heavy studios. If something gets in your way, please open an issue; it counts as a bug.
ARCHITECTURE.md: route tree, component hierarchy and data flowadr/: seventy architecture decision records, one per significant design choice, including the ones a later record reverseddocs/: tutorials, how-to guides, reference (including the TypeDoc API reference) and explanationCONTEXT.md: the project's glossaryDEPLOYMENT.mdanddocs/how-to/write-a-database-migration.md: release and schema-change runbooks- Releases for v1.0.0 onward, and
CHANGELOG.mdfor the history before it
Issues and pull requests are welcome, from typo fixes to new cabinets.
CONTRIBUTING.md covers the scaffolding CLI, branch and
commit conventions, and the quality gates. Contributors follow the
Code of Conduct. Please report security issues
privately as described in SECURITY.md, not in a public
issue.
The application source is licensed under the Apache License 2.0. The repository ships three kinds of material under three different terms, and NOTICE is the authoritative scope statement:
- Application source: Apache-2.0.
app/,components/,hooks/,lib/,types/,prisma/,scripts/,__tests__/, root configuration, and the generateddocs/andopenapi.json. - Laser Loon brand artwork (
public/files/): CC0 1.0 public domain dedication. - Editorial content, biography, resume data, photography, and the
Frederick de Ruiter/deruiter.devmarks: all rights reserved.
Fork the engineering freely; replace the writing and the branding before you deploy.
Made in Minnesota, with care, by Fred.

















