Skip to main content
vibld

Template

Nolliver

Inside a generated CRM app, a deal detail page shows amount, probability, close date and last contact, flags staleness, and lists the next step, company, contact and notes. An AI panel drafts a follow-up email to the contact.

CRM deal detail page with metric cards and AI follow-up draft · App screen: details · 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 700 26px deal title; metric values 22px 700
  • InterBody: Inter 400 16px / 1.5

Patterns

  • breadcrumb + large title with logo tile
  • stage dot with meta line
  • metric cards row with progress bar
  • highlighted stale card with amber border
  • next step callout
  • two-column company/contact cards
  • notes block
  • AI draft email panel with generate button

States it is designed for

  • loading skeleton
  • deal not found
  • stale vs fresh
  • missing contact (card empty state with Add contact)
  • generating draft (streaming) / generation failed
  • edit saving / validation errors
  • deleted

Who it is for

  • account executives
  • small-business owners managing deals

Layout

  1. Builder shell (sidebar, top bar with Edit / Publish) and app tabs (Deals active)
  2. Breadcrumb Deals > deal name
  3. Header: square logo tile, deal title, stage dot + stage + company + contact; Edit and Delete buttons right
  4. Metric cards (4): amount, probability with bar, close date, last contact (amber border + 'Stale' label when > 7 days)
  5. Next step row with clock icon and date
  6. Two cards: Company (logo, name, industry, domain) and Contact (photo, name, title, email, phone)
  7. Notes card
  8. Draft follow-up email card with sparkle icon and Generate button; generated draft appears in an editable textarea with Copy and Open in mail
  9. Mobile: metrics 2x2, company/contact stack

Palette

Clear, businesslike and helpful; one amber flag draws the eye to what needs action.

  • page#f5f5f4
  • surface#ffffff
  • text#1c1917
  • muted text#6b6560
  • progress#cc8308
  • stale border#d97706
  • stale text#92400e
  • danger#dc2626
  • publish cyan#5ce1e6
  • on publish#0f172a
  • focus ring#2563eb

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text on white17.49:14.5:1
Aamuted labels on white5.74:14.5:1
Aastale label text on white7.09:14.5:1
stale card border on white3.19:13:1
probability bar on track3.08:13:1
AaDelete text on white4.83:14.5:1
AaPublish label on cyan11.36:14.5:1
focus ring on page4.74: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.

  • background
  • card
  • muted
  • primary
  • secondary
  • accent
  • destructive

Type scale

Display
Inter 700 26px deal title; metric values 22px 700
Body
Inter 400 16px / 1.5

Section labels uppercase 12px 600 with 0.06em tracking; figures tabular.

Spacing and imagery

Comfortable; 16px gaps, 20px card padding; radius 12px cards, 8px buttons; 1px borders, no shadows; stale card gets a 1.5px amber border.

Company logo tile and contact headshot (use generated or placeholder avatars); sparkle icon for AI.

Components

  • Breadcrumb
  • DealHeader with StageDot
  • MetricCard
  • ProbabilityBar
  • StaleCard
  • NextStepRow
  • CompanyCard
  • ContactCard
  • NotesCard
  • AIDraftEmailCard

Interactions

  • Edit opens a side sheet with the deal form (react-hook-form + zod)
  • Delete opens a confirm dialog and returns to Deals
  • Generate calls the assistant endpoint and streams text into the draft area; Regenerate and Copy appear after
  • Clicking email/phone uses mailto/tel
  • Logging contact from the stale card updates last contact and clears the flag

Data

  • Deal{id, name, company_id, contact_id, stage, amount, probability, close_date, last_contact_at, next_step{text, due}, notes}
  • Company{id, name, industry, domain, logo_url}
  • Contact{id, company_id, name, title, email, phone, avatar_url}
  • DraftEmail{id, deal_id, body, created_at}

Guardrails

Experience

  • Put the four numbers that drive the deal in one row
  • Flag staleness where the date is, with a one-click fix
  • Keep company and contact side by side
  • Make AI drafting optional and editable
  • Keep destructive Delete visually secondary

Accessibility

  • Probability bar is a progressbar with aria-valuenow
  • Stale status is text plus colour
  • Contact links have descriptive names ('Email the contact')
  • Streaming draft announces completion, not each token
  • Delete uses alertdialog

Security

  • RLS scopes deals, companies, contacts and drafts to the workspace
  • Send only necessary deal fields to the AI function; strip notes marked private
  • Rate-limit generation per user
  • Escape generated text; never render it as HTML
  • Confirm deletion and audit it

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 **Nolliver**, a CRM deal detail page with metric cards, stale flag, company and contact cards, notes and an AI follow-up email draft. Seed fictional deals, companies and contacts.

### Stack
Use React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui, Radix, lucide-react, TanStack Query, react-hook-form, zod, Supabase, date-fns. The AI draft uses an Edge Function that calls a hosted language-model API with deal context; stream the response. Use Supabase for Auth, Postgres (row-level security on every table) and Storage where noted; keep only the anon key in the browser and run privileged work in Edge Functions.

### Pages & layout
1. **/deals/:id**: this page.
2. **/deals**: list for breadcrumb and after delete.
3. Edit as a side sheet on the detail route.

Regions, in order:
- Builder shell (sidebar, top bar with Edit / Publish) and app tabs (Deals active)
- Breadcrumb Deals > deal name
- Header: square logo tile, deal title, stage dot + stage + company + contact; Edit and Delete buttons right
- Metric cards (4): amount, probability with bar, close date, last contact (amber border + 'Stale' label when > 7 days)
- Next step row with clock icon and date
- Two cards: Company (logo, name, industry, domain) and Contact (photo, name, title, email, phone)
- Notes card
- Draft follow-up email card with sparkle icon and Generate button; generated draft appears in an editable textarea with Copy and Open in mail
- Mobile: metrics 2x2, company/contact stack

### Design system
- Colors: `--page: #f5f5f4` (page), `--surface: #ffffff` (surface), `--text: #1c1917` (text), `--muted-text: #6b6560` (muted text), `--progress: #cc8308` (progress), `--stale-border: #d97706` (stale border), `--stale-text: #92400e` (stale text), `--danger: #dc2626` (danger), `--publish-cyan: #5ce1e6` (publish cyan), `--on-publish: #0f172a` (on publish), `--focus-ring: #2563eb` (focus ring).
- Fonts: Inter 700 26px deal title; metric values 22px 700 for headings; Inter 400 16px / 1.5 for body. Section labels uppercase 12px 600 with 0.06em tracking; figures tabular.
- Spacing, radius and shadows: Comfortable; 16px gaps, 20px card padding; radius 12px cards, 8px buttons; 1px borders, no shadows; stale card gets a 1.5px amber border.
- 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: Clear, businesslike and helpful; one amber flag draws the eye to what needs action. Imagery: Company logo tile and contact headshot (use generated or placeholder avatars); sparkle icon for AI.

### Components & interactions
Build these components: Breadcrumb; DealHeader with StageDot; MetricCard; ProbabilityBar; StaleCard; NextStepRow; CompanyCard; ContactCard; NotesCard; AIDraftEmailCard.

- Edit opens a side sheet with the deal form (react-hook-form + zod)
- Delete opens a confirm dialog and returns to Deals
- Generate calls the assistant endpoint and streams text into the draft area; Regenerate and Copy appear after
- Clicking email/phone uses mailto/tel
- Logging contact from the stale card updates last contact and clears the flag

### Data & state
Model: `Deal{id, name, company_id, contact_id, stage, amount, probability, close_date, last_contact_at, next_step{text, due}, notes}`; `Company{id, name, industry, domain, logo_url}`; `Contact{id, company_id, name, title, email, phone, avatar_url}`; `DraftEmail{id, deal_id, body, created_at}`.

Staleness is derived (last_contact_at older than 7 days). Drafts are saved so they can be reopened. TanStack Query invalidates the deal after edits.

States to implement and demo:
- loading skeleton
- deal not found
- stale vs fresh
- missing contact (card empty state with Add contact)
- generating draft (streaming) / generation failed
- edit saving / validation errors
- deleted

### Accessibility
- Probability bar is a progressbar with aria-valuenow
- Stale status is text plus colour
- Contact links have descriptive names ('Email the contact')
- Streaming draft announces completion, not each token
- Delete uses alertdialog
- 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 white: #1c1917 on #ffffff = 17.49:1; muted labels on white: #6b6560 on #ffffff = 5.74:1; stale label text on white: #92400e on #ffffff = 7.09:1; stale card border on white: #d97706 on #ffffff = 3.19:1; probability bar on track: #cc8308 on #ffffff = 3.08:1; Delete text on white: #dc2626 on #ffffff = 4.83:1; Publish label on cyan: #0f172a on #5ce1e6 = 11.36:1; focus ring on page: #2563eb on #f5f5f4 = 4.74:1.

### Security
- RLS scopes deals, companies, contacts and drafts to the workspace
- Send only necessary deal fields to the AI function; strip notes marked private
- Rate-limit generation per user
- Escape generated text; never render it as HTML
- Confirm deletion and audit it

RLS: `deals`, `companies`, `contacts`, `draft_emails` - all operations where the user belongs to the row's `workspace_id`.

### Performance & SEO
Load the AI card lazily; stream responses. Images lazy with fixed size. Noindex.

### Guardrails
- Put the four numbers that drive the deal in one row
- Flag staleness where the date is, with a one-click fix
- Keep company and contact side by side
- Make AI drafting optional and editable
- Keep destructive Delete visually secondary
- Use the product name Nolliver 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:
- [ ] Metrics and stale flag reflect data
- [ ] Edit and delete work
- [ ] Draft generation streams and can be copied
- [ ] 390px layout works
- [ ] Contrast pairs pass

Open the builderAll templatesThis palette on its own