This site uses one functional cookie to keep feature rollouts consistent for you. Nothing is set until you choose. See the privacy notice.
Dev notes
Deep-dives into the architecture decisions, trade-offs, and lessons behind everything in this project, grouped by area.
Interviewee
An admin-only interview-prep deck organised by job interview and built around one data shape: topics fed from a markdown template, bullet-point answers with expandable detail, number and arrow-key navigation, and reviewed topics demoted but kept
Budget
A budget tracker built around the add flow: a three-tap bottom sheet, money kept in integer cents, analytics that take the clock as an argument, and an invite link that carries the whole budget because there is no server yet
Updates
A public changelog that isn't a parse of the internal one: curated entries, pure search/sort logic, and a ticket board that says out loud it has no server
Research Explorer
Finding a research topic by measuring the literature: PubMed counts as evidence levels, a curated query layer, and demographic coverage as the gap finder
Learn
Thirteen demos that each rebuilt the same stepper, one useStepPlayer hook, and the overrun the characterisation tests caught
Particle Lab
Two point clouds instead of an object per particle, and why the connection-distance slider is really the performance dial
Explore Toronto
A walkable 3D Toronto built from primitives: a TDD'd pure movement core, an R3F shell around it, a seeded procedural skyline over a real street grid, and exhibits that deep-link back into the site
Gallery Wall
An arranger built pure-core-first: standard frame sizes, an aspect-matching auto-framer with a medium tie-break, a centered shelf-packing layout with overflow detection, and an inches-internal model with a cm toggle at the input edge
Feature Flags
A flag console built engine-first: deterministic FNV-1a bucketing with an avalanche step, sticky and monotonic rollouts, first-match targeting, an explainable evaluation reason, and why the pure core is the whole design
The To-Do List
Soft delete so a mis-click survives, positions assigned server-side so two adds cannot claim the same slot, and an optimistic insert that rolls back the row it added rather than the last one
TCG Pages
API proxy, server/client split, pagination patterns
Calendar
Views, timezone handling, BFF auth pattern
NBA Playoffs Bracket
TDD with MSW, derived state, TBD resolution, submit vs. auto-save design, and leaderboard before results
NFL Fantasy Matchups
A weekly points scoreboard next to the NBA's category one, a date guess deleted for a payload read, and a win probability derived from projected finals since ESPN doesn't provide one
Fantasy TCG
Minting rarity-tiered trading cards from real ESPN fantasy performances, rarity set relative to the pool
Operator Dashboard
Fleet management with tiered polling, optimistic updates, data freshness, and a globalThis singleton for in-memory state
Work Portfolio
Rebuilding features from past jobs as self-contained demos: reconstruction over emulation, anonymizing client work, the no-new-deps rule, the dual-ticker UX, and shipping it as merge-order-independent PRs -- plus a live index of this site's own features
Ketsup
A social app for image and text posts, built and shipped at its own domain
Draft Lab
A Firefox extension living inside the ESPN draft room: pick sync, tier supply, keepers, and live recommendations
AI Agent Patterns
SSE streaming, state machines, tool call UI, approval gates, and streaming markdown — the patterns behind modern agent interfaces
macOS Menu Bar
Turning a desktop clone's dead top-bar labels into a signal-driven macOS menu system — menus derived from window and dock state, real actions, and full keyboard a11y
Craft
A page that reframes the whole site as evidence: ten lead front-end traits, each expandable to the real work that proves it, with a data-integrity test that fails on a dead evidence link
Command Palette
The site-wide ⌘K palette: one globally mounted instance opened from a hotkey or a window event, a registry reused from the hub's FEATURES and THOUGHTS, a hand-rolled fuzzy matcher, and an honest ARIA combobox
Design detox
Making the site read as designed, not generated: dropping the colored-stripe card tell, one editorial page intro, Apple squircle corners, the inline-arrow fix whose first attempt missed the real cause, a film grain that didn't help, and breaking the too-even grid into a bento
Shared Design System
Extracting tokens and components into @paul-portfolio npm packages — CSS custom properties, thin framework wrappers, and token aliasing across React and Angular apps
Framework-Agnostic Charts
Rebuilding recharts and unovis charts as pure SVG from one dependency-free geometry core — Sparkline, BarChart, DonutChart rendering identically in React and Angular, with a token palette and role=img a11y
Design System Showcase
Building a live, in-app gallery for the shared design system: dogfooding the primitives, a data-driven catalog with an integrity test, an interactive props playground, and an axe-checked accessibility contract
Motion Components
TiltCard, GradientBackground, and Spotlight for the shared design system — pointer-driven motion built static-first, with reduced motion as the default and one shared usePrefersReducedMotion hook
Apple Design
Auditing the whole app against Apple's fluid-interface principles and fixing the gaps: the accessibility settings a glass-heavy UI ignored (reduced transparency, contrast, eased theme change), press-down feedback, a critically-damped modal, menus that spring from their trigger, and size-specific typography
Error Toasts
Catching every failed write at one layer: a React Query MutationCache onError that raises a toast app-wide, an imperative toast() built in the design system so it works outside React, an SSR-safe portal, and an accessible live region
Styling Decisions
CSS Modules vs Tailwind v4 and design tokens
UI Redesign
Why CSS keyframes gave way to Framer Motion, where Three.js went, and what's actually measurably better
Accessibility
WCAG 2.1 AA compliance — vitest-axe for unit-level scans, systematic primitive audits, and where automated tooling helps vs. where it doesn't
Performance Improvements
Eliminating the dark-mode flash, ISR on static pages, lazy-loading below-fold sections, and caching public API routes
Render Performance
Runtime rendering costs: context instability, resize allocation, backdrop-filter GPU pressure, and unbounded DOM growth
Web Vitals
Real-user metrics, sendBeacon, P75, the collection pipeline, and alerting when a vital goes bad
Bundle Analysis
How the analyzer found Auth0Provider shipping jose to the browser for no reason
Tree Shaking
The three kinds of dead weight, why removing an unused export isn't a bundle win, the judgment calls a depcheck report can't make, and wiring it all into CI as a blocking check
Tree Shaking, Round 2
A second pass from green dead-code checks: tree-shaking the barrels Next doesn't optimize by default for a measured 148KB, then a real LCP fix — moving the entrance reveal off the JS bundle and lazy-loading the operator charts
Micro-frontends
Splitting the work portfolio into its own repo and loading it at runtime over Module Federation: a contract package, a host that owns the URL and the data, Next's canary React, a CSS collision only a real mount could find, and a strangler flag that fails closed
ZeroProof: A No-Loss Sportsbook
Betting with the loss taken out: a double-entry ledger from the first row, closing-line value captured on every bet, and seven stacked PRs that each deploy on their own
GraphQL
Why GraphQL, why plain fetch over Apollo
Hybrid Rendering
Giving each Angular route the render mode it needs — the Thoughts pages prerender to static HTML at build time via per-route RenderMode, a SeoService writes the head and JSON-LD on the server, and the interactive shell stays client-rendered
API Hardening
Zod validation, fixed-window rate limiting, and body size limits across every API route
API Backend Overhaul
Rebuilding portfolio_api into a typed, layered TypeScript backend across twelve phases, without breaking a single contract paul-explore depends on
Taking the Database Off the Public Internet
A front-end engineer working through the backend half: a Postgres reachable from anywhere, a TLS rabbit hole worth abandoning, migrations nothing ran, and four minutes of downtime from a rotation whose failure arrives late
Login Redirect
Landing back on the route you logged in from, and turning a denied consent screen from a bare 500 into a toast, both fixed at the Auth0 choke point
React Doctor
Working a static-analysis pass: real fixes, the fix that fought back, false positives, and why severity isn't priority
Project Review
An evidence-backed review of the whole codebase — engineering, system design, architecture overfit, and per-feature UX gains
Refactor Pass
The maintainability roadmap after the review — deduping against existing abstractions, the overfits I avoid, and the order I ship in
Testing
3499+ tests (3432 unit + 67 e2e), Vitest + MSW + Playwright, and the delay() trick for proving optimistic updates fire before the server responds
E2E Testing
Auth0 Universal Login, global setup/teardown, the Google OAuth button hijack, and what broke when we actually ran them
CI E2E Reliability
Auth0 crashing all middleware from a module-level throw, and a search test that needed page.route to stop depending on an external API
Green Checks
Four green checks in the design system that were each measuring something other than what they claimed — the suite nothing ran, the visual gate with no quota, the contrast figure taken under the gloss, and the count that moved when you built
Tiered Testing Strategy
Why you shouldn't run every test on every commit: split by cost — fast unit tests per push, integration on merge, e2e nightly, flaky ones quarantined
CSP & Security
Why 'unsafe-inline' is the right call for Next.js static pages, and what actually prevents XSS
AI Security & Bare Repo Attacks
Prompt injection via CLAUDE.md, hardened least-privilege configs, deny lists, and sandboxed environments for untrusted code
Auditing for Absences
AI-written code passes security tests 56% of the time and fails worst on what is missing. A cross-repo audit, and the seven shapes of absence it actually found
npm to pnpm
Strict dependency resolution, version range surprises, and what a package manager migration actually involves
Bundlers
Which bundler this project runs and why, whether it's the right one, and the real situations where a lead reaches for a different bundler — the deliverable and the dominant constraint pick it, not taste
Deployment
Deployment as five separate jobs, choosing a platform from the app's runtime shape, when to decide, the trade-offs that bite, and the Vercel + Cloudflare setup behind this site
PR Screenshots From an Unattended Agent
Embedding before/after screenshots inline in PR descriptions with only the gh CLI — why user-attachments, gists, and release assets all failed, and why we don't prune the PNGs
TypeScript 7
Why the Go-native compiler is a no for now: the lint stack peer-caps below it, and a 4-second type-check makes the 10x moot
Visual Plans
Why I bracket every change with a visual plan before code and a recap after: structured wireframes over prose, the RED list as the plan, and an honest record of where reality drifted
Crawlers
The five files a site is supposed to serve and this one didn't: what to leave out of robots.txt, why the sitemap carries no lastModified, and the test that stops it going stale
Risk-scoring APIdeprecated
Learning Go by building a real-time transaction risk-scoring API: a rules engine, a weighted score and band, and a live SSE feed, with the language and the risk concepts learned side by side
V4 Redesigndeprecated
The landing and hub as a slot machine: three dependent reels (category, option, write-up) derived from the same data as the graph, dependent-reel selection, a decelerating spin, and a listbox-based a11y model
V5 Redesigndeprecated
Retiring the slot machine from the root: a warm editorial palette measured against WCAG before it was written down, eight in-house motion primitives held to a no-opacity-zero-above-the-fold rule, and a landing page briefed against my own defaults
V3 Redesigndeprecated
The whole site as a node graph — a hand-rolled force sim, fit-to-viewport rendering, the drag/hover bugs, and an a11y audit
V2 Redesigndeprecated
URL-based version routing with next/dynamic bundle splitting — Three.js out of the default path, v2 ships a clean slate
Messenger Auth Bugdeprecated
Why links opened in Facebook Messenger showed a logged-in hub for unauthenticated users, and the two-line fix
Route Restructuredeprecated
Why / replaced /protected, the force-static trade-off, and how auth is still enforced
Search Bardeprecated
Server/client split, filtering, and trade-offs
Landing Pagedeprecated
Section layout and functionality preview