Terranova reads a plain KDL schema file and immediately serves a fully functional REST API — no boilerplate, no code generation, no fuss.
application "Todo" version="0.1" {
entity "User" {
schema {
pk "id" type="int"
field "name" type="string"
field "email" type="string"
has-many "Todo" as="tasks" on-delete="cascade"
}
queries {
get "user_by_id" sql="SELECT * FROM user WHERE id = :id" {
param "id" type="int"
}
}
views {
template "/user" query="user_by_id" html="
<h1>{{data.name}}</h1>
<p>Email: {{data.email}}</p>
"
}
}
entity "Todo" {
schema {
pk "id" type="int"
field "title" type="string"
field "done" type="bool"
field "created_at" type="datetime"
belongs-to "User" as="owner"
}
}
profile "dev" default=true {
listen address="127.0.0.1" port=8080
}
}
No scaffolding commands. No generated directories to maintain. No runtime dependencies beyond Terranova itself.
api.kdl file.
terranova serve -f <filename>terranova serve -f ./api.kdlhas-many, has-one, and
belongs-to. Terranova creates foreign keys and rules.
/docs.html that
stays in sync with your KDL.
api.kdl file
KDL (KDL Document Language) is a small, human‑readable node document format. Terranova adds a thin API‑specific vocabulary on top.
| Node | Example | What it does |
|---|---|---|
| application | application "MyApp" version="0.1" |
Root container. Sets name, version, license, and global namespace. |
| entity | entity "User" { schema { ... } } |
Declares a data model. Generates CRUD endpoints and a database table. |
| pk | pk "id" type="int" |
Defines the primary key column. Required for UPDATE/DELETE endpoints. |
| field | field "name" type="string" optional=true |
Defines a column. Supported types: int, float, string, bool, datetime, date, blob, file. |
| has-many/has-one/belongs-to | has-many "Todo" as="tasks" on-delete="cascade" |
Declares relationships. Creates foreign keys and nested routes. |
| queries | get "user_by_id" sql="..." { param "id" type="int" } |
Custom SQL queries (raw or composed). Each becomes an HTTP endpoint. |
| views | template "/user" query="user_by_id" html="..." |
Binds a query to a Mustache template. Renders HTML responses. |
| profile | profile "dev" default=true { listen address="127.0.0.1" port=8080 } |
Environment‑specific server configuration (address, port, TLS). |