AmCom

Why there's a site at all

I've always held that anyone who claims to be a developer ought to have some presence on the web — something showing at least a little of what they do for a living. Acting on that took considerably longer than believing it. A personal site is the perfect example of a job that slides quietly down the list the moment paid work turns up.

It began in 2004, and it began about as modestly as it is possible to begin: a handful of hand-written HTML pages in a folder called CV, sitting on the file server in my house. No source control, no build step, nothing anyone would dignify with the word "deployment".

Twenty-two years later it is still going, and it has been torn down and rebuilt more times than I can entirely justify. Each rebuild ran to the same script: notice the web could suddenly do something it couldn't before, decide the site looked dated, start again.

How it got here

The CV — 2004

It didn't stay hand-written for long, and what it became was considerably more elaborate than an online résumé strictly requires. The CV itself moved into a MySQL database, and every page became a PHP script that queried a table, assembled an XML document from the rows, and ran that through an XSLT stylesheet named after the table to produce the finished HTML.

So the front page was page.php?table=tbl_PersonalDetails, rendered by a matching tbl_PersonalDetails.xsl. Education, experience, qualifications and skills each had their own table and their own stylesheet.

It is, on reflection, the most 2004 thing I have ever built. XSLT was widely held to be the future of templating on the web, and for a while a lot of us believed it.

ASP.NET — 2010

What turned it from a CV into a site was the Carbs & Cals iPhone app. It reached the App Store at the end of August 2010, and it dawned on me that people were about to tap through wanting to know who had built the thing. I needed somewhere for them to land, and I wanted that somewhere to double as a showcase of what I could do with ASP.NET.

It looked, unmistakably, like 2010. A sky-blue gradient background. A dark navy bar across the top carrying my name in bold white, with a reflection underneath it. The content sitting in a white panel with rounded corners and a soft drop shadow, centred, at a fixed width. I was extremely pleased with it at the time.

The 2010 site: a white content panel with rounded corners floating on a sky-blue gradient, beneath a dark navy header bar carrying the name Andrew McLachlan

This is also the version that best explains what building for the web actually involved back then. The site had a base Page class whose entire purpose was deciding whether your browser could be trusted:

public bool ModernBrowser
{
    get
    {
        return !((Request.Browser.Browser.Contains("IE") && !(Request.Browser.MajorVersion >= 9))
            || (Request.Browser.Browser.Contains("Firefox") && Request.Browser.MajorVersion < 3));
    }
}

Fail that test and the page quietly swapped its master page for a .CSS2.master variant, and switched you to a stylesheet theme with CSS2 appended to the name. Two versions of the layout, two sets of styles, chosen on the way in.

It is worth sitting with that for a moment. CSS3 — rounded corners, gradients, shadows, the things that now feel like the absolute floor of what a browser does — was a capability you had to detect, with a fallback plan ready for when it wasn't there. And where detection wasn't enough there were props: a copy of PIE.htc to bolt rounded corners and gradients onto Internet Explorer, and SuperSleight.js to persuade IE6 that transparent PNGs were a reasonable thing to ask for.

I wrote a browser-sniffing base class so that I could have rounded corners. That was not an unreasonable thing to do in 2010. It was simply what the job involved.

That class also opens with using Microsoft.VisualBasic;, in a C# file, for reasons I can no longer account for.

Behind the content sat rather more code than the site strictly warranted. I had written my own blog engine, backed by WCF services — one handling authentication and user management, another handling posts and comments — with versioning and controlled publishing, administered from an entirely separate site I had also written. For a blog with, if I'm honest about it, a readership I could count without taking my shoes off.

I don't regret any of it. Writing a CMS teaches you an enormous amount about why CMSes are shaped the way they are.

A new look — 2013

Three years later the site was redesigned rather than rebuilt, and it is the first version whose influence is still visible today. The pale blue went dark. The floating white panel gave way to a full-width photograph with the headline set over the top of it, and a small monogram appeared in the corner. Underneath sat a "Latest Updates" feed.

The 2013 redesign: a full-width photograph of a frosty village and a footpath signpost, with the headline set over it and a Latest Updates feed below

The photography has never left. Every version since has led with a picture, and the site still does.

The typography is where I would rather draw a veil. The headline was set in bevelled, drop-shadowed chrome lettering. It was 2013, and that was briefly something people did.

ASP.NET Core MVC — 2018

In February 2018 the whole thing came out of TFVC — it had been living on Visual Studio Team Services, and the very first commit in the current repository is an import from changeset 196 — and moved to git.

2019 was the busiest year the repository has ever seen, and most of it was catching up with what browsers had quietly become capable of while I wasn't looking. jQuery came out in March, because everything I had been using it for was by then simply part of the language. The rewrite rules moved out of web.config and into .NET Core. web.sitemap, a genuine relic, finally went.

It is also when the tools arrived. The regex tester was the first, in March 2019, and it is the point React entered the codebase — deliberately fenced into the tools and nowhere else. The site itself stayed server-rendered Razor, which it remains to this day. The CIDR calculator followed a week later.

And in April I started, in the words of the commit, "experimenting with a dark theme". It took a fortnight and a theme switcher to get there.

Umbraco — 2022

In 2022 the site moved onto .NET 6 and, more significantly, onto Umbraco 9 — the first version built on .NET Core.

Which meant retiring the blog engine. Twelve or so years after writing a CMS with versioning and controlled publishing and its own administration site, I replaced it with software that did all of that better, and that I did not have to maintain.

That is the thread running through every rebuild on this page: each one hands another job to someone else. My CMS became Umbraco. My webpack config became esbuild. My SASS variables became CSS custom properties. My theme switcher became a media query.

Visually it carried on from where 2013 left off — a full-width photograph behind the strapline, panels in columns beneath it. The chrome lettering, I am sorry to report, survived. And down in the footer sat a "Dark Theme" link, because choosing a theme was still something a site had to offer you by hand.

The 2022 site: a full-width photograph of the Sphinx and a pyramid behind the strapline Some Solutions are Built to Last, with three columns of panels beneath

Umbraco 10 arrived that August, 11 and 12 in 2023, 13 the following May, and it has kept pace since.

How it's built today

The site runs on .NET 10 and Umbraco 18, hosted on Azure App Service and deployed through a staging slot swap, with media in Azure Blob Storage. Content types are version-controlled through uSync, so a document type change is a pull request like anything else.

The front end is deliberately unfashionable. Pages are server-rendered Razor and work perfectly well with JavaScript switched off. React 19 and Redux Toolkit are present, but only inside the tools — the regex tester, CIDR calculator, base64 encoder and colour explorer — where genuine interactivity earns its place.

The build is esbuild for TypeScript and Lightning CSS for stylesheets, both of which replaced heavier predecessors and are close to instant. Styling is plain CSS with custom properties and light-dark(); there is no preprocessor, because there has not needed to be one for years. That footer link asking which theme you wanted is gone — the browser already knows.

Which is the quiet punchline of the whole thing. The current site does far more than the 2004 one ever did, and I maintain considerably less code to make it happen.