# Auralis Agency Site

*Selling AI automation leaves an agency only its own site as proof. I specified all forty routes first.*

**Category:** WEB PLATFORM / MARKETING SITE
**Status:** in progress
**Period:** 3–5 July 2026
**Built by:** HM Ammar, Digital Architect & Head of IT, Kuala Lumpur

**Stack:** Next.js 15, React 19, TypeScript, Payload CMS 3, PostgreSQL, Tailwind CSS v4, Motion, Zod

## The challenge

An agency selling AI automation and design has only its own site as proof. So it needed real conversion machinery, not a contact form: a scoped quote path, working lead tools, a services and content architecture deep enough for search. The other constraint was scale. Forty routes, sixteen Payload collections and a full design system is more surface than I can hand-write, and the usual shortcut — a headless CMS running as a second service — adds a network hop, CORS and API keys to every page render.

## What I built

I wrote the specification first: eleven documents, about 7,600 lines covering the sitemap, design tokens, every page, the CMS schema and the component API tables. I then had parallel agents build against a verbatim build contract, phase by phase, with an adversarial review pass and a green typecheck before each merge. The result is a single Next.js 15 app with Payload CMS 3 mounted inside it under a separate route group, so content is read through the Local API with no HTTP hop. Forty frontend routes, sixteen Payload collections, eighteen page-builder blocks and around 100 components sit on a dark glass design system driven entirely by CSS variables.

## The detail

### Specification first

Eleven documents covering the sitemap, design tokens, every page spec, the CMS schema and the component API tables, all written before I wrote the first line of code. Parallel agents then built against a contract I pinned to the file layout, the token names and the component APIs so nothing drifted between them. One agent owned one file, two concurrent agents never wrote the same file, and anything capped or skipped had to be logged rather than read as done.

### Scrubbed video hero

The home hero is a pre-rendered clip whose currentTime I drive from scroll progress through Motion's useScroll, eased toward the target inside a requestAnimationFrame loop so arbitrary seeks stay smooth instead of snapping. I re-encoded the clip to H.264 with a keyframe every four frames to make those seeks cheap, taking it from 2.8 MB to 669 KB. It costs a scroll listener rather than a WebGL bundle; reduced-motion and no-JS fall back to a 23 KB WebP poster marked decorative.

### Audit without Chromium

My public audit tool fetches a stranger's URL server-side with a ten-second timeout and a 2 MB body cap, then grades it across four weighted categories using regex over the raw HTML, a robots.txt probe and an http-to-https redirect check. No DOM and no headless browser, so a run finishes fast enough to feel instant. I render the score inline on the page rather than sending it by email, and persist it as structured toolData on the lead so sales sees exactly what was wrong with the prospect's site.

### One form spine

I run contact, book-a-call, newsletter, quote wizard, ROI report and audit through the same server-action sequence: honeypot, Turnstile, Zod, a Payload Local API write, then Resend. Email is fire-and-forget, so a mail failure never costs a submission and a storage failure still returns the visitor their audit score. The leads collection disables public create entirely, and I gave email, phone, toolData and request metadata field-level access limiting them to authenticated CMS users.

### One-file retheme

The original palette was the generic violet-to-cyan AI look. Because every colour resolves through CSS variables bound to Tailwind v4's @theme inline, swapping to emerald, teal and gold on teal ink meant editing the token block in globals.css plus the two literals that sit outside the variable system, the OG image route and the global error page. I retuned both light and dark themes for AA contrast in the same pass, in roughly 100 lines.

## The outcome

Eleven commits took it from scaffold to signature hero in two days. Every route renders against a seeded Postgres and the typecheck runs clean. My six Playwright smoke tests cover the home, service-pillar, work, blog, SEO-endpoint and theme surfaces; the three conversion journeys the specification called for are not covered yet. I committed Lighthouse budgets as config rather than measuring them, since I never installed the runner. It is not deployed, the brand name is still the placeholder I wrote the specification around, and I stopped mid-iteration on the hero: I was not satisfied that the scroll behaviour read as original, and was sketching a successor before the thread ended.

---

[All work](https://hmammar.world/) · [HTML version](https://hmammar.world/work/auralis.html)
