Template
Rubinet
An in-app upgrade page for a collaborative presentation tool, shown on a dark canvas. The user's avatar and name confirm which account is upgrading; a toggle switches billing period; three cards compare team, business and enterprise offerings.
Dark in-app plan picker with billing toggle · 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.
- Plus Jakarta SansHeadings: Plus Jakarta Sans 700, 28px plan names; 32px prices (similar to the observed rounded geometric sans)
- Plus Jakarta SansBody: Plus Jakarta Sans 500, 16px, line-height 1.5
Patterns
- dark full-page plan chooser
- centred account identity (avatar + name)
- pill segmented toggle monthly/yearly
- savings note under toggle
- three equal dark plan cards
- 'Starting at' price with seats line
- check-circle feature list
- enterprise card with 'Let's talk' instead of price
- back link top-left and help button bottom-right
States it is designed for
- monthly
- yearly with savings
- current plan card shows 'Current plan' and disabled CTA
- creating checkout
- checkout cancelled
- not an admin: CTA replaced by 'Ask an admin'
- loading prices skeleton
Who it is for
- team leads buying seats for a presentation tool
- marketing and sales teams
Layout
- top row: back link left, wordmark centred
- identity: avatar (48px, rounded square) and name
- billing toggle pill and savings note
- three cards in a row (max 640px total each ~200px)
- help button fixed bottom-right
- below 900px cards become a horizontal snap carousel; below 600px they stack
Palette
Bold, confident, premium; a dark stage lets prices and plan names pop.
- bg
#000000 - card
#141416 - text
#f5f5f7 - muted
#a3a3ab - toggle
#1f1f23 - accent
#7c4dff - check
#f5f5f7 - border
#6e6e78 - cta
#ffffff - cta-text
#000000
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on card | 16.90:1 | 4.5:1 |
| Aa | muted on card | 7.35:1 | 4.5:1 |
| Aa | text on page | 19.29:1 | 4.5:1 |
| Aa | active toggle label | 4.81:1 | 4.5:1 |
| Aa | toggle inactive label | 15.08:1 | 4.5:1 |
| card border | 4.16:1 | 3:1 | |
| Aa | CTA label | 21.00:1 | 4.5:1 |
| focus ring (accent on page) | 4.36: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
- Plus Jakarta Sans 700, 28px plan names; 32px prices (similar to the observed rounded geometric sans)
- Body
- Plus Jakarta Sans 500, 16px, line-height 1.5
'Starting at' 14px muted; seat add-on line 13px; name 22px 700.
Spacing and imagery
Density: Relaxed. Grid: 8px; card padding 16px; 16px gaps. Container: max 680px centred. Radius: 12px cards, full pill toggle. Shadows: None on black; 1px borders define cards.
User avatar only; white check-circle icons; no illustrations.
Components
- BackLink
- Wordmark
- AccountIdentity
- BillingToggle
- SavingsNote
- PlanCard (name, description, price block, seats, features, CTA)
- EnterpriseCard
- HelpButton
Interactions
- Toggle switches prices and seat add-on costs
- Each card's CTA opens hosted checkout for that plan and period; enterprise opens a contact form
- Back returns to the previous in-app page
- Help opens a support panel
Data
Plan{id, name, description, monthly_cents, yearly_cents, seats_included, seat_addon_cents, features[]}Workspace{id, plan_id, billing_period, seats}Member{workspace_id, user_id, role (admin|editor|viewer)}
Guardrails
Experience
- Show whose account is upgrading at the top
- State seats included and add-on seat price on each card
- Keep the savings note factual
- Give each card exactly one CTA
- Don't use a fake price for enterprise
Accessibility
- Toggle is a radio group with two labelled options
- Price updates announced politely
- Cards are articles with h2 names
- Check-circle icons are decorative; list items carry text
- White focus ring 2px with offset on black
Security
- Only admins can purchase (RLS + server)
- Prices mapped server-side; client sends plan id and period only
- Verify webhooks
- Idempotency keys on checkout creation
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 **Rubinet**, the dark in-app plan picker of a collaborative presentation tool: identity at the top, a monthly/yearly toggle and three plan cards. Build the page, checkout handoff and all states.
### 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. Motion for the toggle and price roll. Hosted checkout provider via Edge Function.
### Pages & layout
1. **Header**: back link, wordmark, avatar + name.
2. **Toggle** with savings note.
3. **Cards**: Team (for small teams, from €X/month, seats included, commenters, guests), Business (analytics, more seats), Enterprise ('Let's talk', unlimited items, 'Everything in Business, plus').
### Design system
- Colors: `--bg: #000000` (page), `--card: #141416` (plan cards), `--text: #f5f5f7` (primary text), `--muted: #a3a3ab` (secondary text), `--toggle: #1f1f23` (toggle track), `--accent: #7c4dff` (active toggle segment), `--check: #f5f5f7` (check-circle markers), `--border: #6e6e78` (card borders), `--cta: #ffffff` (card CTA fill), `--cta-text: #000000` (card CTA label).
- Fonts: Plus Jakarta Sans 700, 28px plan names; 32px prices (similar to the observed rounded geometric sans) for headings; Plus Jakarta Sans 500, 16px, line-height 1.5 for body. 'Starting at' 14px muted; seat add-on line 13px; name 22px 700.
- Spacing: Relaxed. 8px; card padding 16px; 16px gaps. Container: max 680px centred.
- Radius: 12px cards, full pill toggle.
- Shadows: None on black; 1px borders define cards.
- Motion: Toggle thumb slides 180ms; prices roll to new values (reduced motion: instant); cards lift border brightness on hover.
### Components & interactions
PlanCard stacks: name, two-line description, 'Starting at', big price with 'per month', seats line with add-on price, then check-circle list and a white CTA at the bottom.
- Toggle switches prices and seat add-on costs
- Each card's CTA opens hosted checkout for that plan and period; enterprise opens a contact form
- Back returns to the previous in-app page
- Help opens a support panel
### Data & state
Invented plans and euro prices seeded in `plans`. Period in URL. TanStack Query for plans and current workspace.
Entities: `Plan{id, name, description, monthly_cents, yearly_cents, seats_included, seat_addon_cents, features[]}`; `Workspace{id, plan_id, billing_period, seats}`; `Member{workspace_id, user_id, role (admin|editor|viewer)}`.
States to build and show in a dev-only state switcher:
- monthly
- yearly with savings
- current plan card shows 'Current plan' and disabled CTA
- creating checkout
- checkout cancelled
- not an admin: CTA replaced by 'Ask an admin'
- loading prices skeleton
### Accessibility
- Toggle is a radio group with two labelled options
- Price updates announced politely
- Cards are articles with h2 names
- Check-circle icons are decorative; list items carry text
- White focus ring 2px with offset on black
Verified contrast: body text on card: #f5f5f7 on #141416 = 16.9:1; muted on card: #a3a3ab on #141416 = 7.35:1; text on page: #f5f5f7 on #000000 = 19.29:1; active toggle label: #ffffff on #7c4dff = 4.81:1; toggle inactive label: #f5f5f7 on #1f1f23 = 15.08:1; card border: #6e6e78 on #000000 = 4.16:1; CTA label: #000000 on #ffffff = 21.0:1; focus ring (accent on page): #7c4dff on #000000 = 4.36:1.
### Security
- Only admins can purchase (RLS + server)
- Prices mapped server-side; client sends plan id and period only
- Verify webhooks
- Idempotency keys on checkout creation
RLS detail: `plans` read-only; `workspaces` plan fields updated only by service role; `members` select for same workspace.
### Performance & SEO
Server-render plans; font subset for Plus Jakarta Sans; private route noindex.
### Guardrails
- Show whose account is upgrading at the top
- State seats included and add-on seat price on each card
- Keep the savings note factual
- Give each card exactly one CTA
- Don't use a fake price for enterprise
- 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:
- Toggle updates all prices
- Current plan disabled
- Checkout per plan/period
- Admins only
- All text passes on black