A self-hosted plugin registry, built for operators.
Tabularium is a directory of plugins (or any release-shipping artefact) with a SvelteKit UI, an OAuth-driven submission flow, a typed OpenAPI surface, and a built-in CMS. Authors connect their GitHub, GitLab, or Gitea account, pick a repo, and every new tag becomes a release in the registry.
Multi-provider
GitHub, GitLab, Gitea — any instance. Webhook-driven; new tags become releases.
Paste-friendly manifest
Drop a .tabularium at the repo root. IDE autocomplete via a public JSON Schema.
Operator-extendable
Locked core fields plus admin-defined extensions — global and per kind.
Built-in CMS
Markdown pages, widgets, translations per locale. No external CMS needed.
Multi-dialect
SQLite, Postgres, or MySQL. Auto-detected from DATABASE_URL.
Audit log
Every admin mutation tracked with actor and target. No silent state.
Drop one file into your repo
Tabularium ships with a small, locked core schema plus operator-defined extensions. Authors write a paste-friendly YAML or JSON manifest and get IDE autocomplete from the registry's public JSON Schema.
- Default filenames:
.tabularium,.tabularium.json,tabularium.yaml,tabularium.json - Filename whitelist is admin-configurable (up to 12 entries)
- Schema URL exposed at
/manifest.schema.json - Per-kind schema override at
/manifest.schema.json?kind=…
# yaml-language-server: $schema=https://tabularium.wiki/manifest.schema.json name: My Plugin description: A short tagline shown on the catalog card. category: databases kind: theme tags: [dark, minimal] license: MIT icon: ./assets/icon.svg screenshots: - url: ./assets/screen-1.png caption: Live query view documentation_url: https://docs.example.com/my-plugin homepage: https://example.com/my-plugin support: email: support@example.com issues_url: https://github.com/me/my-plugin/issues min_runtime_version: '2.4.0' readme: README.md
# Pull the image, drop in a compose file, go. $ curl -O https://codeberg.org/Tabularium/Tabularium/raw/branch/main/docker-compose.example.yml $ mv docker-compose.example.yml docker-compose.yml # Generate real secrets — both must be 32+ chars. $ openssl rand -hex 32 # JWT_SECRET $ openssl rand -hex 32 # TOKEN_ENC_KEY # Edit docker-compose.yml, replace both placeholders. $ docker compose up -d # First-run wizard prints a bootstrap password to the logs. $ docker compose logs registry | grep -A2 FIRST-RUN
Self-host in one Compose file
The published container image lives on the Codeberg container registry, built with Buildah on a Forgejo runner. The runtime is Bun on Alpine — no Node, no rebuild-on-config.
- Image:
codeberg.org/tabularium/tabularium:latest - Runtime: Bun on Alpine, healthcheck on
/healthz - State: SQLite by default, swap to Postgres / MySQL via
DATABASE_URL - Cache: in-memory or Bun.redis (Dragonfly-compatible)
See the deploy guide for env vars, reverse-proxy notes, and the full admin console walkthrough.