loor.json
The single declarative manifest behind every Loor project. You usually don't write it by hand — Studio and Vibe Chat keep it in sync — but here's the whole schema.
What it is
Every Loor project has a loor.json at its root. It describes services, ports, domains,
backing services (MongoDB, Redis, R2…) and TLS. Studio reads and writes this file as you work — you
can also edit it directly.
Shape
{
"version": "1",
"project": { "name": "my-app" },
"build": {
"command": "pnpm build",
"installCommand": "pnpm install --frozen-lockfile",
"nodeVersion": "20"
},
"services": { /* see below */ },
"tls": { "provider": "auto" }
} Services
Each service is keyed by name and points at a folder. Loor auto-detects the type from your repo (12 framework presets); you can override or pin it explicitly.
"services": {
"web": {
"type": "next", // detected automatically if omitted
"root": "apps/web",
"port": 80,
"domain": "app.example.com",
"env": { "NODE_ENV": "production" },
"replicas": 2
}
} Services from plugins
Services like MongoDB, Redis, and R2 are first-class entries — Loor provisions them
for you, manages backups and TLS, and injects connection strings into dependent services via
exposeAs.
"db": {
"type": "service",
"service": "mongodb", // mongodb · redis · r2 · mail
"version": "16",
"storage": "10Gi",
"exposeAs": "DATABASE_URL" // injected into dependent services
} Env vars & secrets
Static env vars live under services.<name>.env. Secrets and per-environment
overrides are set in the Studio sidebar (or via the CLI) and encrypted at rest. Never paste
a secret into loor.json — Studio will refuse to deploy.
Branch previews
"web": {
"domain": "app.example.com",
"branches": {
"*": { "domain": "{branch}.preview.example.com" }
}
}
Each branch you push gets its own URL via the {branch} template. Wildcard TLS is auto.
How Studio uses it
Studio reads loor.json to build the project sidebar, decide what to provision, and
plan the deploy. When Vibe Chat adds a service ("add MongoDB for me"), it edits this file and
asks you to confirm — you can always click see diff before accepting.