Learn
Start with code
Orbit is a statically typed language for APIs and microservices. You need a C compiler, Python, and git. Nothing else stands between you and a running service.
What a route looks like
A service is a list of routes. Each one takes a request, does something small, and returns a status and a body. There's no framework object to subclass and no plugin registry to configure.
A segment like :id or {id} captures one non-empty segment and binds through req.param("id"). Static routes win over parameter routes, so /posts/search and /posts/:id both work without colliding.
// Excerpt from examples/params_service.orb
route GET "/notes/:id" {
val id = req.param("id")
return ok 200 "{\"note\":\"" + id + "\"}"
}
route GET "/posts/search" {
return ok 200 "{\"static\":true}"
}
route GET "/posts/:id" {
val id = req.param("id")
return ok 200 "{\"post\":\"" + id + "\"}"
}Models are tables
Declare a model and the runtime creates its table on startup. Reads and writes work today.
// Excerpt from examples/posts_crud.orb
model Post {
id: string
title: string
body: string
views: int
rating: float
published: bool
}
route GET "/posts" {
val posts = Post.all()
return ok 200 posts
}
route POST "/posts" {
val payload = req.body()
if payload == "" || payload == "{}" {
err 400 "post a JSON body with id and title"
}
val created = Post.create(payload)
if created {
return ok 201 payload
}
return ok 400 "{\"stored\":false}"
}The runtime creates the table on startup from the declared fields: string to TEXT, int and bool to INTEGER, float to REAL, and an id field to the primary key.
Model.create() stores the row and returns true, or false when the id already exists or the payload has no usable fields.Model.delete() returns true only when a row was actually removed.
The standard library is a path
No package manager, no registry, no lockfile. An import is a string, and it resolves from anywhere in the tree.
A path is relative to the file doing the importing, or to the standard library. Those two spellings of the same file both resolve, from any directory:
import "std/string/string.orb" reaches the library, and import "lib/arena.orb" reaches a sibling of the importing file. The search path is the compiler binary's directory, its parent, then the working directory, so a build run from the repository root finds everything.
What landed in September: test, string, hash, collections, fs, io, time, process and log. Seven earlier stubs were deleted rather than shipped unusable.
One naming hazard worth knowing before it costs you an afternoon: a function called read, write, open or close collides with the C library of the same name. orbit check passes and the link fails.
import "std/sys/term/color.orb"
import "lib/arena.orb"
fn main() -> int {
val line = wrapBold("orbit std imports work")
print(line)
return 0
}Where to go next
01
Clone and build the compiler
Two commands with a C compiler and Python. The build reaches a fixed point you can verify, and a committed C file is the trust root.
Getting started02
Read the language tour
Functions, bindings, models, routes, SQLite reads, and telemetry. Every snippet is runnable and every output is verified.
Language tour03
Build a real service
A blog API with bearer auth, expected outputs included. Then a file server, then deploying one binary.
Blog API tutorial04
Check what it can't do
Eight known limits, four of them with a worked-around recipe, kept next to the documents that use each feature.
Known limitations
Build it yourself
Orbit's own compiler is written in Orbit, so the toolchain is something you can read end to end. If a build step surprises you, the answer is in the repository.
On Windows the same commands produce .\orbit.exe. Theplatform support page lists what is verified where.
git clone https://github.com/joacokhzyx/orbit-lang.git
cd orbit-lang
python scripts/build_selfhost.py --out orbit
./orbit build examples/health_service.orb -o health_service
./health_service 8080Prefer the source?
The compiler, the runtime, the test suite, and the documentation all live in one repository. I'd rather you check my claims than take them.