Skip to content
Formray
Back to Field Notes
Build Log4 min read

Building formray.dev

Giuseppe Albrizio/
January 2026

This is the build log for the site you're reading. A 16-page, dark-mode, i18n-ready marketing site built with Next.js 15, Tailwind v4, and a deliberate aesthetic borrowed from 1970s lab equipment.


The aesthetic

Design Direction

The visual language of Formray is amber phosphor on dark stone. CRT warmth. Oscilloscope traces. Grain textures. Scan lines. The feeling of a well-maintained analog lab — precise, warm, intentional.

Not cold. Not neon. Not cyberpunk. Vintage instrumentation.

This wasn't arbitrary. The reference companies — Anthropic, Vercel, Linear, Stripe — share a quality: restraint. Clean layouts, generous whitespace, typography that breathes. We wanted that discipline, but with warmth. The amber palette gives the site a physicality that pure monochrome lacks.

Every effect component serves this direction:

ComponentPurpose
OscilloscopeCanvas waveform — hero background, 404 flatline
Grain textureSVG noise overlay at 4% opacity — film grain
Scan linesCRT horizontal lines on hero sections
Cursor glowMouse-following amber gradient — ambient light
CRT glowHover amber box-shadow on cards
TypewriterCharacter-by-character text reveal
VU meterSVG analog gauge with animated needle

Stack decisions

ChoiceWhy
Next.js 15 App RouterServer Components by default, RSC streaming
Tailwind v4 (CSS-first)Design tokens as CSS custom properties in @theme
Motion (framer-motion)Scroll animations, page transitions, hover effects
next-intlType-safe i18n, EN primary, IT secondary
MDX for blogRich components inside blog posts
Self-hosted fontsNo external CDN, no Google Fonts

The guiding principle: Server Components by default. Only add "use client" for components that need browser APIs — canvas, mouse events, motion, forms. Everything else stays on the server.


Design system

The entire color palette, typography scale, spacing, and transitions live as CSS custom properties in globals.css via Tailwind v4's @theme block. No tailwind.config.ts. No JavaScript token files. Just CSS.

Color Tokens
  • Background: Stone 950 (#0C0A09) — near black with warmth
  • Surface: Stone 900 (#1C1917) — cards, elevated elements
  • Accent: Amber 500 (#F59E0B) — links, CTAs, the signature glow
  • Text: Stone 50 (#FAFAF9) — primary, high contrast
  • Text secondary: Stone 400 (#A8A29E) — body, descriptions

Amber on Stone 950 hits 8.2:1 contrast ratio — AAA. Accessibility isn't an afterthought.

Typography is Inter for body and headings, JetBrains Mono for code. Both variable, both self-hosted, both loaded with font-display: swap.


Blog system

Blog posts are MDX files in content/blog/. Frontmatter parsed by gray-matter. Content evaluated at build time with @mdx-js/mdx and rendered with custom components.

The custom components — InfoBox, ComparisonTable, StepHeader, Quote, StatCard, and others — are injected via the MDX component map. No imports needed in the MDX files themselves.

What This Means

Authors write MDX with components like <InfoBox>, <ComparisonTable>, <StepHeader> — and they just work. The rendering pipeline handles component resolution, syntax highlighting via rehype-highlight, and GitHub-flavored markdown via remark-gfm.


i18n

English is the default locale with no URL prefix. Italian gets /it/ prefix. The as-needed strategy from next-intl means English URLs are clean — /products/darc, not /en/products/darc.

Translation keys cover navigation, headings, CTAs, UI copy, and meta descriptions. Product names (DARC, AEGIS, PRISM) are never translated. Brand terms stay as-is.


Performance

Targets
  • Lighthouse Performance: 95+
  • Lighthouse Accessibility: 100
  • LCP: under 2.5s
  • CLS: under 0.1
  • Initial JS bundle: under 100KB

Canvas animations use requestAnimationFrame. All motion respects prefers-reduced-motion. Images use next/image with AVIF/WebP. Fonts are self-hosted and variable.

The site ships as a standalone Docker container for deployment flexibility, though primary hosting is Vercel.


What I learned

Building a marketing site for your own company is a different exercise than client work. There's no brief to hide behind. Every decision — the amber instead of blue, the oscilloscope instead of a gradient, the grain texture at exactly 4% — is a statement about what the company is.

The site is the first product. If the craft isn't visible here, why would anyone trust the software?

Technology, thoughtfully. That's not just copy. It's the build process.

Back to Field Notes