Template
Harbor & Pine
A minimalist monospace portfolio for an independent designer: a fixed left sidebar with studio name, page links and contact links, and a main column with a short intro followed by a flowing masonry of project images in full, half and third widths. Case study pages, an about page, a styleguide and a validated contact form round it out.
Monospace 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
Cutive Mono is a single-weight typewriter face, which suits a regular-weight-only, typewritten designer notebook.
- Cutive MonoHeadings: intro 20-24px regular
- Cutive MonoBody: body 16px, nav and meta 13px
Who it is for
- Freelance designers and illustrators
- Independent consultants
- Agencies needing white-label portfolio sites
- Designers wanting a distinctive personal site
Layout
- Fixed left sidebar: two-line studio name top, Work (underlined active) / About / Styleguide, then Email / Instagram / LinkedIn with arrows at bottom
- Main column: monospace intro paragraph
- Flow masonry grid of project images in full-width, half and third-width tiles with tight 4px gaps
- Project case study pages with role, team, timeline metadata and next/previous navigation
- About page
- Styleguide page
- Contact form
- Mobile: header with right slide-in drawer
Palette
Minimal, quiet, typographic, honest, crafted. It feels like a designer's working notebook.
- background
#ffffff - text
#000000 - muted text
#555555 - secondary/muted tint (black 5% = #f2f2f2)
#0000000d - decorative border (black 10%)
#0000001a - input border
#767676 - primary
#000000
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on white | 21.00:1 | 4.5:1 |
| Aa | muted text on white | 7.46:1 | 4.5:1 |
| Aa | muted text on 5% tint | 6.66:1 | 4.5:1 |
| Aa | text on 5% tint | 18.76:1 | 4.5:1 |
| Aa | white hover label on black | 21.00:1 | 4.5:1 |
| input border on white | 4.54:1 | 3:1 | |
| focus ring on white | 21.00:1 | 3:1 | |
| active nav underline on white | 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
- Cutive Mono regular (400) 20-24px for intro
- Body
- Cutive Mono 16px regular for body (line-height 1.6); 13px regular for nav and meta
All-monospace at regular weight reads like a typewritten index; no display type
Spacing and imagery
40px sidebar padding, ~180px sidebar, main column from 220px with 40px right margin, 4px image gaps, zero radius
Documentary-style photos of design objects, books, lifestyle and art in varied crops arranged edge-to-edge
Components
- Fixed sidebar nav
- Contact links with arrows
- Intro paragraph
- Flow masonry grid (full/half/third)
- Project tile
- Case study metadata block
- Sequential project navigation
- Slide-in mobile drawer with overlay
- Contact form with validation
- Styleguide page
- Skip link
Interactions
- Scroll-reveal on tiles
- Hover dims/brightens tiles
- Mobile right drawer with dimmer and 50px targets
- Next/previous project navigation
- Form validation with inline errors
- Lazy-loaded images fade in
Data
Project{slug, title, role, team[], timeline, year, cover, width: full|half|third, images[], body}Profile{name, intro, email, instagram, linkedin}ContactMessage{name, email, message}
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 minimalist portfolio for a fictional independent designer called **Harbor & Pine**. The audience is brand managers and agencies looking for a thoughtful freelancer. Everything is set in a quiet monospace, with a fixed sidebar for navigation and contact and a flowing image grid of projects that leads into detailed case studies.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix Sheet for the mobile drawer, Form), lucide-react, React Router with slug routes, Framer Motion for scroll reveals, Embla for case-study galleries, and react-hook-form + zod. The contact form posts to one serverless function.
### Pages & layout
1. Sidebar (fixed, ~180px): a two-line studio name at the top; Work, About and Styleguide links (active underlined); Email →, Instagram → and LinkedIn → at the bottom.
2. Work (home): an intro paragraph in 20–24px regular (400) monospace, max ~60ch; then a flow grid where each project tile declares its width (full, half or third) and tiles pack left to right with 4px gaps.
3. Case study: title, a metadata block (role, team, timeline, year), intro, image sequence using the same full/half/third system, and previous/next project links.
4. About: portrait, longer bio, services, and selected clients (fictional).
5. Styleguide: shows type sizes, colors, spacing and components.
6. Contact: form with name, email and message.
Mobile: top bar with the name and a menu button; the right-side drawer has a dimmed overlay and 50px tap targets.
### Design system
Tokens: `--background: #ffffff; --foreground: #000000; --muted: rgb(0 0 0 / .05); --border: rgb(0 0 0 / .10) (decorative); --input-border: #767676; --muted-foreground: #555555; --radius: 0`. Font: Cutive Mono 400/500 (no light weights, since no text reaches 32px). Scale: 24 / 20 / 16 / 13px; nav 13px at weight 400; line-height 1.5 for intro and 1.6 for body, max 70ch. Spacing: 40px sidebar padding, 220px main offset, 4px grid gap, 64px section gaps. No shadows, no radius. Motion: 400ms opacity reveals; image fade-in on load; drawer 250ms slide. Light only.
### Components & interactions
- FlowGrid: CSS grid with 6 columns (full = span 6, half = span 3, third = span 2); tiles keep their own aspect ratios; on mobile everything is full width.
- Tile: hover lowers opacity to 0.9 and shows the title in a 13px white-on-black label; focus ring 2px black; a skeleton with fixed ratio while loading.
- Drawer: focus trap, Esc to close, overlay click closes, body scroll locked.
- Contact form: labelled fields, inline errors, loading, success and error messages (not just toasts).
### Data & state
`Project{slug,title,role,team[],timeline,year,cover{src,w,h},width,images[{src,w,h,width}],body}`, `Profile{name,intro,email,instagram,linkedin}`. Static typed data; next/previous computed from array order. Invent project names and clients.
### Accessibility
All text uses weight 400 or heavier so the monospace strokes stay legible at 13px, secondary text is #555555 (7.5:1 on white, 6.7:1 on the 5% tint), and form fields use a #767676 border so their edges reach 3:1. Include a skip link to main content. The sidebar is a `<nav>`; the image grid is a list of links with accessible names from project titles. All images get alt text. Reduced motion disables reveals. Verified contrast: body text on white: #000000 on #ffffff = 21.0:1; muted text on white: #555555 on #ffffff = 7.46:1; muted text on 5% tint: #555555 on #f2f2f2 = 6.66:1; input border on white: #767676 on #ffffff = 4.54:1.
### Security
Validate the contact form with zod on the client and in the function; add a honeypot and rate limiting; keep email-service keys server-side. External social links use `rel="noopener noreferrer"`.
### Performance & SEO
Serve AVIF/WebP with `srcset` matched to each tile's width; lazy-load everything except the first row; reserve aspect ratios. Code-split case-study routes. Person and CreativeWork JSON-LD; per-project meta and OG images. Target CLS under 0.05 and LCP under 2.5s.
### Guardrails
- Use original copy, invented clients and placeholder or licensed images; no real brand logos.
- Don't publish fabricated testimonials.
- Store only contact form fields.
- Keep components small and typed, never use `any`, and handle failed loads visibly.
- Done when: the flow grid packs full/half/third tiles correctly at three breakpoints; the mobile drawer is fully keyboard-operable; case studies link sequentially; the contact form shows inline success and error; the styleguide page lists all tokens.