How this site is built
Colophon
How caseycharlesworth.com is built: the stack, the fonts, the performance budget and where the images come from.
- Build
- 2284450
- Built
- 2026-10-05
- Next.js
- 16.3.8
Stack
| Package | Version | What it does here |
|---|---|---|
| Next.js | 16.3.8 | App Router, with every page prerendered |
| React | 19.3.0 | Server components first, small client islands |
| TypeScript | 6.0.3 | Strict, end to end |
| Tailwind CSS | 4.3.3 | Utilities over generated tokens |
| GSAP | 3.15.0 | Scroll-linked motion, loaded after first paint |
| Lenis | 1.3.26 | Smooth scrolling on the GSAP ticker |
| Content Collections | 0.15.3 | Typed MDX case studies |
| Zod | 4.6.5 | Content schemas, so every figure needs a source and a date |
| nuqs | 2.10.1 | The /work filters live in the URL |
| zustand | 5.0.15 | One small client store |
| cmdk | 1.1.1 | The ⌘K menu, fetched on first open |
| Resend | 6.31.0 | Delivers the contact form |
| Biome | 2.5.14 | Lint and format |
| Vitest | 5.0.2 | Unit tests |
| Playwright | 1.63.0 | End-to-end and axe checks |
Hosted on Vercel. Versions are read from package.json at build time.
Motion
- Every page is prerendered HTML, so the headline, the work, every case study and the contact details all read with JavaScript off. The Lab demos render their results on the page first too, and their controls load when you scroll to them.
- GSAP, ScrollTrigger and Lenis arrive in one chunk after the page has loaded and the main thread is idle, and only when motion is allowed.
- Most of the motion is CSS. The headline’s words rise with CSS transforms, one IntersectionObserver switches the reveals, and the footer name uses scroll-driven animation where the browser supports it.
- Nothing is drawn with WebGL. The glass is backdrop blur and gradients, and the globe is a 2D canvas that only draws while it’s on screen.
What turns it off
- Read mode
- Solid panels instead of glass, nothing sticky or moving, and the motion code never loads. It turns on by itself when the browser asks to save data.
- Reduced motion
- Turns Motion off: no smooth scrolling and nothing tied to the scroll position. Content that would fade in is simply there.
- Motion switch
- The same as reduced motion, from the menu or ⌘K, for any visitor.
Fonts
Satoshi by Indian Type Foundry
Every heading, paragraph, link and button
- Source
- Fontshare
- License
- ITF Free Font License
- Loading
- 3 weights (400, 500, 700), all preloaded because all of them are in the first screen
- Size
- 24.7 KB to 25.0 KB per weight, 74.6 KB in total
JetBrains Mono by JetBrains
Labels, numbers and code
- Source
- Google Fonts
- License
- SIL Open Font License 1.1
- Loading
- One static weight (400), not preloaded
- Size
- 20.7 KB
Self-hosted at build by next/font, with a metric-matched fallback for Satoshi so the swap doesn’t move the layout. Budget: 100 KB on first load.
Generated art
6 images on this site are generated. They’re atmosphere only: light and illustration behind the content, never an interface. Project screenshots are real captures, and no client screenshot or client art is ever uploaded to a generator.

Home: the light behind the hero

Services: Build

Services: Ship onchain

Services: Review

Services: AI features

Contact: the horizon under the globe
Each image has a record in the repo with its prompt, the tool, the date and the post-processing. This list is built from those records.
Performance
| Budget | Target | Measured |
|---|---|---|
| Home first-load JavaScript | ≤ 180 KB gzipped | 175 KB gzipped |
| Other routes, first-load JavaScript | ≤ 200 KB gzipped | 173 KB gzipped at most (/work) |
| Motion chunk (GSAP, ScrollTrigger, Lenis) | ≤ 70 KB gzipped, after first paint | 52 KB gzipped |
| Ask drawer | ≤ 45 KB gzipped, on first open | 30 KB gzipped |
| Fonts on first load | ≤ 100 KB | 95.4 KB |
| Largest Contentful Paint | ≤ 2.5 s on a mid-range phone over 4G | Not yet measured |
| Cumulative Layout Shift | < 0.1 | Not yet measured |
| Interaction to Next Paint | < 200 ms | Not yet measured |
pnpm budgets measures the JavaScript after each build: what each page loads first, and the motion chunk and Ask drawer that load later. The font total is the size of the files that ship. The JavaScript numbers are from the build on October 3, 2026. Real-user numbers from Vercel Speed Insights replace the lab numbers after launch.
Credits and data
- Design and code
- Casey Charlesworth
- Type
- Satoshi by Indian Type Foundry and JetBrains Mono by JetBrains
- Logos
- Company logos belong to their owners and appear with permission.
- Globe
- Land from Natural Earth (public domain), reduced to 2,029 dots.
- Price data
- The range demo uses SOL/USDC history from CoinGecko, committed with a source stamp.
- Transaction sizes
- solana.com: larger transaction sizes (checked 2026-09-29)
Release notes
v2.0This build
- A full redesign: glass panels on near-black, Satoshi, and every project shown in a browser frame.
- 15 case studies and 4 lab demos, all prerendered.
- A Questions drawer, with my answers to common questions about my work.
- Read mode, the Motion switch and the ⌘K menu carry over from v1.
v1.0
- The first version: a WebGL hero, the first case studies and the lab demos.