Sign in

Harry Roberts

@csswizardry.com
6.4K followers 196 following 427 posts

🚀 Independent Web Performance Consultant • Speaker • Google Developer Expert, Web Performance • Accepting new clients • harry.is/for-hire

PostsRepliesMedia
Harry Roberts @csswizardry.com · 28/09/2026
Tomorrow, I’m starting a new project with LEGO. Look how excited I am!
An AI rendering of Harry Roberts as a LEGO man. He’s wearing a pink shirt and dark jeans and is gesturing as though speaking/presenting.
3370
Harry Roberts @csswizardry.com · 09/09/2026
I have ChatGPT read my `.vimrc` and send me a daily #Vim tip to read with my morning coffee.
040
Harry Roberts @csswizardry.com · 04/09/2026
I’ve always had a very good habit of `[TAGGING]` things like calendar events or Jira titles and the like — it makes it so much easier to find arbitrary topics with simple grep or search. It turns out it’s *incredibly* useful in this agentic world!
030
Harry Roberts @csswizardry.com · 03/09/2026
I really don’t think it’s that deep though man. I’m trying to support an indie builder by gifting something in return for trying to get them some more exposure. It’s an app that I use regularly and really want to see them win.
110
Harry Roberts @csswizardry.com · 03/09/2026
It’s not an ad. But the app was made by a friend of mine and I am trying to share and support it. I am fully paid up and I do want to see them win. Gifting a license as a result. It’s $189 and they only do lifetime licenses anyway.
100
Harry Roberts @csswizardry.com · 03/09/2026
I’ve been using @talat.app for a few months now and it’s completely changed how I handle meetings. I’ll prime Codex for an upcoming call and what I need out of it, then point it at the Talat MCP and get it to extract the bits that are meaningful.
220
Harry Roberts @csswizardry.com · 03/09/2026
I added BCP 14 rules to `AGENTS.md`. Let’s see if/how that helps when writing spec-like prompts.
### Interpret Requirement Keywords Consistently

Interpret requirement keywords in Harry’s input in accordance with BCP 14 when, and only when, they appear in all capitals. Give forms that are not in all capitals their ordinary English meanings. Apply the same rule to third-party input when the context reasonably suggests that the author intended BCP 14 usage. Uppercase keywords do not by themselves make the input contractual or formally normative.

If a keyword’s meaning, feasibility, priority, or interaction with another instruction is uncertain, ask a focused clarifying question before proceeding. Name the conflict and its practical consequence; for example: ‘You said `MUST`, but the current API cannot satisfy that requirement. How should we proceed?’ Treat this as an illustrative pattern, not an exhaustive scenario.
120
Harry Roberts @csswizardry.com · 22/08/2026
Dry-run. Unreal.
000
Harry Roberts @csswizardry.com · 22/08/2026
Today, I walked around Costco snapping photos of meat labels. I slung them all into my own personal chef GPT, Pierre. 👈 This was my input and 👉 That is their output. For <£400 all in, I’m eating like a king five days a week up until 19 November.
ChatGPT prompt detailing exact instructions for designing meals around my calendar.Calendar events that my ChatGPT pal, Pierre, has earmarked for me. Live in Google Calendar.
170
Harry Roberts @csswizardry.com · 20/08/2026
Instead of asking Codex to look in Gmail for ‘[subject]’ (risky and prone to duplicates or misinterpretation), head to ‘Show original’ and use the RFC 822 `MESSAGE-ID` (from 1982!) to target an exact specific message. From there, it can surface the entire visible thread.
250
Harry Roberts @csswizardry.com · 31/07/2026
I’ve started including a `mission-statement.md` alongside my project-level `AGENTS.md`. It contains philosophical notes about the project: why it exists, what questions it exists to answer, what ‘good’ looks like, etc.
Three vertically stacked Vim windows showing Markdown mission statements for different client engagements. Each document begins with a heading and concise project summary. Client names have been replaced with placeholders and identifying path information is redacted.
2441
Harry Roberts @csswizardry.com · 15/07/2026
Yeah, I recently added this to mine: github.com/csswizardry/...
110
Harry Roberts @csswizardry.com · 08/07/2026
If you’re doing any reasonable amount of performance work, ensure you have a fresh browser profile with no ad blockers installed, and ensure this is unchecked (Chrome)! You’re only getting part of the picture otherwise.
160
Harry Roberts @csswizardry.com · 29/06/2026
For the last month or so, I’ve been playing Wordle against ChatGPT and keeping track of our scores. It’s incredibly close, but I’m just winning.
ChatGPT screenshot showing a Wordle leaderboard. Of 27 games played, it shows that I’ve spent 103 total guesses (for an average of 3.81/game) to its 107 (3.96 average).
220
Harry Roberts @csswizardry.com · 26/06/2026
My lunch the other day was a chicken sandwich with herby mayo and crispy chicken skin and I miss it so much 😭
020
Harry Roberts @csswizardry.com · 25/06/2026
It’s true…
Harry Roberts presenting on stage at Developers Up North beside a large slide reading ‘that shouldn’t have been an spa’. Audience members are seated in the foreground while he speaks from behind a lectern with a laptop.
4104
Harry Roberts @csswizardry.com · 27/05/2026
Woohoo! That was fun. And so nice to give a talk on home turf.
Harry Roberts presenting a web performance talk at LeedsJS, speaking beside a slide reading ‘build for the web, build on the web, build with the web’ during a talk on platform-first web development and modern front-end architecture.
020
Harry Roberts @csswizardry.com · 09/04/2026
PSA, this is why you keep seeing Times New Roman all over your site. #CSS #CLS #Typography
/**
 * FONT-FAMILY
 * ===========
 *
 * font-family rules do not ‘inherit’ or fall back; they’re standalone
 * declarations. This means any emissions or errors in the current element’s
 * font-family declaration won’t fall back to a parent’s font-family, but to the
 * browser’s default for that element.
 *
 * This is why you’ll often see a flash of Times (New Roman) in place of
 * something more suitable.
 *
 * It’s vital that, in order to avoid layout shifts and unsightly fallbacks, you
 * should always specific a complete font stack for font-family rules, and not
 * just a single value.
 */

body {
  font-family: system-ui, sans-serif;
}

/**
 * INCORRECT
 * =========
 *
 * While your custom web font is loading, the following does NOT fall back to
 * the parent’s font-family (system-ui/sans), but to the browser’s default font
 * family for this element (usually serif).
 */
h1 {
  font-family: Open Sans;
}

/**
 * CORRECT
 * =======
 *
 * Delete the leading underscore.
 *
 * Now that we have a full font stack, the browser WILL fall back to
 * system-ui/sans while waiting on your custom font. No more flash of Times!
 */
h1 {
  _font-family: Open Sans, system-ui, sans-serif;
}
4141
Harry Roberts @csswizardry.com · 20/03/2026
🇳🇱 Freshly back from a wonderful working week in The Hague. I shall never tire of this beautiful city.
Sunlit canal in The Hague with calm reflections, a white villa on the left, cyclists and parked bikes along the right-hand path, and a tram crossing a bridge in the distance under a clear blue sky
0220
Harry Roberts @csswizardry.com · 13/03/2026
Well, Brighton, you’ve been stunning as always. Thank you so much to @adactio.com and the @clearleft.com team for having me at #WebDayOut, an invigorating and inspiring shot in the arm to kick conference season off proper.
Me gazing longingly at Jeremy while he introduces me on stage at Web Day Out.
1111
Harry Roberts @csswizardry.com · 12/03/2026
Me looking at standardised web APIs like… #WebDayOut
A photo of me on-stage taken from the vantage point of an audience member. I’m pulling a face that looks almost kind of lustful in a way. I’m actually glad you can’t see it—it isn’t flattering.
0150
Harry Roberts @csswizardry.com · 12/03/2026
And we’re off! #WebDayOut
Jeremy Keith on stage introducing Web Day Out.
190
Harry Roberts @csswizardry.com · 11/03/2026
Hey, Bluesky! Have some blue sky. I’m in beautiful Brighton for @clearleft.com’s #WebDayOut tomorrow. Who else is here?
3221
Harry Roberts @csswizardry.com · 24/10/2025
What a beautiful trip to Toronto for @fitc.ca. Thank you so much for having me.
0110
Harry Roberts @csswizardry.com · 21/10/2025
Not only is @jpamental.bsky.social a really good friend, he’s an exceptionally good MC. You should hire him for your event.
020
Harry Roberts @csswizardry.com · 20/09/2025
I recently started instrumenting both @cloudflare.social and browser cache hits/misses and the numbers, while obvious, are compelling. The best request is the one that never happens. Check that 0ms TTFB 😍 ℅ @speedcurve.com
0132
Harry Roberts @csswizardry.com · 18/09/2025
My little salt and oil station.
131
Harry Roberts @csswizardry.com · 18/09/2025
I would wholeheartedly recommend this by the way. 2:1 salt:MSG used anywhere you’d use salt in a savoury context. Amazing on meat and green vegetables.
A small glass ramekin filled with a 2:1 salt:MSG mix. Behind it are a bag of MSG and a box of kosher salt.
3150
Harry Roberts @csswizardry.com · 08/09/2025
Create a Gist on the website, clone it to your machine, and you’re off. You can’t have branches or directories, but by that point you probably need a full GitHub repo anyway. They are so so so useful; you should definitely be using them more.
A screenshot from gist.github.com showing the ability to clone a GUI-created Gist to your machine via SSH.
020
Harry Roberts @csswizardry.com · 01/09/2025
I wanted to create a slightly tighter lockup for Obs.js’ logo and `h1` but I didn’t want the two to ever touch. Solution? A little dead-zone (coloured red) attached to `::after` which occupies the area overing the j’s descender.
DevTools screenshot showing how an ::after pseudo element creates a reserved space in its parent, thus preventing it colliding with a nearby image.
140
Harry Roberts @csswizardry.com · 30/08/2025
Binary code paths with /**//*//**/
1150
Harry Roberts @csswizardry.com · 29/08/2025
Audio quality is dreadful but I promise I’ll rerecord it over the weekend. Too good not to share.
140
Harry Roberts @csswizardry.com · 29/08/2025
`--word-diff` and `--word-diff-regex` are your new favourite Git tips:
Terminal screenshot of a git show for a commit titled “Fix stupid typo”. The same HTML change is displayed three ways: a normal unified diff, a word diff, and a regex-based word diff. Each shows corrections to meta tag image paths in demo/index.html, replacing /assets/og-image.png with /Obs.js/demo/assets/og-image.png
270
Harry Roberts @csswizardry.com · 29/08/2025
🪄 Really neat trick for docs/demo pages. You can add `display: block` to `script` and `style` and show folk the actual, literal code you’re running. It’s what I do with Obs.js:
Screenshot of browser DevTools showing how adding `display: block` and some other cosmetic properties can not only make active <script>s visible, but actually become part of the documentation themselves.
3394
Harry Roberts @csswizardry.com · 23/08/2025
As a developer, I’ve always struggled with design. I know/appreciate what looks nice, but I can never get there myself. Anyway, I spent a few hours this morning working on a small logotype for Obs.js. Based on Gotham, I’m pretty happy with the results so far.
A screenshot showing ‘Obs.js’ written in untreated, black Gotham Bold on the left. On the right, a modified, kerned, and coloured logotype showing soft rounding and adjusted letterforms. The centre of the ‘O’ contains a simplified ECG graph.
270
Harry Roberts @csswizardry.com · 22/08/2025
Toying around with some silly things on my Friday evening.
110
Harry Roberts @csswizardry.com · 19/08/2025
I used this to build a quick obfuscator. This will be great for anonymising @speedcurve.com dashboards before putting them in talks etc. Peep the address bar and tab name, too!
042
Harry Roberts @csswizardry.com · 19/08/2025
Chrome DevTools snippets are incredibly powerful, but they don’t accept parameters. One crude way around it is to use `prompt()` to take input on the fly.
3245
Harry Roberts @csswizardry.com · 15/08/2025
It is.
040
Harry Roberts @csswizardry.com · 15/08/2025
Yes please!
140
Harry Roberts @csswizardry.com · 14/08/2025
🦋 It took far longer than I’d like to admit, but I made @bsky.app a desktop-installable app. If anyone wants the snippet, get at me.
2183
Harry Roberts @csswizardry.com · 13/08/2025
It finally happened!
1123
Harry Roberts @csswizardry.com · 09/08/2025
What’s your favourite text editor and why is it Vim?
3141
Harry Roberts @csswizardry.com · 06/08/2025
Same code, same infrastructure, different context. Web performance is sometimes an ‘us thing’ and sometimes a ‘them thing’. For better or worse, we have a responsibility to cater to both.
165
Harry Roberts @csswizardry.com · 05/08/2025
🎞️ Here’s an example:
041
Harry Roberts @csswizardry.com · 05/08/2025
🎥 I spent a few hours recording a bunch of short-form web performance tips and tricks on Sunday. I plan to continue recording and releasing as I encounter fascinating real-life scenarios. Interested?
2391
Harry Roberts @csswizardry.com · 01/08/2025
I’m working with a client who has a very diverse (adverse?) customer base, so we’re sending off some more high fidelity Network and Device information to @speedcurve.com:
152
Harry Roberts @csswizardry.com · 30/07/2025
You can’t park there, mate.
2252
Harry Roberts @csswizardry.com · 23/07/2025
I went in pretty deep on this…
030
Harry Roberts @csswizardry.com · 23/07/2025
The syntax is pretty cumbersome, but the Extensibility API is worth looking at for any longer-term instrumentation.
Screenshot of Chrome DevTools’ Performance panel showing a custom track titled ‘csswizardry.com — custom track’, with a nested group ‘Technical Timings’. Within the group are three visible timing bars labeled `headTime`, `cssTime`, and `contentTime`, each rendered as light purple horizontal spans. Below this custom track is the ‘Main’ thread track, displaying standard task activity.<script>
  performance.mark('headEnd');

  performance.measure('headTime', {
    start: 'headStart',
    end: 'headEnd',
    detail: {
      devtools: {
        dataType: 'track-entry',
        trackGroup: 'csswizardry.com',
        track: 'Technical Timings',
        tooltipText: 'Head Tags Parsed',
        color: 'secondary-light'
      }
    }
  });
</script>
1161