Run and ship
Clone it, run it, and put it on the internet without a server.
This is the shortest chapter in the guide, and that is the whole point of it.
8BEETY is a static single-page app. No backend, no database, no API keys, no build-time secrets. Hosting it means serving one folder of files. That was not a happy accident discovered at deploy time; it was a non-goal written into the spec ("no server-side anything") before there was anything to host. This chapter is where that decision pays out.
Before you start
- Node.js 20 or newer, 22 recommended, and npm.
- A modern browser. Playback works in Firefox and Safari. Use Chrome or Edge for the video export.
One note before the commands. 8BEETY is an npm project, so every command below is npm. If your muscle memory types something else, this is a good repo to retrain it on.
Clone and run
git clone https://github.com/ShaneDolphin/8beety.git
cd 8beety
npm install
npm run dev # http://localhost:5173
Drop any .mid file onto the page. If you do not have one handy, the repo ships three original demo MIDIs under public/demo-midis/.
The full command set
| Command | What it does |
|---|---|
npm run dev |
Vite dev server with hot reload |
npm test |
The whole Vitest suite, close to 300 tests, all Node-side, roughly 10 to 15 seconds |
npm run build |
Type-checks with tsc -b, then writes the static site to dist/ |
npm run preview |
Serves the production build locally |
npm run lint |
ESLint over the whole repo |
What "working" means for this repo
npm test green and npm run build green. Both actually run, with the output in front of you.
That is the entire definition, and every milestone during development ended on exactly that check. It is the same gate chapter 3 put into CLAUDE.md, and it is worth restating here because this is the moment you are most likely to let it slide. The app is on screen. It makes noise. It looks finished. That is precisely when a claim from an agent is cheapest to accept and most expensive to have accepted.
If you extend the app, keep the rule. If you have an agent extend the app, keep it harder.
Deploy
Vercel, which is how the live site is hosted
npm run build
npx vercel deploy --prod
Framework preset: Vite. Build command npm run build, output directory dist. That is the configuration in full. No environment variables, no serverless functions, nothing to keep warm, no secrets to rotate. Attach a custom domain in the Vercel dashboard if you have one; the live app runs at www.8beety.com this way.
Any other static host
Run npm run build, then upload dist/ to Netlify, GitHub Pages, Cloudflare Pages, an S3 bucket, or a web server you already pay for. There is no server-side rendering and no routing to configure, because the whole thing is one index.html. If your host asks you about an SPA fallback, you do not need one.
Two things will actually bite you, and both of them are quiet.
Serve it over HTTPS, or over localhost. AudioWorklets and the Web Audio API require a secure context. Opening the built files off your disk with file:// will not work, and it fails in the way that costs you an hour: the page loads, the interface works, you press play, and nothing happens.
The worklet module has to be served as JavaScript. Every mainstream static host does this without being asked. A hand-rolled server does not always, and a .js file sent with the wrong content type will refuse to load as an AudioWorklet module. Send .js as text/javascript.
Notice that both failures land on the audio engine. It is the part of this app with the strictest requirements about the environment it runs in, and the part that goes silent instead of throwing when the environment is wrong. Test with sound on.
Things that trip people up
- No sound until you interact. Browsers suspend audio until a user gesture. Press play, and the app handles resuming the context. This is also the first thing that will confuse you if you point automation at the page.
- Video export runs in real time. A two-minute song records for two minutes. It keeps running in a background tab, because it clocks frames off a worker timer and holds a screen wake lock, but do not close the tab. Output is H.264 MP4 in Chrome and Edge; browsers without MP4 recording fall back to WebM.
- Share links carry the whole project in the URL, compressed, MIDI included, with no server involved. Above roughly 100 KB embedded, a link falls back to carrying the arrangement without the MIDI payload. That is a limit on how much you can reasonably put in a URL, not a bug waiting to be fixed.
- Some of the DSP tests have explicit 30-second timeouts. They normally finish in a few seconds. They are not leftover debris and they are not there to be tidied up. Rendering audio is slow on a cold machine, and a suite that goes red on a slow machine is a suite people learn to ignore.
Where to look when you extend it
Chapter 4 mapped the pipeline: src/engine/ for import, compile, pitch and instruments, src/audio/ for the DSP and the offline render, src/viz/ for the drawing and the video export. Two directories that table did not name are worth knowing before the next chapter. src/components/ is the React UI. src/theory/ is the key and chord detection behind Chord Assist. docs/superpowers/ holds the design docs and implementation plans as they were written, and tests/ is the safety net that let an agent refactor aggressively without breaking things quietly.