Routes
Routes are the HTTP endpoints your Grove application exposes. Each route is a file named
route.groveplaced inside your app'sapi/directory. The file's location in the directory tree determines the URL path — there is no inline path string.
Prerequisites: Concepts Overview, Activities for data block familiarity. What you'll learn: How to create route files, handle HTTP methods, use named handlers, access request input, and work with data blocks inside routes.
Route File Convention
Routes use filesystem-based routing. Create a file named route.grove inside apps/<app>/api/ and the directory structure becomes the URL path:
| File path | URL |
|---|---|
apps/main/api/todo/route.grove | /api/todo |
apps/main/api/todo/[id]/route.grove | /api/todo/:id |
apps/main/api/organizations/route.grove | /api/organizations |
apps/main/api/organizations/[id]/route.grove | /api/organizations/:id |
Dynamic segments use bracket syntax: a directory named [id] captures that portion of the URL as a path parameter accessible via input.params.id.
Route Block Syntax
Every route.grove file contains a single route { } block with no path argument. The path comes entirely from the file's location:
route {
GET {
// handle GET requests
}
POST {
// handle POST requests
}
}
HTTP Method Handlers
Place one or more HTTP method blocks inside the route. Each method handler is independent and has its own data blocks:
route {
GET {
data result {
query todo.list_todos {
limit: input.query.limit
}
}
}
POST {
data result {
invoke todo.create_todo {
title: input.body.title
}
}
}
}
Named vs Unnamed Handlers
When a route needs only one handler per HTTP method, use an unnamed handler:
POST {
data result {
invoke todo.create_todo { title: input.body.title }
}
}
When a route needs multiple handlers for the same HTTP method, give each handler a name:
POST create {
data result {
invoke organization.create_organization { name: input.body.name }
}
}
POST archive {
data result {
invoke organization.archive_organization { id: input.body.id }
}
}
Named handlers let you expose multiple operations under the same method on a single route.
The Input Object
Inside a route handler, the input object provides access to the incoming request:
| Field | Description |
|---|---|
input.body.* | The parsed request body (POST requests) |
input.params.* | Path parameters extracted from [segment] directories |
input.query.* | Query string parameters |
The ctx object provides additional context:
| Field | Description |
|---|---|
ctx.principal | The authenticated user (null if anonymous -- see Identity Flow) |
Data Blocks
Route handlers use data blocks to perform operations. Each data block gives its result a name so you can reference it later:
data result {
invoke module.action {
field: value
}
}
data records {
query module.query {
limit: input.query.limit
}
}
Available operations inside route data blocks:
| Operation | Purpose |
|---|---|
invoke | Call an activity to perform a side effect |
query | Execute a database query |
fetch | Retrieve a single record by identifier |
Complete Example: Collection Route
A collection route handles listing and creating resources. Place this at apps/main/api/organizations/route.grove to serve /api/organizations:
route {
GET {
data result {
query organization.list_organizations {
limit: input.query.limit,
offset: input.query.offset
}
}
}
POST {
data result {
invoke organization.create_organization {
name: input.body.name
}
}
}
}
Complete Example: Record Route
A record route handles operations on a single resource. Place this at apps/main/api/organizations/[id]/route.grove to serve /api/organizations/:id:
route {
GET {
data result {
fetch organization { id: input.params.id }
}
}
POST update {
data result {
invoke organization.update_organization {
id: input.params.id,
name: input.body.name
}
}
}
POST delete {
data result {
invoke organization.delete_organization { id: input.params.id }
}
}
}
Notice how the record route uses named POST handlers (update and delete) to expose multiple operations under the same HTTP method.
See Also
- Activities -- Data block operations shared with routes
- Services -- External APIs called via
fetchin route handlers - Queries -- Database queries used via
queryin route handlers - API Routes in Apps -- How routes fit into the app directory structure
- Full Language Reference -- Route grammar