Skip to main content
vibld

Template

Sprigly

An invite-friends modal in a social reading tracker that nudges readers to bring friends in exchange for a free month of the premium tier. It explains the benefit in one line, shows progress toward the reward and offers one copy-link action.

Reading-app invite-friends modal with reward progress · App screen: referral · 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.

  • Source Serif 4Headings: Source Serif 4 500, 24px headline (similar to the observed book serif)
  • InterBody: Inter 400 16px body at 1.55; 15px reward title (500); 14px rule text; 14px nav

Patterns

  • modal with hand-drawn line-art illustration header
  • serif headline over sans body
  • reward card with gift icon badge overlapping its top edge
  • thin progress bar toward reward
  • full-width neutral "Copy your link" button
  • circular close button top-right
  • monochrome sidebar with Library and Collections groups
  • Friends / Everybody feed tabs

States it is designed for

  • 0 of 3 friends (empty bar with "0 of 3" label)
  • Partial progress (1-2 of 3)
  • Reward unlocked (card shows "Premium month added" with date)
  • Already premium (modal copy changes to gifting)
  • Clipboard failure (show selectable link text)
  • Link loading skeleton

Who it is for

  • Readers tracking books and sharing reviews
  • Book clubs
  • Social reading communities

Layout

  1. Left sidebar (~135px): wordmark, Home, Feed, Explore, Highlights; Library (To read, Reading, Read); Collections (+ Create new); reading goal and user row at bottom
  2. Main: "Feed" title with Friends / Everybody tabs; empty-state illustration and copy behind the modal
  3. Modal (~300px): close circle; ink illustration across top; serif H2; two-line paragraph; reward card with overlapping gift badge, title, rule text and progress bar; "Copy your link" button
  4. Scrim 60% grey
  5. Mobile: modal as full-height sheet; sidebar as bottom tabs

Palette

literary, gentle, monochrome, friendly. Like a bookmark with a doodle.

  • modal and page background#ffffff
  • headline and strong text#1f1f1f
  • paragraph and rule text#5e5e5e
  • neutral button fill#f2f2f2
  • progress track#8c8c8c
  • progress fill#1f1f1f
  • reward card border (decorative)#e3e3e3
  • overlay (decorative)#666666
  • focus ring#1f1f1f

Every checked pair, measured again

SampleWhereRatioNeeds
Aaheadline16.48:14.5:1
Aamuted paragraph6.48:14.5:1
Aabutton label on neutral fill14.72:14.5:1
progress track on white3.36:13:1
progress fill on white16.48:13:1
focus ring16.48: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
Source Serif 4 500, 24px headline (similar to the observed book serif)
Body
Inter 400 16px body at 1.55; 15px reward title (500); 14px rule text; 14px nav

The serif appears only for headlines to evoke print; everything else is a quiet sans. Numbers inside copy are bolded, not coloured.

Spacing and imagery

Airy and centered: 8px base; modal padding 16px, 24px between blocks; reward card padding 20px; radius 12px modal, 8px card and button, full on close; modal shadow 0 16px 48px rgba(0,0,0,.18).

Black ink line-art illustrations of animals carrying books, cropped at the modal edges; a small outline gift icon in a white circle; no colour photography.

Components

  • Monochrome sidebar
  • Feed tabs
  • Invite modal
  • Line-art header illustration
  • Reward card with overlapping icon badge
  • Progress bar with count label
  • Copy link button
  • Close circle button
  • Copied toast

Interactions

  • Copy link copies and swaps label to "Link copied" with a check for 2s
  • Progress bar animates to new value when a friend joins (400ms)
  • Close, Esc and scrim click dismiss; modal does not reappear for 30 days
  • Hover on nav items tints background light grey

Data

  • Profile{id, username, is_premium, premium_until}
  • InviteLink{user_id, code}
  • Invite{id, inviter_id, invitee_id, joined_at}
  • RewardGrant{id, user_id, kind (premium_month), granted_at}
  • Book{id, title, author}
  • Shelf{user_id, book_id, status (to_read|reading|read)}

Guardrails

Experience

  • State the reward rule in one sentence with the number emphasised
  • Show progress as "N of 3" text as well as a bar
  • Offer a single primary action (copy link); sharing elsewhere is secondary
  • Do not show the modal more than once per 30 days
  • Change the message for users who already have premium

Accessibility

  • Progress uses role="progressbar" with aria-valuenow/max and a visible text label
  • Illustrations are decorative (alt="")
  • Close button labelled "Close invite dialog"
  • Serif headline is at least 24px; body 16px
  • Focus trapped in modal and returned to the trigger

Security

  • Invite codes random; joins attributed server-side on sign-up
  • Reward grants written by a server function after verifying distinct, active new accounts
  • RLS: users read only their own invites and grants
  • Prevent self-referral and duplicate accounts (email/device checks)

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 **Sprigly**, an invite-friends modal for a social reading tracker. Over the Feed page, a monochrome modal with a line-art illustration says "Read with friends", explains that inviting three friends earns a free month of the premium tier, shows progress toward it and offers one "Copy your link" button.

### Stack
React + TypeScript + Vite, Tailwind CSS, shadcn/ui (Dialog, Tabs, Progress, Toast) on Radix, lucide-react, Motion for the progress animation, TanStack Query, Supabase for auth, profiles, invites and reward grants.

### Pages & layout
1. **Sidebar**: invented wordmark with a small sprout icon; Home, Feed (active), Explore, Highlights; Library: To read, Reading, Read; Collections with "Create new"; a reading-goal link and user row at the bottom.
2. **Feed**: title, Friends / Everybody tabs, an empty state ("Your friends' reviews will show up here") with a line-art reader illustration.
3. **Invite modal** (340px): circular close top-right; an ink illustration spanning the top edge; serif H2 "Read with friends"; a two-line paragraph; a bordered reward card with a gift icon in a white circle overlapping its top border, a title ("Get a free premium month"), the rule ("Invite **3** friends with your link") and a progress bar with "1 of 3" label; a full-width neutral "Copy your link" button.
4. Mobile: the modal is a full-height sheet and the sidebar becomes bottom tabs.

### Design system
- Colors: `--bg: #ffffff` (modal and page background), `--fg: #1f1f1f` (headline and strong text), `--muted: #5e5e5e` (paragraph and rule text), `--button: #f2f2f2` (neutral button fill), `--progress-track: #8c8c8c` (progress track), `--progress-fill: #1f1f1f` (progress fill), `--border: #e3e3e3` (reward card border (decorative)), `--scrim: #666666` (overlay (decorative)), `--focus: #1f1f1f` (focus ring).
- Fonts: Source Serif 4 500 for headlines (24px; similar to the observed book serif); Inter for body 16px/1.55, reward title 15px/500, rule text 14px (never below 14).
- Spacing: 8px scale; 16px modal padding; 24px block gap; 20px card padding.
- Radius: modal 12px; card and button 8px; close button full.
- Shadows: modal `0 16px 48px rgba(0,0,0,.18)`; the card has a border only.
- Motion: modal fade/scale 180ms; progress fill 400ms ease-out; none under reduced motion.

### Components & interactions
Sidebar, FeedTabs, EmptyFeed, InviteDialog, InkIllustration (decorative, cropped with overflow hidden), RewardCard (badge, title, rule, ProgressBar with text), CopyLinkButton (label becomes "Link copied" with a check for 2s; falls back to a selectable text field), Toast. Close, Esc and a scrim click dismiss the modal and record `last_invite_prompt_at`.

### Data & state
Tables: `profiles(id, username, is_premium, premium_until, last_invite_prompt_at)`, `invite_links(user_id, code)`, `invites(id, inviter_id, invitee_id, joined_at)`, `reward_grants(id, user_id, kind, granted_at)`, plus `books` and `shelves` for the app shell. Mock progress at 1 of 3. Handle states: 0/3, partial, unlocked (card says "Premium month added, ends 12 Nov"), already premium (gift framing), clipboard failure, loading skeleton.

### Accessibility
The progress bar is `role="progressbar"` with values and a visible "1 of 3" label. Illustrations are decorative. The close button is labelled. Focus is trapped and returned. The serif headline stays at 24px or larger; body text is 16px. Focus rings: 2px ink with a 2px white offset.
Verified contrast: headline: #1f1f1f on #ffffff = 16.48:1; muted paragraph: #5e5e5e on #ffffff = 6.48:1; button label on neutral fill: #1f1f1f on #f2f2f2 = 14.72:1; progress track on white: #8c8c8c on #ffffff = 3.36:1; progress fill on white: #1f1f1f on #ffffff = 16.48:1; focus ring: #1f1f1f on #ffffff = 16.48:1.

### Security
Invite codes are random. Attribution happens server-side at sign-up. A server function grants the reward only after three distinct, verified, active new accounts; self-referrals and duplicates are rejected. RLS: users read only their own invites and grants; nobody can insert grants from the client.

### Performance & SEO
Inline the line-art as optimised SVG you draw yourself, or use compressed PNGs with explicit sizes. Lazy-load the modal. The app is noindex.

### Guardrails
- Original illustrations and invented wordmark; no real brand names.
- Show the modal at most once every 30 days.
- Acceptance criteria: (1) Copy works, with a fallback; (2) progress reflects server data with text and bar; (3) the unlocked and already-premium variants render; (4) the dialog is fully keyboard accessible; (5) contrast pairs pass.

Open the builderAll templatesThis palette on its own