Skip to main content
vibld

Template

Umbrive

The members page of a developer API product's per-application settings. It shows who has access to the application, their role and join time, and a separate invitations block that is empty until someone is invited. A prepaid balance with a Top up button stays visible in the header.

Application members and invitations settings · App screen: team members · 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, 22px section headings
  • InterBody: Inter 400/500, 16px/1.5; table 15px; muted email 14px

Patterns

  • top-level tabs (Overview / Billing / Configure)
  • settings sub-nav with grouped sections
  • members table in card with pagination
  • invitations empty state with inbox icon
  • prepaid balance + top-up in header
  • command-K search shortcut
  • sortable column header

States it is designed for

  • Single owner member
  • Invitations empty
  • Pending invitations list with resend/revoke
  • Invite validation errors
  • Low balance warning chip next to balance
  • Loading skeleton rows
  • Non-owner: Invite hidden, explanatory note

Who it is for

  • Developers running a usage-billed API account
  • Team leads adding engineers to an application
  • Finance-minded owners watching prepaid balance

Layout

  1. Header: logo, app switcher, service switcher (All services); right: 'Balance' label with mono amount, dark 'Top up' button, avatar
  2. Tabs row: Overview, Billing, Configure (active underline); right: search with ⌘K hint
  3. Settings sub-nav (160px): App (General, Members active), Security (Keys), Billing (Spending limit, Notifications)
  4. Main (max 560px): H2 'Members' + description, outlined 'Invite members' button right
  5. Members card: table with Member (sortable), Role, Joined; footer '1 member' left, 'Page 1 of 1' + Previous/Next right
  6. Invitations section: H2 and card with inner dashed box: inbox icon, 'No invitations yet', muted helper
  7. Mobile: sub-nav becomes a select; table becomes cards

Palette

quiet, developer-grade, tidy. An account page that stays out of the way.

  • app background#f9f9fb
  • card surface#ffffff
  • primary text#16171d
  • muted text#5c6070
  • border#8a8e99
  • dark button#16171d
  • avatar/accent blue#1d5fa8
  • focus ring#2563eb
  • low-balance warning#b45309
  • error#b42318

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text on card17.88:14.5:1
Aamuted text on app bg5.94:14.5:1
Aamuted email on card6.25:14.5:1
Aadark button label17.88:14.5:1
Aaavatar initial on blue6.45:14.5:1
Aalow-balance text5.02:14.5:1
card/dashed border3.28:13:1
focus ring5.17: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.

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

Type scale

Display
Inter 600, 22px section headings
Body
Inter 400/500, 16px/1.5; table 15px; muted email 14px

Balance and amounts in JetBrains Mono 14px; similar to observed grotesk + mono.

Spacing and imagery

Airy settings: page padding 32px, 24px card padding, 48px between Members and Invitations; card radius 8px with 1px border; empty box has dashed border radius 6px; buttons 32px tall.

Line icons (inbox, user plus, key); monogram avatars; no imagery.

Components

  • App switcher
  • Service switcher
  • Balance readout
  • Top up button + dialog
  • Tabs row
  • Command search trigger
  • Settings sub-nav
  • Members table with sortable header
  • Pagination footer
  • Invite members dialog (email, role)
  • Invitations list / empty box
  • Role select

Interactions

  • Member column header toggles sort with arrow indicator
  • Invite members dialog accepts multiple emails and a role; on success the invitation appears in the Invitations card
  • Previous/Next disabled at bounds
  • Top up opens a dialog with preset amounts and redirects to a hosted checkout provider
  • ⌘K opens command palette

Data

  • App{id, name, owner_id, balance_cents, currency}
  • AppMember{app_id, user_id, role (owner|admin|developer|viewer), joined_at}
  • AppInvitation{id, app_id, email, role, status (pending|accepted|revoked|expired), sent_at}
  • TopUp{id, app_id, amount_cents, status, provider_ref, created_at}

Guardrails

Experience

  • Separate members from invitations so pending people are never mistaken for active ones
  • Show join time as relative with exact time on hover
  • Keep balance and Top up visible across settings
  • Explain the empty invitations state and link to Invite
  • Disable pagination buttons at bounds rather than hiding them

Accessibility

  • Sortable header is a button with aria-sort
  • Empty state text is real text, icon aria-hidden
  • Balance has an accessible label 'Balance 0.00 euros'
  • Disabled pagination buttons use aria-disabled and remain readable
  • Command palette is a labelled dialog with keyboard navigation

Security

  • RLS: app_members and invitations visible to app members; only owners/admins invite or change roles
  • Top-ups created server-side; balance changes only via verified webhook from the checkout provider
  • Invitation tokens hashed, single-use, 7-day expiry
  • Audit role changes and top-ups

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 **Umbrive**'s application Members page for a usage-billed developer API. Owners see members with role and join time, invite teammates, and track pending invitations, while the prepaid balance and Top up stay in view.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix primitives) and lucide-react icons. TanStack Query for server state, react-hook-form + zod for forms, date-fns for dates. Supabase for Auth, Postgres and Row Level Security. Payments go through a hosted checkout provider; its webhook (verified server-side in an Edge Function) credits the balance.

### Pages & layout
1. **Header**: logo, app switcher ('Harbor Sandbox', invented), service switcher; right: 'Balance' + mono '€0.00', dark '+ Top up', avatar.
2. **Tabs**: Overview, Billing, Configure (active); search with '⌘K'.
3. **Sub-nav**: App (General, Members), Security (Keys), Billing (Spending limit, Notifications).
4. **/apps/:id/settings/members**: 'Members' + 'Manage your application members and invitations.'; outlined '+ Invite members'. Card with table Member (avatar, name, email), Role, Joined ('17m ago'); footer count and pagination.
5. **Invitations**: heading + card with dashed inner box (inbox icon, 'No invitations yet', muted helper) or a list of pending invitations with Resend/Revoke.
6. **Top up dialog**: presets (€10/€25/€50/custom) then redirect to hosted checkout.
7. Mobile: sub-nav as select; tables to cards.

### Design system
- Colors: `--bg: #f9f9fb` (app background), `--card: #ffffff` (card surface), `--fg: #16171d` (primary text), `--muted: #5c6070` (muted text), `--border: #8a8e99` (border), `--primary: #16171d` (dark button), `--accent: #1d5fa8` (avatar/accent blue), `--ring: #2563eb` (focus ring), `--warn: #b45309` (low-balance warning), `--danger: #b42318` (error).
- Fonts: Inter 400/500/600; headings 22px 600; body 16px/1.5; table 15px; JetBrains Mono 14px for money.
- Spacing: 4px base; page padding 32px; card padding 24px.
- Radius: cards 8px, buttons 6px, empty box 6px dashed.
- Shadows: cards `0 1px 2px rgb(22 23 29 / 0.05)`.
- Motion: tab underline 150ms; dialogs 150ms fade/scale.

### Components & interactions
`AppHeader`, `BalanceReadout` (warning chip when under a threshold), `TopUpDialog`, `SettingsTabs`, `CommandPalette`, `SettingsSubNav`, `MembersTable` (sortable Member), `Pagination`, `InviteDialog` (email chips, role select), `InvitationsCard` (empty or list), `RoleSelect` (owners/admins only).

### Data & state
`apps(id, name, owner_id, balance_cents, currency)`, `app_members(app_id, user_id, role, joined_at)`, `app_invitations(id, app_id, email, role, token_hash, status, sent_at, expires_at)`, `top_ups(id, app_id, amount_cents, status, provider_ref, created_at)`. Balance only changes in the webhook handler inside a transaction. Mock: one owner, zero invitations; toggle to three pending.

### Accessibility
`aria-sort` on Member header; pagination buttons `aria-disabled`; empty state text readable; balance labelled with currency name. Command palette: Radix Dialog + listbox semantics. Focus ring 2px `--ring`.
Verified contrast: body text on card: #16171d on #ffffff = 17.88:1; muted text on app bg: #5c6070 on #f9f9fb = 5.94:1; muted email on card: #5c6070 on #ffffff = 6.25:1; dark button label: #ffffff on #16171d = 17.88:1; avatar initial on blue: #ffffff on #1d5fa8 = 6.45:1; low-balance text: #b45309 on #ffffff = 5.02:1; card/dashed border: #8a8e99 on #ffffff = 3.28:1; focus ring: #2563eb on #ffffff = 5.17:1.

### Security
RLS: `app_members` select for members of the app; insert/update/delete only for owner/admin (owner row immutable except by transfer function). `app_invitations` same. `top_ups` select for owner/admin; insert only via server function; `apps.balance_cents` has no client update policy. Webhook signature verified with a server-side secret. Invitation tokens hashed, 7-day expiry. Audit role changes and top-ups.

### Performance & SEO
Small route; lazy-load command palette and top-up dialog. Settings routes `noindex`.

### Guardrails
- Invent app names, members and amounts.
- Refer to payments as a hosted checkout provider.
- Never trust client-sent amounts for balance changes.

Acceptance criteria:
- [ ] Inviting adds a pending row to Invitations
- [ ] Empty invitations state renders with helper
- [ ] Balance updates only after webhook
- [ ] Non-admins cannot invite (RLS)
- [ ] Contrast pairs pass

Open the builderAll templatesThis palette on its own