Skip to Content
How Bahama worksThe project model

The Bahama project model

A Bahama project gives you and your coding agents four small ideas to work with:

  1. the application you are building;
  2. the environments where it runs or receives configuration;
  3. the resources it depends on; and
  4. the bindings that connect produced values to the environments that need them.

These ideas are deliberately small. You and your coding agents should be able to understand a project’s infrastructure by reading one short bahama.yaml file.

Application: what kind of code is this?

The application section tells Bahama—and any agent working in the repository—what kind of source code this is:

bahama.yaml
application: framework: nextjs

The framework must be supported by every hosted environment selected for the application. If the application lives below the repository root, include its relative directory:

bahama.yaml
application: framework: vite-spa dir: apps/web

dir changes which source Bahama packages for deployment. It must stay inside the project.

Environments: where does the application run?

An environment is a place where the application runs or receives configuration:

bahama.yaml
environments: local: provider: local production: provider: vercel

The local provider does not deploy anything. It writes explicitly bound values into a protected environment file so the application can use them during its normal development command.

A hosted environment can own the application project, receive server-side variables, deploy source, and produce a verified production URL—depending on the selected provider’s capabilities.

Environment names describe their purpose. local and production are common, but the name itself does not grant special behavior. The provider determines what the environment can do.

Currently, a project may select a provider for only one environment. For example, it cannot declare two separate Vercel environments in the same manifest yet.

Resources: what else does the application need?

Resources are managed services that exist alongside the application. Add only what the project actually needs:

bahama.yaml
resources: database: provider: neon engine: postgres

The resource key—database here—is the project’s name for that resource. The provider and engine explain what should be created or adopted.

Resources are optional. A static site may need only a hosted environment. A Next.js application might add Postgres later when persistence becomes useful.

Bindings: how do values move between resources?

Providers describe the capabilities they produce and consume. Neon produces a secret connectionUrl; the local and Vercel environments consume variables.

A binding joins those compatible endpoints:

bahama.yaml
bindings: DATABASE_URL: from: resources.database.connectionUrl to: - environments.local.variables - environments.production.variables

DATABASE_URL becomes the destination variable name. Bahama transfers the value while it is sealed, so the connection string does not appear in the manifest, plan, lock, receipt, or agent output.

Binding addresses follow two forms:

resources.<resource-name>.<capability> environments.<environment-name>.<capability>

The source must produce the named capability, and every destination must consume it. bahama plan validates the composition before anything changes.

Provider-native resources stay with their environment

Some resources exist only inside a provider’s application runtime. Bahama Cloud’s native SQL database is one example:

bahama.yaml
resources: database: provider: bahama-cloud environment: production

The environment field says this database belongs to the Bahama Cloud production environment. The database is available to deployed server code as env.DB; it does not produce a connection string that can be sent to another host.

A provider-native resource and its environment must use the same provider. Bahama rejects a manifest that tries to attach a native Bahama Cloud database to a Vercel environment.

A complete open-provider example

bahama.yaml
version: 1 project: name: community-notes application: framework: nextjs environments: local: provider: local production: provider: vercel resources: database: provider: neon engine: postgres bindings: DATABASE_URL: from: resources.database.connectionUrl to: - environments.local.variables - environments.production.variables

You or an agent can read it from top to bottom as one sentence:

community-notes is a Next.js application. Develop it locally, deploy it to Vercel, create its Postgres database in Neon, and make the database connection available in both environments as DATABASE_URL.

That is the level of intent the manifest should contain.

What does not belong in the manifest

Neither you nor your agent should add:

  • provider account, organization, project, database, or deployment IDs;
  • connection strings, passwords, API keys, or tokens;
  • values copied from bahama.lock; or
  • provider capabilities that the live provider guide does not declare.

Safe provider configuration—such as a selected Vercel team slug or Neon organization selector—may appear inside a provider’s config block when a Bahama decision gives the agent an exact write-back path.

Last updated on