Template
Rekinto
A compact sign-in page for a developer API product that leads with three identity providers as icon buttons and offers email below. It suits technical users who mostly sign in with a work or code-host account.
Provider-first sign-in with icon button row · App screen: login · 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 400, 24px 'Sign in' heading; JetBrains Mono 500 for the wordmark lettering
- InterBody: Inter 400, 16px, line-height 1.5
Patterns
- top-centred wordmark
- row of three icon-only provider buttons
- divider between social and email
- email-first form with arrow button
- disabled-until-valid Continue
- copyright footer
States it is designed for
- default (Continue disabled)
- valid email
- submitting
- code step
- invalid code
- OAuth cancelled
- rate-limited
- account uses SSO: redirect notice
Who it is for
- developers integrating a verification or messaging API
- technical founders
Layout
- wordmark centred at top (monospace lettering beside a square mark)
- vertically centred column ~190px (max 360px): heading, three equal icon buttons in a row, divider
- email label, input, Continue button with arrow
- 'No account yet? Sign up' line
- copyright footer centred at bottom
- on mobile the provider row keeps three equal columns with 48px min height
Palette
Precise, neutral, engineered; monospace details hint at a developer audience.
- bg
#ffffff - text
#1b1c1f - muted
#5f636b - button
#f7f7f8 - border
#8b8f98 - primary
#1b1c1f - disabled
#f2f2f3 - link
#3b63d6
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 17.04:1 | 4.5:1 |
| Aa | muted footer | 6.03:1 | 4.5:1 |
| Aa | Continue label (enabled) | 17.04:1 | 4.5:1 |
| Aa | link text | 5.33:1 | 4.5:1 |
| input border | 3.24:1 | 3:1 | |
| provider button border | 3.03:1 | 3:1 | |
| focus ring | 5.33: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 400, 24px 'Sign in' heading; JetBrains Mono 500 for the wordmark lettering
- Body
- Inter 400, 16px, line-height 1.5
Label 14px 500; Continue 15px 500 with trailing arrow icon.
Spacing and imagery
Density: Airy. Grid: 8px; 16px between groups; provider buttons 8px apart. Container: column 360px max. Radius: 6px buttons and inputs. Shadows: Provider buttons 0 1px 2px rgba(0,0,0,0.05).
Full-colour provider glyphs at 20px inside neutral buttons; no illustration.
Components
- Wordmark
- ProviderIconButton ×3 (with visually hidden label)
- Divider
- EmailField
- ContinueButton
- SignUpLink
- CopyrightFooter
- CodeStep
Interactions
- Provider buttons launch OAuth
- Continue enables once the email is valid; Enter submits
- Email step leads to a one-time code step
- Tooltips on provider icons show 'Continue with …'
Data
User{id, email, created_at}Identity{user_id, provider (oauth-a|code-host|workplace|email)}AuthAttempt{email_hash, ip_hash, at}
Guardrails
Experience
- Icon-only providers need tooltips and accessible names
- Keep Continue visibly disabled until valid, but explain why on submit attempt
- Keep the sign-up link on the same screen
- Remember the last provider and outline it
- Keep the page free of marketing copy
Accessibility
- Each icon button has aria-label 'Continue with …'
- Disabled Continue uses aria-disabled so it stays focusable with an explanation
- Divider is presentational
- Visible label above the email input
- Focus ring 2px blue offset 2px
Security
- Rate-limit sign-in and code requests per email and IP
- Validate OAuth redirect targets against an allowlist
- Codes and magic links are single-use and expire in 10 minutes
- Use CSRF-safe, PKCE OAuth flows and httpOnly session cookies
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 **Rekinto**, the sign-in page of a developer API product: three identity-provider icon buttons in a row, a divider, and an email field with Continue that leads to a one-time code. Build sign-in, the code step and sign-up with all error 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. Supabase Auth handles OAuth providers and email OTP.
### Pages & layout
1. **/sign-in**: wordmark top-centre; heading; three provider buttons; divider; 'Email address' label and input; Continue; sign-up prompt; copyright footer.
2. **/sign-in/code**: six-box code input, resend timer.
3. **/sign-up**: same layout with 'Create account' heading.
### Design system
- Colors: `--bg: #ffffff` (page), `--text: #1b1c1f` (headings and labels), `--muted: #5f636b` (footer and helper), `--button: #f7f7f8` (provider buttons), `--border: #8b8f98` (input and button borders), `--primary: #1b1c1f` (enabled Continue fill), `--disabled: #f2f2f3` (disabled Continue fill), `--link: #3b63d6` (Sign up link and focus ring).
- Fonts: Inter 400, 24px 'Sign in' heading; JetBrains Mono 500 for the wordmark lettering for headings; Inter 400, 16px, line-height 1.5 for body. Label 14px 500; Continue 15px 500 with trailing arrow icon.
- Spacing: Airy. 8px; 16px between groups; provider buttons 8px apart. Container: column 360px max.
- Radius: 6px buttons and inputs.
- Shadows: Provider buttons 0 1px 2px rgba(0,0,0,0.05).
- Motion: Continue fades from disabled to enabled over 120ms; arrow nudges 2px on hover.
### Components & interactions
ProviderIconButton is a 56×32px neutral button with a coloured provider glyph and hidden text. Continue is full width, pale when disabled and near-black when enabled.
- Provider buttons launch OAuth
- Continue enables once the email is valid; Enter submits
- Email step leads to a one-time code step
- Tooltips on provider icons show 'Continue with …'
### Data & state
Auth via Supabase; last provider stored in a cookie. react-hook-form + zod for email and code.
Entities: `User{id, email, created_at}`; `Identity{user_id, provider (oauth-a|code-host|workplace|email)}`; `AuthAttempt{email_hash, ip_hash, at}`.
States to build and show in a dev-only state switcher:
- default (Continue disabled)
- valid email
- submitting
- code step
- invalid code
- OAuth cancelled
- rate-limited
- account uses SSO: redirect notice
### Accessibility
- Each icon button has aria-label 'Continue with …'
- Disabled Continue uses aria-disabled so it stays focusable with an explanation
- Divider is presentational
- Visible label above the email input
- Focus ring 2px blue offset 2px
Verified contrast: body text: #1b1c1f on #ffffff = 17.04:1; muted footer: #5f636b on #ffffff = 6.03:1; Continue label (enabled): #ffffff on #1b1c1f = 17.04:1; link text: #3b63d6 on #ffffff = 5.33:1; input border: #8b8f98 on #ffffff = 3.24:1; provider button border: #8b8f98 on #f7f7f8 = 3.03:1; focus ring: #3b63d6 on #ffffff = 5.33:1.
### Security
- Rate-limit sign-in and code requests per email and IP
- Validate OAuth redirect targets against an allowlist
- Codes and magic links are single-use and expire in 10 minutes
- Use CSRF-safe, PKCE OAuth flows and httpOnly session cookies
RLS: `identities` select for the owning user only; `auth_attempts` no client access (service role only).
### Performance & SEO
Under 60KB JS; preload provider glyph sprite; title and meta description; noindex the code step.
### Guardrails
- Icon-only providers need tooltips and accessible names
- Keep Continue visibly disabled until valid, but explain why on submit attempt
- Keep the sign-up link on the same screen
- Remember the last provider and outline it
- Keep the page free of marketing copy
- 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:
- All three providers and email OTP work
- Disabled state explains itself
- Rate limits enforced
- Keyboard and screen reader friendly
- Sign-up link works