Skip to content

Instantly share code, notes, and snippets.

View jokull's full-sized avatar
☺️

Jökull Sólberg Auðunsson jokull

☺️
View GitHub Profile
@jokull
jokull / airplay-custom-apps-macos.md
Created August 19, 2026 11:04
AirPlay on macOS for custom apps: state of play (2026) — APIs, footguns, verified facts

AirPlay on macOS for custom apps: state of play (2026)

Field notes for app developers who want to ship an AirPlay / speaker output picker on macOS. Based on public APIs, Apple/DTS statements, community engineering (WebKit, shairport-sync, Rogue Amoeba, open-source players), and live probes on macOS 26.5.2 (facts verified on hardware are marked 🔬).


TL;DR

  • macOS has no OS-level per-app audio routing. Output routing is a single system-wide selection (the "default output device"). Per-app routing only exists when an app pins a device on its own audio path.
@jokull
jokull / npm-packaging-2026.md
Created August 5, 2026 22:10
npm packaging in 2026 — a recipe for TypeScript libraries (from better-result + tsdown: publint/attw, oxlint/oxfmt, min-TS check, release workflow)

npm packaging in 2026 — a recipe for TypeScript libraries

Distilled from reading better-result (the reference implementation) and the current tsdown docs. Apply to any library — including result-rpc.

The stack, and why

Tool Role
tsdown 0.22+ build: ESM and/or CJS, .d.ts generation, minify, sourcemaps — and built-in publint + attw validation that runs on every build
@jokull
jokull / README.md
Created August 4, 2026 23:55
better-result db errors — classify database failures into tagged Results (driver-agnostic tryDb). Discussion: https://github.com/dmmulroy/better-result/issues/108

better-result db errors — classify database failures into tagged Results

A driver-agnostic tryDb for better-result 3.0. Stop hand-writing instanceof/error.code checks — attempt the insert, get a Result<T, DbError> back, and fold the failure into your domain vocabulary at the handler boundary.

import { tryDb } from "./db-result.ts";
@jokull
jokull / ios-keyboard-punctuation-spec.md
Created July 19, 2026 11:23
The iOS keyboard punctuation & whitespace spec — the undocumented behavior every third-party keyboard reimplements

The iOS keyboard punctuation & whitespace spec

The undocumented behavior that every third-party iOS keyboard has to reimplement — reverse-engineered, with the escape hatches spelled out.

Compiled while building Lyklaborð, a privacy-first Icelandic keyboard. Corrections welcome.


Why this document exists

@jokull
jokull / trip-tour-vertical-gallery-audit.md
Created June 2, 2026 15:52
Trip live listed tours missing vertical gallery assignments
@jokull
jokull / agent-sandbox-blueprint-prompt.md
Last active May 22, 2026 23:24
Agent sandbox blueprint prompt for monorepos

Agent Sandbox Blueprint Prompt

This prompt is for teams that want to bolt an agent-native sandbox onto an existing monorepo.

The goal is not to create another E2E suite or a prettier docker-compose up. The goal is to give coding agents a disposable, inspectable, worktree-local environment where they can behave more like a careful human doing manual QA: open the app in a browser, click through real flows, inspect logs, read local side effects, check emails, review analytics/error events, adjust seeded scenarios, and produce visual proof without waiting for a human to run the project.

Think of this as giving agents vision and x-ray access to the app. Each agent/worktree should be able to spin up its own realistic runtime, keep working longer, avoid port fights with other agents, and leave behind evidence artifacts that make reviews easier.

The shape you are aiming for is this:

@jokull
jokull / blog-intelligence-per-token.md
Last active March 7, 2026 13:31
Draft: Intelligence Per Token

Michael Arnaldi on X:

Hot take: TUIs are a phase, and GUIs that basically emulate TUIs are a phase too. We just don't know how the IDE of the future will look like.

He's talking about the arc of dev tools. Terminal, then Notepad++, then richer IDEs, then VSCode. Each phase building on the last, borrowing metaphors, adding chrome. What comes next?

But something about the question stuck with me.

Unix evolved under constraints. Teletypes. Tiny memory. Slow connections. Those limits forced everything through text — and text turned out to be strangely universal. Decades later, everything still speaks it.

@jokull
jokull / expressive-napping-hummingbird.md
Last active March 2, 2026 12:57
Deployment plan: dato_tour → tour rename (PR #1418)

Deployment plan: dato_tour → tour rename (PR #1418)

Deployment Plan: dato_tourtour Rename (PR #1418)

Context

PR #1418 renames dato_tourtour tables, switches 97 files, and establishes the foundation for admin-first tour creation. Existing tour rows keep DatoCMS IDs as Tour.id; new Tour.datoId column (nullable) links to DatoCMS content. New tours get cuid2 IDs.

Migration strategy: Expand-Contract (zero-downtime reads)

  • Expand (this PR): New tables/columns created alongside old ones, data backfilled, old constraints relaxed
@jokull
jokull / vinext-migration-hurdles.md
Last active March 2, 2026 20:09
Hurdles migrating a Next.js blog to vinext (Cloudflare Workers)

Migrating a Next.js blog to vinext (Cloudflare Workers): Hurdles

This documents the struggles encountered migrating a Next.js 15 blog (with MDX, Shiki syntax highlighting, and OG image generation) to vinext on Cloudflare Workers.

1. EvalError: Code generation from strings disallowed

The showstopper. @mdx-js/mdx's run() internally calls new Function() to evaluate compiled MDX. Workers completely blocks eval and new Function at request time.

EvalError: Code generation from strings disallowed for this context
@jokull
jokull / .gitconfig
Last active February 28, 2026 07:54
dotfiles — fish, starship, kitty (GitHub Dark OKLCH), git, claude code, brewfile
[core]
excludesfile = ~/.gitignore
[user]
name = Jökull Sólberg
email = jokull@solberg.is
[init]
defaultBranch = main
[push]
autoSetupRemote = true
default = current