Deploy a monorepo end to end
Take a monorepo with a web app, an API and a database from a GitHub URL to running services on Vercel and Google Cloud.
This walk-through deploys a typical monorepo: a Next.js app, a Go API behind it, and a Postgres database the API uses. The web app goes to Vercel, and the API and database go to Google Cloud. Swap in any targets from the Clouds overview. The repository can be your own, or examples/polyglot in the Loomplane source, which has the same shape.
You'll need a Loomplane you can sign in to (Quick start), a Vercel token, and a Google Cloud service account key with the permissions listed in Google Cloud.
Create the project and analyze it
Choose New project and paste the GitHub URL. Or from the terminal:
loomctl projects create "Acme shop" --repo acme/shop
loomctl analyze acme-shopWhen it finishes you get a line like "found 4 services (3 deployable), 2 packages and 1 resources at 3f2c1a9" (your numbers will differ). In the dashboard, open the graph and check each service and database against the files it points at. A resource found only from a driver in a dependency list is marked to confirm.
If Loomplane found something you don't deploy (a demo app, say), leave it out of the manifest. If it found a resource you don't use, list its kind under ignore.resources so plans stop asking.
Draft and edit the manifest
loomctl manifest acme-shop --draft > loomplane.yamlEdit it so the web app runs on Vercel and the API and database run on Google Cloud:
version: 1
defaults:
provider: cloud-run
region: us-central1
services:
api:
source: go:services/api
needs: [db]
scale: { min: 1, max: 5 }
size: { cpu: 1, memory: 512 }
web:
source: apps/web
provider: vercel
needs: [api]
environments:
preview:
enabled: false
resources:
db:
kind: postgres
provider: cloud-sql
version: "17"web needs api, so it gets API_URL. The API is public here, which a Vercel app on another cloud needs, because a private Cloud Run service only takes calls from the project's own services. api needs db, so it gets DATABASE_URL through Secret Manager. If the Dockerfile copies files from across the repository, add build: { context: . } to the service.
Save it:
loomctl manifest save acme-shop -f loomplane.yamlConnect the clouds
Under Integrations, add the Vercel token and the Google Cloud key. If a check says permissions are missing, grant them and check again. Then confirm each environment uses the account you meant. With one ready account per cloud, Loomplane picks it for you.
Add variables
Set anything your services read that Loomplane doesn't generate:
loomctl vars set acme-shop LOG_LEVEL=info --env production
loomctl vars set acme-shop STRIPE_KEY=- --secret --env production --service svc:api:go:services/apiThe service ID comes from the graph. See Variables and secrets.
Plan the environment
loomctl plan acme-shop --env productionRead it from the top. Check the actions are only the ones you expect (a database, an API, a web app), that each sits on the provider you chose, and that no problems are listed. Read the warnings too. A service without a port falls back to 8080 with a warning, and you can fix that in the manifest.
Approve and watch
An admin approves:
loomctl approve <plan-id>approve follows the deployment step by step and exits nonzero if it fails. Cloud SQL can take several minutes. If a step fails, fix the cause (often a missing permission) and run loomctl retry <deployment-id>. It resumes from the failed step.
loomctl status acme-shopshows what runs where, with addresses, and flags any drift.
Change and redeploy
Push to the repository. If you've set up the GitHub App's webhook, Loomplane re-analyzes on its own. Otherwise run loomctl analyze. Then plan and approve again. To move only one repository in a multi-repository project, plan with --scope web.
If you don't want a database to move
Resources never move between connections, because their data would stay behind. If you change an environment's connection, choose the old one again for the resource, or plan a fresh one deliberately. See Adopting and moving services.