Hello World
Your first Grove module: define a record, an event, and an action, then run the checker and execute an action request.
Prerequisites: Installation -- Manzano CLI installed via Homebrew. What you'll learn: How to create a project, understand the starter module, run tests, and start the dev server.
Create a Project
manzano init hello-grove
cd hello-grove
This creates:
hello-grove/
grove.toml # project_id = "hello_grove"
modules/hello_grove/module.grove # Starter module
CLAUDE.md # AI assistant context
The Starter Module
Open modules/hello_grove/module.grove:
module hello_grove
record {
kind "todo"
title: String
status: String = "open"
}
event created {
title: String
status: String
}
event status_changed {
status: String
}
@create
action create {
title: String
apply {
emit created {
title: params.title
status: "open"
}
}
}
action update_status {
status: String
apply {
emit status_changed {
status: params.status
}
}
}
Let's break this down:
module hello_grove-- Names this module. The name must match the directory name.record { ... }-- Defines the shape of the entity this module manages. Each module has at most one record.event created { ... }-- Declares an event. Events are immutable facts that have happened.@create action create { ... }-- Declares an action that creates new records. The@createannotation tells the runtime this action produces new entities.apply { emit created { ... } }-- The apply block runs when the action is invoked.emitproduces an event, which updates the record.
Add a Test
Create modules/hello_grove/hello_grove_test.grove:
module hello_grove_test
test hello_lifecycle {
run create {
request {
name: "create",
params: {
title: "Hello, World!"
},
meta: {
id: "test-1",
by: "tester",
timestamp: 1700000000000,
action_id: "cmd-test-1"
}
}
expect ok
assert record.title == "Hello, World!"
assert record.status == "open"
assert events.len == 1
assert events[0].name == "created"
}
run update {
request {
name: "update_status",
params: {
status: "done"
},
meta: {
id: "test-1",
by: "tester",
timestamp: 1700000000100,
action_id: "cmd-test-2"
}
}
expect ok
assert record.status == "done"
}
}
Run it:
manzano test
test "hello_lifecycle" ... ok (2ms)
1 passed, 0 failed (2ms total)
Start the Dev Server
manzano dev
This starts a local server at localhost:3000 with the Manzano Dev console where you can browse your modules, execute actions, and inspect records.
What Just Happened?
manzano initscaffolded a project with a starter module- We added a test that exercises the create and update lifecycle
manzano testdiscovered and ran the*_test.grovefilemanzano devstarted a server with an in-memory database and dev console
This is the core loop of every Grove application: action in, events out, record updated.
See Also
- 5-Minute Tutorial -- Build a complete todo app
- Concepts Overview -- Understand the mental model
- Build a Task Tracker -- A deeper project-based tutorial