Template
Wickerfund
A billing page for a pay-as-you-go developer API where customers prepay a balance and spend it across several metered services. It shows the remaining balance at all times, lists past top-ups and invoices, and breaks down cumulative monthly spend per service so a team can decide when to top up.
Prepaid balance billing screen with top-up history · App screen: upgrade · 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 500, 24px page title, 20px card titles, -0.01em tracking
- InterBody: Inter 400 16px / 1.5; table cells 15px; helper text 14px
Patterns
- top bar with workspace and product switchers
- balance readout beside primary top-up button
- underlined tab row under the top bar
- stacked section cards on a tinted canvas
- dashed-border empty state inside a card
- monthly usage ledger table with monospace figures
- command-palette search trigger with keyboard hint
States it is designed for
- Loading: skeleton rows in both tables and a shimmer bar where the balance sits
- Empty top-up history: dashed box with inbox icon and 'contact support' link
- Zero usage month: row still shows with 0 values, never hidden
- Balance zero or negative: balance turns to a warning style with text 'Top up to keep requests flowing'
- Checkout cancelled: neutral toast, balance unchanged
- Checkout success: success toast and new history row
- Error loading usage: inline error in the card with Retry
- Long service lists: table scrolls horizontally with sticky Date column
Who it is for
- developers on prepaid API plans
- finance or ops leads reconciling invoices
- startup founders watching burn
Layout
- Top bar (56px): square logo mark, workspace switcher, product/service switcher; right side: two-line balance readout (label over monospace amount), dark 'Top up' button, round avatar
- Tab row: Overview / Billing / Configure with a 2px underline on the active tab; search trigger with a keyboard-shortcut chip at far right
- Main canvas: pale grey, centred column max 600px wide on desktop with page title
- Card 1: top-up history (title, helper line, table or dashed empty state with support link)
- Card 2: usage history table (Date, Total cost, one column per metered service) with pagination footer
- Below 768px: switchers collapse into one menu, balance moves under the page title, tables scroll horizontally inside the card with a sticky first column
Palette
Quiet, precise, ledger-like. The page should feel like a bank statement rendered by a developer tool: calm neutrals, one dark action, money always visible.
- canvas
#f9f9fb - surface
#ffffff - text
#18181b - muted
#63636b - border
#e4e4e9 - input-border
#8a8a93 - primary
#18181b - on-primary
#ffffff - link
#2f5bd3 - focus
#3b63d9 - success
#1f7a4d
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 17.72:1 | 4.5:1 |
| Aa | muted helper on canvas | 5.66:1 | 4.5:1 |
| Aa | primary button label | 17.72:1 | 4.5:1 |
| Aa | support link | 5.90:1 | 4.5:1 |
| input border | 3.42:1 | 3:1 | |
| focus ring on canvas | 5.03:1 | 3:1 | |
| Aa | success badge text | 5.32: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 500, 24px page title, 20px card titles, -0.01em tracking
- Body
- Inter 400 16px / 1.5; table cells 15px; helper text 14px
Currency and counts in JetBrains Mono 400 14-15px with tabular numerals; similar to the observed neo-grotesk UI face. No uppercase labels except the shortcut chip (12px, 0.05em tracking).
Spacing and imagery
Comfortable density; 4px base, card padding 24px, 16px gap between cards; main column 600px desktop; radius 12px cards, 8px buttons, 10px inner empty-state box; shadows none, cards use a 1px #e4e4e9 border.
No photography. Line icons (inbox tray for empty state, plus for top-up, magnifier for search) at 1.5px stroke; no charts on this page.
Components
- WorkspaceSwitcher and ServiceSwitcher dropdowns
- BalanceReadout (label + monospace amount)
- TopUpButton opening a top-up dialog with preset amounts
- Underlined Tabs
- SearchTrigger with shortcut chip opening a command palette
- SectionCard
- TopUpHistoryTable with invoice download links
- EmptyState with icon, heading, body and support link
- UsageHistoryTable with per-service columns and cost tooltips
- Pagination (Previous / Next)
- Avatar menu
Interactions
- Top-up dialog: preset amount chips (e.g. 20 / 50 / 100 / custom), then hands off to a hosted checkout provider; balance animates to new value on return
- Cost cells have a dotted underline; hover or focus shows a tooltip with the per-unit breakdown
- Command palette opens with Cmd/Ctrl+K, arrow keys move, Enter navigates
- Tabs are links with aria-current; underline slides 150ms between tabs
- Invoice rows expose a download icon button; row hover tints #f9f9fb
Data
Workspace{id, name, currency (EUR|USD|GBP)}Balance{workspace_id, amount_cents, updated_at}TopUp{id, workspace_id, amount_cents, status (pending|paid|failed|refunded), invoice_url, created_at}UsageMonth{workspace_id, month, service (verify|messages|lookup), units, cost_cents}Member{workspace_id, user_id, role (owner|billing|developer)}
Guardrails
Experience
- Keep the balance visible in the top bar on every tab, not only on Billing
- Show zero-usage months as rows with 0 so the ledger has no gaps
- Let the empty state point to support, since older invoices may not be listed
- Put per-unit pricing in cost tooltips instead of adding columns
- Top-up opens preset amounts first; a custom amount is one extra field, not a separate page
- Never auto-charge from this page; every top-up is an explicit action
Accessibility
- Balance readout is a labelled group so screen readers announce 'Balance, 0.00 euros'
- Tables use th scope='col', a caption, and right-aligned numeric cells
- Tooltips on cost cells open on focus as well as hover and are dismissible with Escape
- Shortcut chip is aria-hidden; the search trigger has an accessible name
- Focus ring 2px #3b63d9 with 2px offset on all interactive elements
- Tab row uses nav with aria-current='page' rather than ARIA tabs, because each tab is a route
Security
- RLS: balances, top_ups and usage_months readable only by members of the workspace; only owner or billing roles can create top-ups
- Balance is credited only by a server-side webhook from the checkout provider after signature verification, never by the client
- Invoice URLs are short-lived signed links generated on demand
- Validate top-up amounts server-side (min, max, integer cents) with zod
- Write an audit log row for every top-up, refund and role change
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 **Wickerfund**, the Billing tab of a prepaid, pay-as-you-go API console. Customers load a balance, spend it across three metered services (verifications, transactional messages, lookups) and use this page to see their balance, their past top-ups and invoices, and a month-by-month ledger of what each service cost. ### Stack React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) with lucide-react icons. TanStack Query for server state, react-hook-form + zod for the top-up form, date-fns for month labels. Supabase Auth and Postgres for workspaces, balances, top-ups and usage; a Supabase Edge Function receives webhooks from a hosted checkout provider. ### Pages & layout 1. **App shell**: 56px top bar with logo mark, workspace switcher, service switcher, balance readout (label 'Balance' above a monospace amount), dark 'Top up' button and avatar menu. Under it a tab row (Overview, Billing, Configure) with a search trigger showing a Cmd K chip on the right. 2. **Billing page**: page title, then two stacked cards in a 600px column on a #f9f9fb canvas. - *Top-up history*: title, one-line description, table (Date, Amount, Status, Invoice) or a dashed-border empty state with an inbox icon, 'No top-ups yet', and a short note with a support link. - *Usage history*: title, 'Cumulative usage per month', table with Date, Total cost and one column per service; Previous / Next pagination. 3. **Top-up dialog**: preset amount chips, optional custom amount, summary line, 'Continue to checkout'. 4. Mobile: switchers collapse into one sheet, tables scroll sideways with sticky first column. ### Design system - Colors: `--canvas: #f9f9fb`, `--surface: #ffffff`, `--text: #18181b`, `--muted: #63636b`, `--border: #e4e4e9`, `--input-border: #8a8a93`, `--primary: #18181b`, `--on-primary: #ffffff`, `--link: #2f5bd3`, `--focus: #3b63d9`, `--success: #1f7a4d`. - Fonts: Inter (400/500) for UI at 16px/1.5, card titles 20px, page title 24px; JetBrains Mono 14-15px with tabular numerals for money and counts. - Spacing: 4px scale (4, 8, 12, 16, 24, 32); card padding 24px; 16px between cards. - Radius: 12px cards, 8px buttons and inputs, 999px amount chips. - Shadows: none; 1px `--border` outlines. Empty-state box uses a 1px dashed border. - Motion: 150ms ease-out on tab underline and hover; balance number counts up over 400ms after a successful top-up (disabled with reduced motion). ### Components & interactions WorkspaceSwitcher, ServiceSwitcher, BalanceReadout, TopUpButton + TopUpDialog (preset chips as a radio group, custom amount field with inline zod errors, disabled submit while creating the checkout session), Tabs-as-links, CommandPalette (Cmd/Ctrl+K), SectionCard, TopUpHistoryTable (status badge, invoice download icon button), EmptyState, UsageHistoryTable (cost cells with dotted underline and a tooltip showing units x unit price), Pagination, Toasts for success, cancel and error. ### Data & state Tables: `workspaces`, `members(workspace_id, user_id, role)`, `balances(workspace_id, amount_cents)`, `top_ups(id, workspace_id, amount_cents, status, invoice_path, created_at)`, `usage_months(workspace_id, month, service, units, cost_cents)`. Balance and lists come from TanStack Query with 30s stale time; after returning from checkout, poll the balance until the webhook lands (max 20s) then show the toast. Seed mock data: one workspace in EUR, two paid top-ups, four months of usage including an all-zero month. Selected page of the usage table lives in the URL. ### Accessibility Label the balance region, give each table a caption, right-align numbers, and make cost tooltips reachable by keyboard. Amount chips are a radiogroup with arrow-key navigation. Status badges carry text, not colour alone. Respect prefers-reduced-motion for the count-up. Verified contrast: body text: #18181b on #ffffff = 17.72:1; muted helper on canvas: #63636b on #f9f9fb = 5.66:1; primary button label: #ffffff on #18181b = 17.72:1; support link: #2f5bd3 on #ffffff = 5.9:1; input border: #8a8a93 on #ffffff = 3.42:1; focus ring on canvas: #3b63d9 on #f9f9fb = 5.03:1; success badge text: #1f7a4d on #ffffff = 5.32:1. ### Security Enable RLS on every table: members can select rows where `workspace_id` is in their memberships; only `owner` or `billing` roles may insert into `top_ups` (as `pending`); no client role may update `balances` - only the webhook Edge Function (service role) credits it after verifying the provider signature and idempotency key. Invoice downloads use signed URLs valid for 60s. Rate-limit checkout-session creation per user. Keep the service key server-side only. ### Performance & SEO Code-split the top-up dialog and command palette. Paginate usage server-side (12 months per page). Mark all console routes noindex. Keep the shell under 150KB gzipped JS. ### Guardrails - All copy, service names and figures are invented; no real brands. - Never show a balance the server has not confirmed. - Keep money in integer cents end to end; format only at render time. - Acceptance criteria: (1) balance shows on every tab; (2) empty, loading, error and populated states render for both cards; (3) a test webhook credits the balance and adds a history row; (4) a developer-role member cannot start a top-up; (5) tables and tooltips work by keyboard alone.