Self-hosted lore database for worldbuilding. A server-only fork of TriliumNext/Trilium, stripped down to its core and rebuilt for writers, game masters, and world builders.
AllCodex stores your worldbuilding notes in SQLite and serves them over a REST API (ETAPI). It handles lore templates, GM-only secrets, world variable expansion, and public sharing out of the box.
AllCodex works alongside the other services in the AllKnower stack:
| Service | Role | Repo |
|---|---|---|
| AllCodex (this repo) | Lore database server, ETAPI, share pages | ThunderRonin/AllCodex |
| AllCodex-Portal | Web frontend for browsing and editing lore | ThunderRonin/AllCodex-Portal |
| AllKnower | AI orchestrator: brain dump, consistency checks, relationship discovery. (Refer to AllKnower's .env.example for LLM model preferences) |
ThunderRonin/Allknower |
AllKnower calls AllCodex. The Portal calls AllCodex. AllCodex serves data.
- 21 lore templates with promoted attributes: Character, Location, Faction, Creature, Event, Timeline, Manuscript, Statblock, Item/Artifact, Spell/Magic, Building/Structure, Language/Script, Session, Quest, Scene, Organization, Race, Myth, Cosmology, Deity, Religion
- GM-only secrets: tag notes with
#gmOnlyor wrap HTML sections inclass="gm-only"to hide them from shared pages - World variables: write
{{currency}}in a note and it expands to the value stored in your#worldVariablesJSON note - Public sharing: render any subtree as a public website at
/share/ - Full REST API with interactive docs at
/docs(Scalar) and a JSON spec at/etapi/openapi.json - Search: query by attributes, labels, note content, or any combination (
#loreType=character #status=alive) - Note relationships: parent/child branches + typed relation attributes between notes
- Revision history: every edit is versioned
- Encryption: per-note protection with password-gated sessions
- Node.js 22.x (Node 26 breaks better-sqlite3 native bindings)
- pnpm 10+
git clone https://github.com/ThunderRonin/AllCodex.git
cd AllCodex
pnpm install
pnpm server:startServer starts at http://localhost:8080. API docs at http://localhost:8080/docs.
docker compose up -dOr build the image yourself:
docker build -t allcodex -f apps/server/Dockerfile .
docker run -p 8080:8080 -v allcodex-data:/home/node/allcodex-data allcodexOn first launch, you must initialize the database before performing any other operations. Follow these two steps in order:
Step 1: Create the database (no body required):
curl -X POST http://localhost:8080/api/setup/new-documentExpected response: empty 200 OK.
Step 2: Set the password:
curl -X POST http://localhost:8080/set-password \
-H "Content-Type: application/json" \
-d '{"password1": "yourpassword", "password2": "yourpassword"}'Expected response:
{"success": true, "redirect": "login"}If you skip step 1 and go directly to POST /set-password, the server redirects to /setup because the database does not exist yet. Once you set the password, any subsequent call to POST /set-password returns 400 Bad Request. To change the password later, use POST /api/password/change with current_password and new_password fields.
After initializing, create an API token via the options page at http://localhost:8080 or via the internal API. The Portal and AllKnower need this token to talk to AllCodex.
Interactive reference: http://localhost:8080/docs
OpenAPI spec (JSON): GET /etapi/openapi.json
OpenAPI spec (YAML): GET /etapi/etapi.openapi.yaml
Common endpoints:
| Method | Path | What it does |
|---|---|---|
GET |
/etapi/notes?search=... |
Search notes by query |
GET |
/etapi/notes/:id |
Get note metadata |
GET |
/etapi/notes/:id/content |
Get note body (HTML) |
POST |
/etapi/create-note |
Create a note |
PATCH |
/etapi/notes/:id |
Update note metadata |
PUT |
/etapi/notes/:id/content |
Update note body |
DELETE |
/etapi/notes/:id |
Soft-delete a note |
POST |
/etapi/attributes |
Add a label or relation |
GET |
/etapi/app-info |
Server version info |
All endpoints require Authorization: <token> header except /docs, /etapi/openapi.json, and /etapi/etapi.openapi.yaml.
Lore entries are standard notes with attributes that categorize them:
#loreType=character characters and NPCs
#loreType=location places, regions, landmarks
#loreType=faction organizations, states, religions
#loreType=creature monsters and beasts
#loreType=event historical events
#loreType=timeline chronologies (book-type notes)
#loreType=manuscript in-world documents
#loreType=statblock D&D 5e stat blocks
Each type has a built-in template with promoted attributes (structured fields like "Race", "Population", "Danger Level", etc.) that appear as metadata on the note.
apps/
server/ Express 5 + SQLite server
server-e2e/ Playwright end-to-end tests
build-docs/ TypeDoc generation
db-compare/ DB comparison tool
dump-db/ DB dump tool
icon-pack-builder/ Icon pack generation
packages/
commons/ Shared types and utilities
codemirror/ Code editor bundle
express-partial-content/ Range request support
turndown-plugin-gfm/ Markdown conversion
pnpm server:start # dev server with hot reload
pnpm server:build # production build
pnpm test:all # run all tests
pnpm typecheck # TypeScript check
pnpm dev:linter-check # ESLintContributions are welcome. If you're interested in working on AllCodex, here's how to get started:
- Fork the repo and clone it locally
- Run
pnpm installto set up the monorepo - Start the dev server with
pnpm server:start - Make your changes on a feature branch
- Run
pnpm test:all && pnpm typecheckbefore opening a PR
A few things to keep in mind:
- Keep PRs focused. One feature or fix per pull request. Avoid drive-by refactors in unrelated files.
- Test your changes. If you're touching ETAPI endpoints or the share renderer, write or update tests.
- Don't break existing APIs. ETAPI is consumed by the Portal and AllKnower. Changing endpoint signatures or response shapes needs discussion first.
- Templates go in
hidden_subtree_templates.ts. If you want to add a new lore type or modify an existing one, that's the file. - Share page rendering lives in
apps/server/src/share/. Content processing (gmOnly, world variables) is incontent_renderer.ts.
If you're not sure where to start, look for issues tagged good first issue, or open a discussion with your idea before writing code.
Forked from TriliumNext/Trilium (which itself continues zadam/trilium). The original client, desktop, and web-clipper apps have been removed. The server, data model, and ETAPI remain intact.
AGPL-3.0-only. See LICENSE.