Your repo should be the cloud contract
Published 2026-05-04 by tavin
The most useful deployment contract is the one your app already carries around: the repo.
A repo contains the application code, package manifests, lockfiles, tests, environment examples, and sometimes a Dockerfile. It is versioned. It is reviewed in pull requests. It is where humans and agents already collaborate.
That makes it a better cloud contract than a pile of provider-specific dashboard settings.
Auto-detection should be the starting point
Most apps should not need a hand-written container recipe before they can get a live URL. A Node service, Python API, Rails app, Go binary, or static frontend usually has enough structure for a builder to infer the right path.
That is where Railpack fits. It reads the repo, detects the stack, builds from source, and produces a normal container.
The important part is that the convenience does not become lock-in. The output is still a container. The source of truth is still the repo.
Dockerfile is the escape hatch, not the entry fee
Automatic builds are convenient until your app needs something more explicit:
- a system package
- a custom binary
- a worker process
- a nonstandard build step
- a language runtime the platform does not detect well
- the exact same image in development, CI, and production
At that point, a Dockerfile is useful because it writes the runtime down. It should be available when you need it. It just should not be required before the first deploy.
Portability is still concrete
“No lock-in” can sound like marketing filler, but repo-to-container portability has a concrete shape:
git clone [email protected]:acme/app.git
railpack build .
# or, if the app owns its runtime explicitly:
docker build -t app .
docker run -p 3000:3000 app
That does not mean every cloud behaves identically. Networking, secrets, storage, billing, observability, and rollout behavior still differ. But the application runtime is not trapped behind a proprietary shim.
A good platform should remove ops work, not hide the build
The point of a PaaS is not to make developers think less by making the system mysterious. The point is to remove repetitive operational work while keeping the important contracts readable.
tavin.cloud treats the repo as that contract:
- Connect a GitHub repo.
- Pick the branch and exposed port.
- Push code.
- tavin.cloud builds with Railpack by default, or your Dockerfile when present.
- The service gets logs, metrics, TLS, domains, and a public URL.
The application remains a normal Linux container. The platform handles the surrounding work.
The repo also helps AI agents
AI agents are better collaborators when the system state is expressed in files, commands, and structured APIs instead of hidden dashboard settings.
A repo gives the agent concrete places to answer questions like:
- Which runtime does this app use?
- Which port should the service expose?
- Which build command is expected?
- Are required environment variables documented?
- Is there a Dockerfile for explicit runtime control?
That is much easier than asking an agent to reverse-engineer a platform-specific build failure from scattered dashboard state.
The contract should stay boring
The repo is not glamorous. That is the point. It is a boring, portable, reviewable contract for how software ships.
Cloud platforms should compete on the work around that contract: deploy flow, reliability, observability, billing, collaboration, and agent control. They should not need to replace the contract with a proprietary runtime story.
For tavin.cloud, the product bet is simple: keep the source contract as Git, build it into a normal container, and make the surrounding platform small enough for a developer and structured enough for an AI agent.