Template
Rivaro
A plans-and-billing page for a pay-as-you-go news data API. The top strip shows plan, billing period and spend; users can set spending alerts; and a comparison table lays out four tiers side by side with the current one highlighted.
Plans-and-billing page with comparison table · App screen: plans · 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, 26px page title; 22px plan prices
- InterBody: Inter 400, 16px; table cells 15px, line-height 1.5
Patterns
- plan status strip with three facts and Manage
- spending alerts card
- feature comparison table with sticky header
- highlighted current-plan column
- top-border accent on current plan
- solid Upgrade on next tier, outlined on others
- status badge
States it is designed for
- pay-as-you-go current
- subscribed tier current (its button reads Current plan, disabled)
- no alerts: helper line
- alert saved toast
- invalid threshold error
- payment past due banner
- loading skeleton strip and table
- non-owner read-only
Who it is for
- developers and data teams paying for API credits
- finance owners setting spend alerts
Layout
- sidebar (shared app shell) with Billing active
- title and subtitle
- status strip card: Plan status (name + Active badge), Billing period, Current spend, Manage button
- Spending alerts card with Add alert
- Compare plans heading and table: feature column + four plan columns; current plan tinted with blue top border
- feature rows grouped by section labels
- below 1024px the table scrolls horizontally with the feature column sticky; below 640px switch to plan cards with accordions
Palette
Transparent and businesslike; numbers first, persuasion second.
- bg
#f4f6fa - card
#ffffff - text
#141821 - muted
#5a6172 - current
#eef2fd - accent
#2f55d4 - button
#0e0e10 - secondary
#e9ecf1 - badge
#1e7e45 - badge-text
#ffffff
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 17.76:1 | 4.5:1 |
| Aa | muted labels | 6.20:1 | 4.5:1 |
| Aa | current plan text | 5.56:1 | 4.5:1 |
| Aa | Upgrade label | 19.28:1 | 4.5:1 |
| Aa | secondary button label | 15.00:1 | 4.5:1 |
| Aa | Active badge | 5.09:1 | 4.5:1 |
| current column top border | 6.23:1 | 3:1 | |
| focus ring | 5.76:1 | 3: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, 26px page title; 22px plan prices
- Body
- Inter 400, 16px; table cells 15px, line-height 1.5
Strip labels 12px uppercase 600 with 0.06em tracking; money uses tabular numerals.
Spacing and imagery
Density: Medium-dense. Grid: 8px; card padding 20px; table cell padding 12px. Container: fluid, max 1100px. Radius: 8px cards; table outer radius 8px; buttons 4px. Shadows: Flat with 1px borders.
None beyond small line icons (gear, plus).
Components
- PlanStatusStrip
- StatusBadge
- SpendingAlertsCard
- AddAlertDialog (threshold, email)
- ComparePlansTable
- PlanColumnHeader
- FeatureRow with section labels
- ManageBillingButton
Interactions
- Manage opens the hosted billing portal
- Add alert opens a dialog with amount threshold and recipients; saved alerts list with delete
- Upgrade starts hosted checkout for that tier
- Talk to sales opens a contact form
- Table header sticks while scrolling
Data
Account{id, plan (payg|starter|scale|enterprise), period_start, period_end, spend_cents}SpendAlert{id, account_id, threshold_cents, recipients[], created_at}PlanFeature{plan, key, value}
Guardrails
Experience
- Put current plan and spend at the top
- Highlight the current plan column in text too ('Current plan')
- Show credits per month under each price
- Keep Enterprise as 'Custom' with a sales action
- Confirm alerts with a toast and list them
Accessibility
- Comparison table uses th scope for plan and feature headers and a caption
- Current plan conveyed with text, not only tint
- Sticky header doesn't hide focused cells
- Dialog labelled with a description of the threshold
- Badge text meets 4.5:1
Security
- Only account owners can change plans or alerts (RLS)
- Validate threshold ranges server-side
- Webhook-driven plan updates with signature checks
- No card data stored
- Audit plan changes
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 **Rivaro**, the plans-and-billing page of a usage-priced API: a status strip, a spending alerts card and a four-tier comparison table with the current plan highlighted. Build the app shell and the page with checkout and alert flows.
### 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. Hosted checkout and billing portal from a hosted checkout provider via Edge Functions.
### Pages & layout
1. **Status strip**: Plan status (name + Active badge), Billing period (date range), Current spend, Manage.
2. **Spending alerts**: title, description, Add alert; list of alerts.
3. **Compare plans**: four columns (Pay as you go, Starter, Scale, Enterprise) with price, credits, action; grouped feature rows (monitoring slots, frequency, history, support).
### Design system
- Colors: `--bg: #f4f6fa` (page), `--card: #ffffff` (cards and table), `--text: #141821` (primary text), `--muted: #5a6172` (labels), `--current: #eef2fd` (current plan column tint), `--accent: #2f55d4` (current plan name and top border), `--button: #0e0e10` (Upgrade button), `--secondary: #e9ecf1` (secondary Upgrade fill), `--badge: #1e7e45` (Active badge fill), `--badge-text: #ffffff` (Active badge text).
- Fonts: Inter 600, 26px page title; 22px plan prices for headings; Inter 400, 16px; table cells 15px, line-height 1.5 for body. Strip labels 12px uppercase 600 with 0.06em tracking; money uses tabular numerals.
- Spacing: Medium-dense. 8px; card padding 20px; table cell padding 12px. Container: fluid, max 1100px.
- Radius: 8px cards; table outer radius 8px; buttons 4px.
- Shadows: Flat with 1px borders.
- Motion: Minimal: row hover tint; alert dialog fades in.
### Components & interactions
PlanColumnHeader shows name, price with '/mo', credit line and the action. The current column gets a 2px accent top border and a soft blue tint down the whole column.
- Manage opens the hosted billing portal
- Add alert opens a dialog with amount threshold and recipients; saved alerts list with delete
- Upgrade starts hosted checkout for that tier
- Talk to sales opens a contact form
- Table header sticks while scrolling
### Data & state
Seed invented tiers and prices; the account is on pay-as-you-go with a small spend. date-fns formats the period.
Entities: `Account{id, plan (payg|starter|scale|enterprise), period_start, period_end, spend_cents}`; `SpendAlert{id, account_id, threshold_cents, recipients[], created_at}`; `PlanFeature{plan, key, value}`.
States to build and show in a dev-only state switcher:
- pay-as-you-go current
- subscribed tier current (its button reads Current plan, disabled)
- no alerts: helper line
- alert saved toast
- invalid threshold error
- payment past due banner
- loading skeleton strip and table
- non-owner read-only
### Accessibility
- Comparison table uses th scope for plan and feature headers and a caption
- Current plan conveyed with text, not only tint
- Sticky header doesn't hide focused cells
- Dialog labelled with a description of the threshold
- Badge text meets 4.5:1
Verified contrast: body text: #141821 on #ffffff = 17.76:1; muted labels: #5a6172 on #ffffff = 6.2:1; current plan text: #2f55d4 on #eef2fd = 5.56:1; Upgrade label: #ffffff on #0e0e10 = 19.28:1; secondary button label: #141821 on #e9ecf1 = 15.0:1; Active badge: #ffffff on #1e7e45 = 5.09:1; current column top border: #2f55d4 on #ffffff = 6.23:1; focus ring: #2f55d4 on #f4f6fa = 5.76:1.
### Security
- Only account owners can change plans or alerts (RLS)
- Validate threshold ranges server-side
- Webhook-driven plan updates with signature checks
- No card data stored
- Audit plan changes
RLS detail: `accounts` select for members, plan fields updated by service role only; `spend_alerts` select/insert/delete for owners.
### Performance & SEO
Server-render plan data; the table is static per plan set so cache it; private route noindex.
### Guardrails
- Put current plan and spend at the top
- Highlight the current plan column in text too ('Current plan')
- Show credits per month under each price
- Keep Enterprise as 'Custom' with a sales action
- Confirm alerts with a toast and list them
- 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:
- Current plan clearly marked by text and tint
- Alerts can be added and removed
- Upgrade goes to hosted checkout
- Table works on mobile
- Owners-only changes enforced