Skip to main content
vibld

Template

Mizzen

An onboarding question for an AI assistant workspace that asks which work tools the new member already uses. Picks are used to recommend connections later; nothing is connected yet. The page is deliberately sparse: one question, one explanatory line and nine tiles.

Tool-picker onboarding step with logo tile grid · App screen: account setup · 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.

  • GeistHeadings: Geist 600, 24px, tracking -0.01em for the question
  • GeistBody: Geist 400, 16px/1.5; tile names 15px 500; top bar label 15px 500

Patterns

  • minimal onboarding top bar with repeated primary action
  • 3x3 selectable logo tile grid
  • multi-select tiles with focus glow
  • right-aligned next button
  • generous whitespace single-question screen

States it is designed for

  • no selection (button reads Skip)
  • some selected
  • tool list loading (9 grey skeleton tiles)
  • tool list failed (fallback static list)
  • saving answers
  • save failed toast with retry
  • returning user sees previous picks pre-selected

Who it is for

  • knowledge workers joining a team workspace
  • operations and support staff
  • team admins

Layout

  1. Top bar: 'Joining <workspace>' label left, compact dark Next button right, 1px bottom hairline
  2. Main: content column ~520px wide, vertically centred; heading, one-line description
  3. Tile grid: 3 columns x 3 rows of equal tiles (icon + name), 8px gap
  4. Footer of column: dark Next button right-aligned
  5. Below 640px: grid becomes 2 columns, then 1 column under 360px; top-bar Next hidden in favour of a sticky bottom button

Palette

Quiet, uncluttered, respectful of time. One question per screen, lots of white.

  • surface#ffffff
  • text#111827
  • muted#4b5563
  • tile-border#e5e7eb
  • tile-hover#f9fafb
  • selected-border#2b89c9
  • selected-bg#f0f8fe
  • primary#1f2937
  • on-primary#ffffff
  • focus#2b89c9

Every checked pair, measured again

SampleWhereRatioNeeds
Aaheading text on white17.74:14.5:1
Aamuted description on white7.56:14.5:1
Aabutton label on dark14.68:14.5:1
selected tile border on white3.80:13:1
Aatile name on selected tint16.53:14.5:1
focus ring on white3.80:13: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
Geist 600, 24px, tracking -0.01em for the question
Body
Geist 400, 16px/1.5; tile names 15px 500; top bar label 15px 500

Similar to the observed geometric grotesk; if Geist is unavailable use Inter.

Spacing and imagery

Sparse; 8px base; tiles 48px tall with 12px padding; column max 540px; radius 8px tiles and 10px buttons; no shadows except a 3px soft glow ring on the selected tile.

Small full-colour app glyphs at 20px inside tiles, generic placeholders in the build (no real logos).

Components

  • onboarding top bar
  • question heading
  • selectable tool tile
  • tile glow selected state
  • next button
  • skip link

Interactions

  • Tiles toggle on click, Space or Enter
  • Selected tiles get a blue border, tint and glow in 150ms
  • Arrow keys move focus within the grid (roving tabindex)
  • Next is always enabled; with zero picks it reads 'Skip'
  • Next advances with a 200ms cross-fade to the next question

Data

  • Tool{id, name, icon_key, category}
  • OnboardingAnswer{user_id, question_key, tool_ids[], answered_at}

Guardrails

Experience

  • One question per screen with a single primary action
  • Make selection state obvious with border, tint and a check, not colour alone
  • Allow skipping without penalty
  • Explain in one line why the question is asked
  • Do not start any OAuth connection from this step
  • Persist picks so Back does not lose them

Accessibility

  • Grid is a group of toggle buttons with aria-pressed
  • Selected tiles show a check icon in addition to the border colour
  • Roving tabindex with arrow-key navigation; Tab leaves the grid
  • Duplicate Next buttons share one accessible name and the top one is hidden on mobile
  • Focus ring 2px blue with 2px offset
  • Logos are decorative (alt empty) because the name is shown

Security

  • RLS: users can only read and write their own onboarding answers
  • Validate tool ids against the known list server-side
  • No third-party tokens are requested or stored on this step

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 **Mizzen**, an onboarding question in a team AI-assistant workspace: 'Which tools does your team use?'. The user taps any of nine tool tiles and continues. Picks feed later recommendations; this screen connects nothing.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Button, Toggle), lucide-react, Motion for the step transition. TanStack Query and Supabase for loading the tool list and saving answers.

### Pages & layout
1. **/join/tools** (this screen): 56px top bar with 'Joining Northwind Studio' (invented) and a compact Next. Centred column: heading 'Which tools does your team rely on?', description 'We'll suggest the right connections later. Pick as many as you like.', 3x3 grid of tiles (Team chat, Wiki, Knowledge base, Code host, CRM, Issue tracker, Shared inbox, Email, Mail and calendar) each with a generic coloured glyph, then Next aligned right.
2. Neighbouring questions (role, team size) as stubs to show the flow.
3. Mobile: 2-column grid, sticky bottom Next with safe-area padding.

### Design system
- Colors: `--surface: #ffffff`, `--text: #111827`, `--muted: #4b5563`, `--tile-border: #e5e7eb`, `--tile-hover: #f9fafb`, `--selected-border: #2b89c9`, `--selected-bg: #f0f8fe`, `--primary: #1f2937`, `--on-primary: #ffffff`, `--focus: #2b89c9`.
- Fonts: Geist (or Inter), heading 24px/600 -0.01em, body 16px/1.5, tile label 15px/500.
- Spacing: 8px base; heading to description 16px; description to grid 24px; grid to button 24px.
- Radius: tiles 8px, buttons 10px.
- Shadows: none, except selected glow `0 0 0 3px rgba(43,137,201,.25)`.
- Motion: 150ms tile state change; 200ms step cross-fade; reduced motion swaps to instant.

### Components & interactions
`OnboardingTopBar`, `QuestionHeader`, `ToolTile` (icon, name, check badge when pressed), `ToolGrid` (roving focus), `NextButton` (label switches Skip/Next). Hover lightens tile background; pressed adds tint, blue border, glow and check.

### Data & state
`tools(id, name, icon_key, category)` seeded with nine generic tools; `onboarding_answers(user_id, question_key, tool_ids uuid[], answered_at)` with primary key (user_id, question_key). Local selection in React state, saved on Next with upsert. Preselect from existing answers.

### Accessibility
Each tile is a `button` with `aria-pressed`. The grid has `role="group"` labelled by the heading. Check badge is shown on selected tiles so state is not colour-only. Arrow keys move within the grid. The page title updates per question.
Verified contrast: heading text on white: #111827 on #ffffff = 17.74:1; muted description on white: #4b5563 on #ffffff = 7.56:1; button label on dark: #ffffff on #1f2937 = 14.68:1; selected tile border on white: #2b89c9 on #ffffff = 3.8:1; tile name on selected tint: #111827 on #f0f8fe = 16.53:1; focus ring on white: #2b89c9 on #ffffff = 3.8:1.

### Security
RLS on `onboarding_answers`: `user_id = auth.uid()` for all operations. Server validates that every tool id exists. This step never requests third-party authorisation or stores external credentials.

### Performance & SEO
Tool list is small and cached for the session; icons are inline SVG components. Onboarding pages noindex.

### Guardrails
- Use generic tool names and invented icons; no real product logos
- Do not trigger any connection flow here
- Keep the page to one question
- Typed code, visible errors
- Acceptance criteria: (1) tiles toggle by mouse and keyboard with visible state; (2) Skip works with zero picks; (3) answers persist on Back and reload; (4) RLS isolates users; (5) grid reflows at 390px.

Open the builderAll templatesThis palette on its own