Headless-CMS

Headless CMS

0
0
0
TypeScript
public

Studio Atelier — Minimal Editorial Website

A clean, ultra-minimal, vertically scrolling marketing site translated from a
4-page horizontal presentation mockup. Built as a custom Next.js front-end with
a typed mock-content layer designed to be swapped for a headless CMS (Sanity
recommended) without component changes.

What this is

A single-page editorial website composed of four scroll sections — Index,
Practice, Work, Contact — anchored from a sticky nav. Premium serif
display type (Instrument Serif) paired with Geist Sans for body and Geist Mono
for eyebrows. Generous white space, asymmetric editorial grid for the work
section, and a sticky blurred header.

Imagery is sourced from Unsplash for now via next/image, with a reusable
Placeholder component that falls back to a labeled grey box (with the
reserved aspect ratio baked into the corner) for any media item without a
src — so the layout stays stable while final assets are being finalized.

Stack

Layer Choice
Framework Next.js 16 (App Router, Turbopack)
Runtime React 19 + React Compiler (auto memo)
Styling Tailwind CSS v4 (CSS-based @theme)
Typography Geist Sans / Geist Mono / Instrument Serif
Images next/image with images.unsplash.com allowed
CMS (planned) Sanity (embedded Studio at /studio)
Language TypeScript (strict)

Getting started

npm install
npm run dev

Open http://localhost:3000.

Scripts

Command Purpose
npm run dev Start the Turbopack dev server
npm run build Production build
npm run start Run the production build
npm run lint ESLint (eslint-config-next)

Project structure

src/
├── app/
│   ├── layout.tsx              # Fonts, metadata, html shell
│   ├── page.tsx                # Composes the 4 sections
│   ├── globals.css             # Tailwind v4 tokens + base styles
│   └── _components/            # Non-routable UI (Next.js private folder)
│       ├── Nav.tsx
│       ├── Section.tsx         # Shell + <Eyebrow> primitive
│       ├── Hero.tsx            # Section 1 — Index
│       ├── Statement.tsx       # Section 2 — Practice
│       ├── Works.tsx           # Section 3 — Work (editorial grid)
│       ├── Contact.tsx         # Section 4 — Contact
│       ├── Placeholder.tsx     # next/image w/ grey-box fallback
│       └── Footer.tsx
└── lib/
    └── content.ts              # Typed mock content — single source of truth

Content model

src/lib/content.ts is the single source of truth for every piece of copy
and structure on the page. It follows the principles in
.agents/skills/content-modeling-best-practices/:

  • Content is data, not pages — sections are typed objects with semantic
    fields (eyebrow, headline, pillars, media), never presentation blobs.
  • Single source of truthsite.name, site.tagline, nav, and social
    are consumed by layout.tsx, Nav, and Footer from one place.
  • Media is described, not embeddedMediaPlaceholder { label, ratio, src?, alt?, caption? }. When src is absent the layout still reserves the
    correct aspect ratio.

Swapping in a headless CMS later

Because components only read from typed exports in content.ts, the CMS
integration is mechanical:

  1. Install sanity + next-sanity.
  2. Generate Sanity schemas matching the Hero, Statement, Work,
    WorksSection, Contact, and Site types.
  3. Replace the named exports with async fetchers
    (export const hero = await getHero(), etc.) inside Server Components.
  4. Mount Studio at app/studio/[[...tool]]/page.tsx.

No component file needs to change.

Responsive design

Breakpoint Behavior
< sm (mobile) Single-column stack; nav links hidden, Contact shortcut shown
smmd Nav links re-appear, tighter type, single-column content
md (≥768px) 12-column editorial grid kicks in for Statement, Works, Contact
lg (≥1024px) Larger display sizes, increased vertical rhythm (py-40)

Smooth-scroll between sections is handled by native
html { scroll-behavior: smooth } and in-page # anchors — no client JS,
no hamburger needed at the current section count.

Design system

Tokens live in src/app/globals.css and are exposed as Tailwind utilities via
@theme inline:

  • bg-background / text-foreground — paper + ink
  • text-muted — secondary copy
  • border-rule — hairline section dividers
  • bg-placeholder / text-placeholder-fg — grey-box fallback
  • font-sans / font-serif / font-mono — Geist / Instrument Serif / Geist Mono

Conventions

This repo follows Next.js 16-specific guidance — see
AGENTS.md and node_modules/next/dist/docs/ before writing code, as APIs
differ from older training data. Key choices in use:

  • Server Components by default (no "use client" anywhere yet).
  • React Compiler is on in next.config.ts → no manual useMemo /
    useCallback.
  • _components/ is the Next.js convention for non-routable UI colocated
    inside app/.
  • Tailwind v4 uses CSS-based theming via @theme inline — there is no
    tailwind.config.ts.

Roadmap

  • Wire Sanity with embedded Studio at /studio
  • Replace content.ts
  • Optional: per-project detail pages at /work/[slug]
v0.3.3[beta]