Getting Started
# Getting Started with Clockwork
What You'll Learn
This guide explains the Clockwork runtime model and how to use packages in your project.
You will learn:
- How packages are grouped and when to install each
- How
AppBuilder,World, andSchedulerfit together - How plugins register systems/resources/components
- Where to begin when adding engine features in your game/app
Prerequisites
Before continuing:
- Complete Installation
- Have a TypeScript or JavaScript project ready
- Be familiar with JavaScript basics (TypeScript optional)
Package Groups
Clockwork is split into three package families:
- Core runtime (
qti-clockwork-app,qti-clockwork-ecs,qti-clockwork-scheduler,qti-clockwork-math,qti-clockwork-physics,qti-neon-client,qti-clockwork-particles,qti-clockwork-lighting, etc.) - Renderer (
qti-clockwork-gl,qti-clockwork-shaders,qti-clockwork-materials,qti-clockwork-passes) - Platform bridge (
qti-clockwork-tauri-bridge)
Runtime Flow
The runtime lifecycle is:
- Build app with
AppBuilder - Register plugins (
builder.use(plugin)) - Build runtime (
builder.build()) - Start loop (
app.run()) - Tick frames (
await app.step(dt)) - Shutdown (
await app.shutdown())
The scheduler processes stages in order:
BootPreUpdateFixedUpdateUpdateLateUpdateRenderPrepRenderPostRenderShutdown
ECS Fundamentals
qti-clockwork-ecs provides:
- Entities: generation-safe entity handles
- Components: sparse stores keyed by component type
- Queries:
with/without/optional/changedfilters - CommandBuffer: deferred spawn/destroy/component mutation
- Resources: typed global runtime state via resource tokens
Minimal world usage:
import { World } from 'qti-clockwork-ecs'
const world = new World()
const e = world.spawn().build()
world.addComponent(e, 'position', { x: 0, y: 0 })
Clockwork JVM example:
import com.quietterminal.clockwork.ClockworkApp;
import com.quietterminal.clockwork.ecs.Commands;
import com.quietterminal.clockwork.ecs.QueryResult;
record Position(int x, int y) {}
ClockworkApp app = new ClockworkApp().build();
Commands commands = app.world().commands();
long entity = commands.spawn().with(new Position(0, 0)).id();
app.world().commit(commands);
for (QueryResult<Position, Void, Void, Void> row : app.world().query(Position.class)) {
System.out.println(row.entity() + " -> " + row.a().x() + "," + row.a().y());
}
app.shutdown();
Plugin Model
qti-clockwork-app provides plugin orchestration:
- Dependency-ordered plugin initialization
- Ownership-aware registries for components/systems/resources/assets
- Plugin shutdown in reverse init order
- Isolated plugin reload error handling
Plugin shape:
const plugin = {
id: 'example',
version: '1.0.0',
depends: [],
init(app) {},
shutdown(app) {},
reload() {}
}
Clockwork JVM example:
import com.quietterminal.clockwork.ClockworkApp;
import com.quietterminal.clockwork.ClockworkPlugin;
import com.quietterminal.clockwork.WorldApi;
ClockworkPlugin plugin = new ClockworkPlugin() {
@Override public String name() { return "example"; }
@Override public void register(ClockworkApp app, WorldApi world) {
world.resources().insert("example-config", true);
}
@Override public void shutdown(ClockworkApp app, WorldApi world) {
// cleanup
}
};
ClockworkApp app = new ClockworkApp().use(plugin).build();
app.shutdown();
Development Workflow
Use this baseline loop:
- Add/update your game/app systems/plugins
- Run your tests (
npm test) - Run typecheck (
npm run typecheck) - Run lint (
npm run lint)
Where to Go Next
- Packages Overview for package-by-package responsibilities
- Math Package for fixed-point math APIs and examples
- Physics Package for rigid-body simulation APIs and examples
- Neon Package for Neon networking APIs and examples
- Particles Package for simulation/visual particle APIs and examples
- Lighting Package for deferred lighting APIs and examples
- Runtime and Plugin APIs for detailed runtime concepts
- Testing for project-level validation guidance
- FAQ for common setup and architecture questions
- Architecture Overview for full system design
- ECS Deep Dives for entities/components/query internals
- Renderer Deep Dives for batching, text, and render graph flow