Skip to main content
vibld

Template

Alderpin

A single-screen editor where a creator fills in a profile, social handles and a list of custom links and instantly sees a phone-sized public page. All page data is compressed into the share URL, so there is no account or database: publishing means copying a link. It is a starter for tiny, privacy-friendly profile tools.

Database-free link-in-bio builder with live phone preview · App · Small tools and apps · front-end app (local state)

A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.

Add app screens

Pick up to 6 screens, such as a dashboard, settings or an empty state. Each is built in this design’s own palette and typefaces, with its states and guardrails.

Account setup
Add edit
Analytics
Appearance
Calendar
Chat
Checklist
Checkout
Confirmation
Dashboard
Delete account
Details
Discovery questions
Empty state
Flowchart
Import export
Inbox
Integrations
Invite team
Loading
Login
Onboarding
Plans
Playground
Product tour
Referral
Search
Settings
Share
Sign up
Success
Table
Team members
Text editor
Upgrade
Usage
Verification
Welcome

Start from this templateRead the build prompt

Typefaces

Hind is a plain, open sans that stays clear at 14-18px, so the form-first builder feels like a tidy settings page while the preview does the showing off.

  • HindHeadings: section titles 18px 600, preview name 22px 600
  • HindBody: inputs and helper text 16px/1.5 400, field labels 14px 500

Patterns

  • split editor: form left, live device preview right
  • section rows with label column and card column
  • icon-prefixed URL input group
  • two-column field grid inside card
  • phone-frame preview mockup
  • sticky bottom action bar with icon buttons
  • state serialised into a shareable URL
  • dashed add-row button for repeatable items

States it is designed for

  • Empty editor: phone preview shows a faint placeholder avatar and 'Your name' ghost text
  • Invalid URL or email field with inline message
  • Encoded URL exceeds 2,000 characters: warning meter turns amber with advice to shorten links
  • Clipboard permission denied: fall back to a selectable read-only field
  • Public page opened with corrupt or truncated data: friendly error with a link to start a new page
  • Avatar image fails to load: initials fallback
  • Long bio or link labels: wrap in preview, truncate with ellipsis in editor rows

Who it is for

  • creators and freelancers who want a quick profile page
  • developers prototyping a URL-state app
  • event organisers sharing a one-off link list

Layout

  1. Two fixed panes on desktop: scrollable editor pane (~62% width, pale slate canvas) and preview pane (~38%, white) with a centred phone frame
  2. Editor sections stacked top to bottom: Profile, Social links, Custom links; each is a row with a 1/3 label column (title + helper text) and a 2/3 white card
  3. Profile card: name input, bio textarea, avatar image URL input
  4. Social card: two-column grid of icon-prefixed URL inputs (nine networks plus email and phone)
  5. Links card: repeatable rows (label, icon key, URL) plus a full-width dashed add button
  6. Sticky bottom bar spanning the editor pane: Load sample data, Copy share link, Source link; a small credit chip bottom-right of the preview
  7. Public page route: same phone layout full-screen: avatar, name, bio, icon row, stacked link buttons
  8. Below 900px: preview collapses into a toggleable sheet opened from the bottom bar; label column stacks above cards; social grid becomes one column

Palette

Plain, utilitarian, form-first. It feels like a settings page that happens to produce a pretty profile.

  • editor canvas#f1f5f9
  • card / preview surface#ffffff
  • primary text#111827
  • secondary text#4b5563
  • placeholder / muted#69707d
  • field label#374151
  • input border#8b95a4
  • hairline divider (decorative)#e5e7eb
  • phone frame / primary button#1e293b
  • focus ring / link accent#2563eb

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text on card17.74:14.5:1
Aahelper text on canvas6.90:14.5:1
Aaplaceholder text on white input4.98:14.5:1
Aafield label on card10.31:14.5:1
input border on white3.03:13:1
focus ring on canvas4.72:13:1
Aaprimary button label14.63:14.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
Hind 600, 18px section titles, 22px name on preview (similar to the observed humanist geometric sans)
Body
Hind 400, 16px inputs and helper text, line-height 1.5; field labels 14px 500

No oversized headings; the preview is the hero. Helper text never below 14px; bottom-bar labels 14px (observed 12px is too small).

Spacing and imagery

Medium density on a 4px grid; section rows 32px apart with a hairline between; card padding 24px; field gap 16px vertical, 24px column gap. Radius 6px on inputs and cards, 40px on the phone frame (8px stroke). Shadows: a single 1px soft shadow under cards; none elsewhere.

Only the user's avatar (circular, 72px) and outline social icons in 18px grey boxes attached to inputs. No illustrations.

Components

  • SectionRow (label column + card)
  • IconInputGroup (leading icon cell + URL field)
  • BioTextarea with character counter
  • LinkRow (label, icon key, URL, drag handle, remove)
  • Dashed AddLinkButton
  • PhoneFramePreview
  • PublicProfile page (avatar, name, bio, social icon row, link buttons)
  • BottomActionBar
  • CopyLinkButton with toast
  • URL length meter

Interactions

  • Every keystroke updates the preview within one animation frame (debounced URL write at 300ms)
  • Copy share link copies the full encoded URL and shows a 'Link copied' toast
  • Load sample data fills every field with fictional content; confirm first if fields are not empty
  • Link rows reorder by drag handle or Alt+Arrow keys; remove shows an Undo toast for 5s
  • Invalid URLs get an inline error on blur and are omitted from the preview
  • Mobile: Preview button opens a bottom sheet; Escape or swipe down closes it

Data

  • ProfileState{name, bio (max 160), avatarUrl, socials{network (enum: website|microblog|photo|code-host|messenger|professional|video|email|phone): value}, links[{label, iconKey, url}] (max 12)}
  • Encoded as compact-key JSON -> UTF-8 -> base64url in the ?d= query param; template id as the path segment

Guardrails

Experience

  • Keep the preview visible at all times on desktop; never hide it behind a tab
  • Show the current URL length and warn before it gets unwieldy
  • Ask before overwriting non-empty fields with sample data
  • Group social inputs in a consistent order with the network label above each field
  • Make 'Copy share link' the single primary action; source and sample-data buttons stay secondary
  • Fix the observed mobile failure: on narrow screens the preview must never overlap the form

Accessibility

  • Each icon-prefixed input has a visible text label; the icon is aria-hidden
  • Bottom-bar buttons have text labels, not icon-only
  • Announce copy success and validation errors via an aria-live polite region
  • The phone preview is a live region set to off and labelled 'Preview'; the public page itself uses real headings and a list of links
  • Link reordering works with keyboard, and the new position is announced
  • Input borders use #8b95a4 (3.03:1) rather than the observed light grey

Security

  • Validate every URL with zod and allow only http, https, mailto and tel schemes; reject javascript: and data:
  • Render user text as text only; never inject decoded values as HTML
  • Decode inside try/catch with size limits (reject payloads over 8 KB) to avoid crashes and abuse
  • Links on the public page use rel="noopener noreferrer nofollow" and target="_blank"
  • Warn users that everything in the link is public and readable by anyone holding it

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 **Alderpin**, a link-in-bio page builder that needs no account and no database. A creator fills in a profile, a set of social handles and a short list of custom links on one screen, watches a phone-sized preview update live, and publishes by copying a URL whose query string carries the whole page. Anyone opening that URL sees the rendered profile.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) primitives and lucide-react icons. Use react-hook-form + zod for the editor, dnd-kit for reordering links, and a tiny router with two routes: `/` (editor) and `/p` (public page). No backend: state lives in the URL.

### Pages & layout
1. **Editor (`/`)**: two panes. Left, a scrollable editor on a pale slate canvas; right, a white pane with a centred phone frame (rounded 40px, 8px dark stroke) showing the live preview. The editor has three section rows, each with a label column (title, one line of helper text) and a white card: *Profile* (name, bio with counter, avatar URL), *Social links* (two-column grid of inputs with a leading icon cell for web, social networks, email and phone), *Custom links* (repeatable rows plus a dashed full-width add button). A sticky bottom bar holds Load sample data, Copy share link (primary) and a View source link, plus a URL-length meter.
2. **Public page (`/p?d=...`)**: the same phone layout at full width on mobile and centred at 420px on desktop: circular avatar, name, bio, a row of social icons, then stacked full-width link buttons.
3. **Responsive**: below 900px the preview becomes a bottom sheet opened by a Preview button in the bar; label columns stack above their cards and the social grid collapses to one column. Nothing overlaps.

### Design system
- Colors: `--canvas: #f1f5f9`, `--surface: #ffffff`, `--text: #111827`, `--text-2: #4b5563`, `--placeholder: #69707d`, `--label: #374151`, `--input-border: #8b95a4`, `--divider: #e5e7eb` (decorative only), `--ink: #1e293b` (phone frame and primary button), `--focus: #2563eb`.
- Fonts: Hind (a humanist sans close to the observed system font) 600 for section titles at 18px and the preview name at 22px; 400 at 16px for inputs and body, line-height 1.5; labels 14px 500.
- Spacing: 4px base; 24px card padding; 32px between sections with a hairline divider; 24px column gap in grids.
- Radius: 6px inputs, cards and buttons; phone frame 40px; public link buttons 10px.
- Shadows: `0 1px 2px rgb(15 23 42 / 0.06)` on cards only.
- Motion: 150ms colour transitions; bottom sheet slides in over 200ms; respect reduced motion.

### Components & interactions
SectionRow, IconInputGroup (icon cell is `aria-hidden`, label above), BioTextarea (160-character counter), LinkRow (drag handle, label, icon key, URL, remove), AddLinkButton (dashed border), PhoneFramePreview, PublicProfile, BottomActionBar, UrlLengthMeter, Toast. Typing updates the preview immediately; the URL is rewritten with `history.replaceState` after 300ms idle. Copy share link writes the absolute URL to the clipboard and toasts "Link copied". Load sample data asks for confirmation when fields are filled, then inserts a fictional profile (for example "Rowan Vale, ceramicist" with four made-up links). Removing a link shows Undo for 5 seconds. Link rows reorder by mouse or Alt+Arrow keys.

### Data & state
`ProfileState { name; bio; avatarUrl; socials: Record<Network, string>; links: { label; iconKey; url }[] }` with at most 12 links. Serialise with short keys, encode as UTF-8 base64url in `?d=`, and version it (`v:1`) so templates can evolve. Decode on load with a zod schema; on failure show an error state instead of a blank page. Keep a URL-length meter: green under 1,200 characters, amber to 2,000, red above with a hint to shorten labels or use a link shortener.

### Accessibility
All inputs have visible labels and associated error text via `aria-describedby`. The bottom bar uses text-plus-icon buttons at 14px minimum. Copy results and errors go to a polite live region. The public page uses a single h1 for the name and a `<ul>` of links with descriptive text; social icons carry accessible names. Drag-and-drop has a keyboard alternative with announcements. Focus rings are 2px `--focus` with 2px offset.
Verified contrast: body text on card: #111827 on #ffffff = 17.74:1; helper text on canvas: #4b5563 on #f1f5f9 = 6.9:1; placeholder text on white input: #69707d on #ffffff = 4.98:1; field label on card: #374151 on #ffffff = 10.31:1; input border on white: #8b95a4 on #ffffff = 3.03:1; focus ring on canvas: #2563eb on #f1f5f9 = 4.72:1; primary button label: #ffffff on #1e293b = 14.63:1.

### Security
Allow only `http`, `https`, `mailto` and `tel` URLs (zod refinement); strip anything else before rendering. Render all decoded strings as text, never as HTML. Cap the decoded payload at 8 KB and the link count at 12. External links open with `rel="noopener noreferrer nofollow"`. Show a small note that page content is public to anyone with the link. No analytics or third-party scripts on the public page.

### Performance & SEO
Ship the public route as a separate lightweight chunk with no form libraries. Lazy-load dnd-kit in the editor. Set the public page's `<title>` and meta description from the decoded name and bio; add `noindex` to the editor. Target Lighthouse 95+ on the public page.

### Guardrails
- All sample names, bios and links are invented; no real people or brands.
- No copied icons or artwork; use lucide-react or a generic icon set.
- Keep the editor usable on a 360px-wide phone.
- Acceptance criteria:
  - [ ] Editing any field updates the preview instantly and the URL within 300ms
  - [ ] Opening a copied URL in a private window renders the identical page
  - [ ] `javascript:` links are rejected with an inline error
  - [ ] Corrupt `?d=` values show the error state, not a crash
  - [ ] Keyboard-only users can add, reorder, remove and copy

Open the builderAll templatesThis palette on its own