Skip to content

The Nubo docs

Scripts. APIs.
Your Go app, too.

A small, typed language for the things you want to build. Start with a script, grow into an API, or make it part of your Go app.

Open source. Built with Go. Ready for your ideas.

hello.nubo
fn greet(name: string = "World") string {
return "Hello, " + name
}
println(greet(name: "Ada"))
nubo hello.nubo
Hello, Ada
Named arguments. Real types. One little file. Explore the language

Types where they help

Inferred variables, nullable and union types, typed collections, structs, interfaces, and automatic struct initializers.

Go in, Nubo out

Embed the interpreter, register Go functions, and write public package APIs in Nubo while Go handles host operations.

HTTP APIs built in

File routes, dynamic parameters, JSON, cookies, forms, uploads, static files, and custom error pages.

HTML is a value

Compose HTML literals and function components, pass children, and escape interpolated text without a separate template language.

Start with a file. Add types, methods, and interfaces as your program grows.

hello.nubo
struct User {
name: string
roles: []string
}
impl User {
fn greet(self: User) string {
return "Hello, " + self.name
}
}
let user = User(name: "Ada", roles: ["developer"])
println(user.greet())
Terminal window
nubo hello.nubo

No explicit initializer is needed here: Nubo initializes public fields by name. Functions support defaults, named arguments, closures, and typed function values too.

Expose a supported Go function without manually building Nubo argument objects.

main.go
package main
import (
"fmt"
"log"
"github.com/nubolang/nubo"
)
func main() {
app := nubo.New()
err := app.AddFunc("Greeting", nubo.GoFunc(func(name string) string {
return "Hello, " + name
}))
if err != nil {
log.Fatal(err)
}
result, err := app.ExecString(`return Greeting("Ada")`)
if err != nil {
log.Fatal(err)
}
if result != nil {
fmt.Println(result.Value())
}
}

The bridge converts supported scalars, lists, and dictionaries. Returned Go errors become catchable Nubo errors. Use Go for database access, application services, filesystem operations, or calls to existing Go packages, then expose a small script-facing API.

Learn Go embedding · Build a Go HTTP API with Nubo

A hybrid package defines its public functions in Nubo and imports its own Go bindings privately through @native:

package.nubo
import native from "@native"
fn encode(value: string) string {
return native.encode(value)
}

The host registers nubo.Package{Source: code, Funcs: bindings} under an @std/... name. Callers use a normal import; they do not need to know how the package is implemented.

import hex from "@std/hex"
println(hex.encode("hello"))
println(hex.decode("68656c6c6f"))

@std/hex is a working hybrid package included with Nubo. Create your own package with inline source, helper files, or an embedded filesystem.

app/users/[id].nubo
import request from "@server/request"
import response from "@server/response"
response.json(dict[string, any] {
id: request.param("id"),
active: true
})
Terminal window
nubo serve app --addr :3000

GET /users/42 returns JSON. Use request.json() for request bodies and response.status(...) for status codes. Route scripts run on the server; they do not require browser JavaScript.

Build your first endpoint · Request API · Response API

app/index.nubo
import { Context } from "@std/component"
import response from "@server/response"
fn Button(ctx: Context) html {
return <button class="btn">!{ctx.children.join("")}</button>
}
let name = "Ada"
response.write(<main>
<h1>Hello, {name}</h1>
<Button>Save changes</Button>
</main>)

{value} escapes text. !{value} inserts raw HTML, as used above to render component children. Use raw insertion for trusted HTML rather than untrusted request data.

Make an HTTP request with per-client defaults and per-request options:

import http from "@std/http"
let client = http.create({
baseUrl: "https://example.com",
timeout: 10,
headers: {Accept: "text/html"}
})
let result = client.request("GET", "/")
println(result.status)
println(result.body())

Explore the HTTP client, OS helpers, reflection, SQL, JSON, hashing, and concurrency libraries. SSH, Telnet, and serial packages are available for host automation too.

catch err {
panic("Cannot load account")
}
if !isNil(err) {
println(err.message)
println(string(err))
}

Caught failures are built-in Error structs with source locations, stack traces, and optional causes. Use defer for cleanup when a scope exits.

Download an executable for your OS and CPU from GitHub releases, or install the CLI with Go:

Terminal window
go install github.com/nubolang/nubo/cmd/nubo@latest

Installation and PATH setup · Language basics · Go integration