[Blog](https://cohesivity.ai/blog)

Agent-native backend

Published Jun 30, 2026·Updated Aug 30, 2026

![](https://cohesivity.ai/authors/arag.webp)![](https://cohesivity.ai/authors/anshu.webp)[Arag](https://www.linkedin.com/in/aragagrawal/) and [Anshu](https://www.linkedin.com/in/aanshuaggrawal120/)

# Building a Full-Stack App With Claude Code and Cohesivity: A Complete Walkthrough

[Read as Markdown](https://cohesivity.ai/blog/full-stack-app-with-claude-code-and-cohesivity-walkthrough.md)

Claude Code

Plan

Backend

Live app

Claude Code can build and deploy a full-stack waitlist with Cohesivity by creating an ephemeral tenant, provisioning Postgres and Railway hosting, adding a server-only signup endpoint, testing duplicate writes, and uploading the built application. A human is still required before claiming the project or crossing a paid boundary.

This walkthrough uses a waitlist because it is small enough to inspect and still exercises data validation, uniqueness, server credentials, retries, and deployment.

## Define the behavior before provisioning

The application needs:

- an email form with visible pending, success, and error states;
- a server endpoint that validates and normalizes the address;
- a Postgres table with a unique email constraint;
- duplicate-safe insertion;
- server-only backend credentials;
- a deployable application and public health check.

It does not need social login, realtime, vector storage, or a model API. Provisioning them would add setup without helping the task.

The [backend provisioning guide](https://cohesivity.ai/blog/how-ai-coding-agents-provision-databases-auth-storage-hosting) explains the control-plane and data-plane split used below.

## Ask Claude for a plan first

Start Claude Code in the project and ask it to identify the framework, package manager, existing test setup, server-only environment convention, build output, and deployment command. The official [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code/cli-usage) supports plan-oriented permission modes and tool restrictions, so keep external calls disabled during this inspection.

The plan should name the exact files it will change and the resources it wants. If it proposes putting a Cohesivity key in a `NEXT_PUBLIC_`, `VITE_`, or browser-readable variable, reject the plan.

## Create an isolated tenant

Claude should reuse a valid `.cohesivity` file when one exists. Otherwise it can preview and run the bootstrap:

```bash
npx @cohesivity/init --dry-run
npx @cohesivity/init

```

The created tenant is ephemeral for 72 hours. The command also provides the project context Claude needs. Do not paste the resulting keys into chat, logs, or source code.

## Read and provision Postgres

Claude must fetch the current Postgres offering page before calling it:

```bash
curl -sS -A "ClaudeCode-Waitlist/1.0" \
  https://cohesivity.ai/offerings/postgres

```

After you approve the selected region, Claude provisions `postgres` through the documented management endpoint with a stable idempotency key. Then it creates the schema from server-side code:

```sql
CREATE TABLE IF NOT EXISTS waitlist_signups (
  id BIGSERIAL PRIMARY KEY,
  email TEXT NOT NULL UNIQUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

```

The uniqueness constraint is the final protection against two requests inserting the same normalized address. Application code should still handle the conflict and return the existing signup state rather than a generic 500.

## Add the server endpoint

The handler should:

1. Parse JSON and reject a missing or malformed address.
2. Trim and normalize the email according to one documented rule.
3. Use parameterized PostgreSQL with `$1` placeholders.
4. Send one idempotency key for the logical signup operation.
5. Map a unique conflict to a successful existing-signup response.
6. Return a small public shape without internal errors or credentials.

The browser calls your application endpoint. Only the server calls Cohesivity. This keeps the management and application keys out of the client bundle.

## Test the failure paths

Run at least four cases:

| Case                            | Expected result                          |
| ------------------------------- | ---------------------------------------- |
| Valid new email                 | One row and a success response           |
| Invalid email                   | Validation response and no database call |
| Same normalized email twice     | One row and a stable existing response   |
| Lost response followed by retry | One logical result and no duplicate row  |

Also search the built client assets for `coh_man_` and `coh_app_`. A passing unit test does not prove the bundler kept a secret server-side.

The [second-user backend review](https://cohesivity.ai/blog/why-ai-generated-apps-still-need-better-backend-infrastructure) adds cross-user and cross-tenant tests when the application grows beyond a public waitlist.

## Provision and deploy through Railway hosting

Claude fetches `https://cohesivity.ai/offerings/railway-hosting`, provisions the offering, and uploads the application through Cohesivity's Railway deployment API. It should use the returned Cohesivity `deployment_url` and `logs_url`. It should not install Railway CLI, connect a GitHub repository, or request Railway credentials.

Wait until the deployment and public route are ready. Then run the health check and one real signup against the public server. A provider deployment state alone does not prove the route works.

## Hand the result back cleanly

Claude should report:

- the public deployment URL;
- the tests it ran and their results;
- the resources it created;
- the tenant expiry;
- the action required to claim the project;
- the files that contain server environment wiring;
- the cleanup path if the user declines to keep it.

The prompt below carries the whole task while preserving the approval points.

or send it to[Claude Code](https://claude.ai/new?q=Build+a+small+full-stack+waitlist+in+this+repository+using+its+existing+framework.+Add+a+server-side+POST+endpoint+that+validates+and+normalizes+email%2C+inserts+it+into+Postgres+with+a+unique+constraint%2C+returns+the+existing+record+on+a+duplicate%2C+and+never+exposes+backend+credentials+to+the+browser.+Add+a+visible+success+and+validation+state%2C+plus+tests+for+a+valid+signup%2C+invalid+email%2C+duplicate+email%2C+and+interrupted+retry.+Reuse+a+valid+.cohesivity+file+or+run+npx+%40cohesivity%2Finit+to+create+an+ephemeral+tenant.+Fetch+the+current+Cohesivity+postgres+and+railway-hosting+offering+pages+before+provisioning.+Show+me+the+exact+resource+list+and+plan+first.+Do+not+claim+the+tenant%2C+spend+money%2C+upgrade%2C+or+deploy+until+I+approve.+After+approval%2C+provision%2C+test+locally%2C+upload+through+Cohesivity+Railway+hosting%2C+wait+for+the+public+route%2C+and+return+the+deployment+URL+plus+the+72-hour+claim+deadline. "Send to Claude")[Cursor](https://cursor.com/link/prompt?text=Build+a+small+full-stack+waitlist+in+this+repository+using+its+existing+framework.+Add+a+server-side+POST+endpoint+that+validates+and+normalizes+email%2C+inserts+it+into+Postgres+with+a+unique+constraint%2C+returns+the+existing+record+on+a+duplicate%2C+and+never+exposes+backend+credentials+to+the+browser.+Add+a+visible+success+and+validation+state%2C+plus+tests+for+a+valid+signup%2C+invalid+email%2C+duplicate+email%2C+and+interrupted+retry.+Reuse+a+valid+.cohesivity+file+or+run+npx+%40cohesivity%2Finit+to+create+an+ephemeral+tenant.+Fetch+the+current+Cohesivity+postgres+and+railway-hosting+offering+pages+before+provisioning.+Show+me+the+exact+resource+list+and+plan+first.+Do+not+claim+the+tenant%2C+spend+money%2C+upgrade%2C+or+deploy+until+I+approve.+After+approval%2C+provision%2C+test+locally%2C+upload+through+Cohesivity+Railway+hosting%2C+wait+for+the+public+route%2C+and+return+the+deployment+URL+plus+the+72-hour+claim+deadline. "Send to Cursor")[Codex](https://chatgpt.com/codex?prompt=Build+a+small+full-stack+waitlist+in+this+repository+using+its+existing+framework.+Add+a+server-side+POST+endpoint+that+validates+and+normalizes+email%2C+inserts+it+into+Postgres+with+a+unique+constraint%2C+returns+the+existing+record+on+a+duplicate%2C+and+never+exposes+backend+credentials+to+the+browser.+Add+a+visible+success+and+validation+state%2C+plus+tests+for+a+valid+signup%2C+invalid+email%2C+duplicate+email%2C+and+interrupted+retry.+Reuse+a+valid+.cohesivity+file+or+run+npx+%40cohesivity%2Finit+to+create+an+ephemeral+tenant.+Fetch+the+current+Cohesivity+postgres+and+railway-hosting+offering+pages+before+provisioning.+Show+me+the+exact+resource+list+and+plan+first.+Do+not+claim+the+tenant%2C+spend+money%2C+upgrade%2C+or+deploy+until+I+approve.+After+approval%2C+provision%2C+test+locally%2C+upload+through+Cohesivity+Railway+hosting%2C+wait+for+the+public+route%2C+and+return+the+deployment+URL+plus+the+72-hour+claim+deadline. "Send to Codex")[opencode](https://opencode.ai/?q=Build+a+small+full-stack+waitlist+in+this+repository+using+its+existing+framework.+Add+a+server-side+POST+endpoint+that+validates+and+normalizes+email%2C+inserts+it+into+Postgres+with+a+unique+constraint%2C+returns+the+existing+record+on+a+duplicate%2C+and+never+exposes+backend+credentials+to+the+browser.+Add+a+visible+success+and+validation+state%2C+plus+tests+for+a+valid+signup%2C+invalid+email%2C+duplicate+email%2C+and+interrupted+retry.+Reuse+a+valid+.cohesivity+file+or+run+npx+%40cohesivity%2Finit+to+create+an+ephemeral+tenant.+Fetch+the+current+Cohesivity+postgres+and+railway-hosting+offering+pages+before+provisioning.+Show+me+the+exact+resource+list+and+plan+first.+Do+not+claim+the+tenant%2C+spend+money%2C+upgrade%2C+or+deploy+until+I+approve.+After+approval%2C+provision%2C+test+locally%2C+upload+through+Cohesivity+Railway+hosting%2C+wait+for+the+public+route%2C+and+return+the+deployment+URL+plus+the+72-hour+claim+deadline. "Send to OpenCode")
