This is the code behind my portfolio site, tylerpixel.com.
I'm a designer. Project Upscale was me rebuilding my own website without a website builder — no Webflow, no Framer, no templates — using AI as the pair programmer and staying the one making every call about what it does and how it works.
That's a deliberate choice, not a shortcut. Getting a real, working system out the door and keeping it running is the job. Which tools you reach for to get there matters far less than whether it ships, whether it holds up under a real audit, and whether you're still the person maintaining it two years later.
This one has been live and getting better since May 2024. Every version of it is in this repository's history.
Website builders are quick, and they charge you every month for the privilege. More to the point, they decide things for you. You get the animations they support, the page speed they give you, and the layouts their editor allows. When you want something they didn't think of, you're stuck.
I wanted three things:
To own it. No monthly subscription and no company between me and my own site. Hosting it now costs close to nothing.
To make it fast. Everything a browser downloads before it can show you the
site — the page, the typeface, the way it looks, and everything it does — comes
to about 83 KB. That's a fraction of a single photo off your phone, and it
means the site loads more or less instantly, anywhere. You can check that
number yourself at any time with node scripts/weigh.js, which measures it the
way the browser actually receives it rather than the way it sits on disk.
To be able to follow through. A builder hands you a site you can only change in the ways it allows. Here nothing is off limits, because I know where everything lives and why it's built the way it is. Every colour, every animation, every keyboard shortcut is something I can go and change this afternoon — and the site is better than it was at launch precisely because I keep doing that.
A portfolio with five sections — Intro, Selected Works, Store, Writing and About — that behave like one continuous app rather than separate pages. Nothing reloads. Panels fade between each other at one consistent speed.
Some of the details I'm happiest with:
- A command palette. Hit
⌘Kand jump anywhere, the way you would in a code editor or Linear. Arrow keys and number keys work too. - Sound. Hovering, clicking and typing make quiet, tactile sounds — and not one of them is an audio file. They're generated by the browser as you go, so the entire set adds about 2 KB. There's a switch to turn them off.
- Light and dark. A full dark theme, and a settings panel to choose between them or follow whatever your computer is set to.
- Case studies with proper next/previous navigation, a photo lightbox, a merch store, a booking calendar, and a contact form that actually emails me.
The interesting constraint: there is nothing to install. No npm install,
no dependency folder, no framework, no build system to learn. Clone the
repository, point a local server at it, and it runs. The two small tools that
shrink the code before it goes live are fetched when needed and never stored
here.
| Written in | HTML, CSS and JavaScript. That's the whole list. |
| Lives on | Cloudflare, at the edge — served from a data centre near whoever's visiting |
| Content | All the words and images live in one file I edit through a small editor that runs on my own machine, so updating the site never means touching code |
| Publishing | One command builds it, stamps a version number on it, saves it to GitHub and pushes it live |
| Weight | Measured, not guessed. scripts/weigh.js reports what a cold visit actually costs, compressed the way the CDN compresses it |
Three things earn most of that speed, and each one is a build step rather than a rule anybody has to remember:
- The typeface is cut to fit. DM Sans ships around 400 characters per weight. The site is English in two weights, so each one is cut down to what a keyboard can actually type — letters, numbers, punctuation — plus the currency symbols, the copyright marks, and the handful of typographer's characters the writing already uses, like proper apostrophes and em dashes. Everything else, chiefly accented letters, goes into a second file the browser fetches only if a page ever needs one. Almost nobody does. The type that loads on a normal visit went from 73 KB to 24 KB, and the single-storey g the whole site is set in survives the cut — the build fails outright if it ever doesn't.
- Images are sent at the size they're shown. Every case-study image renders in a 360-pixel column, and the files behind them were up to 2000 pixels wide. Each now has a display-size copy alongside it, and the full-resolution original is still exactly what the lightbox opens.
- The comments don't ship. The page's source is full of explanations of why things are the way they are. They're stripped on the way out and kept in the repository, so the reasoning survives without anyone downloading it.
The design side is handled the same way a design system would be. Every colour, size, corner radius and animation speed is defined once at the top of the stylesheet — a control panel. Change one number there and it moves everywhere it's used. That's how the dark theme was added without rewriting the site: each colour simply gained a second value.
Lighthouse is Google's standard health check for websites. Run against the live site in August 2026, out of 100:
| mobile | desktop | |
|---|---|---|
| Performance | 100 | 94 |
| Accessibility | 100 | 100 |
| Best practices | 100 | 100 |
| SEO | 100 | 100 |
Mobile is the one Lighthouse reports by default and the one that matters most, since it assumes a slow connection and a modest phone. Performance was 92 before the page was put on a diet.
Desktop sits at 94 for a duller reason than it sounds: it grades against a fast connection, where the same 1.3-second largest paint that scores full marks on mobile is merely fine. Nothing renders differently. The only thing it flags is that the stylesheet and the tiny theme script block the first paint — and the theme script blocks on purpose, because applying a stored dark mode after the first paint would mean showing a white page first.
Layout shift is zero and blocking time is zero on both, which is the part I'd actually defend: nothing on the page jumps around while it loads, and nothing locks up the browser while it starts.
Accessibility at 100 is the one I care about most. The whole site can be navigated by keyboard alone, the text colours were picked against a contrast floor rather than by eye, and it all still reads correctly to a screen reader.
A site I control completely, that costs almost nothing to run, that I can update in minutes, and that I can keep pushing whenever I want to try something. The interaction sounds and the dark theme were both added long after it first went live, and neither needed the foundations disturbed to do it.
That's the part worth pointing at. Anyone can get a website made — plenty of tools will hand you one this afternoon. Working out what it should do, getting it built and live, holding it to a real standard, and still being the person maintaining it two years later is a different thing entirely.
That's problem solving, and it's what I actually get paid for.