Skip to content

TWN-Systems/mercato-sandboxes-poc

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

39 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Open Mercato

Mercato Sandboxes

Self-hosted onboarding tool that provisions Open Mercato dev environments
in Coder workspaces β€” one click per signup.

Quick start AGPL-3.0 Coder Open Mercato develop


🌍 What is this

A signup tool that provisions a self-hosted Coder workspace running an Open Mercato dev environment per signup. A user signs up at the onboarding UI, clicks Create sandbox, and lands in a fresh workspace with browser-based VS Code, a web terminal, the live build splash, and direct port forwards to the running Mercato app. Every workspace ships with the opencode, codex, and claude code CLIs preinstalled, so AI-assisted edits work out of the box.

🧱 Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ docker compose (host) ──────────────────────┐
β”‚                                                                   β”‚
β”‚  postgres-onboarding   postgres-coder    coder-server             β”‚
β”‚  :5545                 :5432 (internal)  :80 internal             β”‚
β”‚         β–²                     β–²              β–²                    β”‚
β”‚         β”‚                     β”‚              β”‚                    β”‚
β”‚  next-onboarding (3000) β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚         β”‚ admin API token                                         β”‚
β”‚         β”‚                                                         β”‚
β”‚  nginx edge: :80 redirect-only, :443 HTTPS/WSS                    β”‚
β”‚    sandbox.lvh.me β†’ onboarding, coder.sandbox.lvh.me β†’ Coder,     β”‚
β”‚    *.apps.sandbox.lvh.me β†’ Coder wildcard app proxy               β”‚
β”‚                                                                   β”‚
β”‚  bind-mount: /var/run/docker.sock ──────────────────────────────► β”‚
β”‚         (coder-server uses host Docker daemon to spawn workspaces)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
       Workspace container (one per signup, mercato-workspace:latest):
         - node 24, yarn 4, code-server, postgres-client, git
         - opencode + codex + claude code CLIs on PATH
         - sidecar postgres (pgvector pg17) on a private docker network
         - on first start: npx create-mercato-app@develop, yarn setup
         - splash on :4000, app on :3000, code-server on :13337
         - 16 GB RAM, 4 vCPU
Service Image Purpose
postgres-onboarding postgres:17-alpine Onboarding app's user + sandbox tables
postgres-coder postgres:17 Coder control-plane metadata DB
coder ghcr.io/coder/coder:latest Coder server on internal :80; spawns workspaces via host Docker
onboarding node:24-alpine (custom build) Next.js 15 signup + dashboard UI on :3000
edge nginx:alpine Standard-port HTTPS/WSS edge for onboarding, Coder, and wildcard apps

🎯 What you get per signup

  • πŸ–₯️ Browser-based VS Code (code-server)
  • πŸ’» Web terminal
  • βš™οΈ Live build splash on port 4000
  • πŸš€ The Mercato app on its own subdomain (<workspace>.lvh.me locally, <workspace>.<your-domain> in prod) β€” full asset URLs, WebSockets, no path-prefix surprises
  • πŸ€– opencode, codex, and claude code CLIs preinstalled
  • 🐘 Sidecar PostgreSQL 17 (pgvector)
  • πŸ’ͺ 16 GB RAM allocation per workspace

⚑ Quick start

cp .env.example .env       # set OPENAI_API_KEY (and optionally ANTHROPIC_API_KEY)
./start.sh                 # ~3 min on first run, ~30 s afterwards
open https://sandbox.lvh.me # sign up and create your sandbox

First run takes ~3 min β€” Coder has to boot, the workspace image has to build, and the template has to be pushed. Subsequent ./start.sh runs are idempotent and finish in ~30 s.

πŸ”‘ Logging in

  • Onboarding (your users) β€” https://sandbox.lvh.me β€” any email + 8+ character password.
  • Coder admin (operators) β€” https://coder.sandbox.lvh.me β€” admin@local.dev / Sup3rSecret!.

🧭 End-user flow

  1. Sign up at https://sandbox.lvh.me.
  2. Land on the dashboard.
  3. Click Create sandbox, give it a name, submit.
  4. Wait ~30–60 s for status to flip to ready.
  5. Click into VS Code, Terminal, Splash, or App.

🌐 Networking

The stack is published by one nginx edge proxy on standard ports. HTTP on :80 redirects to HTTPS on :443; all interactive traffic uses HTTPS/WSS.

  • Onboarding: https://sandbox.lvh.me
  • Coder: https://coder.sandbox.lvh.me
  • App: https://3000--main--<workspace>--<user>.apps.sandbox.lvh.me
  • Splash: https://4000--main--<workspace>--<user>.apps.sandbox.lvh.me
  • VS Code: https://13337--main--<workspace>--<user>.apps.sandbox.lvh.me/?folder=/home/coder/app
  • Terminal: https://coder.sandbox.lvh.me/@<user>/<workspace>/terminal

Local dev uses SANDBOX_DOMAIN=sandbox.lvh.me, which wildcards every subdomain to 127.0.0.1; no /etc/hosts edits are required. ./start.sh generates .runtime/tls/sandbox-lvh-me.crt and .runtime/tls/sandbox-lvh-me.key if they are missing. Trust the certificate in your OS/browser keychain to remove privacy warnings.

Fresh workspace agents do not use the browser-facing HTTPS URL to bootstrap. The template rewrites Coder's generated agent script to the internal Docker network URL http://coder.${SANDBOX_DOMAIN} by default (AGENT_CODER_URL can override this). This is required locally because coder.sandbox.lvh.me resolves to the Coder container on Docker DNS, where :443 is intentionally not open.

For production:

SANDBOX_DOMAIN=sandbox.example.com
WILDCARD_APPS_DOMAIN=apps.sandbox.example.com
CODER_ACCESS_URL=https://coder.sandbox.example.com
CODER_PUBLIC_URL=https://coder.sandbox.example.com
CODER_WILDCARD_ACCESS_URL=*.apps.sandbox.example.com
PROXY_SCHEME=https
COOKIE_SECURE=true

Production TLS must cover ${SANDBOX_DOMAIN}, *.${SANDBOX_DOMAIN}, and *.apps.${SANDBOX_DOMAIN}.

⏱️ "Ready" semantics

The Coder agent reports ready as soon as the startup script returns, so the splash and VS Code are usable immediately. The Mercato app on port 3000 takes another 3–7 minutes on first start while yarn install, generate, db migrate, initialize, and the Next.js compile finish β€” the app URL returns 502 until Next.js prints Ready in Xms. Watch the splash for live progress.

πŸ€– AI CLIs

opencode, codex, and claude are on PATH inside every workspace terminal. Set OPENAI_API_KEY and (optionally) ANTHROPIC_API_KEY in .env before running ./start.sh so the template picks them up. If you change the keys later, rerun:

bash scripts/push-template.sh

Workspaces created before the keys were set will not have them β€” recreate those workspaces from the onboarding UI.

πŸš€ Deploying to production

Production deploys go to a single Hetzner VPS under *.sandbox.openmercato.com with a wildcard Let's Encrypt cert (DNS-01 via Cloudflare). The deploy is idempotent and safe to re-run β€” every named docker volume (Coder DB, onboarding DB, issued certs, workspace homes, sidecar postgres data) is preserved across redeploys.

# On the VPS:
git clone https://github.com/<org>/dokploy-sandboxes-poc.git /opt/mercato-sandboxes
cd /opt/mercato-sandboxes
cp .env.production.example .env.production
$EDITOR .env.production         # CLOUDFLARE_API_TOKEN, JWT_SECRET, passwords
./scripts/deploy-hetzner.sh

See .ai/SPEC-PROD.md for the canonical production spec β€” DNS prerequisites, the wildcard-TLS architecture, the data-preservation contract, and the operational runbook.

πŸ› οΈ Development

make ps      # show stack containers
make logs    # tail compose logs
make stop    # docker compose down (preserves volumes)
make reset   # docker compose down -v + wipe .runtime/ (irreversible)
make test    # run the Playwright happy-path suite

πŸ§ͺ Tests

make test runs the Playwright happy-path suite in e2e/. The stack must already be up (./start.sh). Takes ~50 s with warm caches.

🩺 Troubleshooting

  • Coder restart-looping β†’ docker logs coder (usually host.docker.internal resolution).
  • Workspace stuck on "building" β†’ docker logs coder-<owner>-<workspace> and docker logs coder-<workspace_id>-postgres.
  • Port 5544 in use β†’ we now default to 5545 (orphan postgres detection); override via ONBOARDING_DB_PORT in .env.
  • Disk full β†’ ./reset.sh && docker system prune -a --volumes.

πŸ“ Project layout

.
β”œβ”€β”€ apps/onboarding/      Next.js 15 signup + dashboard + sandbox UI
β”œβ”€β”€ coder/
β”‚   β”œβ”€β”€ template/         Terraform: agent + sidecar pgvector + workspace
β”‚   └── workspace-image/  Dockerfile for mercato-workspace:latest
β”œβ”€β”€ scripts/              bootstrap-coder, build-workspace-image, push-template, migrate-onboarding
β”œβ”€β”€ e2e/                  Playwright happy-path suite
β”œβ”€β”€ proxy/                nginx edge config template
β”œβ”€β”€ .ai/                  specs, worklist, handoff notes
β”œβ”€β”€ AGENTS.md             coding standards + operational lessons for agents
β”œβ”€β”€ docker-compose.yml    postgres-onboarding, postgres-coder, coder, onboarding, edge
β”œβ”€β”€ start.sh / stop.sh / reset.sh
β”œβ”€β”€ Makefile
└── README.md

🚫 Out of scope (POC)

  • Email delivery (we surface the temp Coder password on screen rather than emailing).
  • Multi-tenancy / orgs in Coder (single default org).
  • Certificate automation for production TLS. The stack expects cert/key files mounted under .runtime/tls.
  • Production hardening (TLS, secret management, OIDC).

πŸ“œ License

This project is licensed under the AGPL-3.0 β€” the same license as Coder. Open Mercato itself is licensed by its maintainers separately.

πŸ™ Credits


Built for learning AI-assisted engineering at scale. Powered by Open Mercato.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 78.6%
  • HCL 9.5%
  • Shell 8.8%
  • Dockerfile 1.7%
  • CSS 0.6%
  • Makefile 0.5%
  • JavaScript 0.3%