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.

Add app screens

Pick up to 6 screens, such as a dashboard, settings or an empty state. Each is built in this design’s own palette and typefaces, with its states and guardrails.

Account setup
Add edit
Analytics
Appearance
Calendar
Chat
Checklist
Checkout
Confirmation
Dashboard
Delete account
Details
Discovery questions
Empty state
Flowchart
Import export
Inbox
Integrations
Invite team
Loading
Login
Onboarding
Plans
Playground
Product tour
Referral
Search
Settings
Share
Sign up
Success
Table
Team members
Text editor
Upgrade
Usage
Verification
Welcome

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 15+ color tokens vibld styles a project with, each text color 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 color 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, labeled 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