DocsGuidesSeveral apps in one projectFor AI agents
Guides

Several apps in one project

A site and its API, a shop and its admin — deployed together, sharing one database and one set of people.

4 minutes to read

Many projects are more than one app. A school website with a separate admin area for updating it. A shop with its own API. A blog and the tool that writes to it. Your AI may have built these as separate folders in one repository — apps/web, apps/api, apps/admin.

Run the one command at the top of the repository and all of it goes live, as one project with several parts:

detected  3 apps in one project: web (apps/web), api (apps/api), admin (apps/admin)
web       Next.js · Postgres (drizzle)
api       Hono API · Postgres (drizzle)
admin     Next.js · Postgres (drizzle)

✓ pack       412 files · 2.1 MB
✓ live       https://quiet-harbor-4471.uarpieapps.com/#k=7f3a…
✓ api        https://quiet-harbor-4471-api.uarpieapps.com
✓ admin      https://quiet-harbor-4471-admin.uarpieapps.com/#k=9c1e…

What "one project" means

  • One database. Every part reads and writes the same data. The admin area changes what the site shows, with nothing to wire up.
  • One set of people. Claim the project once and every part is yours. Invite someone and they can open every part.
  • Each part's own door. Every part starts private, and each can be made public on its own: a public site beside a private admin is the usual shape.
  • One name. The first part gets the project's address; the others get it with their name on the end — quiet-harbor-4471-api. Rename the project and every part follows.
  • One command. npx uarpie at the top of the repository deploys every part, in order. When each part's folder installs on its own, a part with nothing new in its folder is skipped. In a workspace (one install for the whole repository) every part is built from the whole repository, so a change anywhere builds every part again.
  • Removed together. Delete the project and its parts go with it. Delete one part and the rest stay.

Each part is still its own app underneath: its own versions, its own rollback, its own logs, its own spending on the meter. The whole project counts as one app on your plan, however many parts it has.

Which part is the main one

The part whose folder is called web, site, frontend, www, app or client comes first and gets the project's main address. If none is, the first folder alphabetically does. The order is recorded in deploy.json under services, and your AI can reorder it before the first deploy.

The main part goes live first, and its home page is checked before the next part deploys. If another part is the one that makes the database tables, the main part's home page meets an empty database on the very first deploy. When that first check fails, the deploy carries on with the other parts, whose migrations make the tables, and then deploys the main part again. To save that second build, make the main part's home page answer while the tables do not exist yet (a short "being set up" page rather than an error).

A site that reads from its own private admin part over the network (the admin's API, say) needs a key that the admin part can only make once it exists. So on the first deploy, make the site's pages answer while the admin cannot be reached (the same "being set up" page), then make a key on the admin part (npx uarpie keys new site -p prj_…, with the admin's id) and give it to the site as a setting.

A public site with a private admin

Commands for one part take that part's id with -p, run from the top of the repository. The ids are in deploy.json, under services. Once the person agrees that anyone with the address may open the site, make that one part public:

Terminal
npx uarpie visibility public --confirm-public -p prj_…

The admin stays private: only people invited to the project can open it. If the admin keeps the pictures the site shows, let anyone read just those, with the admin's id:

Terminal
npx uarpie open-paths /media/ -p prj_…

An open path takes about a minute to reach every edge location.

When you want only one of them

If the repository holds several apps but you only want one online, tell the command which: run it inside that folder, or set "build": { "rootDirectory": "apps/web" } in deploy.json. Then it is an ordinary single app.

What is recorded

deploy.json at the top of the repository lists the parts and, after the first deploy, their ids:

JSON
"services": [
  { "name": "web", "rootDirectory": "apps/web", "project": { "id": "prj_…" } },
  { "name": "api", "rootDirectory": "apps/api", "project": { "id": "prj_…" } }
]

Names are short, lowercase, letters, digits and hyphens, because they become part of an address. Detection refreshes the list on every deploy; the ids are kept.

To change something for one part, write it in that part's entry, with the names a single app's deploy.json uses: kind, runtime (start, memoryMb, timeoutSec), build (command, outputDir), database.migrate and jobs. It is laid over what detection finds for that part on every deploy, and kept:

JSON
{ "name": "api", "rootDirectory": "apps/api", "project": { "id": "prj_…" },
  "runtime": { "start": "node dist/server.js", "memoryMb": 1024 } }

The speed layer and languages are set once, at the top of the file, for every part.

This page as Markdown: /docs/several-apps-in-one.mdllms.txt
↑ ↓ to moveEnter to open