Plinth
Plinth is a portfolio for a developer who takes the work seriously and themselves less so: freelancers, independent studios, consultants. Your work is the permanent collection of a contemporary art museum, told with a straight face: real-looking photos of white rooms where a laptop, a server rack or a box of packing peanuts is displayed as precious art, museum labels beside every work, Instrument Serif for titles and a gallery white that turns to night blue in the dark theme. The home page is short: the opening, a few works, the artist, a chronology of where you have worked, an invitation to the private view and closing time. The demo is a fictional developer in Prague, Leo Marek.
Plinth comes in two variants, chosen when you create the site: files/Sanity (static pages, 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) |
| Collection (every work, a filter by room) | Pages → Collection page |
| A work (the label, curator’s note, visitors’ book, wall text, installation views, provenance, materials) | Content → Exhibits |
| Gift shop (services with price tags, a private viewing, questions) | Pages → Shop page and Content → Services |
| Visit (opening hours, the enquiry form, a call, house rules) | Pages → Visit page |
| Name, role, availability, opening hours, navigation, profiles | Pages → Site settings |
| Buttons, labels, chat, emails and the game’s texts | Content → Interface texts |
| Privacy, terms | Pages → Legal |
In titles, words wrapped in *stars* are set in italic, like the title of a work, as in
“Websites that *belong in a museum*”.
The opening
Section titled “The opening”The hero is the site’s signature: four photos of the same room, taken from exactly the same spot (Pages → Home page → Hero → Photos, 16:9):
- The hall at night, the first photo people see. The headline, one line, Commission a work and See the collection sit over it from the first frame.
- One spotlight on the vitrine: it comes on as you start to scroll.
- All the lights: the room lights up, the camera moves in on the vitrine and its museum label slides out beside it (Hero → The label beside the vitrine).
- A visitor stops before the work (and the guard sleeps in the corner).
Set Vitrine to where the exhibit is in the photos (in % of the photo). The later photos load after the page, so they never slow the first frame. On phones the whole room stays in view and the label hangs above it. With reduced motion, or in a browser without scroll-driven animations, the hero is one still: the headline over the room with the visitor.
The demo’s four photos were made from one photo of the room, edited for each step, so nothing moves between them. When you replace them, use a tripod (or edit one photo the same way).
The collection
Section titled “The collection”Each work is a project: its title, the year, a room (the collection page filters by room without any
JavaScript), the medium (the stack, in words), the client (the credit line, “Courtesy of…”), a summary,
the curator’s note (the brief), a 16:9 installation view, more views with captions, the provenance
(results before and after; the first one is shown on the card), the visitors’ book (the client and a
quote), the materials (the stack, with logos from Simple Icons) and links. The body is the wall text.
Search engines get each one as a schema.org CreativeWork.
The chronology
Section titled “The chronology”Pages → Home page → Chronology lists the places you have worked, oldest first: the years, the place, your role and a sentence. Mark the current one as Current and it keeps a lit dot. As the section scrolls into view, the line draws itself from the first year to the last and each place lights up as the line reaches it: across the page on wide screens, down the left edge on phones.
The gift shop
Section titled “The gift shop”Every service is an item with a price tag: a line, the price and a note, how long it takes and what’s included. The private viewing is a paid hour, a one-time payment with Stripe (a Price id) or Lemon Squeezy (a variant id) in Pages → Shop page → A private viewing. Without keys the button explains how to switch it on.
Commissions and the call
Section titled “Commissions and the call”The visit page’s enquiry form asks for a name, email, an optional company, what’s needed, a budget and when it should open, each picked from a short list you set in Pages → Visit page → Enquiry form, and a message. The choices are written above the message in the email you receive (Resend, to the email in Site settings). The call books through Cal.com; until it’s connected the page shows a preview of the calendar with your times.
Integrations
Section titled “Integrations”Everything works without keys; each feature switches on with its variables in .env.example.
| Feature | Where | Service |
|---|---|---|
| Book a call | Visit page, loads on click; a preview of the calendar until connected | Cal.com |
| A private viewing | Gift shop (one-time payment) | Stripe or Lemon Squeezy |
| Newsletter (invitations to the private view) | Home page, with a welcome email | Supabase or Mailchimp |
| Commissions | Visit page; to the email in Site settings | Resend |
| AI chat (the guide) | Every page; answers about services, prices, works and availability | Claude or OpenAI |
| Search | ⌘K or the search button: the collection, the gift shop, the visit page | built in, or Algolia |
| Analytics | Every page; Google Analytics only after consent | Plausible, Umami, Google Analytics, PostHog |
| Pictures | Production builds | Cloudinary (optional) |
Sections
Section titled “Sections”The home page is built from these sections, in any order: Hero (the opening), Now showing (works from the collection, their photos lighting up as they scroll in), The artist (your photo as an exhibit, with a label, a wall text and facts), Chronology (where you have worked), Newsletter (an invitation card) and Closing time (the closing call over a photo of the museum at closing, dark in both themes).
Colors and brand
Section titled “Colors and brand”src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent
(museum red: buttons, the “open” sign, the lit dot), the second (brass: small capitals, rules, the
invitation card) and the third (night blue: the dark theme, the opening and closing time). Buttons
are darkened until their text reads; every color is adjusted for each theme, and one that can’t get
there stops the build with a message. Brand also sets the fonts (text and titles) and the corners (square
by default, or soft). The site opens in its light theme; the toggle switches to the museum after hours and
the browser remembers it.
Availability and opening hours
Section titled “Availability and opening hours”Site settings → Availability turns the “open” sign in the header and the footer on (taking on work) or off, with your line next to it. Site settings → Opening hours are shown in the footer and on the visit page.
Languages
Section titled “Languages”Plinth is ready for more languages: see Languages.
The 404 page
Section titled “The 404 page”A small game, Hang the show: the opening is tonight and nothing is on the walls. Hang framed works on two or three walls so every wall is filled exactly, end to end (tap a work, then a wall; or keys 1–9 and A–C; tap a hung work to take it down). Some works are spares that fit nowhere useful. The fewest moves is worked out for every room, and you score 100 × that ÷ your moves. Three rooms; the titles of the works are yours to write (Interface texts → 404 game). 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, works and services for AI assistants, in every language.- Pages carry JSON-LD: you as a
Person(your role, your profiles, your services as offers), works asCreativeWorks and questions as aFAQPage.
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).