Site architecture

Big picture: one edge service, profile data baked into the deploy, what loads in the browser, and how tabs and exports fit together.

Back to the live site

Overall designs

Tab Designs

Site Feature Designs

How the pieces fit together

This page summarises how the live site is structured end to end—the same story as the project’s technical DESIGN.md, told for visitors. For each screen, use the tab and feature links in the navigation.

What I optimised for

The site is deliberately small and self-contained: one program at the edge (Cloudflare) serves every request.

Career facts live in structured source data, not in a separate CMS. Months, industry totals, and skill totals are calculated on the server so charts, downloads, and the API always agree.

There is no sign-in editor and no client-side router: the career views are in-page tabs only, so refreshing the page always starts on Industries again.

Where it runs

The browser talks to that edge service over HTTPS. There is no database or key–value store in the current design: the profile is compiled into the deployment package, and the worker serves a precomputed profile JSON object from memory.

Optional features (for example chat or board-game feeds) use secrets on the server only; they are not embedded in the page source.

What loads when the career page opens

First comes a small HTML document with the page frame and global styles. Then a single JavaScript file runs. It fetches one JSON document that describes the whole public profile.

Only after that data arrives do the hero line, donuts, timeline, lists, and other widgets render. If the fetch fails, an error message appears instead of half-populated charts.

How raw data becomes the on-screen view

Authors maintain roles with start and end months, industry references, skills, capabilities, and impact bullets. A server-side build step turns that into the shape the browser consumes: each industry and skill gets totals and fractions; each role gets a resolved duration, including “present” roles.

Capabilities are normalised with stable slugs so several roles can share one donut slice. Month arithmetic is shared logic so the API, downloads, and UI stay in sync.

Important URLs (simplified)

Tabs and accessibility

The tab strip uses standard tab semantics: one panel is visible at a time, others are hidden. Keyboard focus shows a clear outline.

Visually the tabs are plain text spaced evenly across the content column, not pill buttons inside a heavy frame.

Heavy visuals load on demand

Journey, Ribbon, and Constellation each ship as their own script bundle. Nothing downloads until that tab is first selected, which keeps the first load lighter.

Ribbon may use WebGL; if reduced motion, data saver, or WebGL is unavailable, a static diagram is shown instead.

Generative backdrop

After profile data loads, the page derives a stable colour recipe from the sorted list of role identifiers and feeds it into CSS custom properties.

Gradients are static in CSS (no extra canvas, no drift animation). Reduced motion at the OS level still applies to other UI transitions.

The one-page download is print-oriented and does not include this backdrop layer.

Consistent panel height on large screens

On wide viewports the main tab areas share a common minimum height based on the tallest rendered tab panel, measured off-screen at the current content width. Side panels and long lists scroll inside their own region so the overall column does not grow and shrink wildly when switching tabs.

On narrow screens that rule is turned off so stacked layouts can scroll naturally.

Security and privacy (short version)

Deploys and caching

Shipping a new version of the worker picks up profile changes bundled with it. Cache policy is route-specific: HTML and APIs stay short-lived, app.js is immutable and versioned, and board-game API responses are cached briefly at the edge.

Design tradeoffs worth noting

Simple layout sketch

Request flow: the browser, the edge service, and the assets or data it returns.