Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Organize sites into a project

A project is boatramp’s owning + tenant boundary. It groups many sites together with their functions and compute, and it is the tenant a managed handler’s row-level scope resolves to. Every resource belongs to exactly one project; a reserved default project holds everything that predates projects, so if you never name a project you keep the single-site experience unchanged.

Use projects when you run more than one site per operator (agencies, monorepos, multi-tenant SaaS) and want each tenant’s sites, functions, and compute isolated — including their names. Two projects can each own a site called blog.

Before you start

1. Create a project

boatramp project create acme --display "Acme, Inc."
boatramp project ls

create needs a slug (unique, no /); --display, --description, and --region are optional. project ls lists every project; project show acme prints the full record; project rm acme deletes an empty project (it refuses while the project still owns resources, and the default project can never be removed).

2. Target a project

Every site-scoped command takes a --project flag; it falls back to [publish].project in project.cfg, then the BOATRAMP_PROJECT environment variable, then the default project. So these are equivalent:

boatramp --project acme sync ./dist --site blog
BOATRAMP_PROJECT=acme boatramp sync ./dist --site blog

With --project omitted you are working in default, byte-identical to how boatramp behaved before projects existed. A site name only has to be unique within its project, so acme/blog and beta/blog are two different sites that deploy, serve, and run their background work independently.

3. Declare a whole project at once

boatramp apply reconciles an entire project from one manifest — see Declare a project with apply. A minimal apply.cfg:

(
    project: "acme",
    sites: [
        ( name: "www",  path: "www/dist" ),
        ( name: "blog", path: "blog/dist", routing: ( clean_urls: true ) ),
    ],
)
boatramp apply -f apply.cfg

What a project owns

  • Sites — each with its own deployments, aliases, domains, and background work (consumers, crons). Same-named sites in different projects are fully isolated.
  • Functions — top-level functions and their versions, triggers, invocations, and metering.
  • Compute — container / micro-VM workloads.
  • A tenant identity — a request routed to one of the project’s sites carries the project as its host-asserted tenant, which is what a managed handler’s Authorized::db() scopes rows to (nothing guest-supplied).

Content-addressed bodies (blobs, manifests, site and compute config) are shared across projects and deduplicated — a byte-identical asset uploaded by two projects is stored once, and it is only garbage-collected when no project references it.

Authorization

Cedar gains a Project resource with three project-scoped roles — project_admin, project_publisher, project_viewer — that govern a project’s sites, functions, compute, and workflows. A token scoped to one project cannot touch another: a project_admin:acme token is refused (403) on project beta. Legacy site-only grants (publisher:blog) read as publisher:default/blog, so existing tokens keep working against the default project. See RBAC roles, actions & resources.

See also