Terminal recordings for Astro with astro-asciinema
I wanted terminal recordings in my posts without making every article
responsible for setting up a player. astro-asciinema is the small
integration that came out of fixing that.
Here is one of those recordings:
The article only needs an import and a component:
---
import { Asciinema } from "astro-asciinema";
import Demo from "./demo.cast";
---
<Asciinema src={Demo} />
That is the interface I wanted: keep the recording beside the article, import it like any other asset, and let the component deal with the player.
Letting Astro own the recording
The asciinema player was not the problem. It already handles terminal rendering, playback, seeking, and controls. The friction was everything around it.
Vite does not recognize .cast files as assets by default, and TypeScript does not know what their imports return. Without some glue, each article has to work around both.
astro-asciinema adds .cast files to Vite’s asset pipeline and teaches TypeScript about their imports. A recording can then move through development and production builds with the page that uses it.
The dark-mode wrinkle
Once that worked, I ran into a less obvious problem. The recording looked right on the initial page load, but switching the site theme left it behind.
The asciinema player reads the terminal palette’s CSS properties only when it starts. If the site later toggles a dark-mode class, the page changes but the terminal keeps the palette it loaded with.
The component now watches the same signal as the site. It can follow prefers-color-scheme, the dark class on <html>, data-theme, or a custom root class or attribute:
<Asciinema
src={Demo}
options={{ theme: "site" }}
theme-source="class"
/>
When that signal changes, the component creates a fresh player so it reads the new palette. Recreating the player would normally restart the recording, so it first remembers the current time and whether playback is active. The new player seeks to the same position and resumes if needed.
The result is deliberately uneventful: the terminal changes theme without losing its place.
Keeping it small
astro-asciinema does not try to replace the player. It gives Astro a clean way to ship recordings and handles the integration details I did not want repeated in every post.