Skip to content

Getting Started

  • Node.js ≥ 22.13
  • pnpm ≥ 11.4
  • Docker + Docker Compose (for production or dev-infra mode)
  • GNU Make (included on Linux/macOS, on Windows use WSL or Git Bash)

Clone and install:

Terminal window
git clone https://github.com/archispark/archispark
cd archispark
pnpm install
pnpm dev

pnpm dev (via Turborepo) starts every app in parallel, all bound to 0.0.0.0:

ServiceURL
control-api (REST + Better Auth)http://localhost:3000
tenant-api (workspaces/elements/views)http://localhost:3002
MCP Serverhttp://localhost:3001/mcp/
Web UIhttp://localhost:8000
Admin web (platform_admin only)http://localhost:8001
API Docs (Swagger UI)http://localhost:3000/docs

tenant-api is internal-only in production (no Traefik route, reached over the Docker network) — locally it’s just another pnpm dev process on port 3002. /openapi.json and /docs are served by tenant-api and proxied through control-api, so they’re reachable on port 3000 too.

PostgreSQL and Redis must be running. The quickest way is make dev-infra (see below) before pnpm dev.

Four demo accounts are seeded on first startup — see Authentication & Authorization.


Two compose files cover every deployment mode:

FilePurpose
docker-compose.ymlProduction — pulls published images from Docker Hub. Includes Traefik v3, control-api, tenant-api, mcp-server, web, PostgreSQL 17 and Redis 7
docker-compose.dev.ymlDevelopment infra — PostgreSQL 17 + Redis 7 only, used by make dev-infra while the apps run via pnpm dev on the host

apps/admin-web is not part of either compose file — it’s deployed independently (its own Vercel project or subdomain). See Admin web.


The Makefile wraps every common operation. Run make or make help for the full list.

Terminal window
make env # copies .env.example → .env
# edit .env: set DB_PASSWORD, BETTER_AUTH_SECRET, TENANT_JWT_SECRET (min 32 chars each)
Terminal window
make up # start full stack (Hub images, detached)
make down # stop
make restart # restart all services
make logs # follow logs
make ps # service status
make pull # pull latest Hub images

Overridable variables:

Terminal window
make up OS=trixie-slim VERSION=1.2.3
Terminal window
# Option A — full dev stack in Docker (hot-reload, mounted sources)
make dev
# Option B — infrastructure only, then pnpm dev on the host
make dev-infra # starts postgres + redis
pnpm dev # control-api :3000 · tenant-api :3002 · mcp-server :3001 · web :8000 · admin-web :8001
make dev-down # stop dev stack
make dev-logs # follow dev logs

Images are tagged {REGISTRY}/archispark-{service}:{OS}-{VERSION} and :{OS}-latest.

Terminal window
make build # all services, OS=alpine (default)
make build-api # API only
make build-web # Web only
make build-mcp # MCP server only
make build-all # both alpine and trixie-slim variants
make build OS=trixie-slim VERSION=1.3.0
Terminal window
make push # all services, current OS/VERSION
make push-all # both OS variants
make release VERSION=x.y.z # build-all + push-all in one command
Terminal window
make version # print version from package.json
make clean # remove local ArchiSpark images
make prune # docker system prune

PostgreSQL is the primary datastore for ArchiSpark. Control-plane data (organizations, users, sessions, API tokens) and tenant-plane data (workspaces, elements, relationships, views) are persisted in PostgreSQL — see Multi-tenant database architecture.

VersionDefault portDefault database
PostgreSQL 175432archispark

The schema is split into packages/db/src/schema.control.ts (shared control-plane) and packages/db/src/schema.tenant.ts (per-organization tenant-plane), managed by Drizzle ORM. Migrations are applied automatically on every control-api/tenant-api startup — no manual migrate command is needed in Docker deployments.

For a bare-metal or external database, run migrations before the first startup:

Terminal window
cd packages/db
DATABASE_URL=postgresql://user:password@host:5432/archispark npx drizzle-kit migrate

Set the database password in .env (used by the Docker Compose services):

DB_PASSWORD=<strong-password>

To use an external PostgreSQL instance (managed service, RDS, Supabase…), override DATABASE_URL directly:

DATABASE_URL=postgresql://user:password@my-pg-host:5432/archispark

When DATABASE_URL is set, the compose-managed PostgreSQL container is ignored — you can remove it from the compose file or simply leave it unused.

ArchiSpark loads each active workspace from PostgreSQL and maintains it in memory for fast reads. Every mutation (create, update, delete) writes through to PostgreSQL synchronously, so the in-memory state is always consistent with the database.


Redis is mandatory. control-api, tenant-api and mcp-server all refuse to start without REDIS_URL. It provides:

FeatureDescription
Session storageShared session cache for Better Auth across all control-api replicas
Rate limitingDistributed rate-limiting across all replicas

Set a password in .env:

REDIS_PASSWORD=<strong-password>

To use an external Redis (managed service), override REDIS_URL directly:

REDIS_URL=redis://:mypassword@my-redis-host:6379

Traefik implements the following routing rules (see Architecture for the full diagram):

/* → port 80 → Traefik
/api/* → strip /api → control-api:3000 (Express REST; non-owned routes
are proxied on to tenant-api)
/auth/* → control-api:3000 (Better Auth)
/mcp/* → mcp-server:3001 (stateless Streamable HTTP)
/* → web:8000 (Next.js, catch-all)

tenant-api:3002 is never exposed by Traefik — it’s reached only over the Docker network by control-api and mcp-server. apps/admin-web is deployed separately and isn’t part of this routing table.


Uncomment certificatesResolvers in traefik.yml, then change router entrypoints from web to websecure and add tls.certresolver=letsencrypt to each router label in docker-compose.yml.


VariableUsed byDescription
ARCHISPARK_URLcontrol-apiFull public URL — used for Better Auth cookies and CORS
DB_PASSWORDpostgresPostgreSQL password (required)
DATABASE_URLcontrol-api, tenant-apiFull PostgreSQL connection string — overrides DB_PASSWORD-based default
BETTER_AUTH_SECRETcontrol-apiSession signing secret, min 32 chars (required)
TENANT_JWT_SECRETcontrol-api, tenant-api, mcp-serverInter-service JWT secret — control-api signs, tenant-api/mcp-server verify (required)
TENANT_DB_ENCRYPTION_KEYtenant-api, mcp-serverDecrypts per-organization Neon connection strings (required if any organization has a dedicated tenant database)
SEED_ADMIN_PASSWORDcontrol-apiInitial admin password (defaults to admin if unset — change in production)
SEED_USER_PASSWORDcontrol-apiInitial user password (defaults to user if unset)
SEED_CONTRIB_PASSWORDcontrol-apiInitial contrib (demo org admin) password (defaults to contrib)
SEED_ARCHI_PASSWORDcontrol-apiInitial archi (demo org owner) password (defaults to archi)
REDIS_PASSWORDredisRedis password (recommended in production)
REDIS_URLcontrol-api, tenant-api, mcp-serverFull Redis URL — override for external Redis
TRUSTED_ORIGINScontrol-apiComma-separated additional CORS/cookie origins
COOKIE_DOMAINcontrol-apiOptional — share the session cookie across subdomains, e.g. .example.com
NEON_API_KEY / NEON_PROJECT_ID / NEON_BRANCH_IDcontrol-apiOptional — enable per-organization dedicated Neon databases
ARCHISPARK_OSMakefileImage OS variant: alpine (default) or trixie-slim
ARCHISPARK_VERSIONMakefile / composeImage version tag (default: version from package.json)