kingtan.com.au
I designed this site. AI built it. I opened an empty repo on 8 June 2026 and the site went live on the 18th. Since then I have added a CMS, a deploy that shouts when it breaks, a glass design system and three case studies. Every step is a commit, and you can scrub through all of them below.
01The build, day by day
Every bar is a day and every stop is a decision. The bars count commits to the site, from the first homepage on 10 June to the build that published this page. Hover a bar for its day. Tap a stop, drag the scrubber or swipe the strip for what I decided, what AI built and what I learned; the bar under each stop is my estimate of how the work split between the call and the code.
The first homepage, and the plumbing
Start with the page that matters. A homepage grid of video tiles before any project page, and a way to ship it before anything else.
The grid on the Monday night, Astro and a visual CMS the next day, then a GitHub Action that built the site and pushed it to my old host over FTPS.
Ship the plumbing on day two. Every change after that had somewhere to go.
Started again, dark
Throw the first version away after two days. Dark canvas, one accent, and the work carries the colour.
A second scaffold, motion-led from the first commit, with a drag-to-order project list in the CMS in place of a priority number.
A restart on day four is cheap. The same restart in week four is a rebuild.
Banners as live ads
HTML5 banners belong on the page as the real ads, at true pixel size, grouped by size with a replay button.
Labelled banner suites with dividers, a hide-from-site toggle, and cache headers that revalidate HTML and pin hashed assets.
State the rule once, real ads at true size, and every new size lands in the same layout.
The deploy that shouts
A broken build had frozen the deploy without a word. I wanted my phone to buzz.
A Telegram push on deploy failure, proven with a deliberate build break and a revert, plus the Sydney Metro banners hosted same-origin so ad blockers leave them alone.
Test the alarm by setting the fire. Forty commits that day, the busiest of the build.
Every project, through the CMS
Load the work myself, project by project, through the CMS and nothing else. If it hurt, the CMS was wrong.
A fix for the duplicate slug that broke the order picker, the hero copy, the marquee, the page title, the capabilities and about copy.
Entering your own content is the review no AI can do for you.
Live, 16:15
Go live on a Wednesday afternoon, with the canonical domain and a guarded production deploy in place first.
The client logo grid, the EDM showcase, canonical URLs, the production deploy, and the homepage copy made CMS-editable the same evening.
Live is a commit like any other. The site went up at 16:15 and I was editing copy by 17:17.
The first write-up
Write the build up while it was fresh, as a deck at /case-study, and fix what the writing showed me.
The deck, one-at-a-time video playback with play and pause, an accent progress bar on gallery videos, count-up stats on the About section.
Writing it up showed me three rough edges the build had skipped past.
Logos, sizes, a way to measure
Measure without cookies. One script, named events on the calls to action.
Umami analytics with click events, Aldi Mobile and Alinta in the logo grid, a 1190x250 banner size in the CMS.
Add the measuring before you need the answer.
Case studies, two decks
Retitle every study 'with AI'. The tool's name goes in the body, never the headline.
The AMP interview task as a live presentation site, the case-studies hub, the 'Ready when you are.' study, both decks matched to the site's brand lockup.
A title that names the tool reads as the tool's work. The decisions were mine.
The July pass
Have AI audit the running site, then work the list: weight, motion, clarity. And no hover on anything that is not a link.
Self-hosted GSAP and fonts, Flip only where used, a copy-email toast, a full-screen mobile menu, a glitch 404, the pen-trace hero, a light theme with a wipe.
Static content with a hover state fakes a link. That rule now covers the whole site.
Cloudflare, one origin
Leave shared hosting. DNS on Cloudflare, the site on Pages, every asset in the repo, and the site readable by answer engines.
The Pages deploy through wrangler, 2,700 banner files mirrored in, old WordPress URLs redirected, llms.txt, a FAQ with schema, a fuller Person record.
The apex served the old host's frozen build for four days after cutover. Check where the domain points before you check anything else.
Facts only, credited
Where a banner suite ran through Adobe Animate the page says so. 'Hand-coded' only where it is true.
Process notes on every project, 27 press credits grouped by campaign, the Notes section with dated schema, Behance and Vimeo wired both ways.
AI drafted 'hand-coded' for five projects that ran through Animate. The correction is one sentence in CLAUDE.md, and it has held.
Glass, all the way through
One glass recipe for every control, gold for the selected chip and nothing else, and the light theme gone until glass has a light variant.
The crystal hero, the glass pass, the hub as a real page, thumbnails at the size a screen needs (1.5 MB down to 170 KB), a copy scan that runs on every save, and the site moved into its own repo with its history.
Headless Chromium said the header was fine. WebKit was blanking it on scroll. A phone bug needs a phone.
Print joins the grid
Print earns a filter once there is work to fill it: three campaigns from my finished-art years.
Underbelly, City Homicide and Top Gear, a Print filter derived from the work, and image optimisation that runs inside the deploy.
The filter row comes from the work, so a category can never show an empty grid.
Metcash, three ways
Show the studio work: one loyalty layout skinned three ways, three catalogues under three rulebooks.
Two project pages with grouped galleries, and the Interactive category.
Re-saving a project in the CMS wrote the old .jpg names over the .webp files and killed seven images on a green deploy. Green is not the same as right.
Studio Daybreak, a page not a deck
The third case study as a page with four things to play with, in place of another deck.
An Astro page, four widgets, one dataset of invented jobs and real rules.
A deck tells. A page lets you drag the handle. This study followed a day later.
This page
Replace the deck you would have read with the page you are on: the whole build, live numbers, and the site's own parts to play with.
This page, and the script that counts the site's commits inside every deploy.
A case study that counts its own commits cannot go stale. The number at the top came from the build that published it.
Sydney timeJune from the old workspace, July on from this repo's own historyTap a stop, drag the scrubber, or swipe the strip
02Flat to glass, drag it
On 17 August the header was a bar and every control on the site was a hairline: a mono label, a border, a solid gold fill on the selected chip. On the 18th the bar went and they all became glass. Drag the handle across the same header, the same filter row and the same work card. The markup is identical on both sides; one recipe in the stylesheet changed.
Drag the handleLeft, the site on 17 AugustRight, the site today, same markup
The recipe is one fill, one frost and one lit edge, shared by the nav, the wordmark, the menu button, the chips, the pager and the footer bar. I tuned it against real work sitting behind it, so a label stays readable over a white poster frame as well as a dark one. The gold stayed where it was: on the selected chip, and nowhere else.
03One accent, and it means on
Every yellow on this site marks something that is on, happening or just happened: the selected chip, the playhead, the copy toast. No resting control wears it. Click a chip and the gold moves with you. Then give every chip the accent and watch the row stop meaning anything.
The chip row
One gold chip: the category you are looking at.
The toast
The footer's copy button, unchanged. Press it: the accent toast says what just happened, the one job the accent has.
The card
The homepage card, link and all. Hover it for the crop marks and the accent title; both are allowed, because it goes somewhere.
The pill, on the bench
Move the sliders. The first pill rests, the second is on.
Every control here is the site's own classHover only where a click goes somewhere
The recipe on the bench is the real one: 2px of frost, a 40% black scrim, a rim at 49%. The ON chip is the same glass with gold in place of the scrim, because gold over a black wash reads as army green, the trap that killed the light theme. Nothing here hovers unless a click goes somewhere.
04Push, and it's live
Every save in the CMS and every merge is a push to main, and a push starts this. Press play: sixty-three seconds run in eight. The stages are the real ones from deploy.yml, timed from run 171 on 9 September. Flip the switch to break the build and watch what shouts.
Serving the last good build while the runner works.
63 seconds in 8Stage lengths measured on run 171, 9 Sep 2026; the stats step joined after it
The site never goes dark during a deploy, or after a bad one: Cloudflare keeps serving the last good build until a new one lands. Since 17 August a failure can no longer be silent either. A watcher outside the deploy sees the conclusion however early the job died, opens one tracking issue, pushes a line to my phone, and closes the issue on the next green run.
05Edit in the browser, no code
Every project on the site is one JSON file, and the CMS at /admin is a form over it. This is that form for TAL, with the card and the homepage filter row wired to it. Change anything. The row rebuilds itself from the work, so a category button exists only while one project carries it: add a category and watch the button appear, untick it and the button goes.
{
"title": "TAL",
"slug": "tal",
"client": "TAL",
"year": 2019,
"cat": [
"Motion"
],
"services": [
"Motion Design",
"Animation",
"Social Design",
"HTML5 Development",
"Multi-Size Adaptation",
"Ad-Spec Build"
]
} The CMS is Sveltia, at /adminNothing here saves; the real one commits to main
Save in the real CMS and this JSON is the commit; the deploy above runs on it and the card is live a minute later. I load every project this way myself, which is the review no AI can do for me: if a field hurts to fill in, the form is wrong. The category list is a dropdown in the CMS config: a new value there is one line, and its button shows on the homepage the moment a project carries it.
06Built to be read by AI
A page has three readers. A visitor sees the card. Google reads the structured data under it. An answer engine reads /llms.txt, a plain-text summary of the whole site that the build writes from the same JSON. Switch the tabs; it is the same TAL project each time.
Digital work for TAL's "Scars", the brand platform positioning the life insurer as Australia's "Human Insurer," using scars as symbols of strength and a life lived. A DOOH spot and a Financial Standard publisher takeover, both holding the campaign's quiet tone.
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://kingtan.com.au/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Work",
"item": "https://kingtan.com.au/#work"
},
{
"@type": "ListItem",
"position": 3,
"name": "TAL",
"item": "https://kingtan.com.au/work/tal/"
}
]
},
{
"@type": "CreativeWork",
"name": "TAL",
"url": "https://kingtan.com.au/work/tal/",
"creator": {
"@type": "Person",
"@id": "https://kingtan.com.au/#person",
"name": "King Tan"
},
"description": "Digital work for TAL's \"Scars\", the brand platform positioning the life insurer as Australia's \"Human Insurer,\" using scars as symbols of strength and a life lived. A DOOH spot and a Financial Standard publisher takeover, both holding the campaign's quiet tone.",
"datePublished": "2019",
"text": "\"Scars\" asks for stillness. The campaign's power sits in its portraits and its restraint, so the DOOH spot animates with slow reveals and quiet type, asking no urgency of the viewer.\n\nI carried the system into a Financial Standard publisher takeover, display units and an EDM, holding the \"Human Insurer\" tone in placements where insurers shout."
}
]
} The JSON-LD the work page carries: a breadcrumb trail and a CreativeWork, built from the same file the card reads.
# King Tan — Digital Designer, Sydney, Australia … ## Selected work - [TAL](https://kingtan.com.au/work/tal/) — TAL, 2019. Digital work for TAL's "Scars", the brand platform positioning the life insurer as Australia's "Human Insurer," using scars as symbols of strength and a life lived. …
An excerpt. The full file is at , rewritten by every build./llms.txt, rewritten by every build.
Verified 17 August 2026, redirect-check run 32010039724: each agent gets 200 on the homepage and on a work page, and robots.txt carries no AI directives.
Same project, three readersllms.txt is a build-time endpoint, never hand-edited
The AI crawlers were 403-blocked at Cloudflare's edge until July, so nothing could cite the site. A weekly probe now sends fifteen user agents at the homepage and a work page and expects 200 from each; the check that settled it ran on 17 August. Ask an AI who I am, and it has what it needs.
07What I learned directing AI
- Taste still leads.
The art direction was mine on day one and it is mine now: the dark canvas, the single accent, the rule that gold means selected. AI made executing it cheap enough that I restarted the site on day four without flinching.
- Rules live in a file, not in my head.
Every pitfall goes into CLAUDE.md with a date, and the next session reads it before it touches anything. The case-sensitivity trap that once lost a Sydney Metro banner is a guard in the deploy now.
- Re-fetch before you diagnose.
A weekly health check once ran against a clone 98 commits behind and reported two problems I had fixed the week before. A session now fetches the latest main before it reads any file as current, and again before it pushes.
- Green is not the same as right.
A missing image under public/ is not a build error, so a deploy can pass with seven dead images on a project page. It happened once, after a CMS re-save wrote old filenames back. Screenshots before 'done', every time.
- A phone bug needs a phone.
Headless Chromium swore the header was fine on scroll. WebKit was blanking a fixed element with a backdrop filter, in every iPhone browser. The fix was one line. The hour before it went on evidence from the wrong browser.
- Name the tool in the body, never the title.
'Building kingtan.com.au with AI' is the headline on every study, and the tool's name sits in the copy. A title that names the tool reads as the tool's work, and the decisions were mine.
08By the numbers
in the site's own repo; June lives in the old workspace
the rest are mine, through the CMS or my Mac, plus a few by the deploy
since 16:15 on 18 June 2026
23 motion, 8 static, 4 print
186 of them live on project pages
the site's freshness signal, one JSON each