Flect app
Flect · Applications
Section titled “Flect · Applications”Part of the flect skill set. A Flect application is one
flect.toml: its services are containers, and they use databases
(flect-db), KV (flect-kv) and
object storage (flect-store) by id.
The file
Section titled “The file”[app]name = "shop"scope = "web/shop/production" # workspace/project/environment in the active org# domain = "shop.example.com" # custom domain for the public service
[[databases]]binding = "DB"id = "res_k7f3a2" # flect db create shop-db
[vars] # every serviceLOG_LEVEL = "info"
[services.api]image = "ghcr.io/acme/shop-api:1.4.0"port = 3000uses = ["DB"] # may resolve DB; nothing elsesecrets = ["STRIPE_KEY"]
[services.api.vars] # api only; wins over [vars]CURRENCY = "EUR"
[services.auth]image = "ghcr.io/dotlabshq/auth-service:1.0.1"port = 3000expose = "/v1/auth" # under web's host, prefix stripped
[services.web]image = "ghcr.io/acme/shop-web:1.4.0"port = 3000public = true # owns the domainmemoryMb = 512calls = ["api", "auth"] # API_SERVICE_URL, AUTH_SERVICE_URLService fields: image, port, public, expose, replicas, cpuMhz,
memoryMb, health, uses, calls, secrets, vars, and name (only to
keep an app already running under a name other than <app>-<service>). Every
key is in the flect.toml reference.
Deciding what each service lists
Section titled “Deciding what each service lists”Go through the code of each service:
| The code… | List |
|---|---|
calls env.db('DB') / env.kv(…) / env.store(…) |
the binding in uses |
reads process.env.API_SERVICE_URL |
"api" in calls |
| reads a config value | the name in that service’s vars (or [vars] if every service reads it) |
| reads a key, token, password or signing secret | the name in secrets |
List nothing a service does not read. That is the point: a leaked front end holds no database access and no other service’s secrets.
Routing
Section titled “Routing”| Setting | Reachable at |
|---|---|
public = true |
https://<app>-<service>-<shortid>.up.flect.run, plus [app].domain via a CNAME. One per file. |
expose = "/v1/auth" |
That path under the public service’s host. The prefix is stripped. |
| neither | Private: only the services that call it, through <NAME>_SERVICE_URL. |
Deploy
Section titled “Deploy”# images first (Flect does not build containers; the registry must be public)docker build --platform linux/amd64 -t ghcr.io/acme/shop-api:1.4.0 . && docker push ghcr.io/acme/shop-api:1.4.0
printf %s "$STRIPE_KEY" | flect secret set api STRIPE_KEY # each listed secret, once per scopeflect deployflect deploy first checks the whole file against the scope: every id is a
live resource of this scope, no binding name points elsewhere, every listed
secret is set, and no var kept by the last deploy is silently dropped. On any
problem it stops with nothing changed and says what to run. Then it binds the
resources, declares every service, and deploys each one with only what it
lists.
A changed image tag, var, secret, uses or calls takes effect on the next
flect deploy. A service restarts when its own settings change, or when the
address of a service it calls changes. It does not restart for its other
siblings.
A dev environment
Section titled “A dev environment”cp flect.toml flect.dev.toml# edit: [app].scope = "web/shop/dev"; drop services dev does not needflect db create shop-db -c flect.dev.toml # dev's own database → its id into flect.dev.tomlprintf %s "$DEV_KEY" | flect secret set api STRIPE_KEY -c flect.dev.tomlflect deploy -c flect.dev.tomlThe two files are independent: no inheritance, no shared ids, no shared secret values.
Container requirements
Section titled “Container requirements”FROM node:22-alpineWORKDIR /appCOPY package*.json ./RUN npm ci --omit=devCOPY dist/ ./dist/EXPOSE 3000CMD ["node", "dist/index.js"]- Listen on
port. - Answer
GET /healthzwith200, or sethealth = "/your/path", orhealth = falsefor a worker with no HTTP. Until the check passes no traffic arrives, and services that call it get an empty address. linux/amd64, dependencies bundled (no workspace symlinks).- The environment holds
FLECT_TOKEN,FLECT_BROKER_URL,PORT,NODE_ENV,APP_PUBLIC_URL(public and exposed services), its vars and secrets, and its*_SERVICE_URLs. Nothing else: no database URL.
Using @dotlabshq/flect-sdk
Section titled “Using @dotlabshq/flect-sdk”import { Hono } from 'hono'import { serve } from '@hono/node-server'import { createEnv } from '@dotlabshq/flect-sdk'
const env = createEnv()const db = await env.db('DB') // official @libsql/client; 'DB' is in this service's usesconst app = new Hono()
app.get('/healthz', (c) => c.json({ ok: true }))app.get('/users', async (c) => { const { rows } = await db.execute('SELECT * FROM users') return c.json({ users: rows })})
serve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000) })Moving an old-format file
Section titled “Moving an old-format file”A file with [[apps]], [[services]] entries and resources by name is the
old format. It still deploys, with a warning, but every app gets every var and
binding.
flect db list(andkv,store) for each resource’sres_id.- One
[services.<name>]per[[apps]]. If the app’s current name is not<app>-<service>, setnameto it so the running app is kept. - Add
[app].scope, and per serviceuses,calls,secretsand only the vars it reads. flect secret seteach secret.flect deploy: it stops and lists the kept vars that would be dropped. Check the list, thenflect deploy --yes.
Management
Section titled “Management”flect apps # the scope's apps: status, URL, imageflect bindings # what the file gives each serviceflect db list # resources and the services using themflect secret list # secret names per service; any missingRelated skills
Section titled “Related skills”- flect — the model, CLI, scopes, plan limits.
- flect-db · flect-kv · flect-store — resources.
- flect-pages — static/docs sites instead of a container.