Chris Garrett Chris Garrett


33/M/UK

I'm Chris Garrett, a founder and entrepreneurial technologist working at the intersection of design and engineering.

Work with me

I help startups and established brands develop new digital products through my studio, Hyperlaunch, which specialises in early-stage product development and rapid prototyping.


‘Lantian’, meaning ‘blue sky’ in Mandarin Chinese […] The similarity between Graber’s given name and Bluesky is purely coincidental; Jack Dorsey had chosen the name ‘Bluesky’ for the research initiative before Graber became involved

How cool is that? The Bluesky CEO’s name actually translates to “blue sky”, by pure coincidence.



Hyperkit

I’ve been working on Hyperkit over the past fortnight, and the first release is now live on npm. It’s a collection of headless custom elements/web components designed to simplify building rich UIs with serverside frameworks like Rails or Revel.

It’s more like Headless UI than Shoelace: you bring your own styling.

Here’s an example of a styled sortable list:

<hyperkit-sortable class="bg-white rounded shadow-md w-64 overflow-hidden">
  <hyperkit-sortable-item
    class="flex items-center justify-between pr-4 pl-3 py-2 border-b border-b-stone-200 data-[before]:border-t-2 data-[before]:border-t-blue-400 data-[after]:border-b-2 data-[after]:border-b-blue-400 text-stone-800"
  >
    <hyperkit-sortable-handle>
      <button
        class="cursor-move mr-2 text-stone-400 select-none font-black px-1"
      >
        &#8942;
      </button>
    </hyperkit-sortable-handle>
    <span class="text-xs font-medium flex-grow">Item 1</span>
  </hyperkit-sortable-item>
  <hyperkit-sortable-item
    class="flex items-center justify-between pr-4 pl-3 py-2 border-b border-b-stone-200 data-[before]:border-t-2 data-[before]:border-t-blue-400 data-[after]:border-b-2 data-[after]:border-b-blue-400 text-stone-800"
  >
    <hyperkit-sortable-handle>
      <button
        class="cursor-move mr-2 text-stone-400 select-none font-black px-1"
      >
        &#8942;
      </button>
    </hyperkit-sortable-handle>
    <span class="text-xs font-medium flex-grow">Item 2</span>
  </hyperkit-sortable-item>
</hyperkit-sortable>

The pull of React, for me, has always been the clarity and DX that comes with colocating a component’s behaviour with it’s markup and styling. It makes a complex front-end way more intuitive/easy to reason with. The counterpart in Rails is Stimulus, which comparatively feels disconnected - relying on magic incantations of data attributes to apply behaviour. There’s a lack of traceability with Stimulus.

But for situations like a stylable select, or click to copy component, I don’t want to be reaching for React. Thus, Hyperkit - custom elements for UX patterns like sortable lists, repeating fieldsets and even calendars. Because Hyperkit uses custom elements, they’re just plain HTML tags, with all the behaviour encapsulated in the tag. No need to write a line of Javascript.

And if you use it with Phlex, you can build end-to-end frontends in pure ruby 🤌


I’ve been working on some embedded touch screen projects recently, SPAs built with React. A requirement recently came up to enable D-Pad navigation of the UI - with the entire functionality of the app needing to be accessible.

Making features designed for the capabilities of a full-blown touch screen fully accessible with a 5 button controller isn’t exactly trivial, especially with complex components like dropdowns and a virtual keyboard in the mix.

I ended up undertaking some R&D to come up with a solution. Based on convention, a “virtual cursor” seemed to be the best solution - making every element of the UI accessible without any additional design consideration. I’m sure it’ll have some further utility, so I’ve wrapped it up as a React hook. It’s headless, so you can style the cursor however you like.

It’s currently quite specific in scope: designed for non-scrolling, full screen kiosk apps; there are a couple of clear enhancements that I’ve already identified. I think overtime this could prove to be a great accessibility option for these sorts of kiosk implementations.

Check it out: @hyperlaunch/use-virtual-cursor


I’m very excited to share the public availability of PlanAtom. This is a product that I originally spiked as an internal sales tool within XI, but has since grown into a full blown commercial service.

The premise is quite simple: aggregate planning applications and identify the ones which fit with our service, then reach out to the applicants with a view to being the first builder they engage with. There’s a huge range of use cases for this across the construction ecosystem - from commercial lenders, to materials suppliers, to service providers like building regs.

Tech wise, the data aggregation is wrapped up in a Rails app. It uses GPT to parse very “soapy” planning application descriptions into structured data which can then be filtered and queried. The frontend, as ever, is built with Astro and leans heavily on Tailwind UI. I’m still actively developing the customer control panel, using Turso and Lucia.

Very excited to be shipping this - it’s the first flag in the ground for Project XI as a tech enabled business, and showcases the extent of what we’re working on.


It’s been a while since I shipped a client project with Hyperlaunch, so I’m super excited to release the new Space Baby app for U2. I’m even more excited to be able to say that I’m the first developer in the world to develop an app integration with The Sphere.

3D visualisation of the Space Baby on the Sphere

What is it?

It’s a companion app for U2’s residence at the Sphere. Whenever U2 content is playing on the “exosphere”, the app goes into “broadcast mode”, allowing fans to tune in and listen to the audio accompaniment. This includes the Space Baby speaking, so I had a fair bit of technical wrangling to make sure it’s millisecond accurate - essentially pre-downloading the entire clip and then seeking to the right point, to avoid latency issues with streaming.

Outside of broadcasts, there’s an ambient soundtrack produced by Brian Eno.

When a broadcast starts, we recieve a notification from the Sphere’s internal tooling to update the currently playing clip - and my stack then pushes a socket to all active users to update the state in real time.

Built with…

You can read the full case-study over at Hyperlaunch.


It’s been a while since I indulged in a pure piece of R&D, and the list of tools I’ve been keen to play with has grown pretty lengthy. I finally managed to carve out a week to get down to some serious experimentation and the result is Decimal, a free Binaural Beats generator delivered as a PWA.

Screenshot of invoice in Decimal.fm

I’ve been using Binaural Beats ever since I heard about them in the Huberman Lab episode on concentration, Focus Toolkit: Tools to Improve Your Focus & Concentration. I’ll add that I’ve also found them incredibly effective as a sleep aid.

While the concept works for me, the existing apps are generally pretty poor; ad-laden and lacking in terms of UX. With Decimal, I wanted to deliver an app that users can love, without the ad and tracking bloat that comes with so many apps. My main goals were:

  • Exceptional speed and performance
  • Joyful to use - nicer than any existing apps
  • No invasive ads or tracking

I hope I’ve achieved all three. The end result is what I’ve started to refer to as a toy; it’s fun to use, singular in purpose and has no intention of delivering any commercial outcomes. A true “small web” project.

Tech wise, the app is built with Astro, with some React islands peppered throughout - for interactive components like the player controls. I dropped in Million.js because… well why not?

The biggest epiphany for me was using Nanostores to share state between disparate React components - like the main player and persisted mini player in the header. Nanostores make this super easy, and the resulting code is far clearer than the eqivalent would be with a Provider/Context hook. I’ll definitely be using this approach in future.

The tones themselves are generated with the Web Audio API, so you can switch from the suggested presets to entirely custom frequencies. As part of my three goals above - I was eager to get lock screen controls functional on mobile. The Media Session API, however, doesn’t have any awareness of Web Audio instances, so I resorted to a hack: playing a looping mp3 of silence, and then binding to the Media Session callbacks for that <audio /> to control the Web Audio output.

All of this is made feasible with Astro’s <ViewTransitions />. I can just append transition:persist to any component to have it persist in the client between page navigations - so there’s no loss of audio playback etc as you navigate around. You get some fantastic transitions too - with no implementation overhead.

Astro is increasingly looking like a framework/build tool I can go all in on; the life cycle is super intuitive and ability to drop in piecemeal UI framework components is incredible. The default 💯 page speed scores are pretty compelling, and because the app compiles to static and generates the audio entirely in the client, it costs next to nothing to run.

Tech aside, I’ve also done some experimentation with using GPT 4 and DALLE-3 to generate blog posts that I hope will deliver some educational and actionable information for new comers to binaural beats. I really struggle to pen that sort of content myself, so this was a novel way to overcome a writer’s block; hopefully some craftmanship at the the prompt level pays off in the output. These posts will be rolling out on the blog over the next couple of months.


Anyone who has worked with engineers knows that impl. time is not a pure function of complexity, but is greatly affected by their interest in the work.

This tweet by Lea Verou really resonated with me. I’ve experienced this in myself and other developers I’ve collaborated with. IMHO, a “10× engineer” isn’t born purely of talent, but of a combination of domain understanding and vested interest in the problem space.




Colophon

Giving the blogging thing another go. Super simple stack - but hopefully that means I’ll keep it updated:

I’ll definitely refine the design over time, but let’s see how well I do at keeping this thing up-to-date for now…