Template
Theo Lindqvist
A dark, high-end portfolio for a design lead or solo consultant. A huge light-weight headline sits beside a short positioning paragraph, and below it a staggered two-column grid of rounded project cards carries titles, one-line descriptions and tags. A grid/list view toggle sits in the header, alongside social links and a contacts link. It is built for consultants who compete with larger agencies on premium projects.
Dark design lead 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
Prompt is a clean, loopless geometric sans that looks elegant at 400 on a huge scale and firm at 700, close to Satoshi.
- PromptHeadings: hero 144px 400 at -4.32px, section H2 700 60px
- PromptBody: body 16px, 12px uppercase tags
Who it is for
- Solo consultants competing with agencies
- Design leads charging premium rates
- Creatives presenting client case studies with results
- Brand and product designers
Layout
- Header: name + city left; segmented grid/list toggle centered; TW / IG / DRIB / LIN arrow links and CONTACTS right
- Hero: giant two-line headline left, positioning paragraph right
- Staggered two-column project grid with rounded image cards; title, one-line description, uppercase tags beneath
- List view alternative with compact rows
- Closing 'Let's connect.' section
- Project detail pages with parallax images
- Light theme variant
Palette
Premium, dark, confident, spacious, modern. It feels like a high-end product studio: quiet black canvas, bright imagery.
- background
#000000 - text
#ffffff - secondary text
#a3a3a3 - tag text
#8a8a8a - toggle track
#1c2230 - light theme bg
#ffffff - light theme text
#141414
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on black | 21.00:1 | 4.5:1 |
| Aa | secondary text on black | 8.33:1 | 4.5:1 |
| Aa | tag text on black | 6.08:1 | 4.5:1 |
| toggle icons on track | 6.30:1 | 3:1 | |
| selected toggle pill (white) on track | 15.90:1 | 3:1 | |
| Aa | header links on 85% black scrim over images | 6.00:1 | 4.5:1 |
| Aa | light theme body text | 18.42:1 | 4.5:1 |
| Aa | light theme muted/tag text | 5.33:1 | 4.5:1 |
| focus ring (white) on black | 21.00: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
- Satoshi 400, 144px, -4.32px tracking; section H2 700 60px (Satoshi is not on Google Fonts; a vibld project loads Prompt)
- Body
- Satoshi 16px; tags 12px uppercase tracked (Satoshi is not on Google Fonts; a vibld project loads Prompt)
A single geometric grotesk used very light at huge sizes for elegance, bolder for section headings.
Spacing and imagery
24px outer margins, two columns with 24px gap, alternating vertical offsets for a staggered rhythm, card radius ~16px.
Bright product and brand photography (dashboards, packaging, people, devices) in rounded cards with subtle parallax.
Components
- Header with name and city
- Grid/list segmented toggle
- Arrow social links
- Giant light headline
- Positioning paragraph
- Staggered project card grid
- Tag labels
- List view rows
- Let's connect CTA
- Project detail with parallax
- Theme toggle
- Toasts
Interactions
- Grid/list toggle switches layout with animation
- Project images parallax slightly on scroll (passive listeners)
- Card hover zooms image and brightens title
- Header gains an 85% black scrim over content
- Theme switch dark/light
- Contact CTA copies email with toast
Data
Project{slug, title, summary, tags[], cover, results[], sections[]}Profile{name, city, headline, statement, socials[], 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
Build a dark, premium portfolio for a fictional independent design lead, "Theo Lindqvist". It targets founders and CMOs weighing a solo expert against an agency. A giant, light-weight headline and a short statement set the tone. A staggered grid of rounded project cards (with a list-view option) shows breadth, and each project opens a case study with results.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS with class-based dark mode, shadcn/ui (Radix ToggleGroup, Tooltip), Sonner and lucide-react. Use Framer Motion `layout` for the grid/list switch, a lightweight custom parallax hook (passive scroll listener with rAF) and React Router. Recharts is optional for a results chart on case studies. Static only.
### Pages & layout
1. Header, overlaid and fixed. Left: name in tracked caps plus the city in gray. Center: a pill segmented toggle (grid icon / list icon). Right: short social labels with ↗ and "CONTACTS".
2. Hero: a two-line headline at clamp(64px, 11vw, 144px), weight 400, -0.03em. To its right on desktop, a 3-line statement in gray at 18px.
3. Work (grid): two columns. The right column starts about 120px lower for a stagger. Cards have a 4:3 image with 16px radius, then the title, a one-line summary and uppercase tags.
4. Work (list): rows with title, summary, tags and a small thumbnail that appears on hover.
5. "Let's connect." closing section with a large email link and socials.
6. Case study: hero image, challenge/approach/results sections, a results metrics row and a next project link.
### Design system
- Dark (default): `--background: #000`, `--foreground: #fff`, `--muted-foreground: #a3a3a3`, `--tag: #8a8a8a`, `--toggle-track: #1c2230`.
- Light: `--background: #fff`, `--foreground: #141414`, `--muted-foreground` and `--tag: #6b6b6b`.
- Font: Satoshi (Fontshare) or Prompt (Google Fonts), 400 and 700. Scale: 12 / 14 / 16 / 18 / 24 / 60 / 144px; body 16px at 1.6 line-height, ~65ch measure.
- Spacing: 8px base, 24px margins and gaps, 160px between sections. Radius 16px on cards, 9999px on the toggle.
- Motion: 450ms spring for layout changes, parallax at 0.08x scroll offset and 300ms hover.
### Components & interactions
- ViewToggle: a Radix ToggleGroup with `aria-label`s ("Grid view", "List view"). The selected option is a white pill with a black icon. The choice persists in the URL.
- ProjectCard: hover or focus scales the image to 1.03 and the title to full white. Show a skeleton while loading.
- ListRow: hover reveals a thumbnail and focus does the same. On touch, show thumbnails inline.
- ContactCTA: a `mailto:` plus a copy button with a toast.
- ThemeToggle: persisted, defaults to dark.
### Data & state
`Project{slug, title, summary, tags, cover, results: {label, value}[], sections}` and a `Profile` config. The view mode lives in the URL and the theme in localStorage. Seed eight fictional client projects (banking, finance, wellness, AI, streaming, agency, marketplace, health). Do not use real company names or logos in imagery.
### Accessibility
- The tag gray is #8a8a8a (6.08:1 on black; the lighter #737373 is not used).
- Put an 85% black scrim behind the header when it overlaps images (effective #262626 or darker), so links stay legible.
- The toggle and social links are keyboard reachable in logical order. Staggering is visual only; DOM order stays sequential.
- Parallax is disabled under reduced motion.
- Verified contrast: body #ffffff on #000000 = 21.0:1; secondary #a3a3a3 on #000000 = 8.33:1; tags #8a8a8a on #000000 = 6.08:1; header on scrim #a3a3a3 on #262626 = 6.0:1; light muted #6b6b6b on #ffffff = 5.33:1.
### Security
- No forms. External links use `rel="noopener noreferrer"`.
- No secrets in client-side code. Validate any external URLs in config as https.
### Performance & SEO
Mark parallax listeners passive, use transforms only and lazy-load card images with `srcset`. Preload the display font. Add per-case-study meta and OG images.
### 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.
- Avoid real brand logos or trademarks in placeholder project imagery.
- Done when:
- [ ] Grid/list toggle animates and persists in the URL
- [ ] Staggered grid keeps sequential keyboard order
- [ ] Parallax is smooth and off for reduced-motion
- [ ] Light and dark themes both pass contrast
- [ ] Case studies show a results row and next project