A brand-neutral, manifest-driven content backend for Go 1.25. It uses
fastygo/framework for the process and HTTP lifecycle
and fastygo/panel for UI-neutral control-plane descriptors.
The backend has no SSR, theme, plugin, Redis, or JavaScript runtime dependency. Product CPTs and form catalogs belong to the consumer (BFF or admin composition). This binary accepts a manifest path; it does not ship a storefront schema.
- Dynamic resource schemas, fields, relations, localization, and taxonomies
- Draft, scheduled, published, archived, and trashed lifecycle
- Optimistic locking, revisions, revision restore, and scheduled publishing
- Public/private projection and capability-based access control
- REST, executable GraphQL, GraphQL SDL, JSON Schema, and OpenAPI 3.1
- Secure media upload and download with local durable blob storage
- Transactional audit events
- Cross-adapter metadata backup/restore and media archive backup/restore
- bbolt, SQLite, MySQL, MariaDB, and PostgreSQL storage selection
- Framework health, readiness, metrics, graceful shutdown, and background workers
- Docker and bare-metal operation
cp .env.example .env
# Set HEADLESS_TOKEN_SECRET to at least 32 random bytes.
go run ./cmd/serverLocal development stores SQLite at ./var/lib/headless/backend.sqlite. The default
process is Codex-only (post, page, menu, setting). Point
HEADLESS_MANIFEST_PATH at a product manifest (the consumer repo), then seed
that product's records:
HEADLESS_MANIFEST_PATH=./dev/example.manifest.jsonWithout HEADLESS_MANIFEST_PATH, the process stays Codex-only. Extra CPTs and seed
files belong in the product repository; pass their paths at composition time.
The default bbolt deployment stores data under ./var/lib/headless.
curl -H "User-Agent: headless-client/1.0" http://127.0.0.1:8080/healthz
curl -H "User-Agent: headless-client/1.0" http://127.0.0.1:8080/readyz
curl -H "User-Agent: headless-client/1.0" http://127.0.0.1:8080/go-json/go/v2/openapi.jsonSet HEADLESS_MANIFEST_PATH to a JSON manifest:
{
"name": "store",
"version": "1",
"resources": [
{
"id": "product",
"collection": "products",
"public": true,
"rest_visible": true,
"graphql_visible": true,
"taxonomies": ["brand", "collection"],
"fields": [
{"id": "price", "type": "money", "required": true},
{"id": "description", "type": "text", "localized": true}
]
}
]
}Panel descriptors, REST paths, GraphQL types, JSON Schema, and OpenAPI are generated from this manifest.
Public reads are anonymous. Mutations and private reads require a Framework-signed bearer token.
On an empty identity store, HEADLESS_ADMIN_EMAIL and HEADLESS_ADMIN_PASSWORD create the first
administrator. Remove those bootstrap values after startup, then authenticate with:
POST /go-json/go/v2/auth/login
Content-Type: application/json
{"email":"admin@example.com","password":"..."}Users and roles are durable, versioned, capability-protected resources. Passwords use bcrypt and password hashes are never serialized by the REST API. The token CLI remains available for service accounts and recovery:
export HEADLESS_TOKEN_SECRET="$(openssl rand -base64 48)"
go run ./cmd/headless-token -subject admin -role administrator -ttl 24hUse the output as Authorization: Bearer <token>.
- REST collections:
/go-json/go/v2/{collection} - Discovery and types:
/go-json,/go-json/go/v2/,/go-json/go/v2/types - Optional GraphQL adapter:
/go-graphql - GraphQL SDL:
/go-json/go/v2/graphql.sdl - Schema identity:
/go-json/go/v2/schema - Resource JSON Schema:
/go-json/go/v2/types/{resource}/json-schema - OpenAPI:
/go-json/go/v2/openapi.json - Media:
/go-json/go/v2/media - Taxonomy definitions and terms:
/go-json/go/v2/taxonomies - Login, users, and roles:
/go-json/go/v2/auth/login,/go-json/go/v2/users,/go-json/go/v2/roles - Cookie session:
/go-json/auth/login,/go-json/auth/me,/go-json/auth/logout - Audit:
/go-json/go/v2/audit - Liveness/readiness:
/healthz,/readyz - Metrics:
/metricswhen enabled
The REST Codex envelope and pagination representation is the admin and storefront contract. GraphQL remains an optional adapter over the same services. Default go-codex resources cover posts, pages, menus, settings, media, taxonomies, content types, localized slug lookup, and search.
Select the adapter with HEADLESS_STORAGE:
bbolt: setHEADLESS_BBOLT_PATHsqlite: setDATABASE_URLto the SQLite filemysqlormariadb: set a Go MySQL driver DSNpostgresorpostgresql: set a PostgreSQL URL
SQL schema migrations run idempotently during startup.
Stop writes or place the service in maintenance mode before an operational restore.
go run ./cmd/headless-backup -mode export -path ./backup.json
go run ./cmd/headless-backup -mode restore -path ./backup.jsonThe command writes backup.json and backup.json.media.tar. Metadata backup format v3 includes
content, revisions, audit events, taxonomy definitions, and terms. Restore requires empty metadata
and media stores and verifies the manifest digest before importing.
docker compose up --build backend
docker compose --profile sqlite up --build backend-sqlite
docker compose --profile postgres up --build postgres backend-postgres
docker compose --profile mysql up --build mysql backend-mysql
docker compose --profile mariadb up --build mariadb backend-mariadbDocker requires the secrets declared in .env.example. The image runs as an unprivileged user.
make verifyThe production gate runs tests, conformance, vet, Staticcheck, govulncheck,
Linux race detection, module verification, and all command builds. On Windows,
the race detector runs in Docker. CI additionally exercises PostgreSQL, MySQL,
and MariaDB through make live-sql.
See docs/deployment/bare-metal.md for a systemd installation and
docs/architecture/target-headless.md for architectural boundaries.