Visual Docker Compose editor for building, validating, and exporting self-hosted infrastructure stacks. Compote is for homelab users, self-hosters, and DevOps engineers who want to build Docker Compose stacks visually, detect port/dependency conflicts, and export ready-to-deploy bundles.
Compote lets you build and manage Docker Compose setups through a point-and-click UI instead of hand-writing YAML. You organize services into Compose projects, and projects onto hosts (physical or virtual machines). When you're done, export a ready-to-deploy ZIP bundle with your docker-compose.yml and a generated README.
Key capabilities:
- Validation β real-time rule-based checks catch misconfigured services before you deploy
- Connectivity tracking β detects port conflicts, missing network links, unresolved service dependencies, and cross-project collisions
- Visual service editor β configure images, ports, volumes, environment variables, and
depends_onthrough forms; see the rendered YAML in real time - Multi-host management β model your infrastructure as hosts (with OS/architecture metadata), each carrying one or more Compose projects
- Registry search β browse Docker Hub and GitHub Container Registry to pick images directly in the UI
- README generation β produces a Markdown README from your Compose file automatically
- ZIP export β download a bundle with
docker-compose.yml,.env, and generated docs - Serverless β runs entirely in the browser; no backend, no account, all data stays in local IndexedDB
- Avoid hand-writing repetitive Compose YAML
- Catch port conflicts and missing dependencies before deployment
- Build reusable service catalogs and stack presets
- Export clean, ready-to-deploy Compose bundles
- Works locally in the browser or self-hosted with SQLite
Compote is not a runtime orchestrator. It focuses on planning, validating, templating, and exporting Docker Compose stacks before deployment.
The app is available at compote.aicrafted.org β runs entirely in the browser, data stays in local IndexedDB, no account required.
# docker-compose.yml
services:
compote:
image: ghcr.io/aicrafted/compote:latest
ports:
- "3474:3000"
volumes:
- ./data:/data
restart: unless-stoppeddocker compose up -d
# β http://localhost:3474In self-hosted mode the app uses a local SQLite database stored in ./data instead of the browser's IndexedDB. Data persists across browsers and devices on the same server. The ./data directory also serves as the catalog volume β drop custom service definitions there to extend the built-in catalog at runtime.
| Layer | Technology |
|---|---|
| Framework | React 18 + TypeScript 5 |
| Build | Vite 5 + Bun |
| Styling | Tailwind CSS 3 + shadcn/ui |
| State | Zustand |
| Storage | IndexedDB (browser) Β· SQLite via Bun (self-hosted) |
| Routing | React Router v6 |
Prerequisites: Bun β₯ 1.0
# Install dependencies
bun install
# Start dev server (http://localhost:3010)
bun run dev# Production build
bun run build
# Preview production build
bun run previewEach service lives in its own directory under public/catalog/{service-id}/:
public/catalog/
prometheus/
metadata.json β display name, category, image, ports, env vars, volumes
compose-part.yml β service body injected into Compose output (no top-level keys)
icon.svg / icon.png
catalog.json is auto-generated by a Vite plugin on every build β never edit it directly.
Minimal metadata.json:
{
"name": "Prometheus",
"category": "MONITORING",
"description": "The Prometheus monitoring system and time series database.",
"image": "prom/prometheus:latest",
"containerPorts": [9090],
"defaultHostPort": 9090,
"requires": [],
"requiredEnv": [],
"publicExposure": "optional",
"resourceClass": "medium",
"iconSVG": true
}Icons can be fetched automatically from Simple Icons, selfh.st, or Dashboard Icons via:
node scripts/fetch-icons.mjs {service-id}src/
βββ components/ui/ # shadcn/ui primitives
βββ features/ # Feature modules (builder, hosts)
βββ lib/core/ # Pure logic: importers, exporters, renderers, validation rules
βββ stores/ # Zustand stores
Data model: Host β Compose Projects β Services
Routes: /hosts β /hosts/:hostId β /hosts/:hostId/:composeId

