Deploy with Docker Compose
Readsmith self-hosts as two containers: the app, and Postgres with the pgvector extension. That is the entire stack. There are no external services to sign up for, no build farm, and no telemetry you did not turn on.
The shape of a deployment
docker-compose.yml
├── app the serving shell, your docs prebuilt inside
└── db Postgres 16 + pgvector: search, vectors, jobsThe compose file in the repository root is the reference deployment. An
optional third service exists behind a profile: docker compose --profile s3 up adds MinIO as an S3-compatible bundle store (see
Environment for the STORAGE_* variables). It wires the database with a health check, a persistent volume for each store, and the app port; you provide an .env created from .env.example.
From zero to serving
Clone and configure
git clone https://github.com/readsmith/readsmith cd readsmith cp .env.example .envSet a real
POSTGRES_PASSWORDin.env, pointREADSMITH_CONTENTat your docs directory, and keep the file out of version control.Build and start
docker compose up -d --buildThe image build compiles your content into the site bundle, so the running container serves prebuilt pages and never compiles at request time.
Verify
curl -s http://localhost:4321/llms.txt | head -3
Content is baked at build time
Docs pages are prerendered into the image when it builds. Publishing a content change means rebuilding the image (docker compose up -d --build); rolling back means running the previous image. Deploys are therefore reproducible artifacts, not mutable state on a server. To publish on git push instead, without rebuilding the image, connect a repository.
What runs without a database
Without DATABASE_URL the app runs docs-only: pages, navigation, themes, the API reference, and every agent output (llms.txt, per-page Markdown, skill.md) work from the precompiled bundle alone. The database activates search, Ask AI, and background jobs.
Keys and limits
Set model keys in the environment if you want semantic search and Ask AI; the app degrades gracefully without them (full-text search stays on). The built-in rate limits are on by default and sized for a public deployment. Both are cataloged in the environment reference.