Template
Jo Turns 40
a site for a fortieth birthday party that sets the tone, takes RSVPs with plus-ones, collects song requests for the playlist, and offers a gift fund to a cause instead of presents.
Fortieth birthday party site with song requests · Website · Events and bookings · 1 pages
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.
Start from this templateRead the build prompt
Typefaces
Rammetto One is chunky and cheerful at huge sizes; Pathway Extreme stays readable on a dark background.
- Rammetto OneHeadings: the big "40", headlines and labels
- Pathway ExtremeBody: details, forms and the song list
Who it is for
- Friends from every part of Jo’s life
- Partners and plus-ones who need the details too
- The friend throwing the party
Layout
- Tiny top bar with a mirror-ball mark and Count me in
- Hero: a huge "40" in Rammetto One with duotone photos of Jo through the decades behind it
- Details cards: where, when, dress code, getting home safely
- RSVP form with plus-one
- Song requests form and the list of requests so far, as the host adds them
- Forty things about Jo: a numbered list in two columns
- Gift fund: give to Jo’s chosen cause instead of a present, and a footer
Palette
A dance floor at midnight: black, a hot red-orange and a mint flash, big confident type, a little disco.
- after dark
#101010 - flash white
#f5f5f0 - hot coral
#ff5a36 - mint flash
#3de0b0
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on the page | 17.40:1 | 4.5:1 |
| Aa | text on cards | 15.44:1 | 4.5:1 |
| Aa | secondary text on muted surfaces | 8.35:1 | 4.5:1 |
| Aa | secondary text on the page | 9.99:1 | 4.5:1 |
| Aa | label on the primary action | 6.13:1 | 4.5:1 |
| Aa | label on secondary surfaces | 15.44:1 | 4.5:1 |
| Aa | label on the accent | 11.32:1 | 4.5:1 |
| Aa | error label | 5.46:1 | 4.5:1 |
| primary action against the page | 6.13:1 | 3: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
- Rammetto One, the big "40", headlines and labels
- Body
- Pathway Extreme, details, forms and the song list
Spacing and imagery
Dense and loud: 64px between sections, type that fills the width.
Photos of Jo through the decades in high-contrast duotone, and a mirror-ball shape drawn in CSS.
Components
- Mirror ball drawn in CSS with a conic gradient and tiles
- Duotone photo strip of Jo by decade (the 90s, 2000s, 2010s, 2020s)
- Numbered list with oversized coral numerals
Interactions
- Add to calendar for the party
- The details card shows the night’s countdown in days
Data
songs: a requested song the host added: title, artist, requested by (first name)form rsvp: name, email, coming (yes or no), plus-one name, dietary needsform song-request: your first name, song title, artist, why
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
Each niche site prompt describes a whole small site for one kind of owner: its pages, the records it keeps, the forms it collects and the tools it links to. The rules below apply to every one of them.
### Niche site principles
- The site does the one job its owner needs most (a sign-up, an RSVP, a request, a visit) on the first screen, and every page leads back to it.
- Records the owner adds often (sermons, events, listings, galleries, menus, tour dates) are content collections in `src/content/`, each record with a slug, so a new record gets its page with no code change.
- Tools the owner already pays for or uses (giving, tickets, booking, listing search, ordering) are linked, or framed in an `<iframe>` whose address is in `content.ts`, never rebuilt. With no address, a plain button links out instead, and nothing pretends to work.
- Copy is written for the owner's visitors, specific and plain. Dates, times and places are real fields, never baked into prose.
- The design is this site's own. Its layout, type and motion follow the brief, not a shared template.
### Forms
Every form is a plain HTML form, `<form method="post" action="/__vibld/forms/<name>">`, named as the brief names it (lowercase letters, digits and hyphens). Fields are ordinary named inputs; checkboxes repeat their name; no file uploads. Add a hidden `_next` input with the path to land on, and show a thank-you there when the address has `?submitted=<name>`. Add an empty hidden `_gotcha` input. A script may post it instead with `fetch(form.action, { method: 'POST', body: new FormData(form), headers: { accept: 'application/json' } })`, which answers `{ ok: true }` or `{ ok: false, error }`. A form with limited places lists them in `public/vibld.forms.json` (`{"forms":{"<name>":{"slots":{"field":"<field>","options":{"<value>":<places>}}}}}`), the field a select or radio whose values match those keys exactly; `GET /__vibld/forms/<name>/slots` returns `{ field, options: [{ value, capacity, taken, left }] }`, which the page reads to show what is left and disable full options. vibld adds bot protection when the page is served.
### Engineering baseline
- TypeScript strict mode, small typed components, and one source of truth for design tokens (CSS variables consumed by Tailwind).
- All copy lives in typed content files, so the owner can edit words without touching layout.
- Every form validates on the client, says what went wrong in plain words beside the field, and never claims success it has not had.
- No secrets in the bundle and no third-party scripts beyond Google Fonts; an owner's tool comes in only as a link or a framed page.### Goal
Build **Jo Turns 40**: a site for a fortieth birthday party that sets the tone, takes RSVPs with plus-ones, collects song requests for the playlist, and offers a gift fund to a cause instead of presents.
### Stack
React + TypeScript + Vite, Tailwind CSS and React Router, one route per page. Content collections in `src/content/`, forms posting to vibld (see Forms in the baseline). No backend of its own.
### Pages & layout
- `/` Party: hero, the details, RSVP, song requests, forty things about Jo, gift fund
Home, top to bottom:
1. Tiny top bar with a mirror-ball mark and Count me in.
2. Hero: a huge "40" in Rammetto One with duotone photos of Jo through the decades behind it.
3. Details cards: where, when, dress code, getting home safely.
4. RSVP form with plus-one.
5. Song requests form and the list of requests so far, as the host adds them.
6. Forty things about Jo: a numbered list in two columns.
7. Gift fund: give to Jo’s chosen cause instead of a present, and a footer.
Copy to start from, in `content.ts`: headline "Forty looks good on Jo", subcopy "Friday, June 4, from 8 PM at the Lantern Room. Dress to dance. We will be up late.", primary action "Count me in".
### Design system
Mood: A dance floor at midnight: black, a hot red-orange and a mint flash, big confident type, a little disco.
Palette: after dark `#101010`, flash white `#f5f5f0`, hot coral `#ff5a36`, mint flash `#3de0b0`. Tokens: background `#101010`, foreground `#f5f5f0`, primary `#ff5a36` with `#101010` labels, cards `#1d1d1b`, accent `#3de0b0`.
Type: Rammetto One for the big "40", headlines and labels; Pathway Extreme for details, forms and the song list. Load both from https://fonts.googleapis.com/css2?family=Rammetto+One&family=Pathway+Extreme:wght@400;600&display=swap.
Corners: 999px on controls, 20px on cards, 28px on large panels. Spacing: Dense and loud: 64px between sections, type that fills the width.
Imagery: Photos of Jo through the decades in high-contrast duotone, and a mirror-ball shape drawn in CSS. Use the owner's photos where the project has them. Without them, use the project's stock photos, or shapes and color from the palette; never a stock photo of people at desks.
### Components & interactions
- Mirror ball drawn in CSS with a conic gradient and tiles
- Duotone photo strip of Jo by decade (the 90s, 2000s, 2010s, 2020s)
- Numbered list with oversized coral numerals
Motion:
- Add to calendar for the party
- The details card shows the night’s countdown in days
The signature motion is: light flecks from the mirror ball drift slowly across the hero, as if a real ball were turning above the page. Keep it to that one; everything else is a 150 to 300ms state change. With prefers-reduced-motion, it and every reveal are still.
### Data & state
Collections:
- `src/content/songs.json`: a requested song the host added: title, artist, requested by (first name)
Forms:
- `rsvp`: A guest replies. Fields: name, email, coming (yes or no), plus-one name, dietary needs.
- `song-request`: A guest asks for a song. Fields: your first name, song title, artist, why.
Linked tools:
- Gift fund: Jo’s chosen charity’s donation page, and the host’s payment app for a group gift.
- Venue map link and a ride-share note.
Gift funds: Gift funds are buttons to the owner's payment apps, from `content.ts`: Venmo (`https://venmo.com/u/<handle>`), PayPal (`https://paypal.me/<handle>`) and Zelle, which has no web link, so it shows the email or phone the owner gives with a copy button. Each fund has a name, a line on what it is for and an optional goal shown as words, not a progress bar the page cannot keep true. Leave out any app the owner has not filled in. The site never takes a card number itself.
### Accessibility
WCAG 2.2 AA. Every control has a visible focus ring and a 44px target, every form field a visible label, and errors are announced. Dates and times are written out ("Sunday, March 8, 10:30 AM"), not only shown in a grid. Images have alt text that says what is in them. Verified contrast: body text on the page #f5f5f0 on #101010 17.39:1; text on cards #f5f5f0 on #1d1d1b 15.43:1; secondary text on muted surfaces #bcbcb8 on #222222 8.35:1; secondary text on the page #bcbcb8 on #101010 9.98:1; label on the primary action #101010 on #ff5a36 6.13:1; label on secondary surfaces #f5f5f0 on #1d1d1b 15.43:1; label on the accent #101010 on #3de0b0 11.31:1; error label #ffffff on #c62f2f 5.45:1; primary action against the page #ff5a36 on #101010 6.13:1.
### Security
No third-party scripts other than Google Fonts. Framed tools are `<iframe>`s from the owner's own address with a `title`, `loading="lazy"` and `referrerpolicy="strict-origin-when-cross-origin"`. Forms cap input length and carry the empty `_gotcha` field.
### Performance & SEO
Images as AVIF or WebP with width and height, the first one eager and the rest lazy. Preconnect to Google Fonts. Each page has its own title and description from content, and records' pages take theirs from the record. Structured data where it fits: Event.
### Guardrails
- Avoid: "Over the hill" jokes, gravestone or walker clip art, balloons as icons, and a photo of Jo they did not choose.
- One primary action per screen, one accent color, at most six top-level links.
- No carousel in the hero, no mega menu, no emoji or clip-art icons, no hard offset shadows, no purple-to-blue gradient.
- The names in it are invented. Use no real organization's or person's name, logo or trademark.