Template
Mellowslot
The public page a visitor sees when booking a meeting with someone. It shows the host and meeting details on the left, a month with bookable days in the centre and available start times for the selected day on the right. The visitor picks a time and continues to a short details form.
Public three-column booking widget (event, month, slots) · App screen: calendar · Small tools and apps · full-stack app (auth + DB)
A mock-up of the screen, drawn from its layout, palette and typefaces. A build follows the full prompt below.
Start from this screenRead the build prompt
Typefaces
The catalog's own faces. A screen composed into a template is drawn in that template's typefaces.
- InterHeadings: Inter 600, 20px for event title; 16px 600 month title
- InterBody: Inter 400, 16px/1.5; weekday header 12px 600 uppercase +0.06em; dates 14px 500 tabular; slots 15px 500
Patterns
- three-column booking card (details / month / slots)
- available-day tiles vs plain unavailable days
- selected day in solid dark tile with dot
- 12h / 24h segmented toggle
- stacked outline time-slot buttons
- timezone select
- overlay-my-calendar switch
- layout switcher (month / week / column)
States it is designed for
- loading month availability
- no availability this month (message + next available date jump)
- selected day with slots
- slot taken while choosing (error, list refresh)
- timezone changed
- details form validation
- booking confirmed (summary + add to calendar)
- booking failed with retry
- host paused bookings
Who it is for
- prospects and clients booking a call
- candidates booking interviews
- hosts sharing a booking link
Layout
- Page top-right toolbar: 'Overlay my calendar' switch, settings icon button, 3-way layout switcher
- Booking card (~640px, white on light grey): column 1 host avatar/mark, host name (muted), event title, duration, location/tool, timezone select
- Column 2: month title with year muted, prev/next, weekday header, date grid where available days are filled tiles and unavailable days are plain muted numbers, selected day solid dark with a small dot
- Column 3: selected date label, 12h/24h toggle, vertical list of outline slot buttons
- Footer: small product mark centred below card
- Below 900px columns stack: details, month, slots; slot list becomes a 2-column grid
Palette
Neutral, efficient, trustworthy. Greys everywhere so the host's own branding (optional accent) can sit on top.
- canvas
#f3f4f6 - surface
#ffffff - text
#111827 - muted
#5e636e - border
#d2d4d8 - available
#e5e7eb - selected
#1f1f1f - on-selected
#ffffff - slot-border
#8a8f99 - focus
#2563eb - unavailable
#6b7079
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | event title on white | 17.74:1 | 4.5:1 |
| Aa | muted host name on white | 6.02:1 | 4.5:1 |
| Aa | available date on tile | 14.33:1 | 4.5:1 |
| Aa | unavailable date on white | 4.98:1 | 4.5:1 |
| Aa | selected date on dark tile | 16.48:1 | 4.5:1 |
| slot border on white | 3.25:1 | 3:1 | |
| focus ring on canvas | 4.70:1 | 3:1 | |
| Aa | toolbar label on canvas | 16.12:1 | 4.5: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
- Inter 600, 20px for event title; 16px 600 month title
- Body
- Inter 400, 16px/1.5; weekday header 12px 600 uppercase +0.06em; dates 14px 500 tabular; slots 15px 500
Similar to the observed neo-grotesk.
Spacing and imagery
Compact-comfortable; 4px base; card padding 20px; date tiles 40px square with 4px gap; slots 36px tall full-width; radius 8px card, 6px tiles and slots; card has a 1px border and no shadow; column dividers 1px.
Only the host's small avatar or mark; icons for duration, video and globe.
Components
- host header
- event meta list (duration, location, timezone)
- timezone select
- month navigator
- date tile
- 12h/24h toggle
- time slot button
- overlay calendar switch
- layout switcher
- booking details form
- confirmation screen
Interactions
- Selecting a day loads its slots with a skeleton
- Selecting a slot expands it into 'Confirm' + time split or moves to the details form
- Timezone change re-renders all slots
- Overlay switch prompts sign-in and then greys out times that clash with the visitor's calendar
- Arrow keys move across dates; Enter selects
- Layout switcher changes to week or column view and remembers the choice
Data
Host{id, name, slug, timezone}EventType{id, host_id, title, duration_min, location (video|phone|in_person), buffer_min, min_notice_min}Availability{host_id, weekday, start_time, end_time}Booking{id, event_type_id, start_at, end_at, attendee_name, attendee_email, status (confirmed|cancelled), created_at}
Guardrails
Experience
- Show only bookable days as filled tiles; unavailable days stay readable but plain
- Default the timezone to the visitor's device and show it clearly
- Jump to the next available day if the current month is full
- Keep slot times large and easy to tap (>=44px on touch)
- Re-check availability at confirm time and explain clashes
- Never reveal the host's other meetings
Accessibility
- Date grid uses grid semantics with aria-disabled for unavailable days and full date names
- Selected day conveyed by aria-selected plus the dot, not colour alone
- Slots are buttons with full date/time accessible names
- Timezone select has a visible label
- 12h/24h toggle is a radio group
- Focus ring 2px blue offset 2px on tiles and slots
Security
- Public availability computed server-side; clients never receive other bookings' details
- Booking creation via RPC with a transactional clash check and unique constraint on host + start
- Validate attendee email and rate-limit bookings per IP
- Overlay feature reads visitor calendars only client-side after explicit consent; tokens never stored on the host side
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 **Mellowslot**, the public booking page of a scheduling tool. A visitor sees the host and meeting details, picks an available day on a month grid, chooses a start time from a slot list and completes a short form to confirm. ### Stack React 18 + TypeScript + Vite (or Next.js for SSR of public pages), Tailwind CSS, shadcn/ui (Switch, ToggleGroup, Select, Button, Form), lucide-react, date-fns with time-zone support, react-hook-form + zod, TanStack Query. Supabase Postgres with RPCs for availability and booking; a transactional email service sends confirmations. ### Pages & layout 1. **/:host/:event** (this screen): grey canvas; top-right toolbar (Overlay my calendar switch, settings, layout switcher). White card: column 1 host mark, 'Dana Whitfield' (muted), '30 minute intro', 30 min, Video call, timezone select 'Europe/Lisbon'; column 2 month 'October 2026' with available days as tiles and the selected day dark with a dot; column 3 'Mon 12', 12h/24h, slots 15:00, 15:30, 16:00, 16:30. 2. **Details step**: name, email, notes, guests; back link. 3. **Confirmed**: summary, add-to-calendar links, reschedule/cancel link. 4. Responsive: stacked columns under 900px; slots in 2 columns. ### Design system - Colors: `--canvas: #f3f4f6`, `--surface: #ffffff`, `--text: #111827`, `--muted: #5e636e`, `--border: #d2d4d8`, `--available: #e5e7eb`, `--selected: #1f1f1f`, `--on-selected: #ffffff`, `--slot-border: #8a8f99`, `--focus: #2563eb`, `--unavailable: #6b7079`. - Fonts: Inter (similar to observed). Event title 20px/600; body 16px/1.5; dates 14px/500 tabular; weekday header 12px uppercase +0.06em. - Spacing: 4px base; card padding 20px; tile gap 4px. - Radius: card 8px; tiles and slots 6px. - Shadows: none; 1px borders. - Motion: 120ms tile hover; slot list fade 150ms; reduced motion respected. - Optional host accent colour replaces `--selected` if it passes 4.5:1 with white. ### Components & interactions `BookingToolbar`, `HostPanel` (EventMeta, TimezoneSelect), `MonthGrid` (DateTile states: available, unavailable, selected, today), `SlotPanel` (FormatToggle, SlotButton list), `BookingForm`, `ConfirmationCard`. Available tiles darken on hover; selected slot splits into time + 'Next'. ### Data & state Tables per data model. RPC `available_days(event_type_id, month, tz)` and `available_slots(event_type_id, date, tz)` compute from availability minus bookings, buffers and notice. `create_booking` locks and inserts. Mock host with weekday availability 09:00-17:00 and a few existing bookings. ### Accessibility Grid pattern with arrow navigation; unavailable days are focusable but aria-disabled with explanation. Slot buttons read 'Monday 12 October, 15:00 to 15:30'. Form errors linked; confirmation announced via role=status. Verified contrast: event title on white: #111827 on #ffffff = 17.74:1; muted host name on white: #5e636e on #ffffff = 6.02:1; available date on tile: #111827 on #e5e7eb = 14.33:1; unavailable date on white: #6b7079 on #ffffff = 4.98:1; selected date on dark tile: #ffffff on #1f1f1f = 16.48:1; slot border on white: #8a8f99 on #ffffff = 3.25:1; focus ring on canvas: #2563eb on #f3f4f6 = 4.7:1; toolbar label on canvas: #111827 on #f3f4f6 = 16.12:1. ### Security Public RPCs return only times, never attendee data. `bookings` table has RLS: hosts read their own; inserts only through `create_booking` (security definer) with a unique (host_id, start_at) constraint. Rate-limit per IP; validate email; honeypot field. No calendar tokens stored for visitors. ### Performance & SEO Server-render the shell and month; fetch slots on select. Cache availability for 60s. Public pages get title/description with host and event name, OG image generic. ### Guardrails - Invented hosts and events - Never expose other attendees - Always show timezone - Typed code, errors surfaced - Acceptance criteria: (1) only available days are selectable; (2) timezone change updates slots; (3) double booking is prevented server-side; (4) confirmation email is queued; (5) stacked layout works at 390px.