The core server for WREN — versioned JSON storage and static site deployment.
This is the main application: a Bun/TypeScript HTTP server that provides the REST API, serves the Admin UI, marketing site, and handles authentication. It's the single process inside the reusr1/wren Docker image.
- REST API for documents, versions, labels, trees, schemas, binary assets, permissions
- Binary asset serving with content negotiation (JSON or raw bytes based on
Acceptheader) - Label-aware tree paths (
?label=publishedfor preview/promote workflows) - Multi-tenant Postgres isolation (one schema per org)
- Better Auth integration (email/password, session cookies, API keys)
- Marketing site, tutorials,
/projectsdirectory,/docs(Scalar),llms.txt
# With Docker (recommended)
docker compose up -d
# Server at http://localhost:4000
# Without Docker (needs Bun + Postgres)
bun install
DATABASE_URL=postgres://... bun run index.ts/ shows each new visitor one of the landing variants /a–/e, chosen at random and kept for 90 days in the wren_v cookie (the variant letter only). Views, first Admin UI opens and email sign-ups are counted per day and variant, with nothing that identifies a person; crawlers always get /c and aren't counted.
| Variable | Default | Meaning |
|---|---|---|
WREN_LANDING_VARIANTS |
a,b,c,d,e |
Variants in the experiment. One value (e.g. c) turns it off. |
WREN_OPERATORS |
none | Comma-separated emails that can see the results at /stats/landing. |
| Variable | Default | Meaning |
|---|---|---|
WREN_WEBHOOK_ALLOW_HOSTS |
none | Host names webhooks may reach although they resolve to private addresses (internal receivers) |
WREN_EVENTS_MAX_STREAMS / WREN_EVENTS_MAX_STREAMS_PER_ORG |
2000 / 200 |
Open /_events streams per server / per org |
WEBHOOK_BATCH_WINDOW_MS |
5000 |
Webhook batching window |
WREN sends account confirmations, password-reset links and invites. The delivery method is configuration:
| Variable | Default | Meaning |
|---|---|---|
MAIL_TRANSPORT |
log, or smtp if SMTP_URL is set |
log: nothing is sent; each message and its link is written to the server log. smtp: send via SMTP_URL. |
SMTP_URL |
none | e.g. smtps://user:[email protected]:465 or smtp://user:pass@host:587 (any SMTP provider) |
MAIL_FROM |
WREN <no-reply@localhost> |
Sender address; use one your provider is allowed to send for (SPF/DKIM) |
REQUIRE_EMAIL_VERIFICATION |
false |
true: email/password accounts must confirm before signing in. An unconfirmed sign-in attempt sends a fresh link. Google/GitHub accounts are already confirmed. |
Links in emails use BETTER_AUTH_URL, so set it to the public https:// address. Before switching REQUIRE_EMAIL_VERIFICATION on for an existing instance, make sure mail delivery works: existing accounts that never confirmed will need the link to sign in.
docker pull reusr1/wren:latest
# or pin a version: reusr1/wren:0.10.2
# Platforms: linux/amd64, linux/arm64Building it yourself (run from the folder that contains all the repos, since the build uses auth/, db/, marketing/ and the rest):
docker build -f sandbox/Dockerfile --build-arg WREN_BUILD=$(git -C sandbox rev-parse --short HEAD) -t wren:local .
curl -s localhost:4000/health # → {"status":"ok","version":"0.10.2","build":"<commit>"}Public links that WREN generates (/api/v1/projects, llms.txt, sitemap) use WREN_URL, falling back to BETTER_AUTH_URL. Set it to your public https:// address when running behind a TLS-terminating proxy.
All repos live under github.com/usewren:
| Repo | Description |
|---|---|
| sandbox | Server (this repo) |
| cli | CLI tool (@usewren/cli on npm) |
| adminui2 | Admin UI (vanilla JS) |
| marketing | Landing pages, tutorials, llms.txt |
| docs | OpenAPI 3.1 spec |
| db | Postgres migrations |
| auth | Better Auth configuration |
| client-ts | TypeScript client library |
| client-py | Python client library |
- Website: https://wren.aemwip.com
- Tutorial: https://wren.aemwip.com/tutorial
- Deploy tutorial: https://wren.aemwip.com/tutorial/deploy
- API Docs: https://wren.aemwip.com/docs
- Projects: https://wren.aemwip.com/projects
- npm: @usewren/cli
Apache-2.0