Template
Cass Moreno
A cinematic, near-black one-page portfolio for a documentary photographer and creative director. A giant Bebas Neue name overlays a moody portrait, followed by oversized quote-style accolades and sections for about, skills, work history, education, writing and speaking, with a fixed right-side section nav. It turns a varied career into one strong narrative.
Cinematic documentary photographer one-pager · 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.
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.
Start from this templateRead the build prompt
Typefaces
League Gothic is a tall, classic condensed poster face like a documentary title card, and IBM Plex Sans is a neutral, slightly engineered body.
- League GothicHeadings: name and short headings 128-192px uppercase at 0.05em
- IBM Plex SansBody: body 16px at 1.6, 12px tracked uppercase labels
Who it is for
- Photographers and videographers with a cinematic style
- Creatives who also write and speak
- Consultants building credibility with clients
- Professionals combining varied experience into one story
Layout
- Top-right utility links: Mail, Instagram, Vimeo
- Fixed right-side vertical section nav (About, Skills, Work, Education, Writing, Speaking) with underline on active
- Hero: full-bleed dark portrait with stacked condensed uppercase name and a short accolade paragraph
- Pull quote section: a large sentence-case Inter quote with one underlined phrase and a small tracked attribution
- About with grayscale-to-color images
- Skills list
- Work experience timeline rows
- Education rows
- Writing: article list
- Speaking: talks list
- Get in touch with a playful note and contact links
Palette
Cinematic, dramatic, dark, bold, grainy. It feels like the opening titles of a documentary.
- background
#0a0a0a - text
#fafafa - heading gray
#d1d5db - secondary surface
#1a1a1a - accent gray
#878787 - muted
#828282 - border
#333333
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on background | 18.97:1 | 4.5:1 |
| Aa | heading gray on background | 13.44:1 | 4.5:1 |
| Aa | accent gray labels on background | 5.51:1 | 4.5:1 |
| Aa | accent gray on secondary surface | 4.84:1 | 4.5:1 |
| Aa | muted text on background | 5.15:1 | 4.5:1 |
| Aa | muted text on secondary surface | 4.53:1 | 4.5:1 |
| Aa | hero name/accolade on 80% black gradient over photo | 12.10:1 | 4.5:1 |
| Aa | hero accolade gray on gradient | 8.57:1 | 4.5:1 |
| focus ring / active underline on background | 18.97:1 | 3:1 |
As vibld’s tokens
The palette on the 15+ color tokens vibld styles a project with, each text color 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
- League Gothic, 128-192px, uppercase with 0.05em tracking, name and short headings only
- Body
- IBM Plex Sans 16px at 1.6 line-height (14px only for utility links); 12px tracked uppercase labels
Condensed poster display against a neutral sans; scale contrast is extreme to feel like a film title card.
Spacing and imagery
64px left margin, full-height sections, long page (~13k px), right-aligned nav column, 0 radius, thick underline accents.
High-contrast black-and-white portraits with subtle animated film grain; images shift grayscale-to-color on hover.
Components
- Utility social links
- Fixed vertical section nav with active underline
- Full-bleed hero portrait
- Stacked condensed name
- Oversized pull quote with underline
- Grayscale-to-color images
- Skills list
- Experience rows
- Education rows
- Writing list
- Speaking list
- Contact section
- Film-grain overlay
- Custom scrollbar
Interactions
- Active section in the side nav updates on scroll (scroll spy)
- Smooth scroll to sections
- Scroll-triggered fade/slide-in of headings
- Images go grayscale to color on hover
- Animated film-grain noise overlay
- Link underline animations
Data
Role{title, organization, start, end, summary}Education{program, school, years}Article{title, outlet, date, url}Talk{title, event, date}Skill{name}Accolade{quote, source}
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 color 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, labeled 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 cinematic, near-black one-page portfolio for a fictional documentary photographer and creative director, "Cass Moreno". It serves editors, conference organizers and brand clients who want to understand a whole career, including photography, leadership, writing and speaking, in one scroll. It should feel like a film title sequence: towering condensed type, grainy monochrome portraits and a quiet side nav.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) and lucide-react. Use an IntersectionObserver hook for scroll spy, and CSS or Framer Motion for reveals. Static only.
### Pages & layout
1. Utility links top-right (Mail, Instagram, Vimeo) at 14px.
2. Fixed side nav, bottom-right, right-aligned: About, Skills, Work, Education, Writing, Speaking. The active item gets a 1px underline.
3. Hero: a full-viewport black-and-white portrait with a dark gradient on the left. A three-line uppercase name at clamp(72px, 15vw, 192px) with 0.05em tracking and a two-sentence accolade (fictional) below.
4. Quote: a large pull quote in IBM Plex Sans 600 at 48-72px, sentence case (Bebas is reserved for the name and short section headings), with one phrase underlined by a thick 8px bar, and a small tracked attribution.
5. About: a paragraph and two images that are grayscale by default.
6. Skills: a wrapped list or two-column grid.
7. Work: rows with role, organization and years plus a one-line summary.
8. Education, then Writing (article title, outlet, date) and Speaking (talk, event, date).
9. Contact: a big heading, a wry one-liner and email/social links.
### Design system
- `--background: #0a0a0a`, `--foreground: #fafafa`, `--heading-muted: #d1d5db`, `--secondary: #1a1a1a`, `--accent: #878787`, `--muted: #828282`, `--border: #333`, radius 0.
- Fonts: League Gothic for display only (192 / 128 / 64px, never below 48px, with Impact and sans-serif fallbacks) and IBM Plex Sans 400/500 for body at 16px. Labels are 12px uppercase with 0.12em tracking.
- Spacing: 8px base, 64px page margin, full-height sections. Film grain is an SVG turbulence overlay at 4-6% opacity, animated in steps.
- Motion: 700ms cubic-bezier(0.16,1,0.3,1) reveals, 500ms grayscale transitions. Dark only. Style the scrollbar thin and dark.
### Components & interactions
- SideNav: states for default gray, hover white and active underlined. Click scrolls smoothly. On mobile it becomes a top sheet menu.
- RevealHeading: fades and slides up once. Under reduced motion it is shown immediately.
- MonoImage: grayscale; hover or focus shows color. Show a skeleton while loading.
- Lists (work, writing, speaking): hover draws an underline. External article links show ↗.
- Empty section: hide the section and its nav item automatically if its data array is empty.
### Data & state
Typed config arrays: `Role`, `Education`, `Article{title, outlet, date, url}`, `Talk{title, event, date}`, `Skill` and `Accolade`. The only state is the active section. All names, awards and publications must be invented and marked as sample. Never imply real awards.
### Accessibility
- #878787 on #0a0a0a is 5.51:1. The muted gray is lifted from #666 to #828282 (5.15:1) so it works for small text.
- Condensed display text must stay real text (H1, H2). The side nav is a `<nav aria-label="Sections">` with `aria-current`.
- Pause or disable the grain animation under reduced motion. Hero text sits on a left-side black gradient of at least 80% opacity (effective #333333 or darker behind the text).
- Add a skip link. The underline accent is not the only cue for active.
- Verified contrast: body #fafafa on #0a0a0a = 18.97:1; accent gray #878787 on #0a0a0a = 5.51:1; muted #828282 on #0a0a0a = 5.15:1; hero text #fafafa on #333333 = 12.1:1.
### Security
- No forms. `mailto:` link only.
- External links (articles, Vimeo) use `rel="noopener noreferrer"`. Validate URLs in config (https only).
- No secrets in client-side code.
### Performance & SEO
The page is long (about 9 sections), so lazy-load all images after the hero, preload League Gothic and the hero portrait, and keep the grain as CSS/SVG rather than video. Add Person JSON-LD, section IDs for deep links and OG tags.
### 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:
- [ ] Side nav highlights the section in view and scrolls smoothly
- [ ] Hero text keeps 4.5:1 contrast over the photo
- [ ] Grain and reveals stop under reduced-motion
- [ ] Sections with empty data are hidden with their nav items
- [ ] All accolades and outlets are fictional