TL;DR
To add a backend to an app your agent built, have the agent write a small server in the same repo and describe the rest in floo.app.toml: [managed.default] for Postgres, access_mode = "accounts" for team sign-in, and a [cron.<name>] block for a daily job. The browser calls your server's /api routes, the server reads the signed-in person from a request header and queries Postgres with DATABASE_URL, and nothing in the browser can reach the database.
- The server is the backend. Next.js route handlers or an Express service are enough. The agent writes them in minutes.
- Sign-in is one config line. floo's gateway handles the sign-in page and session, and tells your code who is calling.
- Permissions are a WHERE clause. Filter rows by the signed-in person in the route, instead of writing a policy per table.
- The prompt below does the whole thing, from adding the routes to reporting a live URL.
This walkthrough follows floo's own docs as of November 3, 2026. Links to each guide are at the end.
What are you starting with?
Usually one of three things:
- A frontend with fake data. The agent built screens backed by a hard-coded array or
localStorage. It works on your laptop and forgets everything on another one. - A frontend that calls a hosted database from the browser. Common with app builders: the page holds a public key and the database's access rules decide what each visitor can do.
- A Next.js app with no database yet.
All three end in the same place: a server that owns the data, and a browser that only talks to the server.
What does the finished app look like?
browser -> floo gateway (sign-in) -> your server (/api routes) -> Postgres
The gateway admits only people you invite and adds their identity to every request. Your server reads it, decides what they may see, and queries Postgres. The database credentials exist only in the server's environment, so a mistake in the browser code cannot expose a table. There are no row-level security policies to write, because nothing outside your server has a way to the database.
Step 1: Add server routes that own the data
In a Next.js app, a route handler is the whole server. This one lists the signed-in person's tasks:
// app/api/tasks/route.ts
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export async function GET(request: Request) {
const email = request.headers.get("x-floo-user-email");
if (!email) return new Response("Unauthorized", { status: 401 });
const { rows } = await pool.query(
"select id, title, done from tasks where owner_email = $1 order by id",
[email],
);
return Response.json(rows);
}
Two things in that file replace an auth system and a security policy. The header comes from floo's gateway, so the route knows who is calling without a session store. The where owner_email = $1 is the permission check, written once, with a parameter instead of string concatenation.
For a Vite or React single-page app, the agent adds an Express server that serves the built files and the same /api routes from one container. The Express guide has the Dockerfile and server setup, and the Next.js guide covers standalone output and the HOSTNAME=0.0.0.0 setting Next.js needs.
Then the agent moves every database call out of browser code. Any database URL or key in a NEXT_PUBLIC_, VITE_, or REACT_APP_ variable goes too: floo's docs warn that those are baked into the JavaScript bundle and visible to anyone who opens the app.
Step 2: Create the tables on every deploy
A migration script creates the schema, and migrate_command runs it before traffic moves to a new version. If it fails, the deploy stops and the previous version keeps serving.
create table if not exists tasks (
id bigserial primary key,
owner_email text not null,
title text not null,
done boolean not null default false,
created_at timestamptz not null default now()
);
Use your stack's migration tool if it has one: Prisma, Drizzle, Alembic, Rails, and Django all work. The script has to be inside the Docker image. Change the schema in steps that the previous version of the code can still run against, because it serves traffic until cutover. The Postgres guide calls this expand-then-contract.
Step 3: Write floo.app.toml
# floo.app.toml
[app]
name = "team-tasks"
access_mode = "accounts"
[services.web]
type = "web"
path = "."
port = 3000
migrate_command = "node scripts/migrate.js"
[managed.default]
type = "postgres"
[cron.daily-summary]
schedule = "0 9 * * *"
command = "node scripts/daily-summary.js"
service = "web"
What each block does:
access_mode = "accounts"puts invite-only sign-in in front of every page. You can keep dev public while you iterate with[environments.dev]andaccess_mode = "public".[managed.default]provisions Postgres. Dev and prod get separate databases and credentials, andDATABASE_URLis injected at deploy time. It never appears in git.[cron.daily-summary]runs the script at 9am UTC inside the web service's image, with the sameDATABASE_URL. Cron jobs do not retry, so write the script so a second run does no harm.
Need file uploads or a cache? Add [managed.files] with type = "storage" or [managed.cache] with type = "redis". Redis is cache-only on floo; keep anything you cannot lose in Postgres.
Step 4: Paste this prompt
Replace team-tasks with your app name and edit step 3 to match your app's rules.
Add a backend to this app and deploy it to floo. App name: team-tasks.
1. Confirm the floo org with `floo orgs list`. If the org has no plan, have me run `floo billing upgrade`.
2. Add server routes under /api that read and write Postgres using DATABASE_URL from the environment. Move every database call out of browser code so the browser calls only these same-host routes. Remove any database URL or key from client code and from NEXT_PUBLIC_, VITE_, or REACT_APP_ variables.
3. Read the signed-in person from the X-Floo-User-Email and X-Floo-User-Role headers. Each person sees only their own tasks; only role "admin" may delete. Do not add a login page, password table, or session store.
4. Write a migration script that creates the tables, include it in the Docker image, and write scripts/daily-summary.js so running it twice is harmless.
5. Run `floo init team-tasks`. In floo.app.toml, set access_mode = "accounts" under [app], add [managed.default] with type = "postgres", set migrate_command on [services.web], and add [cron.daily-summary] with schedule = "0 9 * * *", command = "node scripts/daily-summary.js", and service = "web".
6. Run `floo preflight --json` and fix every error.
7. Commit and push to the default branch.
8. Have me open https://github.com/apps/getfloo/installations/new, choose the repository's owner, and select this repository. Wait for me to confirm.
9. Run `floo apps github setup --no-browser` and give me the printed link. Wait for me to confirm GitHub access.
10. Run `floo apps github connect <owner>/<repo> --no-browser`.
11. Run `floo deploys status --app team-tasks --json` until the deploy is live, then report the URL.
If your agent does not have floo yet, install it with curl -fsSL https://getfloo.com/install.sh | bash and sign in with floo auth login. Agent setup covers Claude Code, Codex, Cursor, and agents that use the HTTP API instead.
Step 5: Check it and invite people
Open the dev URL in a private window. You should see floo's sign-in page, not your app. Then invite the people who should use it:
floo apps invite teammate@example.com --role member --app team-tasks
floo apps invite lead@example.com --role admin --app team-tasks
floo cron list --app team-tasks
floo cron run daily-summary --app team-tasks
App users do not use builder seats and get no access to floo itself. Removing someone with floo apps member-remove revokes their sessions immediately.
Every push to the default branch deploys to dev. When you want a stable version for the team, publish a GitHub release and floo deploys that commit to prod with prod's own database. A small tool for a few people can stay in dev alone.
How do I test sign-in on my laptop?
The gateway is not in front of localhost, so run floo dev --app team-tasks --fixture-user you@example.com. It starts a proxy that adds the same X-Floo-User-* headers, and your routes behave as they do deployed. There is no "skip auth in development" branch to forget.
What if an agent needs to call the app?
Declare a route that takes an API key, then mint a key for that agent. People keep signing in on /, and the key works only on the routes declared with its scope:
[[routes]]
path = "/"
service = "web"
access = "accounts"
[[routes]]
path = "/api/agent"
service = "web"
access = "api_key"
scope = "tasks.read"
How to give your agent its own key walks through consumers, scopes, and revocation.
What if I'd rather not start from my code?
floo projects create my-appmakes a Next.js app with sign-in and managed Postgres in a repository floo hosts, with no GitHub account needed.- The templates are working apps, such as an approval queue and an inventory tracker with a daily low-stock job, with sign-in, Postgres, and an agent API already in place.
Before you share the link, run through the backend checklist. The backend overview lists every part floo supplies.
Sources
- floo: quickstart, host an internal tool, Next.js, Express, app sign-in, Postgres, managed services, cron jobs, environment variables, environments, app API keys, agent setup, recommended defaults
Frequently asked questions
How do I add a database to an app my agent built?
Have the agent add server routes that query Postgres, then declare the database in floo.app.toml with [managed.default] and type = "postgres". The next deploy creates separate dev and prod databases and injects DATABASE_URL into your server. The browser calls your routes, never the database.
Do I need to write a login page?
No. Set access_mode = "accounts" under [app]. floo's gateway shows invited people a hosted sign-in page and adds X-Floo-User-Email, X-Floo-User-Id, X-Floo-User-Name, and X-Floo-User-Role headers to every request your code receives.
How do I run a job every day?
Add a [cron.<name>] section with a schedule, a command, and the service whose image runs it. The job gets the same DATABASE_URL and environment variables as that service. Jobs run in UTC and do not retry, so make the command safe to run again.
My app is a Vite or React single-page app with no server. What do I do?
Add one. A small Express server can serve the built files and the /api routes from the same container. floo runs any app with a Dockerfile, and floo init offers to write one.
What if I don't use GitHub?
floo projects create makes a Next.js app with sign-in and managed Postgres in a repository floo hosts, deploys it, and returns its URL. Move your code into it and push.