Skip to main content
vibld

Template

Linnea Farrow

A stark, typographic portfolio for a nature and landscape photographer. A five-column top nav holds the name, category links (Landscape, Nature, Animals) and Info, and above a footer with studio address and contact it presents category galleries in a lightbox-driven layout. It helps photographers book clients, sell prints and pitch editorial projects.

Typographic nature photographer site · Website · Portfolio · static site

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

Sen is a small, clean geometric sans close to Satoshi that stays tiny and bold in the nav, leaving the white wall to the photographs.

  • SenHeadings: nav and name 18px 700
  • SenBody: body ~19.5px regular

Who it is for

  • Landscape and wildlife photographers
  • Photographers selling fine art prints
  • Editorial and documentary shooters pitching projects
  • Artists with a consistent visual style

Layout

  1. Top nav spread across five equal columns: name, Landscape, Nature, Animals, Info in bold sans
  2. Category gallery sections: large images per category, opened in a lightbox
  3. Pricing / print sizes section
  4. Booking inquiry form with validation and file upload
  5. Footer: name, studio address, email, Instagram, copyright
  6. Info page with bio and contact

Palette

Stark, minimal, confident, gallery-white, understated. The page is a blank white wall waiting for large nature photographs.

  • background#ffffff
  • text#000000
  • primary#000000
  • muted#f5f5f5
  • border#ededed
  • secondary text#6b6b6b
  • input border#6b6b6b

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody and nav text on white21.00:14.5:1
Aacaptions and muted text on white5.33:14.5:1
Aamuted text on muted surface4.89:14.5:1
Aaprimary button text on black21.00:14.5:1
input border on white5.33:13:1
focus ring on white21.00:13:1
Aalightbox caption on black backdrop21.00:14.5: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
Satoshi 700, 18px for nav and name, no tracking (Satoshi is not on Google Fonts; a vibld project loads Sen)
Body
Satoshi ~19.5px regular (Satoshi is not on Google Fonts; a vibld project loads Sen)

A single geometric sans in bold small sizes; the typography stays tiny so photographs dominate.

Spacing and imagery

Wide 48px margins, nav spread edge to edge in equal columns, zero radius, black-on-white with no decoration.

Landscape, nature and animal photography, shown full-width and uncropped, opened in a lightbox.

Components

  • Five-column text nav
  • Category filter links
  • Gallery sections per category
  • Lightbox (LightGallery-style)
  • Smooth-scroll container
  • Print pricing table
  • Booking inquiry form with file upload
  • Footer with address and contact
  • Info page
  • Skip link

Interactions

  • Category links jump or filter to the matching gallery
  • Images open in a lightbox with zoom, thumbnails, keyboard and swipe
  • Smooth inertial scrolling (Locomotive-style) with GSAP reveals
  • Lazy-loaded images fade in
  • Inquiry form validates and accepts reference image uploads
  • Hover underline on nav links

Data

  • Photo{id, src, alt, category, title, year, printable}
  • Category{slug, title}
  • PrintOption{size, paper, price}
  • Inquiry{name, email, type, date?, message, attachments[]}

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 gallery-white portfolio for a fictional nature photographer, "Linnea Farrow". It serves three audiences: clients booking commissions, collectors buying prints and editors reviewing projects. The design is almost pure typography. A spare, bold nav names the categories, and each category opens into large photographs viewable in a lightbox. A print-pricing section and a booking form turn interest into inquiries.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix Form, Select, Table, Toast) and lucide-react. Use LightGallery (or yet-another-react-lightbox) for zoom and thumbnails, GSAP ScrollTrigger for gentle reveals, Lenis (a lighter alternative to Locomotive Scroll) for smooth scrolling and react-hook-form + zod. The only backend is a small serverless or Supabase Edge Function that accepts inquiries plus optional reference images, stored in a private Storage bucket.

### Pages & layout
1. Nav: a 5-column grid spanning the page, with the name in column 1 and Landscape, Nature, Animals and Info in the others. Bold 18px text; the active category is underlined.
2. Category view: a 2-column grid on desktop (1 on mobile) of large images at natural ratios with a 48px gap and small captions (title, year).
3. Prints: a table of sizes, papers and prices (from a config), with a "Request this print" link that pre-fills the form.
4. Booking: name, email, inquiry type (commission / print / editorial), preferred date (optional), message and up to three reference images.
5. Footer: name, studio address (placeholder), email, Instagram and copyright, laid out on the same 5-column grid.

### Design system
- `--background: #ffffff`, `--foreground: #000000`, `--muted: #f5f5f5`, `--border: #ededed`, `--muted-foreground: #6b6b6b`, `--input-border: #6b6b6b` (the #ededed border is decorative only), `--radius: 0`.
- Font: Satoshi (Fontshare) or General Sans at 400/700. Scale: 14 / 18 / 20 / 32px. Bold is for navigation only; body is 18-20px at 1.6 line-height with a ~70ch measure.
- Spacing: 8px base, 48px page margins, 96px between sections. No shadows.
- Motion: Lenis smoothing with lerp 0.1, 600ms image fade-ins and 250ms lightbox transitions. Light only.
- Typeface: Sen (Google Fonts) for nav and name 18px 700.

### Components & interactions
- CategoryNav: links with `aria-current` and a hover underline.
- GalleryImage: blur placeholder, then fade in. Click or Enter opens the lightbox at that index. Show an error tile if loading fails.
- Lightbox: zoom, thumbnails, keyboard, swipe and a caption. Focus returns on close.
- InquiryForm: states for invalid, uploading (progress), submitting, success and error. Selecting "Print" shows the size select.
- Empty category: "New work coming soon."

### Data & state
Typed JSON: `Photo{id, src, alt, category, title, year, printable}`, `PrintOption{size, paper, price}` and `Category`. The active category lives in the URL. Inquiries go to the function, and attachments go to private storage via short-lived signed upload URLs. Seed 10-15 placeholder photos per category.

### Accessibility
- Smooth-scroll libraries must not break keyboard scrolling, anchor links or screen readers. Disable Lenis under reduced motion.
- Every photo has alt text. The pricing table uses `<th scope>`.
- Form fields have visible labels, errors are announced and the file input has an accessible name and constraints text.
- Verified contrast: body #000000 on #ffffff = 21.0:1; muted #6b6b6b on #ffffff = 5.33:1; muted on surface #6b6b6b on #f5f5f5 = 4.89:1; input border #6b6b6b on #ffffff = 5.33:1.

### Security
- zod validation in the client and in the function. Allow only JPEG/PNG/WebP up to 5MB each, max 3, checked by MIME and size on the server.
- Storage bucket is private, with no public file browsing and signed URLs only. Add a honeypot and per-IP rate limit.
- The service key stays in function env. Never take payments on-site; link to a hosted checkout if prints are sold.

### Performance & SEO
Serve `srcset` AVIF/WebP and lazy-load all images below the fold. Code-split the lightbox. Add ImageGallery and LocalBusiness JSON-LD and per-category titles and OG images.

### Guardrails
- Do write all copy yourself and use placeholder imagery (Unsplash-style stock or generated); no trademarked names, client logos or real people.
- Don't present invented testimonials or awards as real; label sample content as sample.
- Keep components small and fully typed; no `any`. Surface errors visibly instead of failing silently.
- Don't collect or store more personal data than the contact form needs.
- Done when:
  - [ ] Category nav switches galleries and updates the URL
  - [ ] Lightbox supports zoom, keys, swipe and focus return
  - [ ] Inquiry form enforces type/size limits client- and server-side
  - [ ] Smooth scroll is disabled under reduced-motion
  - [ ] Pricing table is semantic and readable on mobile

Open the builderAll templatesThis palette on its own