Skip to main content
vibld

Template

Tidewell Photo

A single-screen, split-pane photography site. The left half auto-cycles through black-and-white images while the right half lists project collections in large type. Choosing a collection opens a full-screen viewer. It suits photographers who want a portfolio that feels like an exhibition wall rather than a scrolling feed.

Split-screen photography portfolio · 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

Readex Pro is an even, geometric-humanist sans whose 500-to-600 step is clearly visible, so the weight shift still marks the active series in the quiet slideshow.

  • Readex ProHeadings: series names 48-56px, 500 inactive / 600 active, -0.03em
  • Readex ProBody: nav 18-20px, captions 16px

Who it is for

  • Documentary and street photographers
  • Photographers organizing work into named series
  • Small photo businesses competing with studios
  • Creatives who want a no-scroll, app-like homepage

Layout

  1. Fixed top links centered over the split: brand name, About, Contact, Instagram
  2. Left 50%: full-height image pane that crossfades through photos from the active collection
  3. Right 50%: white pane with a vertical list of collection names in large sans type; the active one is black and bolder, others dark gray
  4. Full-screen gallery viewer opened from a collection with next/prev and close
  5. About and Contact as simple overlay pages
  6. Mobile: image pane on top, list below

Palette

Stark, gallery-like, focused, rhythmic, monochrome. The page feels like a quiet slideshow in an exhibition room.

  • background#ffffff
  • text / active item#09090b
  • inactive list items#3f3f46
  • primary#18181b
  • muted#f4f4f5
  • border#e4e4e7

Every checked pair, measured again

SampleWhereRatioNeeds
Aaactive series name and body text on white19.90:14.5:1
Aainactive series names on white10.44:14.5:1
Aanav links on white strip19.90:14.5:1
Aaviewer caption on black21.00:14.5:1
Aaviewer counter text on black8.19:14.5:1
focus ring on white pane19.90:13:1
focus ring and control icons in viewer21.00:13:1
play/pause icon on white17.72: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
Readex Pro, 48-56px, 500 for inactive and 600 for the active item, tight -0.03em tracking
Body
Readex Pro 16-20px for nav

One geometric humanist sans in several weights; the weight shift itself marks the active state.

Spacing and imagery

Hard 50/50 viewport split, no scrolling on desktop; the list is vertically centered with ~48px between items; zero radius.

High-contrast black-and-white documentary photographs, full-bleed and cover-cropped, auto-advancing with crossfades.

Components

  • Split-screen shell
  • Auto-cycling image pane
  • Collection list with active state
  • Minimal top link row
  • Full-screen gallery viewer
  • Image counter and close button
  • About overlay
  • Contact overlay/form
  • Pause-on-hover control
  • Social link

Interactions

  • Images crossfade every few seconds (spring-based transitions)
  • Hovering a collection name switches the left pane to that collection and bolds the name
  • Clicking a collection opens the full-screen viewer
  • Arrow keys, swipe and Esc in the viewer
  • Cycling pauses on hover or focus and when the tab is hidden
  • Mobile swipe between images

Data

  • Collection{slug, title, featured, images: Photo[]}
  • Photo{src, alt, width, height, caption}
  • content.json drives all collections

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 one-screen split portfolio for a fictional documentary photographer, "Tidewell Photo". Visitors see one half of the screen as a living slideshow and the other half as a list of named photo series. Hovering a series changes the slideshow and clicking it opens a full-screen viewer. The job is to make a small body of work feel curated and immersive.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix Dialog for the viewer and the About/Contact sheets) and lucide-react. Use React Spring (or Framer Motion) for crossfades and zod to validate `content.json` at load time. No backend; the contact link can be `mailto:` or a small form function.

### Pages & layout
1. Shell at 100dvh with no page scroll on desktop. Left: an image pane with `object-fit: cover`. Right: a white pane.
2. Top: a centered row with the brand name plus About, Contact and Instagram in 20px regular text, set on a solid white strip so link text never sits on a photo.
3. Right pane: 4-6 series names stacked and vertically centered, left-aligned at around 60% of the pane width.
4. Viewer: a full-screen black dialog with the image contained, a caption, a "4 / 18" counter, prev/next buttons and a close button.
5. About and Contact: side sheets with a short bio and email/social links.
6. Below 768px, the image pane takes 55vh on top and the list follows.

### Design system
- Tokens: `--background: #ffffff`, `--foreground: #09090b`, `--inactive: #3f3f46`, `--muted: #f4f4f5`, `--border: #e4e4e7` (decorative hairlines only). Viewer background #000 with white captions and #a1a1aa counter text; focus rings are 2px `--foreground` on white and 2px white in the viewer.
- Font: Readex Pro (Google Fonts) at 400/500/600. Series names use clamp(32px, 4vw, 56px) with -0.03em tracking. Nav is 18-20px; captions 16px with 1.5 line-height.
- Spacing: 8px base; 48px between list items. Radius 0.
- Motion: 900ms crossfade, a 4.5s interval and 200ms weight/color change on hover. Keep a ready dark variant (swap background and foreground) but ship light.

### Components & interactions
- Cycler: holds an index per active collection and preloads the next image. It pauses on hover, on focus within the pane, on `visibilitychange` and under reduced-motion (then it shows a static first image).
- SeriesItem: inactive gray, 500. Hover or focus makes it black, 600, and swaps the active collection. Click or Enter opens the viewer.
- Viewer: arrows, swipe, Esc and a focus trap. Show a loading shimmer while a large image decodes, and an error tile if an image fails.
- A visible play/pause button for the cycler.

### Data & state
`content.json` holds `Collection{slug, title, featured, images: Photo{src, alt, w, h, caption}[]}`. Parse it with zod and render an error state if it is malformed. State covers the active collection, cycle index, viewer open state and viewer index. Seed five fictional series of 6-10 monochrome placeholder photos each.

### Accessibility
- Auto-advancing content needs a pause control (WCAG 2.2.2). Stop cycling for reduced-motion users.
- The list is a `<nav>` of buttons. The active item has `aria-current`, and bolding is not the only cue; add an underline or marker.
- The viewer is a labelled dialog that returns focus on close. Every photo needs alt text.
- #3f3f46 on white is 10.4:1, so inactive items stay readable.
- Verified contrast: active text #09090b on #ffffff = 19.9:1; inactive #3f3f46 on #ffffff = 10.44:1; viewer caption #ffffff on #000000 = 21.0:1; counter #a1a1aa on #000000 = 8.19:1.

### Security
- No secrets. Validate JSON input.
- External links use `rel="noopener noreferrer"`.
- If you add a contact form, validate with zod on both sides and add a honeypot.

### Performance & SEO
Preload only the first image and lazy-decode the rest. Use responsive `srcset` and AVIF/WebP. Give each collection a shareable `?series=` URL with its own title and OG image.

### 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:
  - [ ] Desktop renders a no-scroll 50/50 split; mobile stacks cleanly
  - [ ] Hovering or focusing a series swaps the cycling images
  - [ ] Cycler pauses via button, hover, hidden tab and reduced-motion
  - [ ] Viewer supports keys, swipe and focus return
  - [ ] Malformed content.json shows a readable error

Open the builderAll templatesThis palette on its own