Colophon

How this was built.

Every decision has a reason. Most of them are documented here. This is the page for the curious.

01 \u00b7 Stack

What it's built with.

Framework

Next.js 15 · App Router · TypeScript · Vercel deployment

Styling

Tailwind CSS v4 · @theme syntax · CSS custom properties · No tailwind.config.ts

Animation

Framer Motion · all transitions named · AnimatePresence · useSpring · whileInView

Fonts

Fraunces (display/headings) · DM Sans (hero name) · Plus Jakarta Sans (body/UI) · All via next/font/google

Database

Supabase · PostgreSQL · Row Level Security · 7 tables · Real-time · SSR client

Auth

Cookie-based admin auth · No third-party · ADMIN_PASSWORD env var · 7-day session

CMS

Custom-built · lives at /admin · Fragments · Projects · Shelf · Now · About · Guestbook · Posts

Images

Cloudinary · signed upload · auto WebP/AVIF · admin-only · next/image optimization

Email

Resend · guestbook notifications · publish alerts · signer confirm · hello@ojasmutreja.com

Sound

Howler.js · 6 sounds · ambient room tone (4% volume) · toggleable · off by default

OG Images

next/og · edge runtime · per-page + per-article dynamic · 1200×630 · Fraunces loaded inline

Playground

Font Pairing Explorer · Contrast Checker (WCAG 2.1) · Reading Time + Flesch score

02 \u00b7 Animations

Ten interactions. All named.

The Drape

Page transition curtain · #1C1C1A wipe · 500ms cover · 500ms reveal · GPU composited

The Texture

SVG feTurbulence grain · 4% opacity · mix-blend overlay · fixed position · baseFreq 0.65

The Ghost

Custom cursor · 8px dot + 32px ring · useSpring 80ms lag · pointer:fine devices only

The Badge

Rotating hero ring · SVG textPath · 18s spin · speeds on hover · "Thinker · Developer · Designer · Maker · Reader"

Stellar

Canvas stars + constellations · mulberry32 seeded PRNG · 80 stars · gradient mask fade · pauses when tab hidden

The Rail

Horizontal scroll cards · scroll-snap-type: x mandatory · overflow-x scroll

The Lift

Card hover · translateY -6px · filter drop-shadow · 400ms · GPU layer · never clipped

Emergence

Scroll-triggered reveals · whileInView · opacity + y · once · staggered

Ambient Tooltip

Cursor idle 1200ms → text appears · no bubble · caption size · pointer:fine only

Sound System

Howler.js · ambient loop · transition whoosh · hover ticks · click sounds · nav toggle

03 \u00b7 Design

The decisions behind the decisions.

Type

Typography scale rooted at 128px, divided by φ (1.618) recursively: 128 79 49 30 18.5 11.5px. The same ratio governs all spacing tokens. Nothing is arbitrary.

Ojas

display · 128px

Mutreja

title · 79px

Builder

heading · 49px

Designer

sub · 30px

Software and design, built for humans.

body · 18.5px

The Texture · SVG feTurbulence · 4% opacity

caption · 11.5px

DM Sans: weight 300, letter-spacing 0. Exception: footer “ojasmutreja.com” uses weight 400.

Fraunces: weight 400, letter-spacing -0.02em. Exception: hero intro uses weight 300.

Plus Jakarta Sans: weight 400. Body, UI, captions.

Color

Background

#EFEFED · Warm gray · not pure white

Ink

#0A0A0A · Near black

Surface

#E8E8E6 · Slightly darker warm gray

Drape

#1C1C1A · Transition curtain

Muted

#9A9A98 · Secondary text

Ghost

#C4C4C2 · Borders · dividers

04 \u00b7 Philosophy

Why any of this matters.

The content management system is custom-built and lives at /admin — a password-gated interface for writing fragments, articles, and posts; managing projects, shelf items, and guestbook entries; and editing every part of this site that changes. No third-party CMS. No Notion integration. No markdown files committed to git. Everything lives in a Supabase database and updates instantly without a redeploy.

The /now page changes in under a second. The guestbook sends an email when someone signs. Articles get their own reading page with a full-bleed banner. Posts show a 1:1 image carousel. The whole system was built in one session, prompt by prompt, with obsessive attention to what each piece should feel like to use.

The /colophon itself is the only page that never needs a CMS. It updates when the code does. That feels right.

05 \u00b7 /now movement

What are you focused on right now?

The /now page follows the format proposed by Derek Sivers — a single page that answers the question “what are you focused on right now?” Updated whenever the answer changes, not on a schedule. More at nownownow.com.

06 \u00b7 Credits

Standing on shoulders.

Fraunces by Undercase Type and Octavia Saul. Plus Jakarta Sans by Tokotype. Next.js by Vercel. Framer Motion by Matt Perry.

Home ?