Skip to main content
vibld

Template

Rowport

The processing step of a customer-data CSV import in a messaging automation tool. After upload, field mapping and review, the user waits on a centred 'Uploading…' state with a clear way to cancel.

CSV import uploading step with stepper · App screen: loading · 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 page title and 18px status
  • InterBody: Inter 400, 16px, line-height 1.5

Patterns

  • dark top bar with trial countdown and upgrade
  • icon rail plus labelled sidebar
  • breadcrumb with file name
  • three-step stepper with checks
  • centred uploading message with spinner
  • danger outlined cancel
  • version footer

States it is designed for

  • uploading
  • processing rows with count
  • done summary
  • failed with downloadable error report
  • cancelled
  • partially imported
  • file too large / wrong type (earlier step)
  • trial limit reached mid-import

Who it is for

  • lifecycle marketers importing contact lists
  • growth ops teams

Layout

  1. top bar (dark green): workspace switcher, test-mode badge, trial days left, Upgrade button, help, notifications, settings, profile
  2. icon rail (~30px) plus sidebar (~130px) with product sections and a Data & integrations group expanded
  3. breadcrumb: Imports / file name / Uploading
  4. title 'Import CSV' with Cancel import (danger outline) right
  5. stepper: Upload, Map fields, Review -- all checked
  6. centre: heading 'Uploading…', spinner, one-line message
  7. footer: version string left, credit line right
  8. below 900px sidebar collapses; stepper labels shorten

Palette

Dependable and operational; a long job is shown calmly with an exit.

  • bg#ffffff
  • topbar#0d2a1f
  • upgrade#dcf7c5
  • upgrade-text#0d2a1f
  • text#1c1f24
  • muted#5f6570
  • step-done#2f8a4f
  • danger#d32f2f
  • sidebar#f6f7f8
  • active#e9ecef

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text16.52:14.5:1
Aamuted message5.86:14.5:1
Aatop bar text15.35:14.5:1
AaUpgrade label13.27:14.5:1
Aacancel text and border4.98:14.5:1
stepper check4.31:13:1
Aaactive nav text13.94: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.

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

Type scale

Display
Inter 600, 20px page title and 18px status
Body
Inter 400, 16px, line-height 1.5

Sidebar 15px; breadcrumb 14px muted; version footer 13px.

Spacing and imagery

Density: Medium. Grid: 8px; page padding 16px. Container: fluid main. Radius: 6px buttons, 8px active nav. Shadows: none; top bar provides contrast.

Line icons; a small animated brand-neutral spinner.

Components

  • TopBar with TrialCountdown and UpgradeButton
  • IconRail
  • Sidebar with collapsible groups
  • Breadcrumbs
  • ImportStepper
  • UploadProgress (heading, spinner, message, optional %)
  • CancelImportButton with confirm
  • VersionFooter

Interactions

  • Cancel import asks for confirmation and aborts the job
  • Progress polls every 2s; when rows processed are known show 'n of m rows'
  • On completion show a summary (created, updated, skipped with reasons) and 'View people'
  • Leaving the page keeps the job running with a banner elsewhere

Data

  • ImportJob{id, workspace_id, file_name, status (uploading|processing|done|failed|cancelled), rows_total, rows_done, created, updated, skipped, error_report_url}
  • FieldMapping{import_id, column, attribute, type (text|number|date|bool)}
  • Person{id, workspace_id, email, attributes jsonb}

Guardrails

Experience

  • Keep Cancel import visible throughout
  • Show row counts once known instead of an indeterminate spinner
  • Summarise results with reasons for skipped rows
  • Let users navigate away safely
  • Keep the stepper visible so users know where they are

Accessibility

  • Status heading and count in a live region
  • Stepper is an ordered list with aria-current on the current step
  • Spinner has role=progressbar (indeterminate) and a label
  • Cancel confirm is a labelled alertdialog
  • Completed step labels still meet 4.5:1

Security

  • Accept only .csv under 50MB; sniff content type server-side
  • Store uploads in a private bucket with signed URLs
  • Validate each row with zod on the server; neutralise formula-injection prefixes in exports
  • RLS: import_jobs and people scoped to workspace members
  • Audit who imported what

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 **Rowport**, the processing step of a CSV contact import. After mapping and review, the user sees 'Uploading…' with a spinner and count, a stepper showing all prior steps done, and a clear Cancel import. Build the app shell, the full three-step import with this step emphasised, and the summary.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui on Radix primitives and lucide-react icons. TanStack Query for server state, react-hook-form + zod for every form, date-fns for relative times. Supabase for Auth, Postgres with row-level security and Edge Functions for anything that needs a secret. Parse CSV headers in the browser with a lightweight CSV parser for mapping, then upload the file to Supabase Storage; an Edge Function or worker processes rows in chunks.

### Pages & layout
1. **Shell**: dark top bar (workspace switcher, test-mode badge, 'n days left in trial', Upgrade, help, bell, settings, profile); icon rail; sidebar with groups and Data & integrations expanded.
2. **Import flow**: breadcrumb, title, Cancel import; stepper (Upload CSV, Map fields, Review).
3. **Uploading state**: centred heading, spinner, message ('We're processing your file. This shouldn't take long.'), optional row count.
4. **Summary**: created/updated/skipped counts and error report link.

### Design system
- Colors: `--bg: #ffffff` (page), `--topbar: #0d2a1f` (top bar), `--upgrade: #dcf7c5` (Upgrade button), `--upgrade-text: #0d2a1f` (Upgrade label), `--text: #1c1f24` (primary text), `--muted: #5f6570` (messages), `--step-done: #2f8a4f` (stepper checks), `--danger: #d32f2f` (Cancel import), `--sidebar: #f6f7f8` (sidebar), `--active: #e9ecef` (active nav item).
- Fonts: Inter 600, 20px page title and 18px status for headings; Inter 400, 16px, line-height 1.5 for body. Sidebar 15px; breadcrumb 14px muted; version footer 13px.
- Spacing: Medium. 8px; page padding 16px. Container: fluid main.
- Radius: 6px buttons, 8px active nav.
- Shadows: none; top bar provides contrast.
- Motion: Spinner rotates 1s linear (reduced motion: pulsing dot); step checks draw in on completion; success transitions to the result summary.

### Components & interactions
ImportStepper shows circled checks and muted labels for completed steps. UploadProgress switches from indeterminate spinner to determinate bar once rows_total is known.

- Cancel import asks for confirmation and aborts the job
- Progress polls every 2s; when rows processed are known show 'n of m rows'
- On completion show a summary (created, updated, skipped with reasons) and 'View people'
- Leaving the page keeps the job running with a banner elsewhere

### Data & state
Mock a 4,800-row file processing in chunks of 400 every second, with 12 skipped rows. TanStack Query polls the job.

Entities: `ImportJob{id, workspace_id, file_name, status (uploading|processing|done|failed|cancelled), rows_total, rows_done, created, updated, skipped, error_report_url}`; `FieldMapping{import_id, column, attribute, type (text|number|date|bool)}`; `Person{id, workspace_id, email, attributes jsonb}`.

States to build and show in a dev-only state switcher:
- uploading
- processing rows with count
- done summary
- failed with downloadable error report
- cancelled
- partially imported
- file too large / wrong type (earlier step)
- trial limit reached mid-import

### Accessibility
- Status heading and count in a live region
- Stepper is an ordered list with aria-current on the current step
- Spinner has role=progressbar (indeterminate) and a label
- Cancel confirm is a labelled alertdialog
- Completed step labels still meet 4.5:1
Verified contrast: body text: #1c1f24 on #ffffff = 16.52:1; muted message: #5f6570 on #ffffff = 5.86:1; top bar text: #ffffff on #0d2a1f = 15.35:1; Upgrade label: #0d2a1f on #dcf7c5 = 13.27:1; cancel text and border: #d32f2f on #ffffff = 4.98:1; stepper check: #2f8a4f on #ffffff = 4.31:1; active nav text: #1c1f24 on #e9ecef = 13.94:1.

### Security
- Accept only .csv under 50MB; sniff content type server-side
- Store uploads in a private bucket with signed URLs
- Validate each row with zod on the server; neutralise formula-injection prefixes in exports
- RLS: import_jobs and people scoped to workspace members
- Audit who imported what
RLS detail: `import_jobs` select/insert for workspace members with editor role, update by service role; `people` select for members, write for editors and the service role; storage bucket policies limit paths to the workspace id.

### Performance & SEO
Parse only the first 50 rows client-side for preview; stream the upload; stop polling on terminal states.

### Guardrails
- Keep Cancel import visible throughout
- Show row counts once known instead of an indeterminate spinner
- Summarise results with reasons for skipped rows
- Let users navigate away safely
- Keep the stepper visible so users know where they are
- Write fresh, generic copy and invented sample data; no real brands, logos, product names or people.
- Keep components small and typed (no `any`); surface every error visibly with a way to recover.

Acceptance criteria:
- Cancel aborts and shows cancelled state
- Counts progress and summary is correct
- Invalid files are rejected earlier with reasons
- Private storage with signed URLs
- Stepper and status are screen-reader friendly

Open the builderAll templatesThis palette on its own