Template
Cuetide
A pre-launch page that collects emails, shows how many people are already waiting, and counts down to launch. Signups are stored, rate-limited and confirmed by email so the list is clean on launch day.
Countdown waitlist page with email capture · App · SaaS landing page · full-stack app (auth + DB)
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
Saira's squared, slightly technical forms suit a countdown, giving the digits energy while its regular weight keeps the waitlist copy restrained.
- SairaHeadings: headline 40px 600 at -0.02em, countdown numbers 28px 600 tabular
- SairaBody: body 16px/1.5 400, unit labels 12px uppercase +0.08em, pill 12px uppercase +0.06em
Another design for the same product as Queueline, so the gallery lists it there. A pre-launch waitlist page: a countdown, a signup count and an email form.
Patterns
- centered single-column waitlist hero
- logo tile above status pill
- inline email field with attached button
- avatar stack social proof
- four-unit countdown
- product screenshot peeking below the fold
- vivid gradient backdrop frame
States it is designed for
- idle
- submitting
- success (check your inbox)
- already on the list (friendly message)
- invalid email
- rate limited (try again later)
- countdown reached zero (switch to 'we're live' CTA)
- confirmation link valid / expired
Who it is for
- founders pre-launch
- product marketers
- indie makers testing demand
Layout
- Optional outer gradient backdrop (green-magenta-orange mesh) framing a dark page on wide screens
- Logo tile (lime square with glyph) centered
- Status pill: dot + 'launching soon' style label
- Headline 40px, two-line muted subtext
- Email row: input + lime button attached; stacks under 480px
- Social proof: avatar stack + 'join N others' text
- Countdown: four numeric units (days, hours, minutes, seconds) with small labels
- Small caption above a framed product screenshot that bleeds off the bottom
- Footer: minimal links
Palette
Energetic but restrained. A dark page with one electric lime accent, framed by a vivid gradient mesh.
- page background
#0d0d0d - input / pill surface
#161616 - primary text
#fafafa - secondary text
#a1a1aa - primary button / logo tile
#d4f24a - label on lime
#0d0d0d - input border
#6b6b6b - backdrop mesh stop
#8be07a - backdrop mesh stop
#c64ad8 - backdrop mesh stop
#e0703a
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 18.62:1 | 4.5:1 |
| Aa | muted text | 7.58:1 | 4.5:1 |
| Aa | button label | 15.36:1 | 4.5:1 |
| Aa | text in input | 17.34:1 | 4.5:1 |
| input border | 3.65:1 | 3:1 | |
| focus ring | 15.36: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
- Saira 600, 40px/1.15, tracking -0.02em
- Body
- Saira 400, 16px/1.5
Countdown numbers 28px 600 tabular; unit labels 12px uppercase 0.08em tracking; pill 12px uppercase 0.06em.
Spacing and imagery
Centered 480px column in a 1100px frame; 16px gaps; input 44px tall; radius 8px on input and button, full on pill; screenshot frame radius 12px with 1px border.
Blurred multicolour mesh backdrop, circular avatar photos (invented people or illustrated), a product screenshot in a thin frame.
Components
- LogoTile
- StatusPill
- WaitlistForm
- AvatarStack
- Countdown
- ScreenshotFrame
- Toast
- ConfirmPage
Interactions
- Button shows spinner then success message inline; input stays filled on error
- Countdown ticks each second; announces only minute changes to assistive tech
- Mesh backdrop drifts slowly; static under reduced motion
- Enter submits; focus returns to input after error
Data
WaitlistEntry{id, email, status (pending|confirmed|unsubscribed), referrer, created_at, confirmed_at}LaunchConfig{launch_at, headline, subtext, show_count (bool)}
Guardrails
Experience
- One field, one button; ask for nothing else
- Show the waitlist count only once it is above a set threshold
- Success message says what happens next and when
- Countdown must use the launch time in UTC and show local time on hover
- Keep the screenshot below the form so the form is always above the fold
Accessibility
- Input has a visible label (can be visually hidden but present)
- Errors are announced via aria-live and linked with aria-describedby
- Countdown is a timer role with aria-live off; a separate polite region announces each minute
- Mesh backdrop is decorative
- Button label is near-black on lime for contrast
- Focus ring 2px lime with offset
Security
- Insert via an Edge Function only; RLS denies all client select/insert on waitlist_entries
- Rate-limit by IP and email; add a honeypot field
- Double opt-in: store pending, confirm with a signed expiring token
- Do not reveal whether an email already exists beyond a generic message
- Expose only an aggregate count through a view
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 an entry'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 entries) - 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. ### SaaS screen baseline - Design every screen for its full set of states: first-run empty, loading skeleton, partial data, error with retry, permission-denied, and success feedback. Each entry lists the states its screen needs. - Keep destructive actions (delete, revoke, downgrade, remove member) behind a confirmation that names the object, and prefer undo over a second dialog where the action is reversible. - Enforce authorisation on the server for every action a screen exposes. Hiding a button is not access control; check the role again in the API or RLS policy. - Never show secrets (API keys, tokens) in full after creation. Show them once, then mask them, and offer rotate and revoke. - Keep the app shell (navigation, workspace switcher, account menu) consistent across screens, and preserve filters, sort and scroll position when the user navigates back.
### Goal
Build **Cuetide**, a pre-launch waitlist page. It collects one email, shows how many people are already waiting, counts down to launch, and teases the product with a screenshot. Every signup is rate-limited and confirmed by email so the list is real on launch day.
### Stack
Next.js (App Router), React, TypeScript, Tailwind CSS, shadcn/ui, lucide-react, react-hook-form + zod. Supabase Postgres for entries and an Edge Function for inserts and confirmation; a transactional email service sends the confirmation email.
### Pages & layout
1. **/**: optional vivid mesh backdrop around a dark page on wide screens. Centered 480px column: lime logo tile, status pill ("Launching this spring" or similar, invented), 40px headline, two-line muted subtext, email input with an attached lime "Join" button, avatar stack with "Join 1,200+ others" (invented number), four-unit countdown, small caption, and a framed product screenshot that bleeds off the bottom.
2. **/confirm?token=**: confirmation result page (confirmed, expired, invalid).
3. **/unsubscribe?token=**: one-click unsubscribe.
Under 480px the input and button stack full width; countdown units shrink to 22px.
### Design system
- Colors: `--canvas: #0d0d0d` (page background), `--surface: #161616` (input / pill surface), `--fg: #fafafa` (primary text), `--muted: #a1a1aa` (secondary text), `--lime: #d4f24a` (primary button / logo tile), `--lime-fg: #0d0d0d` (label on lime), `--border: #6b6b6b` (input border), `--mesh-green: #8be07a` (backdrop mesh stop), `--mesh-magenta: #c64ad8` (backdrop mesh stop), `--mesh-orange: #e0703a` (backdrop mesh stop).
- Fonts: Saira 600 headline 40px/1.15 (-0.02em), 400 body 16px/1.5, countdown numbers 28px tabular, unit labels 12px uppercase with 0.08em tracking.
- Spacing: 4px base; 16px vertical rhythm in the column; 64px top padding.
- Radius: 8px input and button, 12px logo tile and screenshot frame, full pill.
- Shadows: screenshot frame `0 30px 60px rgb(0 0 0 / 0.5)`.
- Motion: mesh drifts over 20s; button spinner; reduced motion freezes both.
### Components & interactions
LogoTile, StatusPill, WaitlistForm (states: idle, submitting, success, already-joined, invalid, rate-limited), AvatarStack, Countdown (switches to a "We're live" CTA at zero), ScreenshotFrame, Toast, ConfirmPage.
### Data & state
`waitlist_entries(id, email unique, status, referrer, created_at, confirmed_at)` and `launch_config(launch_at, headline, subtext, show_count)`. A view `waitlist_count` returns only the confirmed count. The Edge Function validates, rate-limits, inserts `pending`, emails a signed link, and confirms on click. Form state is local.
### Accessibility
Labelled input; errors announced politely and tied with `aria-describedby`. Countdown uses `role="timer"` with its own live region off and a separate polite region that announces each minute. Backdrop is decorative. Focus ring 2px `#d4f24a` with 2px offset.
Verified contrast: body text: #fafafa on #0d0d0d = 18.62:1; muted text: #a1a1aa on #0d0d0d = 7.58:1; button label: #0d0d0d on #d4f24a = 15.36:1; text in input: #fafafa on #161616 = 17.34:1; input border: #6b6b6b on #0d0d0d = 3.65:1; focus ring: #d4f24a on #0d0d0d = 15.36:1.
### Security
- RLS denies all client access to `waitlist_entries`; only the Edge Function (service role) inserts and updates. `waitlist_count` view is public select.
- Rate-limit per IP and per email; honeypot field; zod email validation and normalization.
- Double opt-in with signed, expiring tokens; generic responses that do not reveal list membership.
- Store only email and referrer; unsubscribe removes the address.
### Performance & SEO
Static page with a small client island for the form and countdown. Mesh is CSS gradients, screenshot is an optimized image with width/height set. Title, description and OG image; confirm pages noindex.
### Guardrails
- Invent the product name, copy, avatars and counts.
- Never block the form on the count or countdown loading.
- Acceptance criteria: (1) valid email gets a confirmation email and success message; (2) repeat signups get the same generic message; (3) 10 rapid submits from one IP are throttled; (4) countdown flips to live at launch time; (5) all contrast pairs pass.