Apps
Ship a website from your project. You declare it in the manifest; Machine builds it, deploys it to Vercel, and gives you a live URL — plus the DNS records to connect your own domain.
An app is something deployable that lives alongside your agent in the same
project — a marketing site, a docs site, a small dashboard. You declare apps in
machine.toml; Machine builds the source, deploys it, and gives you a public
URL. Your own domains are supported, with the exact DNS records to add shown
right in the dashboard.
[[apps]]
slug = "marketing"
name = "Marketing site"
[apps.source]
type = "git"
branch = "main"
root_path = "apps/site"
[apps.build]
command = "pnpm build"
out_dir = "dist"That's a full deploy. Save the file — via a change request, or the Apps tab in the dashboard, which commits for you — and the next reconcile loop ships it.
How it works
Apps reconcile from the manifest. Three pieces:
- The manifest is the source of truth. Edits to a
[[apps]]entry (a commit to your default branch, or a save in the Apps tab) are picked up by a background sweep that compares each entry's config hash to the last deployment and redeploys anything that changed. - A provider builds and serves it. Today that's Vercel: Machine hands it your source, build config, and environment, then returns a live URL. The provider layer is pluggable, so the backend can change without touching your manifest.
- Every deploy is a row in the
deploymentstable. That row is what the Apps tab shows — status, live URLs, the DNS records for any custom domain, the error if a build failed, and the last-deploy time.
Your URLs
Every app is served on a stable Vercel URL the moment it goes live — something
like your-app-yourteam.vercel.app. You don't configure anything to get it; it
appears on the app's card as soon as the deploy is active.
When you add a custom domain, the card shows both the Vercel URL and your domain, so you always have a working address while DNS propagates.
Custom domains
List the domains you own under domains and Machine attaches each one to the
deployment:
[[apps]]
slug = "marketing"
domains = ["example.com", "www.example.com"]A domain only serves traffic once its DNS points at the provider. Until it does, the app's card shows a DNS records panel with the exact records to add at your registrar — read live from the provider, not guessed:
| Type | Name | Value |
|---|---|---|
A | @ | the provider's IPs |
CNAME | www | the provider's CNAME target |
TXT | … | an ownership-verification record (when required) |
Add those records at your DNS provider. Apex domains (example.com) take A
records; subdomains (www.example.com, docs.example.com) take a CNAME. Once
the records resolve, the domain verifies and starts serving automatically — no
redeploy needed.
Ownership-verified and DNS-configured are different states. A domain can be
verified as yours yet still need its A/CNAME records before it serves
traffic — that's why the DNS panel stays visible until the domain is actually
reachable.
Build behavior
The build phase is optional but defaults sensibly:
[apps.build]withcommand/out_dir— used as given.[apps.build]present but empty — the provider auto-detects the framework.- No
[apps.build], source isgit— auto-detect (most repos need a build). - No
[apps.build], source istar— skip the build; the tarball is treated as the already-built artifact.
Environment
[apps.env] is a flat key = "value" table the build and runtime see. Use it
for non-secret values like a public API URL:
[apps.env]
NEXT_PUBLIC_API_URL = "https://api.example.com"For secrets (API keys, database URLs), declare them in [env].optional, set the
value in the project's Secrets Manager, and reference
them by name — never paste a secret into the manifest.
Changes redeploy automatically
The sweep hashes a stable subset of each app — source, build, env, domains,
framework, enabled — and stores it on the deployment row. When that hash differs
from the last deployment, the next sweep redeploys. Renaming an app (changing
slug or name) doesn't redeploy, because the content didn't change.
To force a deploy without editing the manifest, use Redeploy on the app's card in the Apps tab.
What apps aren't
- Long-running services. Apps target static and edge-server deploys — frontends, marketing sites, docs. Stateful backends belong in their own infrastructure.
- A way to deploy the agent itself. Apps deploy
[[apps]]entries only. They don't deploymachine.toml, your agents, or anything under.machine/opencode/— those run inside sessions.
Next: Deploy a website — the end-to-end
walkthrough, including custom domains. For every field and flag, see the
Manifest reference — [[apps]].
