❀✿❀ SuperLaserNino ✿❀✿

Star Trek, 60 years late

4 September 2026

117 words

It’s almost exactly 60 years since the initial release of Star Trek (the original series), and I thought it would be interesting to watch it in real time, just 60 years later. I made a little page that shows you when new episodes are coming out. There’s even a calendar you can subscribe to.

I was originally thinking I’d just do all Star Trek shows 60 years delayed, but that would leave a huge gap between TOS and TNG, so I made everything after TOS 45 years delayed.

The first episode will be this week, on Tue 8 Sept 2026.

Now I just need to make sure that page doesn’t go offline for the next 25 years.

Browsers need bookmarks that work like real bookmarks

20 July 2026

Modified: 30 July 2026

424 words

Bookmarks in browsers are nice. You can store a place you frequently go, so you don’t have to constantly re-google things or memorise the URL of your employer’s internal Elasticsearch instance. This is all great, but it’s not what bookmarks are used for in the real world.

In the real world, you have one bookmark per book/magazine/article you’re reading, and you move that bookmark to update how far along you are in the document. Browsers should have that too, so you can store how far you’ve gotten in long blog posts or online books (like this one or that or Worm).

The existing solutions for those cases are kind of bad:

  1. You can just leave the tab open and get back to it later. But this is prone to all sorts of accidents. If you resize your browser window, that might mess up your scroll position; if you close the tab or restart your browser, that might mess up your scroll position. And even if your browser syncs your open tabs across devices, it probably won’t sync your scroll position.
  2. If you’re reading an online book where each (short) chapter is one page, you could use regular browser bookmarks to save your reading position. But that means you either need to delete your old reading-position bookmark every time you create a new one, or add a date/time to the bookmark name, like “Reading position 2025-03-29”.1 But this still doesn’t help if you want to read a 20,000-word LessWrong post in more than one sitting.
  3. You can use a more sophisticated bookmark manager (I use Raindrop), and place a highlight on the last bit of text that you read, maybe with a special colour to indicate that this is a reading-progress marker rather than an actual highlight of the content. This syncs between devices and works for long documents, but you still need to tidy up after yourself.

What I’d like is to have a special type of bookmark (call it “Place marker” or something) that I can put in a specific place on a page, and the next time I place a marker with the same name, it deletes the old marker. (Basically, what we have now is the equivalent of tags in Git, and I want the equivalent of branches in Git (which, incidentally, is what Mercurial calls “bookmarks”, I think?)). This would be a perfect feature to build into something like Raindrop so it can sync between devices.

Footnotes

  1. Gosh, it’s been a while since I started this post. ↩

That’s not psychosis

20 July 2026

234 words

Look at this tweet:

Mitchell Hashimoto @mitchellh

I strongly believe there are entire companies right now under heavy AI psychosis and its impossible to have rational conversations about it with them. I can’t name any specific people because they include personal friends I deeply respect, but I worry about how this plays out.

[…]

It’s frightening, because the psychosis folks operate under an almost absolute “MTTR is all you need” mentality: “its fine to ship bugs because the agents will fix them so quickly and at a scale humans can’t do!” We learned in infrastructure that MTTR is great but you can’t yeet resilient systems entirely.

[…]

9:10 PM · May 15, 2026

I sympathise with the worry that tech people are getting overly excited about moving fast and breaking things with LLMs. But that’s not psychosis! Even calling it AI-induced mania would be overselling it. You just disagree with people’s cost-benefit analyses. A human psychiatrist I know in real life suggested you could call it AI hypomania, if you really insist on using a medical term.

This dilution of the meaning of “psychosis” bothers me because it makes it harder to talk about actual psychosis caused or made worse by AI. Psychosis is a real thing with an actual definition, and that definition is not “does stuff that I think is daft”.

Catio Chronicles 2: It’s happening!

25 August 2025

Modified: 8 October 2026

1264 words

After many months of interruption, we have finally finished the catio. Recall that, last time, we left off at a rough sketch of a plan:

And all that was left was getting the materials and actually building the whole thing.

Continue reading

Awaiting an arbitrary trigger in JavaScript/React

7 July 2025

445 words

Context

I was recently working on a little web-based audio recorder tool. To abstract away all the code dealing with the MediaRecorder API, I made a React hook that you could use like this:

const {
  startRecording,
  stopRecording,
  getAudioData,
  // etc
} = useAudioRecorder();

The hook would set up a MediaRecorder instance and startRecording and stopRecording would call start and stop. Calling start(timeslice) will cause a dataavailable event to be triggered every timeslice milliseconds. I then had an event listener that adds the new data Blob to an array in a useRef.

So far, everything was pretty straight-forward. Next, I wanted getAudioData to give me all the audio recorded thus far, but MediaRecorder doesn’t have a method for that. The easy solution would be to return whatever data is currently stored in the audio chunks ref and set the timeslice value to something low, like 100ms. Then, when you call getAudioData, the data you get is at most 100ms out of date. But this also means you have an event handler pointlessly firing every 100ms.

Fortunately, there is a method called requestData, but all it does is queue up another dataavailable event. It does not, itself, return the requested data, or tell you when the dataavailable event has been handled.

The solution

So I wanted a way to call requestData on my MediaRecorder and await until my event handler fired and updated the audio chunks ref with the latest data. The solution I picked was to create a new Promise, “steal” its resolve function from the callback passed into the constructor, and store it in a useRef. As long as the ref is in scope for the event handler, the event handler can now resolve our promise.

This is what it looks like when you put it all in its own hook:

import { useMemo, useRef } from "react";

export function useAwaitTrigger<T = void>(): {
  wait: () => Promise<T>;
  resolve: (val: T) => void;
} {
  const resolveRef = useRef<(val: T) => void | null>(null);

  return useMemo(
    () => ({
      wait: async () => {
        let resolve: (val: T) => void;
        const promise = new Promise<T>((r) => {
          resolve = r;
        });
        resolveRef.current = resolve!;
        return promise;
      },
      resolve: (val: T) => {
        if (resolveRef.current) {
          const resolve = resolveRef.current;
          resolveRef.current = null;
          resolve(val);
        }
      },
    }),
    []
  );
}

You can use this hook for all sorts of things, like awaiting an onclick event on a button. This same general technique also works to get an async function* from an event listener (which, idk, might be useful for some reason).