Skip to main content
vibld

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

  1. Page top-right toolbar: 'Overlay my calendar' switch, settings icon button, 3-way layout switcher
  2. Booking card (~640px, white on light grey): column 1 host avatar/mark, host name (muted), event title, duration, location/tool, timezone select
  3. 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
  4. Column 3: selected date label, 12h/24h toggle, vertical list of outline slot buttons
  5. Footer: small product mark centred below card
  6. 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

SampleWhereRatioNeeds
Aaevent title on white17.74:14.5:1
Aamuted host name on white6.02:14.5:1
Aaavailable date on tile14.33:14.5:1
Aaunavailable date on white4.98:14.5:1
Aaselected date on dark tile16.48:14.5:1
slot border on white3.25:13:1
focus ring on canvas4.70:13:1
Aatoolbar label on canvas16.12:14.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.

Open the builderAll templatesThis palette on its own