Template
Plinth & Lathe
A monochrome single-page site for a small interior-architecture studio that doubles as a lead-qualification tool. Visitors browse filterable case studies, open project detail pages, and use a keyboard-driven command menu to get a cost estimate or send an inquiry without leaving the page.
Interior studio lead-gen site · Website · SaaS landing page · front-end app (local state)
A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.
Start from this templateRead the build prompt
Typefaces
Anek Latin is a clean neo-grotesk with a slightly architectural, drawn precision, which echoes a Swiss studio monograph.
- Anek LatinHeadings: hero 76px semibold, section heads 42px
- Anek LatinBody: body 16px at 1.6, grey metadata
Who it is for
- Interior and architecture studios
- Freelance spatial designers
- Small creative agencies qualifying leads
- Studios with multiple city offices
Layout
- Minimal header: wordmark left, centered discipline tagline, 'Open Menu' label with a ⌘+K key chip right, hairline rule below
- Split hero: huge two-line headline left, short positioning statement right
- Row of three office cities with local greetings
- Full-width grayscale interior photograph
- Work section: type and location filter selects, grid/list toggle, 2-column project cards (image, title, city • year, one-line description)
- Oversized faded section word behind a Services list of four disciplines
- 'Ready to get started?' CTA block
- Sticky-reveal footer uncovered on scroll
- Floating vertical theme switcher (5 color dots) pinned to the left edge
- Project detail route with hero image, metadata and gallery
Palette
Quiet, architectural, precise, monochrome, confident. It feels like a printed studio monograph that happens to have a keyboard shortcut.
- background
#eaeaea - text
#0e0e0e - card
#ffffff - secondary surface
#dbdbdb - muted text (metadata, greetings)
#606060 - input border / theme-dot outline
#868686 - decorative hairline rule
#afafaf - theme dot rose
#e4a3a8 - theme dot sage
#9fbf8f
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on page background | 16.05:1 | 4.5:1 |
| Aa | text on cards | 19.30:1 | 4.5:1 |
| Aa | text on secondary surface | 13.94:1 | 4.5:1 |
| Aa | muted metadata on page background | 5.23:1 | 4.5:1 |
| Aa | muted metadata on cards | 6.29:1 | 4.5:1 |
| Aa | muted text on secondary surface | 4.54:1 | 4.5:1 |
| Aa | white text on dark pill button | 19.30:1 | 4.5:1 |
| input border on page background | 3.03:1 | 3:1 | |
| input border on card | 3.64:1 | 3:1 | |
| focus/selected ring on page background | 16.05:1 | 3:1 |
As vibld’s tokens
The palette on the fifteen colour tokens vibld styles a project with, each text colour on the fill it is read on. Marked tokens are solved from the palette, because no swatch held that role at 4.5:1.
- background
- card
- muted
- primary *
- secondary
- accent
- destructive *
Type scale
- Display
- Anek Latin semibold, 76px hero, tight leading, sentence case; 42px section headings
- Body
- Anek Latin 16px regular, line-height 1.6; muted #606060 secondary text for metadata
Single neo-grotesk family; hierarchy comes purely from size and weight, echoing Swiss architectural print
Spacing and imagery
Airy; full-bleed 24px page gutters on a wide container, 2-column project grid with ~64px gaps, generous vertical section spacing, pill (9999px) buttons and 8px card radius
Large desaturated black-and-white interior renders (cafés, bedrooms, lounges) cropped to landscape, no overlays or captions on the image itself
Components
- Command palette dialog (⌘K)
- Multi-step cost estimator
- Inquiry form inside palette
- Theme switcher dot rail
- City greeting row
- Project card with meta line
- Type and location filter selects
- Grid/list view toggle
- Project detail page with gallery
- Services list with giant watermark heading
- CTA block
- Sticky-reveal footer
Interactions
- ⌘K / Ctrl+K opens command menu with fuzzy search
- Step-through estimator with back/next and live price range
- Filter changes animate cards in/out with layout transitions
- Grid-to-list toggle morphs card layout
- Theme dot click swaps CSS variable palette instantly
- Footer revealed from beneath content as page scrolls
- Route transitions fade between home and project pages
- Hover darkens project images slightly and reveals arrow
Data
Project{slug, title, city, year, type, summary, cover, gallery[]}Service{name, description}Office{city, greeting}EstimateInput{spaceType, area, scope, timeline}Inquiry{name, email, message}
Build prompt
The baseline every prompt in the catalog assumes, then this design’s own ten sections, from goal to guardrails.
The baseline
### How to use these prompts Paste a template's build prompt into your coding agent as the first message. Each prompt names its own stack, tokens and acceptance criteria; the rules below apply to all of them and can be prepended once per project. ### Engineering baseline - TypeScript strict mode, no `any`, small typed components, feature folders, and one source of truth for design tokens (CSS variables consumed by Tailwind). - Validate every input with a shared zod schema on the client and again on the server or edge function. Never trust client-side checks alone. - Show loading, empty and error states for every async view. Surface errors in plain language with a retry, and log details to the console in development only. - Keep secrets out of the bundle. Only publishable keys (for example a Supabase anon key) belong in client code; service-role keys, API keys and webhooks live in server or edge-function environment variables. ### Data and auth baseline (full-stack templates) - Enable Row Level Security on every table before inserting data. Default-deny, then add owner-scoped policies (`auth.uid() = user_id`) and explicit role checks for admin views. - Store roles in a separate table checked by a security-definer function, never in a user-editable profile field. - Upload files to private storage buckets with size and MIME limits, and serve them through signed URLs. - Rate-limit public endpoints (forms, auth, AI calls) and add a honeypot field or captcha to anonymous forms. - Take payments through a hosted checkout and verify webhooks by signature. Never handle raw card data. ### Accessibility and UX baseline - Target WCAG 2.2 AA: 4.5:1 contrast for normal text and 3:1 for large text, input borders, focus rings and meaningful icons or chart lines. Every palette in this catalog lists its verified pairs; re-check with a contrast tool after any colour change. - Keep body text at 16px or larger with 1.5 line height, nothing below 12px, no light weights under 24px, and uppercase only for short labels. - Give every interactive element a visible focus ring, full keyboard support, semantic landmarks, labelled form fields, and alt text on meaningful images. - Respect `prefers-reduced-motion` for every animation. Give drag-and-drop and carousels keyboard and button alternatives. - Build mobile-first and test at 375px, 768px and 1280px. ### Content guardrails - Use original copy, fictional sample data and placeholder or licensed imagery. Do not reuse another product's name, logo, screenshots or marketing text. - Label demo testimonials and metrics as samples. Collect the minimum personal data the feature needs.
### Goal
Build a single-page website for a fictional interior-architecture practice called **Plinth & Lathe**. The audience is prospective residential and commercial clients who want to judge the studio's taste quickly and get a rough price before they get in touch. The site's core job is to show selected projects and convert visitors through a keyboard-first command menu that holds a cost estimator and an inquiry form.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) with the `cmdk` Command component, lucide-react, Framer Motion for layout and route transitions, React Router for project slugs, and react-hook-form + zod. No backend; the inquiry posts to one serverless function.
### Pages & layout
1. Header: wordmark left, discipline tagline centered, "Open menu" label with a `⌘ K` key chip right; thin rule underneath.
2. Hero: very large two-line headline left, short positioning line right.
3. Office strip: three cities, each with a local-language greeting in muted #606060.
4. Full-bleed grayscale interior image.
5. Work: filter selects (type, location), grid/list toggle, two-column project cards with image, title, "City • Year", and a right-aligned one-liner.
6. Services: a giant pale watermark word behind four discipline rows.
7. CTA block "Planning a space?" that opens the command menu.
8. Footer that is revealed from underneath as the main content scrolls away.
9. `/projects/:slug`: hero image, meta grid (location, year, area, type), text, gallery, next-project link.
### Design system
Default theme tokens: `--background: #eaeaea; --foreground: #0e0e0e; --card: #ffffff; --secondary: #dbdbdb; --muted-foreground: #606060; --input-border: #868686; --border: #afafaf (decorative hairlines only); --radius: .5rem`. Provide four alternate light themes (rose, sage, sand, and a warm off-white) swapped by a `data-theme` attribute. Font: Anek Latin (400/500/600). Type scale: 76 / 42 / 24 / 16 / 13px (13px meta at weight 400+; body line-height 1.6), with -1% tracking on display sizes. Spacing uses a 4px base; 24px page gutters, 64px grid gaps, 128px between sections. Buttons are pills; cards and images are square-cornered or 8px. No shadows except on the command dialog. Motion: 250ms `cubic-bezier(.2,.8,.2,1)` for layout, 400ms for page fades. Light only; the themes replace a dark mode.
### Components & interactions
- Command palette: groups for Navigate, Estimate cost, Contact; arrow keys and Enter; empty state "No matches".
- Estimator: four steps (space type, area slider, scope checkboxes, timeline) with a progress bar, back/next, disabled next until valid, and a result showing a price range with a "Send this to us" button.
- Inquiry form: inline validation errors, loading spinner on submit, success toast, error toast with retry.
- Filters and view toggle animate with shared layout; empty state when no project matches.
- Theme rail: five dots with 1px #868686 outlines, a 2px #0e0e0e selected ring, and tooltip names.
### Data & state
Static TypeScript modules: `Project{slug,title,city,year,type,area,summary,cover,gallery[]}`, `Service{name,blurb}`, `Office{city,greeting}`. Filter, view mode and theme live in URL search params or local state; persist theme in localStorage. Seed six projects with invented names and neutral cities.
### Accessibility
The palette meets AA (#0e0e0e on #eaeaea is about 15:1); each alternate theme keeps #0e0e0e text and #606060 metadata, so every theme background must be at least as light as #dbdbdb (verify each at 4.5:1 or higher). The command dialog must trap focus, restore focus to the trigger on close, and announce result counts via `aria-live`. Offer a visible button for the menu, not just the shortcut. Theme dots need `aria-label`s and `aria-pressed`. Respect `prefers-reduced-motion` by disabling layout and footer-reveal animation. Every project image needs descriptive alt text. Verified contrast: body text on page background: #0e0e0e on #eaeaea = 16.05:1; muted metadata on page background: #606060 on #eaeaea = 5.23:1; white text on dark pill button: #ffffff on #0e0e0e = 19.3:1.
### Security
Validate estimator and inquiry input with zod on the client and again in the receiving function. Add a honeypot field and basic rate limiting on the endpoint. Keep no API keys in client code. Treat slugs as lookups into a known list; render a 404 for unknown ones.
### Performance & SEO
Lazy-load project images with `srcset` and dimensions; code-split the detail route and estimator. Give each project page a unique title, description and OG image. Use one H1 per page. Target Lighthouse 95+ on all categories.
### Guardrails
- Use original copy and placeholder or generated interior imagery only; no real studio names or logos.
- Do not invent client testimonials presented as real.
- Store only name, email and message; nothing else from the inquiry.
- Keep components small and typed, never use `any`, and show errors visibly.
- Done when: ⌘K opens the menu from anywhere and the estimator returns a range; filters and grid/list toggle work together; theme choice persists after reload; project detail pages resolve by slug with a 404 fallback; axe reports zero critical issues.