Skip to content

Typical workflow

Your schemas are the contract between server and clients. You author entities, commands, and related types in YAML, golem-bake turns that into typed integration code, then you write game logic against the generated imports. Day to day, that loop is what you repeat as the game grows.

Start with a project config and at least one entity schema:

golem.yaml
entity_schema: schemas/entities/
integrations:
go-server:
out: internal/synced/
schemas/entities/player.yaml
entity: Player
vars:
health: { tag: 1, type: double, sync: tick }
display_name: { tag: 2, type: string, sync: once }

From the project root:

Terminal window
golem-bake
go run ./cmd/server

After the first bake, wire the generated package into main (see Minimal server wiring). From then on the loop is the same:

  1. Edit YAML when the shared protocol changes (entity fields, commands, world types, events, or golem.yaml itself).
  2. Run golem-bake to regenerate the integration outputs you configured.
  3. Run your server (and clients) against the updated generated code.
You authorProtocol output (read-only)No bake needed
golem.yaml, schema YAML under schemas/Integration out: dirs for go-server, go-client, js-client, and similarOnTick handlers, entity methods, startup wiring, gameplay Go/TS/C#

Protocol integrations are fully reproducible from your schemas. Do not hand-edit those files, since the next bake will overwrite them. Whether you commit that output or regenerate it in CI is a project choice.

The ebiten, phaser, and unity integrations are different. Each targets a full client game engine and generates a per-entity bridge that plugs your synced entities into it, with hooks for spawn, removal, incoming state, per-frame updates, and drawing. Keep your own game code in separate files that import or embed the generated types, because bake will overwrite them too. See Ebiten, Phaser, and Unity.

Re-run golem-bake when you change:

  • An entity field (vars): add, remove, or change type or sync mode
  • A command under command_schema (default schemas/commands/): new commands, renamed fields, changed targets
  • A world type under world_schema (default schemas/world/): new types, fields, or source: config
  • A server event under event_schema (default schemas/events/): new events, renamed fields, entity_type, or foi_only
  • golem.yaml: output paths or integration settings

You do not need to re-bake when you only change game logic.

A typical project looks like this once schemas and integrations are in place. Paths follow the defaults and the sample golem.yaml above; override them with the keys in the golem.yaml reference.

mygame/
golem.yaml # project config: schema dirs, output dirs, integrations
schemas/
entities/ # entity YAML (default entity_schema path)
player.yaml
enemy.yaml
commands/ # optional: command YAML (default command_schema path)
move.yaml
world/ # optional: one file per world data type (default world_schema path)
zone.yaml
types/ # optional: custom types for collections (default types_schema path)
item.yaml
events/ # optional: server event YAML (default event_schema path)
chat_message.yaml
internal/
synced/ # go-server output (generated, do not edit)
client/ # go-client output (optional, generated, do not edit)
client/
src/synced/ # js-client output (generated, do not edit)
cmd/server/
main.go

If the CLI is not installed yet, start with Installation. When you are ready to construct golem.Server and call Run, continue to Minimal server wiring.