Skip to main content
vibld

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

  1. Minimal header: wordmark left, centered discipline tagline, 'Open Menu' label with a ⌘+K key chip right, hairline rule below
  2. Split hero: huge two-line headline left, short positioning statement right
  3. Row of three office cities with local greetings
  4. Full-width grayscale interior photograph
  5. Work section: type and location filter selects, grid/list toggle, 2-column project cards (image, title, city • year, one-line description)
  6. Oversized faded section word behind a Services list of four disciplines
  7. 'Ready to get started?' CTA block
  8. Sticky-reveal footer uncovered on scroll
  9. Floating vertical theme switcher (5 color dots) pinned to the left edge
  10. 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

SampleWhereRatioNeeds
Aabody text on page background16.05:14.5:1
Aatext on cards19.30:14.5:1
Aatext on secondary surface13.94:14.5:1
Aamuted metadata on page background5.23:14.5:1
Aamuted metadata on cards6.29:14.5:1
Aamuted text on secondary surface4.54:14.5:1
Aawhite text on dark pill button19.30:14.5:1
input border on page background3.03:13:1
input border on card3.64:13:1
focus/selected ring on page background16.05:13: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.

Open the builderAll templatesThis palette on its own