Architecture Map
A living, interactive map of how the whole system communicates.
RegistriesLiveReactSVG
16nodes
What it is
A content-as-code system map: layers, surfaces-by-zone, integrations, and an interactive ecosystem graph of how they all talk. Public and indexed — the front door to understanding the platform.
Take it with you
The real, committed source behind this system — copy it or download the file. Plus a portable spec of everything on this page.
architecture.mjsjavascript272 lines
The content-as-code system map — layers, surfaces-by-zone, integrations, and the ecosystem-graph edges the /architecture page draws.
// /architecture — content-as-code for the public system map.
//
// v2 is written for a non-technical visitor first. Every part has a plain-English
// name and a one-line "what it does"; the technical name is kept alongside for the
// curious (a toggle on the page swaps them). The centrepiece is a set of guided
// JOURNEYS the page animates across the map.
//
// It references only *public* facts already documented in docs/ARCHITECTURE.md,
// SITE_OVERVIEW.md, docs/ZONES.md and CLAUDE.md — no secrets, no private schemas.
// The __tests__ assert internal consistency (every edge/journey points at real
// nodes, ids are unique, etc.).
// Category accents — Bauhaus palette only (red / blue / yellow + neutral).
export const KIND = {
core: { label: 'The website itself', accent: '#003F88' }, // blue — the request path
data: { label: 'Where things are stored', accent: 'var(--color-text)' }, // neutral — the bedrock
integration: { label: 'Outside helpers', accent: '#D62828' }, // red — third parties
ops: { label: 'Works on a schedule', accent: '#F7B538' }, // yellow — off-request
};
export const ARCH_META = {
title: 'How this site works',
kicker: 'A no-jargon tour',
intro:
'This is one site that builds itself in public — a living lab where a portfolio, a private set of household tools, a small software product, and a few client projects all run on one machine that ships daily, films itself, and tests its own work. Here’s how the pieces fit together — in plain English. Press play on a journey below and watch the site actually work.',
updated: 'June 2026',
stats: [
{ value: '1', label: 'website' },
{ value: '40+', label: 'distinct tools & pages' },
{ value: '11', label: 'outside services' },
{ value: '24/7', label: 'robots on a schedule' },
],
};
// ── The map: every box is a "part of the building" or an outside helper ──────
// friendly = plain name · label = technical name · plain = one-line job · icon
export const GRAPH = {
viewBox: '0 0 1120 780',
nodes: [
{ id: 'client', friendly: 'You', label: 'Browser · PWA', plain: 'Your phone or laptop screen — where it all starts.', icon: 'screen', kind: 'core', x: 560, y: 48 },
{ id: 'edge', friendly: 'Front desk', label: 'Edge middleware', plain: 'Checks who you are and lets you through to the right place.', icon: 'shield', kind: 'core', x: 560, y: 156 },
{ id: 'app', friendly: 'The hub', label: 'App Router', plain: 'Takes every request and decides what should happen.', icon: 'hub', kind: 'core', x: 560, y: 326, hub: true },
{ id: 'lib', friendly: 'The clerks', label: 'Lib accessors', plain: 'Fetch, file, and tidy up information for the hub.', icon: 'clerk', kind: 'core', x: 560, y: 460 },
{ id: 'dbmain', friendly: 'Main memory', label: 'Supabase · main', plain: 'Where almost everything is stored and remembered.', icon: 'database', kind: 'data', x: 520, y: 712 },
{ id: 'dbcrss', friendly: 'Exam vault', label: 'Supabase · CRSS', plain: 'A separate, walled-off store for the exam-prep questions.', icon: 'vault', kind: 'data', x: 800, y: 700 },
{ id: 'storage', friendly: 'Photo store', label: 'Storage buckets', plain: 'Holds uploaded photos, files, and artwork.', icon: 'photo', kind: 'data', x: 248, y: 700 },
{ id: 'claude', friendly: 'AI helper', label: 'Anthropic · Claude', plain: 'Reads photos, answers questions, and drafts writing.', icon: 'ai', kind: 'integration', x: 952, y: 252 },
{ id: 'voyage', friendly: 'Librarian', label: 'Voyage embeddings', plain: 'Makes everything findable so search gives good answers.', icon: 'search', kind: 'integration', x: 966, y: 394 },
{ id: 'resend', friendly: 'Mail room', label: 'Resend', plain: 'Sends the emails and sign-in links.', icon: 'mail', kind: 'integration', x: 956, y: 518 },
{ id: 'stripe', friendly: 'Cash register', label: 'Stripe', plain: 'Handles payments when you buy something.', icon: 'card', kind: 'integration', x: 820, y: 120 },
{ id: 'yt', friendly: 'Video shelf', label: 'YouTube', plain: 'Where the site’s short films are published.', icon: 'video', kind: 'integration', x: 946, y: 630 },
{ id: 'google', friendly: 'Sign-in', label: 'Google OAuth', plain: 'Lets you log in with a Google account or an email link.', icon: 'key', kind: 'integration', x: 176, y: 156 },
{ id: 'ha', friendly: 'Smart home', label: 'Home Assistant', plain: 'Controls real lights and devices at home.', icon: 'home', kind: 'integration', x: 176, y: 470 },
{ id: 'tg', friendly: 'Text bot', label: 'Telegram', plain: 'A chat bot that takes commands by text message.', icon: 'chat', kind: 'integration', x: 176, y: 566 },
{ id: 'ops', friendly: 'Night shift', label: 'Cron · Workflows', plain: 'Robots that do chores on a schedule, even while you sleep.', icon: 'moon', kind: 'ops', x: 180, y: 330 },
],
edges: [
{ from: 'client', to: 'edge', label: 'you visit' },
{ from: 'google', to: 'edge', label: 'sign in', dashed: true },
{ from: 'edge', to: 'app', label: 'let through' },
{ from: 'app', to: 'lib', label: 'go fetch' },
{ from: 'lib', to: 'dbmain', label: 'look it up' },
{ from: 'lib', to: 'dbcrss', label: 'exam bank', dashed: true },
{ from: 'lib', to: 'storage', label: 'photos' },
{ from: 'app', to: 'claude', label: 'ask the AI' },
{ from: 'claude', to: 'lib', label: 'tidy answer', dashed: true },
{ from: 'ops', to: 'dbmain', label: 'save new content' },
{ from: 'ops', to: 'voyage', label: 're-learn' },
{ from: 'voyage', to: 'app', label: 'good results' },
{ from: 'app', to: 'resend', label: 'send email' },
{ from: 'app', to: 'stripe', label: 'take payment' },
{ from: 'app', to: 'ha', label: 'control home', dashed: true },
{ from: 'tg', to: 'app', label: 'text command', dashed: true },
{ from: 'app', to: 'yt', label: 'publish video', dashed: true },
{ from: 'ops', to: 'claude', label: 'draft content', dashed: true },
],
};
// ── Levels for the "Trace the Signal" game ──────────────────────────────────
// Each level is a real request, written as a *linear* path (each step starts
// where the last one ended) so it doubles as a teachable trace AND a puzzle:
// first the player WATCHES the signal travel, then TAKES OVER and taps the next
// part at each hop. `prompt` is the question shown while tracing; `caption` is
// the plain explanation revealed once they get it right. Every pair is a real
// edge in GRAPH (asserted in __tests__). Order = difficulty (unlocked in turn).
export const JOURNEYS = [
{
id: 'visit',
title: 'Open a page',
emoji: '👀',
accent: '#003F88',
goal: 'Get a blog post onto your screen.',
badge: { emoji: '📄', name: 'Page Loader' },
steps: [
{ pair: ['client', 'edge'], prompt: 'It starts with you. Tap where your visit arrives first.', caption: 'You open the site and the front desk checks you in.' },
{ pair: ['edge', 'app'], prompt: 'You’re checked in. Tap who sorts the request.', caption: 'The front desk waves you through to the hub.' },
{ pair: ['app', 'lib'], prompt: 'The hub needs the page fetched. Tap who does the fetching.', caption: 'The hub asks the clerks to go fetch the page.' },
{ pair: ['lib', 'dbmain'], prompt: 'Tap where the clerks look things up.', caption: 'The clerks pull it from memory — and it flies back to your screen.' },
],
},
{
id: 'ask',
title: 'Ask the AI',
emoji: '💬',
accent: '#D62828',
goal: 'Get a clear, cited answer to a question.',
badge: { emoji: '💡', name: 'Question Master' },
steps: [
{ pair: ['client', 'edge'], prompt: 'You type a question. Tap where it goes first.', caption: 'You type a question into the search box.' },
{ pair: ['edge', 'app'], prompt: 'Tap who takes the request from here.', caption: 'You’re waved through to the hub.' },
{ pair: ['app', 'claude'], prompt: 'A question needs answering. Tap who can actually do that.', caption: 'The hub hands it to the AI helper.' },
{ pair: ['claude', 'lib'], prompt: 'The AI needs *real* facts, not guesses. Tap who fetches them.', caption: 'The AI checks real content through the clerks (with the librarian’s help).' },
{ pair: ['lib', 'dbmain'], prompt: 'Tap where those facts are stored.', caption: 'Pulled from memory — and you get a cited answer you can trust.' },
],
},
{
id: 'receipt',
title: 'Scan a receipt',
emoji: '🧾',
accent: '#F7B538',
goal: 'Turn a photo of a receipt into a money entry.',
badge: { emoji: '🧾', name: 'Receipt Wrangler' },
steps: [
{ pair: ['client', 'edge'], prompt: 'You snap a photo. Tap where the upload arrives first.', caption: 'You take a photo of a receipt on your phone.' },
{ pair: ['edge', 'app'], prompt: 'Tap who takes the upload.', caption: 'It’s waved through to the hub.' },
{ pair: ['app', 'claude'], prompt: 'A blurry photo needs reading. Tap who can do that.', caption: 'The hub asks the AI helper to read the photo.' },
{ pair: ['claude', 'lib'], prompt: 'The AI made a tidy entry. Tap who files things.', caption: 'The AI turns the numbers into one clean entry and hands it over.' },
{ pair: ['lib', 'storage'], prompt: 'Tap where photos are kept safe.', caption: 'The photo is filed away, and the amount lands in your money tracker.' },
],
},
{
id: 'overnight',
title: 'Robots overnight',
emoji: '🌙',
accent: '#F7B538',
goal: 'Let the night shift publish fresh content while you sleep.',
badge: { emoji: '🦉', name: 'Night Owl' },
steps: [
{ pair: ['ops', 'claude'], prompt: 'A scheduled robot starts up. Tap who drafts the writing.', caption: 'Overnight, the night shift asks the AI to draft fresh content.' },
{ pair: ['claude', 'lib'], prompt: 'The draft is ready. Tap who tidies and files it.', caption: 'The draft is handed to the clerks to clean up.' },
{ pair: ['lib', 'dbmain'], prompt: 'Tap where it gets saved.', caption: 'It’s saved to memory — and the librarian re-learns it so search stays fresh.' },
],
},
{
id: 'buy',
title: 'Sign in & buy',
emoji: '🛒',
accent: '#003F88',
goal: 'Sign in and pay for something safely.',
badge: { emoji: '🏅', name: 'Checkout Champ' },
steps: [
{ pair: ['google', 'edge'], prompt: 'You log in with Google. Tap where that’s handled.', caption: 'You sign in with Google at the front desk.' },
{ pair: ['edge', 'app'], prompt: 'You’re in. Tap who takes it from here.', caption: 'You’re let through to the hub.' },
{ pair: ['app', 'stripe'], prompt: 'Time to pay. Tap who handles money.', caption: 'The cash register takes the payment, and a receipt is emailed to you.' },
],
},
];
// ── "What it's all for" — friendly framing of the zones (docs/ZONES.md) ──────
export const ZONES = [
{
id: 'business',
name: 'Business',
friendlyName: 'Earns a living',
plain: 'The parts that make money, or are on their way to it.',
accent: '#003F88',
surfaces: [
{ name: 'Court-collections tools', path: '/josephinetx-collections', posture: 'for clients' },
{ name: 'Heddle (software product)', path: '/heddle', posture: 'product' },
{ name: 'Freelance & hire', path: '/hire', posture: 'public' },
{ name: 'Exam-prep course', path: '/crss', posture: 'product' },
],
},
{
id: 'studio',
name: 'Studio',
friendlyName: 'Creative & public face',
plain: 'The portfolio, games, writing, and films anyone can enjoy.',
accent: '#D62828',
surfaces: [
{ name: 'Games (20+)', path: '/games', posture: 'public' },
{ name: 'Novels & essays', path: '/novels', posture: 'public' },
{ name: 'Blog & research', path: '/work', posture: 'public' },
{ name: 'Films & video', path: '/studio', posture: 'public' },
],
},
{
id: 'lab-personal',
name: 'Lab · personal',
friendlyName: 'Private daily tools',
plain: 'Tools Jake and Gina use to run the household — just for them.',
accent: '#F7B538',
surfaces: [
{ name: 'Money & receipts', path: '/money', posture: 'private' },
{ name: 'Mail, to-dos, chores', path: '/todos', posture: 'private' },
{ name: 'Smart-home control', path: '/house', posture: 'private' },
{ name: 'Habits & rituals', path: '/rituals', posture: 'private' },
],
},
{
id: 'lab-experiment',
name: 'Lab · experiment',
friendlyName: 'Playground',
plain: 'Quick experiments and free tools — fun to make, easy to retire.',
accent: 'var(--color-text-secondary)',
surfaces: [
{ name: 'Shared to-do boards', path: '/t', posture: 'free' },
{ name: 'Weather boards', path: '/w', posture: 'free' },
{ name: 'Trip planners', path: '/trip', posture: 'free' },
{ name: 'Countdowns', path: '/cd', posture: 'free' },
],
},
];
// ── The stack, for the technically curious (collapsed by default) ───────────
export const LAYERS = [
{ id: 'client', name: 'Client', tagline: 'Browser · installable PWA · React 19 client leaves', accent: KIND.core.accent, items: ['React 19 (JSX, no TS)', 'Three.js · Tone.js', 'Leaflet · Recharts · KaTeX', 'Multiple PWA manifests'] },
{ id: 'edge', name: 'Edge', tagline: 'Next.js middleware — the auth gate, edge-safe', accent: KIND.core.accent, items: ['auth.config.js (edge-safe)', 'JWT session strategy', 'Per-surface gating', 'Vercel edge runtime'] },
{ id: 'app', name: 'App Router', tagline: 'Server-component-first · ~422 API handlers', accent: KIND.core.accent, items: ['Server components by default', '"use client" at the leaves', 'Route-level metadata', 'Request-time Supabase reads'] },
{ id: 'lib', name: 'Lib accessors', tagline: 'One module per table/surface — no supabase.from() in components', accent: KIND.core.accent, items: ['~105 modules', 'Accessor-module discipline', 'Auth · tokens · email · AI', 'Cross-DB guard (main vs CRSS)'] },
{ id: 'data', name: 'Data', tagline: 'Two Supabase (Postgres) projects + storage buckets', accent: KIND.data.accent, items: ['Supabase main (everything)', 'Supabase CRSS (exam bank)', 'Storage buckets', 'Some Vercel Postgres'] },
{ id: 'external', name: 'External', tagline: 'Third-party services reached server-side', accent: KIND.integration.accent, items: ['Anthropic · Voyage', 'Resend · Stripe', 'Google OAuth', 'Home Assistant · Telegram · YouTube'] },
];
export const INTEGRATIONS = [
{ name: 'Supabase — main', role: 'Postgres for blog/research/projects + every private surface, auth rows, storage.', accent: KIND.data.accent },
{ name: 'Supabase — CRSS', role: 'A second, isolated Postgres project for the exam-prep question bank.', accent: KIND.data.accent },
{ name: 'Anthropic (Claude)', role: 'Runtime concierge + photo/PDF vision parsing; ops orchestrators (enrichment, LinkedIn, Strata).', accent: KIND.integration.accent },
{ name: 'Voyage', role: 'Embeddings for the hybrid (semantic + keyword) search index behind the concierge.', accent: KIND.integration.accent },
{ name: 'Resend', role: 'All transactional email + magic links, From-line resolved per surface so brands never leak.', accent: KIND.integration.accent },
{ name: 'Stripe', role: 'Fixed-scope checkout for the /hire offers and Heddle billing.', accent: KIND.integration.accent },
{ name: 'Google OAuth', role: 'Primary sign-in provider (alongside the Resend magic link).', accent: KIND.integration.accent },
{ name: 'Home Assistant', role: 'MANOR smart-house, reached only through an outbound-only bridge worker — never inbound.', accent: KIND.integration.accent },
{ name: 'Telegram', role: 'One bot + plugin router; unknown senders are silently dropped at the allowlist.', accent: KIND.integration.accent },
{ name: 'YouTube', role: 'The Studio warehouse for the headlessly-filmed site reel + analytics.', accent: KIND.integration.accent },
{ name: 'Vercel', role: 'Hosting + edge + GitHub-integrated deploys.', accent: KIND.core.accent },
];
// ── How the parts compound — the connective tissue that makes ~60 surfaces ───
// behave like one system instead of a directory of separate apps. Public,
// coarse, plain-English; the same build-in-public posture as the rest of the
// page (no secrets, no schemas). Each entry is one real shared system.
export const SYNERGIES = [
{
id: 'memory',
title: 'One shared memory',
accent: KIND.data.accent,
plain:
'Write something once and it shows up everywhere. A new post seeds into the database, and from there it automatically powers on-site search, the AI concierge, the weekly digest, and the social drafts — no piece wired up by hand.',
},
{
id: 'registry',
title: 'One source of truth for navigation',
accent: KIND.core.accent,
plain:
'The menu, the footer, the search palette, and the concierge all read the same single list, so they can never drift out of sync. Even the free shared tools are entries in that same catalog.',
},
{
id: 'nervous-system',
title: 'One nervous system',
accent: KIND.integration.accent,
plain:
'Every key, login, scheduled robot, and permission lives in one control room. Rotate a key once and every surface that needs it picks it up — no redeploy, nothing copied around.',
},
{
id: 'films-itself',
title: 'It films and narrates itself',
accent: KIND.ops.accent,
plain:
'The site records short films of its own screens, drafts social posts from whatever just shipped, and writes a weekly note about what changed — so the act of building is itself the content.',
},
];
Where it lives
- src/app/architecture/architecture.mjs
- src/app/architecture/page.jsx
See it in action
Architecture map →FAQ
Is the architecture map public?
Yes — it is public and indexed, an interactive front door to how the platform fits together.
Part of these stacks
Related systems
Want a system like this built for you?Work with me →