My own studio · Flagship case

Jardine Studio

A production web platform I designed, engineered and operate: the marketing site, a publishing system, free analysis tools, a lead pipeline and paid-search landing pages, secured and tested like a product.

RoleFounder, designer, engineer
StatusLive · 982 commits since May 2026
Built withNext.js, React, TypeScript, Redis

The short version

What it is

Jardine Studio is my web design, development and SEO studio in Toronto. jardinestudio.com is its storefront, its proof of work and its lead engine, built and run entirely by me.

What I built

A Next.js platform with schema-driven content, an MDX journal, three free tools, emailed PDF reports, consent-aware conversion tracking, paid-search landing pages and an admin lead dashboard, behind a deliberate security model.

Why it stands out

It is the kind of system agencies build with a team: 982 commits, 845 automated tests and a written security model, designed, engineered and operated by one person.

Current Jardine Studio desktop homepage in dark mode: a gold ordered-dither field, the headline Websites, systems, and search. Built around your business, and a row of client logos.

The live homepage in dark mode, captured 4 October 2026. The gold field is generated, not photographed.

By the numbers
982Commits8 May to 2 October 2026
845Automated tests710 unit and 135 browser tests
11API routesEvery state-changing route origin-checked; 10 of 11 rate-limited
3Free toolsSEO audit, cost calculator, CMS fit finder

Counted from the repository on 4 October 2026.

01 · Scope

Not a brochure.
A platform.

Four jobs share one codebase, one content model and one design system. Each is ordinary on its own. The work is making them reliable together.

01 · Publish

The public site

  • Service pages from a shared, validated schema
  • MDX journal with related reading
  • Work, proof and local landing pages
  • Central metadata, canonicals and sitemap rules
02 · Analyse

Free tools

  • SEO audit: bounded crawl, scored findings, emailed PDF
  • Website cost calculator with honest scope states
  • CMS fit finder
  • Results that carry into a pre-filled brief
03 · Grow

Acquisition

  • Five paid-search landing pages
  • Consent-aware GA4 and Google Ads conversions
  • First-party attribution for every lead
  • IndexNow submission script
04 · Operate

Behind the scenes

  • AWL, a schema-driven content editor
  • Protected lead dashboard
  • Managed redirects; 410 Gone for retired articles
  • A written data-retention schedule
02 · Security

Public tools are
an attack surface.

A free audit fetches any URL a stranger types, renders PDFs, sends email and stores leads. I treated each of those as a risk with a named control, then tested the control.

Risk, control and how it is checked
RiskControl in the codeChecked by
A visitor’s URL points the crawler at internal systemsSSRF-safe fetcher: every hostname is resolved and must be a public address, re-checked on each of up to five redirects, under one deadline.Dedicated SSRF test suite
Bots run up crawl, PDF and email costsRedis sliding-window limits per action, such as three SEO crawls an hour. In production, if the limiter is unavailable the route refuses with 503 instead of running unprotected.Route tests for limits and failure
Another site submits requests on a visitor’s behalfOrigin and Referer validation on state-changing API routes.Route tests
Oversized or malformed request bodiesBounded readers with per-route limits between 1 and 8 KB, strict UTF-8 decoding and content-type checks.Unit tests
Someone else opens a private reportHMAC-signed unlock tokens bound to the audit and the email address, expiring after 24 hours, verified in constant time.Unlock route tests
Guessing the admin tokenConstant-time comparison of SHA-256 digests, a server session and 10 attempts an hour.Admin action tests
Injected scripts or clickjackingContent Security Policy per surface: app pages cannot be framed; client demos run under a scoped, hash-pinned policy with violation reports sent to a rate-limited endpoint. HSTS with preload and a restrictive Permissions-Policy.Security tests and a production health suite

From the source and test files. Rules for changing a policy live in a written security operations guide: a named requirement, minimum hosts, a privacy review and updated tests.

03 · Decisions

What I chose,
and what it cost.

Fail closed.

Chose
If the rate limiter is unavailable in production, expensive routes return 503.
Instead of
Running unprotected when Redis is down.
Trade-off
Abuse protection can never silently switch itself off.

Separate demo policy.

Chose
Client demos get their own hash-pinned CSP, framed only by the site.
Instead of
Loosening the app policy so every demo works.
Trade-off
Each new demo script must be registered and hashed; the app policy never weakens.

Retire content honestly.

Chose
Retired articles return 410 Gone with noindex.
Instead of
Redirecting everything to the homepage.
Trade-off
A small list to maintain, and search engines get an accurate signal.

Carry choices, not people.

Chose
Only validated, finite scope options travel in shareable links.
Instead of
Putting names, emails and free text in the URL.
Trade-off
A link restores a scope, not a conversation, and personal data never ends up in forwarded links.
04 · Quality

Tested like
a product.

Pricing rules, crawl budgets, tokens and security headers are exactly the things that break quietly. They have tests, and production gets its own health checks.

710unit tests in 121 filesVitest: pricing, scope rules, audit checks, security policy, tokens, rate limits, routes
135browser tests in 13 specsPlaywright: calculator, contact handoffs, funnels, navigation, landing pages
  • Accessibility. axe checks on key routes, the open mobile menu and modals, plus 44px target sizes and keyboard focus through the CMS fit finder.
  • Production health. Asserts the security header baseline, the demo CSP exception, canonical redirects, valid JSON-LD and a cacheable response for Googlebot.
  • Written operations. Security, release QA and media pipeline guides, so changes follow the same checks every time.
05 · Engineering

A free audit that
survives the internet.

The SEO audit crawls up to 25 same-origin pages within a 45-second budget and byte limits, runs PageSpeed on the homepage in parallel, and scores findings against the pages it actually reached. If discovery is cut short, the report says so.

The full report unlocks by email with a signed token and renders to PDF on the server. Rendered PDFs are cached for a day under a 4 MB cap, and audit state expires on a schedule.

From URL to report

  1. Validate and limitURL normalised, body bounded, origin and rate checked
  2. Crawl safelyPublic addresses only, redirect by redirect
  3. Check and scorePage checks, sitemap, robots, PageSpeed
  4. Report on screenFindings with coverage stated
  5. Unlock by emailSigned token bound to audit and address, 24 hours
  6. Render the PDFServer-side, cached and size-capped

Simplified from the implementation.

06 · Product

One tool,
end to end.

The cost calculator shows the product thinking in miniature: it prices what is defined, names what needs discovery and hands the visitor’s choices to the contact form.

Step 1 · Price the defined scope

Calculator result: a planning range of 2,400 to 3,100 Canadian dollars before tax for a new site with 4 to 7 main pages, with Discuss this scope and Copy scope link buttons.
  1. A range, not a quote. Rounded, before tax, labelled in CAD.
  2. One clear next step. The primary action leads to a conversation, not a checkout.
  3. The variance is stated. 30% headroom for normal variation, in plain words.

Live calculator, illustrative configuration, captured 4 October 2026.

Step 2 · Add something uncertain

Calculator result labelled partly priced: 3,000 to 3,900 Canadian dollars for a 4 to 7 page rebuild, with content and data migration listed under Needs a conversation.
  1. The status changes too. “Partly priced” warns before the number is read.
  2. Unknown work is named. Migration moves into its own box instead of inflating the range.

Same live calculator, rebuild with migration, captured 4 October 2026.

Step 3 · Hand over the brief

Contact form with Website build or rebuild selected and the message pre-filled with the project, pages, features, updates and timeline.
  1. Already classified. The inquiry type is chosen for the visitor.
  2. An editable brief. Scope and features are written in; the visitor adds context.

Live contact page, captured 4 October 2026.

07 · Growth

Measure leads
without leaking people.

Paid search only works if Google learns from real inquiries. The site reports accepted leads to GA4 and Google Ads from the same confirmed submit that writes its own first-party record, under consent and privacy rules that hold even when something fails.

Consent first
  • Separate analytics and advertising choices, renewed after 180 days
  • Unavailable storage never counts as permission
  • Tags are environment-gated; an unconfigured build ships none
One confirmed submit
  • First-party attribution records the journey
  • GA4 and Google Ads receive the same accepted lead
  • Smart Bidding gets accepted leads as its signal
Privacy by design
  • Fixed channel labels only; free-text campaign values can hold personal data
  • Audit state kept 72 hours, raw results 7 days
  • Audit, lead and metrics records each have a retention period
08 · Content

Edit content.
Keep the design.

Service pages are structured JSON validated against one shared schema. AWL, the editor I built for the site, generates its fields from that same schema, so the editor and the renderer cannot quietly disagree.

Metadata and canonicals follow central rules, the sitemap respects publication status, and an architecture map supplies related services and reading. A new page type still needs schema and design work, by design.

Inside the editor: AWL

One content contract

  1. Shared schemaZod definitions for service pages
  2. AWL editorFields generated from the schema
  3. Site loaderValidates fields and slugs before rendering
  4. Published pageShared layout, metadata, sitemap, related links
09 · Identity

Stock skyline
to its own signal.

The first version leaned on a photographed waterfront. The current one generates its identity: an ordered-dither field in the same print-inspired language as the type. Drag to compare.

Current homepage with the gold dither field.
Earlier homepage with a photographed city waterfront and the headline You built a real business.
EarlierCurrent
The earlier design as previously shown in this portfolio, and the current design captured 4 October 2026.

Owned, not borrowed.

A skyline could belong to any Toronto business. The dither field comes from the design itself.

Ordinary state first.

A finished CSS treatment sits underneath. The shader starts after load and an idle moment, and motion or data-saving preferences keep it off.

Built to recover.

It pauses when hidden and restores itself if the browser drops the graphics context.

10 · Where it stands

Live, maintained,
still shipping.

Shipped
  • Marketing site, journal and local pages
  • SEO audit with emailed PDF reports
  • Cost calculator and CMS fit finder
  • Five paid-search landing pages
  • Consent-aware conversion tracking
  • Admin lead dashboard and AWL editor
Engineering

982 commits in five months, 845 automated tests, a written security model, CSP reporting and production health checks.

Built with

Next.js 15, React 19, TypeScript, Zod, MDX, Upstash Redis, Resend, React PDF, Three.js, Vitest and Playwright, on Vercel.

Need a site that does more than introduce you? Start a conversation

All projects ↗
Contact

Available for select projects and opportunities

Have a website that needs to win work?

alex@jardinestudio.com

Let’s work together. Have a project in mind or a role you’re hiring for? I’d like to hear about it.

Open email app
Toronto, Canada · --:--Working remotelyLinkedIn (opens in a new tab)