graph.New(app, router) renders the Base's collections as GraphQL and answers every field with a request on the Base's own router, made with the caller's headers, so the list and view rules, tenancy, rate limits and expand's view checks are the REST path's and there is no second authorization. zip's engine executes it: a host mounts g.Schema and g.Resolve with zip.MountGraphFor, so zip is bumped to v1.37.43. - A type per base and view collection, named from the collection (people: BasePerson, person, people, peopleGroupBy, createPerson, updatePerson, upsertPerson, deletePerson), with its fields, relations as objects, the records pointing at it as connections (opportunities_via_company) and its history. - A filter input per collection whose operators per field type are the where clause's: each is one leaf of core.CompileWhere, so and, or, not, @me, relative dates, back-relations and inSegment mean what they mean there, every value bound. - orderBy, cursor connections paged through Base's pages, a totalCount asked only when selected, and aggregate and GroupBy from the aggregate route. - Bounds: 100 a page, four relations deep refused before any request, 50 requests a root field, and zip's 10,000 resolutions. graph_test drives it through zip against a CRM Base: every filter type, paging both ways, the figures, the writes as REST reads them back, the refusals in REST's own words (a rule, a superuser-only collection, another org's token), the budget, and type names on every object. tests.IAM signs IAM tokens for any test, and apis' helper uses it.
Base
Base is a backend in one Go binary: collections of records behind a REST API at
/v1, with realtime updates, files, per-collection access rules and JavaScript
hooks, stored in SQLite. Identity comes from Hanzo IAM, and with IAM on, each
org's data lives in a database file of its own.
Run it
You need Go 1.26.8 or newer.
git clone --depth 1 https://github.com/hanzoai/base
cd base/examples/base
CGO_ENABLED=0 go build
Describe a collection in a migration. Base applies migrations when it starts.
mkdir -p base_/migrations
cat > base_/migrations/1_notes.js <<'EOF'
migrate((app) => {
app.save(new Collection({
type: "base",
name: "notes",
listRule: "",
viewRule: "",
createRule: "",
fields: [{ name: "text", type: "text", required: true }],
}))
})
EOF
./base serve --http 127.0.0.1:8090
Server started at http://127.0.0.1:8090
├─ REST API: http://127.0.0.1:8090/v1/
└─ Dashboard: http://127.0.0.1:8090/
From a second terminal, create a record and list the collection:
curl -s -X POST http://127.0.0.1:8090/v1/collections/notes/records \
-H 'Content-Type: application/json' -d '{"text":"hello"}'
{"collectionId":"hbc_3395098727","collectionName":"notes","id":"kbx358lmic2a4bw","text":"hello"}
curl -s http://127.0.0.1:8090/v1/collections/notes/records
{"items":[{"collectionId":"hbc_3395098727","collectionName":"notes","id":"kbx358lmic2a4bw","text":"hello"}],"page":1,"perPage":30,"totalItems":1,"totalPages":1}
The empty rules let anyone read and write notes; docs/rules.md
shows how to close them. The data is in base_/data.
The startup output has two stale lines. The Dashboard address answers only when
BASE_ENABLE_ADMIN_UI=1 is set, and the hint to run superuser upsert names a
command that was removed. Superusers come from IAM.
Use it as a Go library
In an empty directory, save this as main.go:
package main
import (
"log"
"github.com/hanzoai/base"
"github.com/hanzoai/base/core"
)
func main() {
app := base.New()
app.OnServe().BindFunc(func(se *core.ServeEvent) error {
se.Router.GET("/hello", func(re *core.RequestEvent) error {
return re.String(200, "Hello")
})
return se.Next()
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
go mod init example.com/hello
go mod tidy
CGO_ENABLED=0 go build
./hello serve
GET http://127.0.0.1:8090/hello then answers Hello, next to the whole /v1
API.
Read next
| Page | For |
|---|---|
| docs/versions.md | which tags serve what, and moving from /api and passwords to /v1 and IAM |
| docs/rules.md | access rules, identity from IAM, orgs |
| docs/hooks.md | JavaScript hooks and migrations |
| docs/config.md | every command, flag and environment variable |
| docs/listeners.md | every socket Base can open |
| docs/threat-model.md | what Base defends, and what you configure |
| examples/hooks-hybrid-search | full-text and vector search written as hooks |
Clients
- JavaScript and TypeScript:
@hanzo/base. Give it the origin, as innew BaseClient('http://127.0.0.1:8090'); it adds/v1itself. - Dart: hanzo-dart/base.
Contributing and security
CONTRIBUTING.md covers building and testing. Report vulnerabilities as SECURITY.md describes. Base is MIT licensed; see LICENSE.md.