Mike Zupper

Build Logs line, stop 6 of 6

Monthly Roundup: Gyral, a Builder Engine Milestone, and a Solar System (October 2026)

In October I started Gyral, an open-source web framework, delivered the second milestone of the Livepeer builder engine, got Alibaba's models live on BlueClaw, deployed Joystyk, and built a solar system with my son.

Date
Author
Mike Zupper
Read
15 min, 2,970 words
An orrery with Gyral as a glowing sun and five planets on tilted orbits labeled Sabacc, starwars.run, Joystyk, Football tracker and Solar system, above tiles for 5,038 commits in October, M2 landed Oct 19, and BlueClaw with Alibaba models live

At the end of September’s roundup, I listed three things for October: run BlueClaw on its new stack and report back, deliver the October 16 milestone for the Build Track of Livepeer Network Engineering SPE Phase II, and turn my football pool app into something other people could host for their own pools.

The milestone landed on October 19, three days late. The football pool extraction is built, but it isn’t public yet. BlueClaw is working fine in production, and the Alibaba models that slipped in September went live on it.

The largest thing I built in October wasn’t on that list. On October 4 I started Gyral, a web framework. By the end of the month a games site, a Star Wars archive, a Sabacc table and my football tracker had all moved onto it.

Nearly five times August’s commit count

More of my work now goes through AI coding agents, and the volume shows it. In August I counted about 1,050 commits across 35 repositories. October’s GitHub activity covered 65 repositories, with 3,628 commits and 325 merged pull requests from me. Another 1,410 commits live in 16 local repositories that haven’t reached GitHub yet, which brings the month to 5,038.

Those numbers measure the throughput of an agent-assisted process, not hours at a keyboard or value delivered. Nearly every repository I touched has the same harness: a short AGENTS.md map, Beads for tracking, decision records, and lints that turn architecture rules into failing checks.

My own tracking didn’t keep pace. Gyral, the biggest thing I built all month, never got an entry in the project-management system I described in August.

Gyral, from first commit to 0.3.10

In January 2025 I wrote about the cycle of complexity in web development: frameworks fixing problems they created, upgrades that break working builds, and knowledge that doesn’t carry over from one framework to the next. Most frameworks are still built around older paradigms, even though browsers now support much of what those paradigms were invented to provide, starting with web components. I thought a new framework could sit on the newest web primitives as a thin layer. It would give apps enough structure to be less brittle, and because most of what you learn would be the browser’s own APIs, the knowledge wouldn’t be thrown away with the next framework.

Gyral is that layer. It builds web apps from Model-View-Intent components, and every component is a standard custom element that you can use in any page, inside another framework, or with no framework at all. A component turns platform events, such as clicks and form submissions, into typed messages. It handles each message with a pure reducer and renders a template that names its intents instead of holding event handlers. Side effects happen at the edges, as data. Gyral credits Cycle.js as its inspiration, and replaces Cycle’s streams with plain functions and its virtual DOM with the browser’s own components.

Here’s the counter from the README:

import { define, html } from '@gyral/core';

type Msg = { _tag: 'Increment' } | { _tag: 'Decrement' };

define<{ count: number }, Msg>()('gy-counter', {
  init: () => ({ count: 0 }),
  intent: {
    Increment: () => ({ _tag: 'Increment' }),
    Decrement: () => ({ _tag: 'Decrement' }),
  },
  update: {
    Increment: (s) => ({ count: s.count + 1 }),
    Decrement: (s) => ({ count: s.count - 1 }),
  },
  view: (s, i) => html`
    <output>${s.count}</output>
    <button type="button" data-intent=${i.Decrement}>Decrement</button>
    <button type="button" data-intent=${i.Increment}>Increment</button>
  `,
});

The first release, 0.1.0, went to npm on October 5. Version 0.2.0 dropped Effect the next day. Version 0.3.0, published October 10, replaced Lit with a view layer written only for Gyral and built server rendering and hydration into the core. By October 31 Gyral was at 0.3.10.

In one js-framework-benchmark run, Gyral 0.3.0 averaged 1.03 times the fastest framework’s time across the benchmark’s operations (a geometric mean, where 1.00 would mean fastest everywhere). In the same run, Svelte scored 1.07, Solid 1.08 and Lit 1.31. Those are the project’s own numbers. The benchmarks repo builds the same six apps in Gyral, React, Preact, Vue, Svelte, Solid and Lit, and it commits the results with their caveats, including the places where Gyral loses.

Around the core there’s now a documentation site, an MCP server for coding agents, gyral-rs for rendering Gyral pages inside a Rust server, and gyral-shop, a full department-store app built as a demo. Late in the month every Gyral repository adopted a two-week rule: a new dependency version comes in only after it has been public for two weeks. The exceptions are a security fix the code can actually reach and an approved Gyral release.

Gyral’s development checks also turned up a bug in Vite. When Vite pre-bundles a dependency, the package’s subpath imports lose the development condition, so the dev server quietly serves the production build. I reported it with a minimal reproduction, and it was fixed upstream on November 4.

What a coding agent made of it

On October 11 I ran a small pilot: three tasks, four setups and three trials of each, with Qwen3.8-27B on BlueClaw doing the coding. Working from Gyral’s ordinary documentation, the agent passed none of its 9 trials. With Gyral’s agent skill and MCP server, it passed 2 of 9. React passed 8 of 9, and Svelte passed all 9. In sixteen of the Gyral trials, the agent never edited a source file; it spent its requests exploring documentation and APIs.

Reading the traces the same day showed that the test itself was part of the problem. The Gyral agent got one 654 KB documentation file, while the React and Svelte agents got five hand-picked pages each. No agent could see how many requests it had left. And the bridge to the MCP server dropped the server’s instructions, so the agent never called the tools that scaffold a component or check a snippet.

I fixed the harness, the documentation and the MCP server, and ran it again with the same model and tasks. By October 13 the final documentation-only runs passed 8 of 9, and the skill and MCP server passed 8 of 9 and then 7 of 9. React and Svelte scored 7 or 8 of 9 in the same rounds. Almost all of that gain came from the harness, the documentation and the MCP server, not from changes to the framework.

It’s still one model and one set of tasks, so it doesn’t rank the frameworks. But for a new framework, the documentation an agent reads is part of the product.

The apps that moved onto Gyral

starwars.run used to be a small Cycle.js page that searched an API that no longer responds. On October 5 I rebuilt it as a static Gyral site. Four days later it was a reader for the Wookieepedia archive: about 227,000 pages served from SQLite, search on the server, and an “Ask the archive” box that answers plain-English questions by writing SQL against the archive and showing the query it used. starwars.run credits Wookieepedia for its content.

Sabacc brings Classic Sabacc, the card game from the Star Wars Legends stories, to the browser with a 3D table and online multiplayer.

Joystyk replaced my old games.ziply.io site. It’s a free site with 70 arcade, card and dice games that you can play in the browser alone, against the computer or with friends, without signing up. Its shared code is published as 17 MIT-licensed libraries in the @joystyk scope on npm, built from the game-libraries repository.

The football tracker moved as well. Between October 8 and 11 its web app went from Lit and Effect to Gyral, and the rough edges it hit went back to Gyral as a written feedback report. Gyral 0.3.7 later shipped five fixes found in apps built on it.

The builder engine’s second milestone landed three days late

My other Livepeer commitment is the Build Track of Livepeer Network Engineering SPE Phase II, where I’m responsible for delivery. Its second milestone, M2, covered the engine’s foundation and its integration contracts. It was due October 16. We closed it on October 19, three days late, with nothing cut from its scope.

The engine is livepeer-builder-core, which an application can import as a Python package or run as a REST service. It decides who may run jobs and which allocation they spend from, finds and pays a runner, records every attempt, and attributes each network charge to the job that caused it. On October 14 it ran paid jobs on public Livepeer orchestrators. By October 19, on the tagged builds, every charge matched its job and the reconciliation balanced exactly.

Some of the fixes landed upstream. The remote signer rejected orchestrators whose ticket recipient differed from their node address; Josh fixed that, and the fix shipped in node v1.0.2. On October 28 every Build Track repository moved off our forks and onto upstream livepeer/* builds.

We showed the work at a wrap demo on October 20. John demonstrated an enterprise desk built on the engine’s REST API. I showed ChatLPT, a chat app that embeds the engine, runs Qwen3.8-27B and FLUX schnell on Livepeer orchestrators, and shows the retail price beside the network cost under every reply. Late in the month the engine got a third consumer, an inference gateway with OpenAI- and Anthropic-compatible APIs.

The third milestone, a complete builder journey, is due November 20. Its reference application is a builder console: an operator issues keys and funds an allocation, and a builder runs jobs and sees what each one cost. As of November 3, 17 of its 18 tasks were closed. The last is a funded run through all seven builder outcomes, capped at $1. The M2 status update has the details, and the public project tracks the milestones.

BlueClaw: Alibaba’s models, and the end of the welcome credit

BlueClaw moved to a Python backend and Livepeer’s Live Runner on September 30, so October was its first full month on the new stack. The short version of the report I promised: it’s working fine in production.

The Alibaba models went live during the month. Getting there meant teaching BlueClaw to offer models that a vendor serves through its own API alongside the models running on Livepeer. Vendors now have their own table with encrypted keys, each model shows the vendor that serves it, and the pricing for a vendor’s model decides how it’s listed.

The rest of the month was a lesson in running a paid service in public. New Terms of Service and a Privacy Policy were approved on October 3. On October 9 about a hundred scripted sign-ins arrived at once. I fixed how BlueClaw read visitors’ addresses behind its proxy, capped the welcome credit per network, and put a Cloudflare Turnstile check in front of sign-in. On October 15 a second wave got past all three, and I removed the welcome credit that day.

At the end of October I started on the next version of BlueClaw’s platform. It’s built on the Build Track’s builder engine, so BlueClaw stops running its own Livepeer integration, and it leans into Livepeer Node, the newer version of Livepeer’s Live Runner that replaces go-livepeer. It made its first paid call on October 31. It isn’t deployed yet.

The football pool, extracted but not yet public

To be precise about September’s plan: Football Pool Tracker isn’t being replaced. It stays a companion for our pool and keeps reading the organizer’s Google Sheets. The plan was to extract a generic version that anyone can host for their own pool, without the spreadsheets.

That version is built. Members sign in with an emailed code, keep private drafts, submit their own picks and get a receipt. Entries close, and everyone’s picks are revealed, two hours before the week’s first kickoff. It runs in Docker with SQLite. It isn’t public yet, so that part of September’s plan slips to a later month.

From a Star Wars prototype to DayFlo’s native apps

In September I wrote that my DayFlo contributions were complete. October brought a new piece of work for SpeedyBird: native iOS and Android apps.

I started with research. On October 17 and 18 I built Holocron, a Star Wars explorer over the public SWAPI data, to prove out one architecture: a SwiftUI app and a Jetpack Compose app calling the same Rust core through Mozilla’s UniFFI. Rust owns the data, state and offline rules, and each platform owns its interface. I wrote it up on October 23 in Native iOS and Android Apps With a Shared Rust Core.

The next day, Holocron became the template for DayFlo’s native apps: the same crate layout, the same pinned toolchain and the same packaging scripts. From October 19 to 26 I built clients for iPhone, iPad and Android over a shared Rust client that talks to DayFlo’s existing API. They cover Google and Apple sign-in, the daily briefing, the rolling week, sources, pins, actions with undo, and notifications. The Rust client’s wire types are generated from the backend’s own schemas. On the backend side, I added what installed apps need: exported contracts, a versioned API protocol, native sessions and sign-in, and push delivery.

The apps are private, and they aren’t in beta yet. The goal is full parity with DayFlo’s web app before anyone outside the team tests them.

A solar system with my youngest son

The most fun build of the month was my youngest son’s idea. He’s been fascinated with space and astronomy, and he wanted something grounded in real science. On October 31 we built Solar System Classroom together: a page for teachers and students that shows the Sun and the eight planets at true scale, in 3D, for any moment from 2000 to 2050.

The positions come from NASA JPL’s DE440 ephemeris, and every year of data is checked against JPL’s Horizons service before it’s published. Across 5,508 comparisons the worst error is 4.7 meters. It also matches the timing of the August 12, 2026 solar eclipse in NASA’s catalog to within a second. It runs on Gyral and Three.js, and it’ll be live at solar-system.mikezupper.com soon.

Early projects: Livepeer experiments and two product ideas

A handful of projects stayed on my machine in October. They’re early, but here’s what each one is for:

  • swarm-live sends live audio from a phone to Swarm. The phone signs every byte it publishes, a Livepeer-paid relay carries it, and listeners verify every chunk they play.
  • An AI VTuber whose brain drives language, speech and rendering runners on Livepeer. It can host its own shows on Twitch or YouTube, or appear as a co-host avatar in a streamer’s OBS.
  • livepeer-media-runners plans Live Runners for media and AI jobs, such as speech-to-text, vision and object detection, with typed clients that call them through the builder engine. So far it’s contracts and a plan.
  • KeepQuitting is a paid AI accountability coach. Each member gets a personal coach in Telegram that runs a 12-week cycle with them, on BlueClaw’s Livepeer-served model.
  • Gathered Wishes (a working name) is a group video gift. Friends each record a message in their browser, and the service stitches them into one video for the organizer to approve.

One public Livepeer project fits here too: runners that serve text-to-video models (LightX2V, SGLang Diffusion and vLLM-Omni) through Livepeer’s Live Runner. They passed paid acceptance runs on an RTX 5090 on October 18.

CI runners, agent skills and two posts

I moved many of my repositories’ GitHub Actions jobs off my workstation and onto a runner fleet of my own: disposable Docker workers in two regions, with a private image registry beside them.

I open-sourced two-track, a zero-dependency library for railway-oriented programming in TypeScript, with an agent skill that teaches it. I also wrote agent skills that bring the judgment of books such as Designing Data-Intensive Applications, Domain-Driven Design and Enterprise Integration Patterns to coding agents. Those are private for now.

Nusend, my transactional email service, gained webhooks that match Resend’s payloads and retry schedule.

I published two posts: September’s roundup on October 2 and the Holocron post on October 23.

A new look for mikezupper.com

If you’re reading this on the site, you’ve already noticed. On November 1 I relaunched mikezupper.com with a new design called Mainline, which draws the whole site as a transit map. Topics are lines, posts are stops, and each course is a branch with a tick for every lesson. The map on the home page is generated from the posts when the site builds, so this roundup added its own stop to the Build Logs line. Every hero image was redrawn in code to match, and the learn site moved to the same style.

November: Ziply, BlueClaw and the M3 gate

Ziply is getting a new job. Joystyk took over the games, and the Ziply name now belongs to a video service I built in the last five days of October. Ziply.io handles uploads, signed playback, and live RTMPS broadcasts with automatic replay and captions. It’s compatible with Mux’s SDKs, so an app that already uses Mux should keep working after a few documented configuration changes. Transcoding, speech-to-text and caption translation run as Live Runners on the Livepeer network, through the same builder engine the Build Track is delivering. By October 31 it had passed all 20 of its acceptance gates, including paid runs on Livepeer, and it launches this month.

BlueClaw stays on the list, and the Build Track has one fixed date: the M3 gate on November 20, with the funded dry run due a week earlier. Around those, there’ll be the usual side projects and research.

Find me on X, in the Livepeer Discord (#orchestrating, @mike_zoop), or at [email protected].

Mike