The ledger becomes an app
You started with println("Ledger ready"). You now have types, a list, functions, structs, and errors. This chapter is the last mile of that same program:
- Split it into modules (the files you just learned)
- Serve it as a Keel API with a page
- Pack a ship
That is the 1.0 loop. Not a rewrite in another language. Not a framework migration.
1. Split the CLI
From the ledger project:
ledger/
buraaq.pkg
src/main.bq
src/tx.bq
src/account.bq
src/tx.bq:
pub struct Tx {
amount: int
note: text
}
pub fn deposit(cents: int, note: text) -> Tx {
Tx { amount: cents, note: note }
}
pub fn withdraw(cents: int, note: text) -> Tx {
Tx { amount: 0 - cents, note: note }
}
src/account.bq:
use tx.Tx
pub struct Account {
owner: text
balance: int
}
pub fn open(owner: text) -> Account {
Account { owner: owner, balance: 0 }
}
pub fn apply(a: Account, t: Tx) -> Account {
Account { owner: a.owner, balance: a.balance + t.amount }
}
src/main.bq:
use tx.{deposit, withdraw}
use account.{open, apply}
fn main() {
mut a = open("Ada")
a = apply(a, deposit(5000, "payroll"))
a = apply(a, withdraw(1200, "rent"))
println(a.owner)
println(a.balance)
}
buraaq run
You should see Ada and 3800. Unique std.io names still import themselves. The use lines are only for your modules.
2. Serve the same idea
A CLI proves the language. A service proves the stack. Keep the project. Change main to declare a hull:
fn main() {
page("/", "public/index.html")
api("accounts", "name, note")
api("ledger", "account, cents, memo")
run()
}
page, api, and run auto-import from std.keel. Put a page in public/index.html (or run buraaq new ledger in a fresh folder if you want the scaffold).
Set Postgres on the host, not in source:
$env:BURAAQ_DATABASE_URL = "host=127.0.0.1 port=5432 dbname=ledger user=postgres"
buraaq run
Keel creates the tables, serves /api/accounts and /api/ledger, and /api/health is SELECT 1. If a Neon pooler drops an idle socket, Keel reconnects on the next query.
Do not put JSON in a Buraaq "..." string ({ interpolates). POST from curl or from the page.
curl http://127.0.0.1:8080/api/health
Open http://127.0.0.1:8080. TLS is on 8443.
This is the same ledger: accounts, amounts in cents, a memo. The difference is the OS can exec it as a service.
3. Pack it
buraaq up
That packs a hashed .bur, starts a local Dock if needed, and runs the process. On a VM you own:
buraaq land --cloud hetzner
buraaq ship HOST
Put BURAAQ_DATABASE_URL in ~/.buraaq/dock/env (or an env file next to the binary). Never in git. A Windows .bur will not run on Linux: pack on the host OS.
This chapter is the full arc in public docs: modules, ownership, spawn, a Keel ledger, Postgres, Land. Private demos may go further; your ledger here is the version you can ship from the public tree.
What you just beat
| Step | What you did not need |
|---|---|
| Two files | headers, mod.rs, a bundler |
| Auto-import | a use list for println / page / run |
| The API | Express, Axum, a Dockerfile |
| The database | an ORM, a migration DSL for api() tables |
| The deploy | Kubernetes, a guest Linux |
You wrote Buraaq the whole way. Native LLVM the whole way. Next: stdlib if you want Stream, Gfx, Hold, and Grid, or Servers for REST depth, or Ship for the hash and the dock.
