Skip to main content
vibld

Template

Pressvane

The Company watchlists page of a news and business-events data API, before any list exists. Watchlists are uploaded lists of companies that can be searched across at once. The page gives a search/filter frame and a single creation path so analysts can go from empty to monitoring quickly.

Company watchlists empty state in a news-events API console · App screen: empty state · 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, 24px/1.3, -0.02em
  • InterBody: Inter 400 16px/1.5

Patterns

  • collapsible grouped sidebar with project picker
  • tinted active nav item
  • page title with help tooltip
  • search bar with filters button
  • card empty state with icon, text and CTA
  • referral credits card in sidebar footer
  • floating chat launcher
  • CSV upload to create list

States it is designed for

  • empty (no watchlists)
  • search with no results (distinct from empty)
  • uploading with progress
  • CSV errors (missing column, too many rows, bad encoding) listed per row
  • created (toast + row highlighted)
  • loading skeleton rows
  • permission-denied for viewers (Create hidden)

Who it is for

  • market intelligence analysts
  • sales researchers
  • developers building news monitoring

Layout

  1. sidebar (~240px) with collapse chevron: wordmark; 'Events API' group with a project picker and items (New search, Past searches, Monitoring, Company watchlist active); 'News API' group (Overview, Playground); 'Manage' group with an inbox icon badge (API keys, Usage, Billing); footer referral card with gift icon
  2. main header: 24px title with help icon; black 'Create watchlist' button right
  3. full-width search input with Filters button
  4. white card: bank-building icon in indigo, bold 'No watchlists yet', helper, black CTA
  5. populated: table of watchlists (name, companies, last hit, created, actions)
  6. chat launcher bottom-right
  7. mobile: sidebar drawer; header button becomes icon+label under title

Palette

Crisp and data-serious with a cool blue-grey canvas and black actions.

  • app background#f3f6f9
  • card / sidebar surface#ffffff
  • primary text#111827
  • helper text#58627a
  • active nav fill#e7ecfb
  • active nav text / icon#3346c9
  • primary button#0b0b0f
  • group label#5f6675
  • input border#8a93a3
  • notification badge#4b5563

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text16.36:14.5:1
Aahelper text on card6.10:14.5:1
Aaactive nav text6.22:14.5:1
Aaprimary button label19.64:14.5:1
Aagroup label5.76:14.5:1
input border3.10:13:1
badge on sidebar7.56: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
Inter 600, 24px/1.3, -0.02em
Body
Inter 400 16px/1.5

Sidebar 14px 500; group labels 12px uppercase 600 with 0.06em tracking; helper text 16px in the card.

Spacing and imagery

Compact console: sidebar rows 32px, 8px radius; main padding 24px; search 40px tall; empty card 48px vertical padding, 8px radius, 1px #e5e8ee border.

Line icons only, one accent-coloured icon (a classical building) in the empty card; no illustrations or photos.

Components

  • Sidebar with CollapsibleGroup
  • ProjectPicker
  • ReferralCard
  • PageHeader with HelpTooltip
  • SearchInput + FiltersButton
  • EmptyCard
  • CreateWatchlistDialog (name + CSV upload + column mapping)
  • WatchlistsTable
  • ChatLauncher

Interactions

  • Create opens a dialog: name, drop or pick a CSV, preview first 5 rows, map the company-name and domain columns
  • search filters lists as you type (debounced 200ms)
  • Filters opens a popover (created by, size, last activity)
  • sidebar groups collapse and remember state
  • help icon shows a tooltip explaining watchlists

Data

  • Watchlist{id, project_id, name, company_count, created_by, created_at, last_match_at}
  • WatchlistCompany{id, watchlist_id, name, domain, country}
  • Project{id, org_id, name}
  • Upload{id, watchlist_id, file_path, rows_ok, rows_failed, status}

Guardrails

Experience

  • Differentiate 'nothing created yet' from 'no search results' with different copy and actions.
  • Explain the benefit in the helper ('search across all of them at once').
  • Offer a sample CSV download inside the create dialog.
  • Keep the two create buttons consistent in label and style.
  • Show row-level CSV errors and allow importing the valid rows anyway.

Accessibility

  • Search input has a visible label or aria-label and announces result counts.
  • Collapsible groups use buttons with aria-expanded.
  • Upload drop zone is also a keyboard-accessible file button.
  • Active nav uses aria-current plus colour and weight.
  • The chat launcher has an accessible name and does not cover focused content.

Security

  • Accept only .csv under 2 MB; parse server-side with row limits; neutralise formula-injection prefixes (=,+,-,@) on export.
  • Store uploads in a private bucket with signed URLs.
  • RLS: watchlists scoped to project members; viewers read-only.
  • Rate-limit uploads per project.

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 **Pressvane**, the Company watchlists section of a news-events API console. Users upload a CSV of companies to create a watchlist and then search news across the whole list. Focus on the empty state, the create-from-CSV dialog and the first populated table.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Dialog, Popover, Collapsible, Table), lucide-react, TanStack Query and Table, react-hook-form + zod, date-fns, a lightweight CSV parser. Supabase Auth, Postgres, private Storage bucket and an Edge Function to parse uploads.

### Pages & layout
1. **Console shell**: grouped collapsible sidebar, referral card.
2. **/watchlists**: header, search + filters, empty card or table.
3. **Create watchlist dialog**: name, upload, preview, column mapping, import.
4. **/watchlists/:id**: company list with remove and add.

### Design system
- Colors: `--bg: #f3f6f9` (app background), `--surface: #ffffff` (card / sidebar surface), `--fg: #111827` (primary text), `--muted: #58627a` (helper text), `--nav-active: #e7ecfb` (active nav fill), `--nav-text: #3346c9` (active nav text / icon), `--primary: #0b0b0f` (primary button), `--label: #5f6675` (group label), `--input-border: #8a93a3` (input border), `--badge: #4b5563` (notification badge).
- Fonts: Inter 600, 24px/1.3, -0.02em for headings; Inter 400 16px/1.5 for body. Sidebar 14px 500; group labels 12px uppercase 600 with 0.06em tracking; helper text 16px in the card.
- Spacing: Compact console: sidebar rows 32px, 8px radius; main padding 24px; search 40px tall; empty card 48px vertical padding, 8px radius, 1px #e5e8ee border.
- Radius: 8px buttons, inputs, cards and nav pills.
- Shadows: none except dialogs and the chat launcher.
- Motion: 150ms fills; new-row highlight fades over 1.5s.

### Components & interactions
Sidebar, CollapsibleGroup, ProjectPicker, ReferralCard, PageHeader, HelpTooltip, SearchInput, FiltersPopover, EmptyCard, CreateWatchlistDialog, CsvPreviewTable, WatchlistsTable, ChatLauncher.

Interactions: Create opens a dialog: name, drop or pick a CSV, preview first 5 rows, map the company-name and domain columns; search filters lists as you type (debounced 200ms); Filters opens a popover (created by, size, last activity); sidebar groups collapse and remember state; help icon shows a tooltip explaining watchlists.

States to build: empty (no watchlists); search with no results (distinct from empty); uploading with progress; CSV errors (missing column, too many rows, bad encoding) listed per row; created (toast + row highlighted); loading skeleton rows; permission-denied for viewers (Create hidden).

### Data & state
Upload → Edge Function parses, validates and inserts companies, updating `company_count`. Search is client-side on name for up to 200 lists, server-side beyond. Seed one project with no watchlists and a sample CSV of 25 invented companies.

Model: `Watchlist{id, project_id, name, company_count, created_by, created_at, last_match_at}`; `WatchlistCompany{id, watchlist_id, name, domain, country}`; `Project{id, org_id, name}`; `Upload{id, watchlist_id, file_path, rows_ok, rows_failed, status}`.

### Accessibility
Search input has a visible label or aria-label and announces result counts. Collapsible groups use buttons with aria-expanded. Upload drop zone is also a keyboard-accessible file button. Active nav uses aria-current plus colour and weight. The chat launcher has an accessible name and does not cover focused content.
Verified contrast: body text: #111827 on #f3f6f9 = 16.36:1; helper text on card: #58627a on #ffffff = 6.1:1; active nav text: #3346c9 on #e7ecfb = 6.22:1; primary button label: #ffffff on #0b0b0f = 19.64:1; group label: #5f6675 on #ffffff = 5.76:1; input border: #8a93a3 on #ffffff = 3.1:1; badge on sidebar: #4b5563 on #ffffff = 7.56:1.

### Security
Accept only .csv under 2 MB; parse server-side with row limits; neutralise formula-injection prefixes (=,+,-,@) on export. Store uploads in a private bucket with signed URLs. RLS: watchlists scoped to project members; viewers read-only. Rate-limit uploads per project. RLS per table: `watchlists` select for project members, insert/update/delete for editors; `watchlist_companies` follows parent watchlist; `uploads` select for the uploader and editors, insert via Edge Function; `projects` select for org members.

### Performance & SEO
Parse CSVs off the main thread (worker) for preview. Virtualise company tables over 500 rows. Console routes noindex.

### Guardrails
- Differentiate 'nothing created yet' from 'no search results' with different copy and actions.
- Explain the benefit in the helper ('search across all of them at once').
- Offer a sample CSV download inside the create dialog.
- Keep the two create buttons consistent in label and style.
- Show row-level CSV errors and allow importing the valid rows anyway.
- Write all copy fresh; use invented people, companies and numbers only. No real brands, logos, wordmarks or third-party product names anywhere in the UI or seed data.
- Do not trace or copy any existing product's layout assets, icons or illustrations; draw generic ones.
- Acceptance criteria:
  - [ ] Empty state and no-results state are distinct
  - [ ] A valid CSV creates a watchlist with the right count
  - [ ] Invalid rows are reported with row numbers
  - [ ] Viewers cannot create
  - [ ] Every control is reachable by keyboard

Open the builderAll templatesThis palette on its own