The Bahama project model
A Bahama project gives you and your coding agents four small ideas to work with:
- the application you are building;
- the environments where it runs or receives configuration;
- the resources it depends on; and
- 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:
application:
framework: nextjsThe framework must be supported by every hosted environment selected for the application. If the application lives below the repository root, include its relative directory:
application:
framework: vite-spa
dir: apps/webdir 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:
environments:
local:
provider: local
production:
provider: vercelThe 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:
resources:
database:
provider: neon
engine: postgresThe 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:
bindings:
DATABASE_URL:
from: resources.database.connectionUrl
to:
- environments.local.variables
- environments.production.variablesDATABASE_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:
resources:
database:
provider: bahama-cloud
environment: productionThe 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
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.variablesYou or an agent can read it from top to bottom as one sentence:
community-notesis 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 asDATABASE_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.