Lava
Lava is a developer portfolio built around a lava lamp: home, work with case studies, about, notes and contact. Every page has a temperature, from 40 °C on the home page to 100 °C on the contact page; the hotter the page, the faster the wax rises. Moving between pages floods the screen with wax.
Lava comes in two variants, chosen when you create the site: files/Sanity (static, any host)
and EmDash (--cms emdash, rendered on request on Cloudflare). The pages
are the same in both.
Pages and their content
Section titled “Pages and their content”| Page | Edit it in |
|---|---|
| Home | Pages → Home page (a list of sections) |
| Work, about, contact, notes, 404 | Pages → the page’s own entry |
| Projects (case studies) | Content → Projects |
| Notes (short articles) | Content → Notes |
| Your name, role, email, navigation, profiles | Pages → Site settings |
| Your photo | Pages → About page |
| Buttons, labels, chat, search, emails, game texts | Content → Interface texts |
| Privacy, terms | Pages → Legal |
Projects marked Featured come first, then by Order. The home page shows as many as its Selected work section asks for.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Contact form | Contact page; messages go to the email in Site settings | Resend |
| Book a call | Contact page, loads on click | Cal.com |
| Paid sessions | Contact page → Paid sessions (a Stripe Price id per offer) | Stripe |
| Newsletter for notes | Notes page, with a welcome email | Supabase |
| Ask about my work | Chat on every page, answers from your about page, projects and notes | Claude |
| Search | ⌘K or the search button: projects, notes, about | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Hero, Selected work, Skills (with your photo and the skill groups from the about page), Latest notes and Closing call to action.
Palette and brand
Section titled “Palette and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) picks a palette: Classic
(blue, orange, amber), Raspberry, Forest, Ink or Ocean, or Custom with your own three colors:
the lamp (the dark theme’s background) and two waxes. Text, buttons, links and the light theme
are derived from them and checked for readable contrast; a color that can’t be made readable
stops the build with a message. Brand also sets the fonts (text, headings, labels), corners
and button shape.
The lava
Section titled “The lava”The wax is drawn by a small WebGL program that starts after the page has loaded, so it never
slows the first view. Without a graphics card, without JavaScript, or with reduced motion
turned on, simple CSS wax (or a still frame) takes its place. Each page’s temperature and the
lanes the wax flows in are in src/lib/temperature.ts; the wax keeps clear of the text, since
light text on wax isn’t readable.
Languages
Section titled “Languages”Lava is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Pop the wax: pop the blobs before they reach the top of the lamp, with a click, a tap or the keys 1–9. The best score is kept in the visitor’s browser.
AI assistants and search engines
Section titled “AI assistants and search engines”AGENTS.mddescribes the project for coding assistants (Claude Code reads it throughCLAUDE.md, Cursor through.cursor/rules/)./llms.txtlists your pages, projects and notes for AI assistants, in every language.- Pages carry JSON-LD: you as a person on the home page, each project and note.
Commands
Section titled “Commands”pnpm dev # local site, editor at /keystaticpnpm build # production buildpnpm cms sanity schema|seed # move content to Sanity (see Content → Sanity)In the EmDash variant: npm run dev, npm run deploy (Cloudflare) and npm run emdash:schema
(after changing the content model).