Documentation #
Budo is a small runtime for building animated apps in JavaScript, TypeScript, Lua, or WebAssembly, then taking the same project to desktop, Android, and the web. It gives application code a direct creative surface: Skia drawing, shader passes, input, audio, MIDI, SQLite, files, HTTP, sensors, wake locks, and optional ONNX Runtime inference.
This documentation is written for developers who want to build apps with Budo. It starts with a tutorial you can follow in one sitting, then opens into deeper guides for the runtime model, rendering pipeline, data APIs, platform behavior, and language-specific details.
Where to begin #
If this is your first Budo app, start with Getting started. You will create a project, draw a scene, add input, keep a tiny bit of state, and run it locally.
If you already know what you are building, Project model explains how Budo chooses an entrypoint, loads metadata, resolves assets, and exposes capabilities. That page is the best mental model before you reach for platform-specific features.
For day-to-day API work, keep API reference open. It groups the public JavaScript and Lua namespaces by task and points to the WebAssembly import names where the model differs.
What Budo feels like #
A minimal JavaScript app is just a directory with main.js:
// Draw one frame of the app.
function frame(t) {
// Clear the canvas with a dark background.
sys.canvas.clear('#0e0e12');
// Choose the text color.
sys.canvas.setFillColor('#7c6ff7');
// Draw a greeting at x=40, y=80 with a 32-pixel font size.
sys.canvas.drawText('Hello, Budo!', 40, 80, 32);
// Request the next frame so the app stays alive.
sys.animation.requestFrame(frame);
}
// Start the animation loop.
sys.animation.requestFrame(frame);Run the directory:
# Run the project directory as a desktop app.
./build/budo run my-appFor a throwaway sketch, you can also pipe one file directly into run:
cat <<'EOF' | ./build/budo run --from-input js
let pulse = 0;
function frame(t) {
const width = sys.window.getWidth();
const height = sys.window.getHeight();
const radius = 32 + Math.sin(pulse) * 12;
sys.canvas.clear('#0e0e12');
sys.canvas.setFillColor('#7c6ff7');
sys.canvas.drawCircle(width * 0.5, height * 0.5, radius);
sys.canvas.setFillColor('#f7f2e8');
sys.canvas.drawText('Hello from stdin', 40, 80, 28);
pulse += 0.04;
sys.animation.requestFrame(frame);
}
sys.animation.requestFrame(frame);
EOFThat same project can grow into a TypeScript app, a Lua app, a WebAssembly module, a shader-heavy visual tool, a game, an offline SQLite app, or an Android package with store metadata. Budo keeps the project shape deliberately plain so you can see your own code.
Documentation map #
Getting started walks through a complete first app with drawing, input, animation, and project files.
Project model explains entrypoints, app.json, asset paths, modules, TypeScript stripping, file sandboxing, and capability checks.
Drawing and layout covers canvas drawing, paint state, paths, transforms, text, fonts, SVGs, colors, and density-aware coordinates.
Rendering and shaders explains the GPU-immediate canvas pipeline, framebuffer reads, immediate fullscreen shaders, render targets, mesh drawing, textures, and Skia-backed canvas textures.
Input, time, and state describes the animation loop, timers, keyboard and pointer input, focus, touch handling, and state patterns that stay comfortable across platforms.
Data, files, and network documents SQLite, file access, HTTP fetch, UDP sockets, and the network and filesystem policies in app.json.
Audio, MIDI, sensors, and AI covers synthesis, sample buffers, decoded WAV/MP3/Ogg/FLAC assets, MIDI I/O, RTP-MIDI, accelerometer and compass data, screen wake locks, and neural inference.
Lua and WebAssembly shows how the same runtime concepts map to Lua tables and WebAssembly host imports.
Packaging and deployment explains desktop runs, web export, Android APK/AAB packaging, metadata, icons, permissions, and release flow.
API reference is the compact reference for commands and namespaces.
A few useful principles #
Budo apps are ordinary folders. Put your code, shaders, fonts, images, databases, model files, and metadata beside each other, then refer to those files with project-relative paths.
The runtime is immediate enough to feel like a creative coding environment, but the platform APIs are real. Network access is policy-gated, file paths are sandboxed, shader paths are checked, and Android packaging reads the same metadata your app reads.
When a feature may not exist on every target, probe sys.capabilities before you depend on it. This keeps your app pleasant on desktop, Android, and web without scattering defensive exceptions through the code.
Command shape #
The current Budo CLI uses subcommands:
# Run a project directory explicitly.
./build/budo run my-app
# Create a starter project.
./build/budo init my-app
# Export a self-contained web build.
./build/budo web-export my-app -o dist/my-app-web
# Export and serve locally for browser testing.
./build/budo web-serve my-app
# Build an Android APK release.
./build/budo android-apk my-app --release
# Build an Android App Bundle release.
./build/budo android-aab my-app --release
# Print the TypeScript declarations bundled with the runtime.
./build/budo budo.d.ts
# Print the generated developer API reference.
./build/budo budo-llm.md
# Show the command help.
./build/budo helpThe shorthand ./build/budo my-app is accepted for run, but using the explicit subcommand in scripts makes intent clearer.