Template
Mara Ellis
A deep forest-green portfolio for a product and brand designer. It opens with a split hero (centered greeting and bio on the left, full-height portrait on the right), then lists selected work as oversized text titles that reveal an image following the cursor. It closes with an agency-style footer of address, clients and an email signup.
Dark green brand designer portfolio · Website · Portfolio · static site
A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.
Start from this templateRead the build prompt
Typefaces
Syne and Unbounded stay as the named wide display fallbacks, and Lexend Deca is a calm geometric body close to Satoshi for the boutique agency.
- SyneHeadings: display 72-96px 500 at -1.8px
- UnboundedHeadings: the named alternative wide display
- Lexend DecaBody: body 16-18px at 1.6, 14px labels
Who it is for
- Product and brand designers seeking premium clients
- Freelance creatives presenting case studies
- Small agencies pitching professionally
- Designers who want a text-led work index
Layout
- Small monogram top-left; no conventional nav bar
- Split hero: left half dark green with display greeting, two centered bio paragraphs and a small photo; right half a full-bleed portrait
- 'Selected Work' list: very large display-type project titles stacked vertically, each with a cursor-following image preview on hover
- Agency statement paragraph in large display type with a hairline divider above
- Footer grid: address column, 'Selected Clients' two-column list, 'Get in touch' email input
Palette
Rich, calm, premium, personal, editorial. It feels like a boutique agency site: deep color, big type and a friendly voice.
- background (forest green)
#1c3a2e - text (cream)
#f7f2e9 - muted text
#c9c4b8 - monogram accent (dusty pink)
#d9a5a5 - divider
#2f5244 - page base (fallback)
#ffffff
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | cream body text on forest | 11.12:1 | 4.5:1 |
| Aa | muted text on forest | 7.13:1 | 4.5:1 |
| Aa | dimmed project titles at 60% opacity | 5.06:1 | 4.5:1 |
| Aa | dusty pink monogram on forest | 5.83:1 | 4.5:1 |
| email input underline on forest | 7.13:1 | 3:1 | |
| focus-visible underline (cream) on forest | 11.12:1 | 3:1 | |
| Aa | placeholder text in email input | 7.13:1 | 4.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
- Clash Display 500, 72-96px, -1.8px tracking, sentence case (Clash Display is not on Google Fonts; a vibld project loads Syne)
- Body
- Satoshi / Lexend Deca 16-18px for body at 1.6 line-height; 14px labels with slight positive tracking (1.4px) (Satoshi is not on Google Fonts; a vibld project loads Lexend Deca)
A wide geometric display face gives personality; a neutral grotesk keeps bio and footer quiet.
Spacing and imagery
Hero is an exact 50/50 split at full viewport height; content centered in ~380px column; later sections use a 1150px container with 64px gutters and large vertical breaks. Square corners.
Warm, shallow-depth-of-field portrait photography, plus project images that only appear as floating previews tied to the cursor.
Components
- Monogram mark
- Split hero with portrait
- Centered bio block
- Inline small photo
- Oversized project title list
- Cursor-following image preview
- Statement paragraph
- Hairline dividers
- Address block
- Two-column client list
- Email capture input
- Case study page layout
Interactions
- Hovering a project title shows an image that trails the cursor with spring physics
- Titles dim siblings on hover to spotlight the active one
- Scroll-triggered fade-up for sections
- Email input underline animates on focus with validation message
- Page transitions into case studies
- Touch devices show a static thumbnail instead of cursor preview
Data
Project{slug, title, cover, year, role, summary, sections[]}Client{name}Profile{name, bio[], portrait, address}Subscriber/Inquiry{email}
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 a template'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 templates) - 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.
### Goal
Create a text-led, deep-green portfolio for a fictional product and brand designer named "Mara Ellis". It targets founders and marketing leads choosing a designer for premium work. The site should feel personal (a warm bio next to a big portrait) and confident (the work index is huge typography with image previews that follow the cursor).
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) for input and toast, and lucide-react. Use Framer Motion for spring-driven cursor previews (`useSpring`, `useMotionValue`) and scroll reveals, React Router for case-study routes, and zod for email validation. If the email capture must persist, post it to a serverless endpoint or a Supabase Edge Function that inserts into a single `leads` table. No other backend is needed.
### Pages & layout
1. Hero at 100vh, split 50/50. On the left, on a forest background: a monogram top-left, a centered two-line display greeting, two short centered bio paragraphs and a small landscape photo. On the right: a full-bleed portrait. On mobile, the portrait stacks above the text.
2. Selected Work: a small label, then 5-7 project titles set at 72-120px, one per row, left-aligned, each linking to a case study.
3. Statement: a hairline rule and then a 3-4 line paragraph in display type about the practice.
4. Footer grid with three columns: address lines, a "Selected Clients" list in two sub-columns (fictional names) and "Get in touch" with an underlined email input.
5. Case study: title, meta row, cover, alternating image/text sections.
### Design system
- `--bg: #1c3a2e`, `--fg: #f7f2e9`, `--muted: #c9c4b8`, `--rule: #2f5244`, `--mark: #d9a5a5`, `--input-border: #c9c4b8` (email underline and focus-visible outlines use `--fg`).
- Fonts: a wide geometric display (Clash Display from Fontshare, or Syne/Unbounded from Google Fonts as a fallback) at 500, tracking -0.02em. Body is Lexend Deca 400 at 16-18px with 1.6 line-height and a ~65ch measure. Labels are 14px with 0.1em tracking.
- Scale: 14 / 16 / 18 / 28 / 48 / 72 / 112px. Container max 1150px, 64px side padding, 128px between sections.
- Radius 0 and no shadows. Motion: spring (stiffness 150, damping 20) for the cursor preview and 500ms ease-out for fade-ups.
- Dark palette only. It is intentional, so do not invert it.
### Components & interactions
- WorkTitle: default cream. While hovering the list, non-hovered titles drop to 60% opacity (blends to #9fa89e, 5.06:1 on the forest background). Focus-visible gets an underline. The cursor preview is a 320x220 image that springs toward the pointer and hides on leave.
- On touch or coarse pointers, disable the cursor preview and show a small thumbnail beside each title.
- EmailField: states for empty, focus (brighter underline), invalid (message below), submitting (spinner) and success (inline confirmation).
### Data & state
Projects are a typed array `{slug, title, year, role, cover, summary, sections}`. Clients are `string[]`. The only runtime state is pointer position, hovered index and form state. Seed five invented projects and ten made-up client names.
### Accessibility
- Cream on forest is 11.1:1. Keep muted text at #c9c4b8 or lighter.
- The cursor preview is decorative (`aria-hidden`). Each title's link text alone must describe the project.
- Give the email input a visible label, not just a placeholder.
- Honor `prefers-reduced-motion` by showing a static preview with no spring.
- Add a skip link.
- Verified contrast: cream #f7f2e9 on #1c3a2e = 11.12:1; muted #c9c4b8 on #1c3a2e = 7.13:1; dimmed titles #9fa89e on #1c3a2e = 5.06:1; monogram #d9a5a5 on #1c3a2e = 5.83:1.
### Security
- Validate the email on the client and in the function.
- Add a honeypot and rate limit by IP.
- If you use Supabase, enable RLS on `leads` with insert-only access for anon and no select.
- Keep the service key out of the client.
- Store only the email address.
### Performance & SEO
Mark the portrait as the LCP image with `fetchpriority="high"`. Preload preview images for the hovered row only. Self-host the display font with `font-display: swap`.
### Guardrails
- Do write all copy yourself and use placeholder imagery (Unsplash-style stock or generated); no trademarked names, client logos or real people.
- Don't present invented testimonials or awards as real; label sample content as sample.
- Keep components small and fully typed; no `any`. Surface errors visibly instead of failing silently.
- Don't collect or store more personal data than the contact form needs.
- Done when:
- [ ] Hero split renders 50/50 on desktop and stacks on mobile
- [ ] Cursor preview follows pointer smoothly and is disabled on touch and reduced-motion
- [ ] All project titles reachable and operable by keyboard
- [ ] Email capture validates and shows success/error states
- [ ] Footer client list uses only fictional names