Template
Pressed Petal
A soft, monochrome-on-sage wedding site built around polaroid-style photos, big serif headlines and a long single scroll: invitation message, venues, photo gallery, hotel details, categorized registry and a conditional RSVP form. It gives couples a personal, scrapbook-like link to send guests.
Scrapbook wedding invitation site · Website · Events and bookings · 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
Libre Bodoni is a classic, slightly old-fashioned high-contrast serif that reads like a printed keepsake, and Rosario is a soft humanist sans for the serene scrapbook.
- Libre BodoniHeadings: headlines 96px 400 in charcoal, 500 italic accents
- RosarioBody: body 16px charcoal, 12px tracked uppercase labels
Who it is for
- Couples wanting a personal invitation site
- Wedding planners
- Guests on mobile
- Agencies on tight timelines
Layout
- Ghost header: couple's names in serif left, tracked RSVP link right, no background
- Hero: tilted polaroid photo with shadow on sage, then huge charcoal serif 'We're Getting Married' and names
- Invitation paragraph about ceremony, reception and dress code
- Venue list: small caps label, serif venue name, spaced address lines (ceremony gardens, reception ballroom)
- Three-column polaroid photo gallery
- Hotel details section/page
- Categorized registry
- 'Will You Celebrate With Us?' RSVP with conditional fields
- Footer
Palette
Soft, intimate, nostalgic, playful, serene. It feels like a scrapbook of instant photos laid on a pastel tablecloth.
- background (sage)
#bacfc4 - text (charcoal)
#262626 - primary (off-white)
#ebebeb - primary-foreground (charcoal)
#262626 - secondary gray
#555555 - polaroid frame
#fafafa
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body and heading text on sage | 9.23:1 | 4.5:1 |
| Aa | secondary caption text on sage | 4.55:1 | 4.5:1 |
| Aa | charcoal label on off-white primary button | 12.69:1 | 4.5:1 |
| Aa | handwritten-style caption on polaroid frame | 14.50:1 | 4.5:1 |
| Aa | input text in field | 14.50:1 | 4.5:1 |
| input border on sage page | 3.02:1 | 3:1 | |
| input border against field fill | 4.74:1 | 3:1 | |
| focus ring on sage | 9.23: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
- Libre Bodoni 400, 96px headlines, charcoal, normal case
- Body
- Rosario 16px charcoal; 12px tracked uppercase labels
Classic serif plus neutral sans, both in charcoal on a single pastel field, creates a monochrome, paper-like calm.
Spacing and imagery
Single long scroll (6000px+), centered narrow text column (~760px), huge vertical breathing room, 12px radius on form fields.
Candid instant-film couple photos in white polaroid frames, slightly rotated with drop shadows.
Components
- Ghost navigation
- Rotated polaroid photo
- Giant serif headline
- Invitation text block
- Venue info blocks
- Polaroid gallery grid
- Hotel cards
- Registry category groups
- Conditional RSVP form
- Confirmation state
Interactions
- Scroll-triggered fade and rise on every block
- Polaroid slight rotation/hover straighten
- RSVP fields appear only when attending is yes
- Form confirmation state
- Smooth scroll to RSVP
Data
Venue{label, name, address, time}Photo{src, caption, rotation}Hotel{name, address, rate, bookingUrl}RegistryItem{category, store, url}RSVP{name, email, attending, guestCount, guestNames[], dietary, note}
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 **Pressed Petal**, a single-scroll wedding invitation site for fictional couple June & Idris. It should feel like a handmade scrapbook: instant-film photos on a soft pastel background, big serif type, and just enough information for guests to plan and reply. Guests mostly open it from a text message on their phones.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Form, RadioGroup, Input, Textarea, Select), lucide-react, Framer Motion for scroll reveals and polaroid motion, react-hook-form + zod with conditional validation, React Router for optional Hotel and Registry subpages. RSVP posts to a serverless function (or Supabase insert-only table).
### Pages & layout
1. **Home (long scroll)** – ghost header: names in serif at left, tracked "RSVP" link at right, no background. Hero: one polaroid photo rotated ~-2° with a soft shadow, then a very large charcoal serif headline and the names on the next line. Invitation paragraph (ceremony time, reception, dress code). Venue list: tiny caps label (Ceremony / Reception), serif venue name, address in tracked small caps. Gallery: three columns of polaroids with handwritten-style captions and alternating rotations. Hotels teaser. Registry grouped by category. "Will you celebrate with us?" RSVP. Footer with date and a thank-you line.
2. **Hotel details** – cards with rate, distance and booking link.
3. **Registry** – categories (Home, Experiences, Honeymoon fund) with store links.
### Design system
- Tokens: `--background: #bacfc4` (sage), `--foreground: #262626`, `--primary: #ebebeb`, `--primary-foreground: #262626`, `--secondary: #555555`, `--border: #adadad` (decorative), `--input-border: #707070`, `--input: #fafafa`, `--radius: 0.75rem`, `--polaroid: #fafafa`.
- Fonts: Libre Bodoni (400, 500 italic) and Rosario. Scale: 12 (labels, uppercase +0.25em) / 14 / 16 / 20 / 32 / 56 / clamp(56px, 8vw, 96px).
- Spacing: 8px base; sections separated by 160–200px; text column 760px.
- Shadows: polaroids `0 18px 40px rgb(0 0 0 / .15)`.
- Motion: reveal 800ms ease-out with 20px rise; polaroids straighten to 0° on hover in 300ms; smooth scroll for the RSVP link.
### Components & interactions
Ghost nav (focus-visible underline), polaroid (rotation prop, caption, hover), venue block, gallery grid (lightbox optional), hotel card, registry group, RSVP form: attending yes/no radio; if yes, guest count select reveals that many name fields plus dietary notes; if no, only a message field. States: pristine, invalid (inline messages), submitting, success (thank-you card replaces form), error with retry.
### Data & state
`Couple{names,date,city}`, `Venue{label,name,address,time}`, `Photo{src,alt,caption,rotation}`, `Hotel{name,address,rate,url}`, `RegistryItem{category,store,url}`, `Rsvp{name,email,attending,guests:[{name,dietary}],message}`. All content in a typed config; form state in react-hook-form. Use placeholder couple photos of models.
### Accessibility
White on sage `#bacfc4` would be only about 1.6:1, so all text, including headings, is charcoal `#262626` on sage (9.2:1); white is reserved for the polaroid frames. The secondary gray is darkened to `#555555` so captions pass on sage. Form fields are `#fafafa` with a `#707070` border (3:1+ on both the field and the sage page). Faded "reveal" text must end fully opaque. Form fields need visible borders (3:1) and labels. Conditional fields are announced (focus moves to the first new field). Reduced motion removes rotations and reveals.
Verified contrast: body and heading text on sage #262626 on #bacfc4 = 9.23:1; secondary caption text on sage #555555 on #bacfc4 = 4.55:1; charcoal label on off-white primary button #262626 on #ebebeb = 12.69:1; handwritten-style caption on polaroid frame #262626 on #fafafa = 14.5:1; input text in field #262626 on #fafafa = 14.5:1.
### Security
Proportionate: zod schema shared by client and function (conditional rules enforced server-side too), honeypot and rate limit, optional invite code, no secrets in the client, anon insert-only RLS if using Supabase, and `rel="noopener noreferrer"` on registry links. Don't expose the guest list publicly.
### Performance & SEO
Only a handful of images: serve them as responsive WebP, preload the hero polaroid, lazy-load the gallery. `noindex` by default; OG image and description for message previews. Lighthouse 95+.
### Guardrails
- Fictional couple, venues and placeholder photos; no real venue names or logos.
- No fabricated guest messages.
- Collect only what planning needs and allow the couple to purge responses.
- Small typed components, no `any`, visible errors.
- Done when: the long scroll renders all sections with reveals that end fully visible; the conditional RSVP works and validates on both sides; text contrast passes AA; the page is smooth on a mid-range phone.