Skip to main content

Dashtro

CI Docker image npm @dashtro/client npm @dashtro/mcp License: MIT

A self-hosted CMS with a project → workspace → collection → document model, a FastAPI backend, and a React/TypeScript frontend. Ships as a single Docker image, published to ghcr.io/1atharvad/dashtro. This repo only builds and publishes that image — running it in production (nginx, tunnel/domain routing, etc.) is owned by the consuming project (e.g. the portfolio site that embeds Dashtro as its admin/CMS backend).

Contents

Structure

Path What it is
cms_backend/ FastAPI backend — API, auth, schema engine, data clients. See its README.
cms-frontend/ React + TypeScript + Vite frontend. See its README.
cms_mcp/ MCP server exposing Dashtro operations to MCP-compatible clients (Python, console script dashtro-mcp, direct database access).
sdk/js/ @dashtro/client — JS/TS client SDK for /api/sdk/*.
sdk/python/ dashtro-client — Python client SDK for /api/sdk/*, released in lockstep with sdk/js/.
sdk/mcp/ @dashtro/mcp — npx-runnable MCP server (Node/TS port of cms_mcp/) for consuming projects; talks to /api/cms/* over HTTP, no Python required.
nginx/ Reverse proxy config for local dev only.

Packages

Everything this repo publishes, and what it's for:

Package Registry Install What it's for
ghcr.io/1atharvad/dashtro GHCR docker pull ghcr.io/1atharvad/dashtro The CMS itself — backend + built frontend in one image. See Running the image elsewhere.
@dashtro/client npm npm install @dashtro/client JS/TS client SDK for /api/sdk/* — read/write a project's documents and RTDB from an external app.
dashtro-client PyPI pip install dashtro-client Python equivalent of @dashtro/client, released in lockstep with it.
@dashtro/mcp npm npx @dashtro/mcp init npx-runnable MCP server — lets Claude/other MCP clients read and write your CMS content. Node port of cms_mcp/, no Python needed.
dashtro not published n/a — run from a repo checkout Root package: the dashtro backup/restore CLI (cms_backend/scripts/cms_schema.py, see Backup / restore CLI). Also bundles cms_mcp/dashtro-mcp, but use @dashtro/mcp instead for MCP access — this package isn't on PyPI.

Architecture

flowchart LR
    Browser["Browser SPA\n(cms-frontend)"] -->|"/api/*"| Backend["FastAPI backend\n(cms_backend)"]
    Backend --> DB[("sqlite / postgres")]
    ExternalApp["External app"] -->|"/api/sdk/*"| Backend
    ExternalApp -.->|uses| ClientSDK["@dashtro/client\ndashtro-client"]
    MCPClient["MCP client\n(Claude, etc.)"] -->|stdio, npx| MCPNode["@dashtro/mcp\n(Node)"]
    MCPNode -->|"/api/cms/*"| Backend
    MCPClient -.->|stdio, local install| MCPPy["dashtro-mcp\n(cms_mcp, Python)"]
    MCPPy -->|"/api/cms/*"| Backend

Everything ultimately talks to the same FastAPI backend — the frontend over its own API, external apps over the API-key-scoped /api/sdk/* surface (via either client SDK), and MCP clients over /api/cms/* through either MCP server (@dashtro/mcp for a zero-install npx setup, or cms_mcp/dashtro-mcp if you're already in a Python environment with direct database access).

Data backends

DB_TYPE selects the storage backend, defaulting to sqlite:

  • sqlite — single-file DB, zero external dependencies. Default.
  • postgres — set DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD. An optional bundled postgres compose service is available (see below) if you don't want to point at an external instance.

Both backends implement the same interface (get_data_client() / get_auth_client() / get_audit_client() in cms_backend/api/utils/__init__.py), so routers don't change depending on which one is active.

Running locally (dev)

Hot-reloading, separate frontend/backend containers, Cloudflare tunnel support:

cp .env.example .env   # fill in real values
npm run dev             # docker compose -f docker-compose.dev.yml up --build
npm run dev:down

Optional local Postgres instead of an external one:

docker compose -f docker-compose.dev.yml --profile postgres up

Running the image elsewhere

The published image serves both the API and the built SPA on port 7312, and reads its config from env vars (see below) — no other dependency beyond whichever DB_TYPE backend you point it at:

dashtro:
  image: ghcr.io/1atharvad/dashtro:latest
  environment:
    JWT_SECRET_KEY: ...
    CORS_ORIGINS: ...
    CMS_PUBLIC_URL: ...
    DB_TYPE: sqlite
    # ...see .env.example for the full list
  volumes:
    - uploads_data:/app/uploads

Put it behind whatever reverse proxy/tunnel the consuming project already uses to route a subdomain (e.g. admin.example.com) to it.

Environment variables

See .env.example for the full list (DB_TYPE, JWT_SECRET_KEY, CORS_ORIGINS, CMS_PUBLIC_URL, etc.).

Backup / restore CLI

cms_backend/scripts/cms_schema.py (installed as the dashtro console script) exports/imports schemas, documents, and media to/from a backup/ directory.

Local (direct database access)

# Export
dashtro export schema --project-id <id>
dashtro export documents --project-id <id> --workspace <name>
dashtro export media

# Import
dashtro import schema --project-id <id>
dashtro import documents --project-id <id> --workspace <name>
dashtro import media

Run against a running container:

docker exec <container> dashtro export schema --project-id <id> --backup-dir /app/backup
docker exec <container> dashtro import schema --project-id <id> --backup-dir /app/backup

Remote (HTTP API with authentication)

Use --base-url to export/import from/to a remote Dashtro instance. Requires an API key generated in the CMS settings.

Via command line:

# Export from remote
dashtro export schema --project-id <id> --base-url https://your-cms.com --api-key <api-key>
dashtro export documents --project-id <id> --workspace <name> --base-url https://your-cms.com --api-key <api-key>
dashtro export media --base-url https://your-cms.com --api-key <api-key>

# Import to remote
dashtro import schema --project-id <id> --base-url https://your-cms.com --api-key <api-key>
dashtro import documents --project-id <id> --workspace <name> --base-url https://your-cms.com --api-key <api-key>
dashtro import media --base-url https://your-cms.com --api-key <api-key>

Via environment variable (recommended):

export CMS_API_KEY=<api-key>
dashtro export schema --project-id <id> --base-url https://your-cms.com
dashtro import documents --project-id <id> --workspace <name> --base-url https://your-cms.com

Full backup/restore workflow

Export must run in order: schema → documents → media. Restore uses the same order:

# Backup from source instance
dashtro export schema --project-id abc123 --base-url https://source.com --api-key <key>
dashtro export documents --project-id abc123 --workspace production --base-url https://source.com --api-key <key>
dashtro export media --base-url https://source.com --api-key <key>

# Restore to destination instance
dashtro import schema --project-id abc123 --base-url https://dest.com --api-key <key>
dashtro import documents --project-id abc123 --workspace production --base-url https://dest.com --api-key <key>
dashtro import media --base-url https://dest.com --api-key <key>

Options:

Flag Meaning
--backup-dir Backup directory location (default: ./backup/)
--base-url Remote API URL (if omitted, uses direct database access)
--api-key API key for authentication (or set CMS_API_KEY env var)
--merge Merge documents instead of replacing (local mode only)

CI/CD

.github/workflows/build-image.yml runs on every push to main (or manually via workflow_dispatch):

  1. lint — frontend npm run lint + backend isort/black/ruff --check. Must pass before anything builds.
  2. build-and-push — builds Dockerfile.dashtro, pushes to ghcr.io/1atharvad/dashtro tagged latest and the commit SHA.

That's it — this repo doesn't deploy anywhere itself. Whatever consumes the image (e.g. the portfolio project) is responsible for pulling and running it.

Tests

cd cms_backend && pytest              # backend, SQLite by default
TEST_DB_TYPE=postgres pytest          # backend, against a reachable Postgres

cd cms-frontend && npm test           # frontend (vitest)

License

MIT

Release files for dashtro 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dashtro 0.1.0
File Size Uploaded
dashtro-0.1.0.tar.gz 44.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dashtro 0.1.0
File Interpreter ABI Platform
dashtro-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 93.3 kB

Release files / dashtro-0.1.0.tar.gz

Download URL dashtro-0.1.0.tar.gz
Size 44.0 kB
Tags Source
SHA-256 checksum
How to use checksums
98d21c8f930a9bc1aefd626b5f9f641a74651a7ef939843cd0ecd8c59f28e718
BLAKE2b-256 checksum
How to use checksums
65d576673049140377c6a8178e74e4fbce5af25227f373f5add1cec4a3a48e24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release files / dashtro-0.1.0-py3-none-any.whl

Download URL dashtro-0.1.0-py3-none-any.whl
Size 49.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a009054e0cf26c4b5cb1af331ca6709349c812e1a20b74bc1bc55fa96469fdd6
BLAKE2b-256 checksum
How to use checksums
fb1062f7d9c8cd23ae4017bd8b988e3b68e162dc07aaab827facb0bdd0e7a6fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page