Skip to content

Repository files navigation

Align

Marketing site for Align, a pre-seed network that connects founders with the investors who back them. Eight pages, a custom grid system, and a generative logo animation — built from a Figma file, pixel for pixel.

The Align landing page: a dithered generative logo with three annotated callouts

Live: https://align-mauve.vercel.app · Source: https://github.com/k-jdev/align

Stack

Layer Choice
Framework Next.js 16 (App Router, React 19, Server Components by default)
Language TypeScript 5, strict: true
Styling Tailwind CSS v4 (CSS-first @theme, no tailwind.config.js)
Components shadcn/ui primitives + Base UI
Fonts IBM Plex Sans / IBM Plex Mono via next/font
Animation p5.js (isolated), CSS keyframes
Tooling ESLint 9 (flat config), Prettier + prettier-plugin-tailwindcss

Features

  • Eight routes: landing, about, founders, investors, work index, work detail, and three legal pages — all statically prerendered at build time.
  • A four/eight-column layout system driven entirely by CSS custom properties, with a keyboard-toggled grid overlay for verifying alignment against Figma.
  • Generative dithered logo on the landing hero, rendered with p5.js.
  • Portfolio company pages generated from a typed data module via generateStaticParams, with per-page metadata.
  • Legal pages (Terms, Privacy, Disclosures) rendered from one typed schema, so the three documents can never drift apart structurally.
  • Responsive from 320px up, with a mobile nav and mobile-specific art direction.

Architecture notes

The grid is the design system. Rather than hardcoding container widths, the layout is expressed as four CSS variables — --grid-cols, --grid-gap, --grid-pad, --grid-content — redefined at the lg breakpoint. Every section composes GridContainer, which reads those variables. Changing the design's column count is a one-line change in app/globals.css, not a sweep across forty components.

The grid overlay is a dev tool, not a shipped feature. GridOverlay draws the live column grid on Ctrl+G so a section can be checked against the Figma frame in the browser. It is mounted from the root layout only when process.env.NODE_ENV === "development", so it costs production visitors nothing.

The p5 sketch lives in an iframe, on purpose. public/hero-logo.html is a self-contained p5.js sketch that dithers the Align logo. Embedding it as an iframe rather than a React component keeps a 60fps canvas loop, its own RAF scheduling, and its own font loading entirely outside React's reconciliation — and means a sketch crash degrades to a blank hero instead of taking the page down.

Optical alignment is measured, not guessed. DynamicShiftText reads the rendered text box and compensates for the left side bearing of the display face, so large headings optically align to the grid edge the way they do in Figma. It bails out to zero shift when the text wraps.

Content is typed data, not JSX. Portfolio companies (lib/work-detail.ts) and legal documents (lib/legal-content.ts) are typed modules. Pages map over them. Adding a portfolio company is one object; it gets a static route, sitemap entry, and metadata for free.

Running locally

Requires Node 20+.

git clone https://github.com/k-jdev/align.git
cd align
npm install
npm run dev

Open http://localhost:3000. Press Ctrl+G on any page to toggle the grid overlay.

Script What it does
npm run dev Dev server
npm run build Production build (also typechecks)
npm run start Serve the production build
npm run lint ESLint
npm run typecheck tsc --noEmit
npm run format Prettier over all TS/TSX

Project structure

app/                 routes, root layout, sitemap.ts, robots.ts
components/
  landing/ about/    section components, one folder per page
  founders/ investors/
  work/ work-detail/
  legal/
  shared/            header, footer, GridContainer, GridOverlay, text effects
  ui/                shadcn primitives (not hand-edited)
lib/                 typed content modules + utilities
public/              images, logos, the standalone p5 sketch

What I would do differently

  • The p5 iframe costs a second document. It buys isolation and paid for itself during development, but a React-hosted canvas with a manual RAF loop would drop a request and let the sketch react to the theme. Worth revisiting now that the animation has stopped changing.
  • Images are shipped unoptimized. next.config.ts sets images.unoptimized: true, so three PNGs weighing ~1.7MB reach mobile as-is. Converting the art to AVIF/WebP and turning the optimizer back on is the single largest win available on this site.
  • No tests. For a site this static, Playwright smoke tests over the eight routes — asserting no console errors and no broken internal links — would catch more real regressions per line than unit tests would.
  • The legal pages are template copy. Terms, Privacy, and Disclosures demonstrate the typed-schema rendering, not reviewed legal text — Align has no operating entity behind it yet, so jurisdiction, venue, and registered address are deliberately unstated.
  • Section components take no props. Several sections hardcode their copy. Lifting that into lib/ the way the work and legal pages already do would make the whole site editable from one place.

Roadmap

  • Replace placeholder portfolio companies with real ones
  • AVIF/WebP art direction, images.unoptimized off
  • /contact page with a real form
  • Playwright smoke suite in CI
  • OG image generation via next/og

License

MIT — see LICENSE.

About

Pixel-perfect Figma → Next.js 16 build. Eight statically prerendered routes, a CSS-variable grid system, and a generative p5.js hero. TypeScript strict, Tailwind v4.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages