Template
Nuvello
Before running a potentially expensive news or web search job, the user confirms which mode to run. The dialog compares a fast, cheap mode with a slower, richer mode across speed, enrichments, monitors and credit cost, so the trade-off is explicit before credits are spent.
Mode comparison confirmation dialog before running a job · App screen: confirmation · Small tools and apps · front-end app (local state)
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 dialog title, -0.01em
- InterBody: Inter 400 16px / 1.5; table cells 15px (dense table)
Patterns
- confirmation modal with segmented mode switch
- side-by-side feature comparison table inside modal
- primary action label that names the chosen mode
- dimmed workspace with right configuration panel behind
- available / unavailable status text with icon
States it is designed for
- default with the mode preselected from the configuration panel
- insufficient credits: primary disabled, inline note with a Buy credits link
- mode unavailable on current plan: segment disabled with explanation
- estimating cost skeleton in the Credits row
- run started toast / run failed toast with retry
Who it is for
- analysts running data searches
- developers testing query configurations
- teams on credit-based plans
Layout
- Background: app with left nav (saved searches, sections, account), a query header and a right Configuration panel with a large Run button - all dimmed by a 70% dark scrim
- Dialog (~400px wide): title, one-line description, a two-option segmented control (selected option solid black), comparison table with Feature column and one column per mode, footer with Cancel (grey) and primary 'Run <mode> search' (black)
- Mobile: dialog fills width with 16px margins; the table keeps three columns but abbreviates the feature column; buttons stack full width
Palette
Stark, technical and decisive: black-and-white with a single blue accent for the fast mode.
- dialog
#ffffff - table header bg
#f7f7f8 - text
#111111 - muted text
#6b6f76 - selected segment
#111111 - on selected
#ffffff - mode accent
#2f5bea - available
#12883e - table border
#e2e3e6 - secondary button
#f0f0f1 - scrim
#333333 - focus ring
#2f5bea
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on dialog | 18.88:1 | 4.5:1 |
| Aa | muted feature names | 5.05:1 | 4.5:1 |
| Aa | selected segment label | 18.88:1 | 4.5:1 |
| Aa | mode accent header text | 5.15:1 | 4.5:1 |
| Aa | Available status text | 4.55:1 | 4.5:1 |
| Aa | Cancel label on grey | 16.58:1 | 4.5:1 |
| focus ring on white | 5.52:1 | 3:1 | |
| Aa | unselected segment label on grey | 4.71: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 dialog title, -0.01em
- Body
- Inter 400 16px / 1.5; table cells 15px (dense table)
Similar to the observed neo-grotesk. Credits column uses tabular numerals.
Spacing and imagery
Compact dialog; 24px padding, 16px gap between title block, segment, table and footer; table rows 44px; radius 4px on segments and buttons, 6px dialog; dialog shadow 0 20px 50px rgba(0,0,0,.35).
Small glyph icons per mode (a bolt and a flask-like icon) from lucide; green check before Available.
Components
- ConfirmModeDialog
- ModeSegmentedControl
- ModeComparisonTable
- AvailabilityCell (check icon + text / muted Unavailable)
- CreditCostCell
- DialogFooter with dynamic primary label
Interactions
- Switching the segment updates the primary button label ('Run fast search' / 'Run deep search') and highlights that mode's column
- Arrow keys move between segments; Enter on the primary runs the job
- Cancel returns to the configuration panel without changes
- Running closes the dialog and shows a progress toast with a Cancel run action
- A 'Don't ask again for this search' checkbox is optional and remembered per saved search
Data
SearchConfig{id, query, sources[], date_range, mode (fast|deep)}ModeSpec{mode, eta_label, enrichments (bool), monitors (bool), credit_cost, cost_unit (run|record)}Run{id, config_id, mode, status (queued|running|done|failed), credits_charged}Account{credits_remaining, plan}
Guardrails
Experience
- Compare modes on the same rows so the trade-off is scannable
- Name the chosen mode in the primary button
- Show credit cost in the unit it is charged (per run vs per record)
- Default to the cheaper mode unless the config requires enrichments
- Keep Cancel visually quieter but equally large
Accessibility
- Segmented control is a radiogroup (or tabs with aria-selected) with visible focus
- Comparison table is a real table with th scope='col' and scope='row'
- Availability uses icon plus text; Unavailable is not only grey
- The dialog title is the accessible name; description is aria-describedby
- Primary button label changes are announced by being part of the focused element
Security
- Recheck credits and plan entitlement server-side when a run is created (in the real app)
- Validate query text length and sources list
- Debounce run creation to prevent double submits
- Do not expose internal cost multipliers in client bundles
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 **Nuvello**, the confirm-mode dialog that appears when a user presses Run on a search configuration. Include a dimmed configuration screen behind it, realistic mock mode specs and credit balances, and all decision states.
### Stack
Use React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui, Radix, lucide-react, react-hook-form, zod. Keep everything in local state backed by a typed mock-data module and a fake async API (200-600 ms latency, a toggle to force errors) so every state can be demonstrated without a backend.
### Pages & layout
1. **Search builder**: left nav, query header, right configuration panel with a Run button (can be simplified).
2. **Confirm mode dialog** opened by Run.
Regions, in order:
- Background: app with left nav (saved searches, sections, account), a query header and a right Configuration panel with a large Run button - all dimmed by a 70% dark scrim
- Dialog (~400px wide): title, one-line description, a two-option segmented control (selected option solid black), comparison table with Feature column and one column per mode, footer with Cancel (grey) and primary 'Run <mode> search' (black)
- Mobile: dialog fills width with 16px margins; the table keeps three columns but abbreviates the feature column; buttons stack full width
### Design system
- Colors: `--dialog: #ffffff` (dialog), `--table-header-bg: #f7f7f8` (table header bg), `--text: #111111` (text), `--muted-text: #6b6f76` (muted text), `--selected-segment: #111111` (selected segment), `--on-selected: #ffffff` (on selected), `--mode-accent: #2f5bea` (mode accent), `--available: #12883e` (available), `--table-border: #e2e3e6` (table border), `--secondary-button: #f0f0f1` (secondary button), `--scrim: #333333` (scrim), `--focus-ring: #2f5bea` (focus ring).
- Fonts: Inter 600 - 20px dialog title, -0.01em for headings; Inter 400 16px / 1.5; table cells 15px (dense table) for body. Similar to the observed neo-grotesk. Credits column uses tabular numerals.
- Spacing, radius and shadows: Compact dialog; 24px padding, 16px gap between title block, segment, table and footer; table rows 44px; radius 4px on segments and buttons, 6px dialog; dialog shadow 0 20px 50px rgba(0,0,0,.35).
- Motion: 150-200 ms ease-out for hover, focus and overlay transitions; overlays fade and scale from 98% to 100%; everything collapses to an instant change under prefers-reduced-motion.
- Mood: Stark, technical and decisive: black-and-white with a single blue accent for the fast mode. Imagery: Small glyph icons per mode (a bolt and a flask-like icon) from lucide; green check before Available.
### Components & interactions
Build these components: ConfirmModeDialog; ModeSegmentedControl; ModeComparisonTable; AvailabilityCell (check icon + text / muted Unavailable); CreditCostCell; DialogFooter with dynamic primary label.
- Switching the segment updates the primary button label ('Run fast search' / 'Run deep search') and highlights that mode's column
- Arrow keys move between segments; Enter on the primary runs the job
- Cancel returns to the configuration panel without changes
- Running closes the dialog and shows a progress toast with a Cancel run action
- A 'Don't ask again for this search' checkbox is optional and remembered per saved search
### Data & state
Model: `SearchConfig{id, query, sources[], date_range, mode (fast|deep)}`; `ModeSpec{mode, eta_label, enrichments (bool), monitors (bool), credit_cost, cost_unit (run|record)}`; `Run{id, config_id, mode, status (queued|running|done|failed), credits_charged}`; `Account{credits_remaining, plan}`.
Mode specs come from a typed constant; the account balance comes from the fake API. Derive whether each mode is affordable from `credits_remaining` and an estimated record count.
States to implement and demo:
- default with the mode preselected from the configuration panel
- insufficient credits: primary disabled, inline note with a Buy credits link
- mode unavailable on current plan: segment disabled with explanation
- estimating cost skeleton in the Credits row
- run started toast / run failed toast with retry
### Accessibility
- Segmented control is a radiogroup (or tabs with aria-selected) with visible focus
- Comparison table is a real table with th scope='col' and scope='row'
- Availability uses icon plus text; Unavailable is not only grey
- The dialog title is the accessible name; description is aria-describedby
- Primary button label changes are announced by being part of the focused element
- Body text is 16px with line-height 1.5 (15px only inside dense tables), nothing renders below 12px, weights of 300 or lighter appear only at 24px and above, and uppercase is limited to short labels with at least 0.05em tracking.
Verified contrast: body text on dialog: #111111 on #ffffff = 18.88:1; muted feature names: #6b6f76 on #ffffff = 5.05:1; selected segment label: #ffffff on #111111 = 18.88:1; mode accent header text: #2f5bea on #f7f7f8 = 5.15:1; Available status text: #12883e on #ffffff = 4.55:1; Cancel label on grey: #111111 on #f0f0f1 = 16.58:1; focus ring on white: #2f5bea on #ffffff = 5.52:1; unselected segment label on grey: #6b6f76 on #f7f7f8 = 4.71:1.
### Security
- Recheck credits and plan entitlement server-side when a run is created (in the real app)
- Validate query text length and sources list
- Debounce run creation to prevent double submits
- Do not expose internal cost multipliers in client bundles
### Performance & SEO
Dialog and table are tiny; keep them in the main chunk. Avoid layout shift when the cost estimate loads by reserving row height.
### Guardrails
- Compare modes on the same rows so the trade-off is scannable
- Name the chosen mode in the primary button
- Show credit cost in the unit it is charged (per run vs per record)
- Default to the cheaper mode unless the config requires enrichments
- Keep Cancel visually quieter but equally large
- Use the product name Nuvello and fresh, generic copy throughout; all people, companies, amounts and IDs are invented, and no third-party brand, logo or wordmark appears.
- Keep components small and typed (no `any`), and surface every failure visibly instead of swallowing it.
Acceptance criteria:
- [ ] Switching modes updates table highlight and button label
- [ ] Insufficient credits disables run with explanation
- [ ] Keyboard users can choose a mode and run
- [ ] Works at 390px width
- [ ] Contrast pairs pass