Code Canvas Database

Add a real Postgres database to any Code Canvas project. Theo writes code against live tables, auto-seeds sample rows, and can repair runtime errors with a click. Built on Neon Serverless Postgres.

Data tab layout

Overview

The default landing surface. Surfaces a storage meter, table count, total row estimate, auth user/session counts, last activity, plus three primary actions: New table, Open SQL runner, and Open workspace.

Data Workspace

Click the maximize icon next to the DB pill in the header (or the Overview action card) to open a full-screen workspace: searchable left rail of tables, wide row grids, a taller SQL editor, and side-by-side schema + history cards. Selection + sub-view state sync with the sidebar.

All five sub-views (Overview, Tables, SQL, Schema, History) live in both surfaces. Auth lives in a single chip in the workspace header and as a full-width card at the top of the sidebar Overview — click either to enable, disable, or view user / session counts.

Enable the database

Open a Code Canvas project, switch to the Data tab, and click Enable Database. Provisioning takes a few seconds and drops a green indicator next to the project name.

Behind the scenes we create a new Neon project, wire a restrictedapp_reader role for the public share proxy, and store the connection strings encrypted in Appwrite.

What you get

Live Postgres database

Every Code Canvas project can provision its own Neon Postgres instance. Theo and the preview talk to it through window.__db.

End-user authentication

One-click enable creates `_auth_users` + `_auth_sessions`. Your generated app calls `window.__auth.signup()`, `.login()`, `.currentUser()` just like a real SaaS.

Seed data after each table

When Theo creates a table it auto-generates 3–5 realistic rows so the preview isn't empty. Call `db_seed_table` later for more.

Per-user scoping

Theo can call `scope_table_to_user` to add a `user_id UUID` + index (or RLS policy) so each signed-in user only sees their own rows.

Schema history + revert

Every DDL applied to your database is logged. Open the History tab to see the full ledger and revert non-destructive migrations in one click.

CSV import / export

Export up to 10,000 rows from any table. Import rows client-side — we parse and insert them in chunks, showing per-row errors inline.

The window.__db SDK

The preview iframe exposes window.__db. Generated code reads and writes like any other Postgres client:

const { rows } = await window.__db.query('SELECT * FROM todos ORDER BY created_at DESC');

await window.__db.query(
  'INSERT INTO todos (title, completed) VALUES ($1, $2)',
  [title, false]
);
  • Always parameterized — never string-concatenate user input.
  • Always awaited.
  • Wrap in try/catch — Theo reads Postgres errors via the Try-to-fix button (see below).

Theo has full database control

Theo isn't limited to creating tables. In an edit turn it can run any SQLagainst your project's database: add or reshape columns, create indexes for slow queries, define views, functions, triggers, enum types, and row-level-security policies, install Postgres extensions, and read or write data — multi-step migrations run inside a single transaction so a partial failure rolls everything back.

Theo also sees the whole schema — tables, columns, indexes, foreign-key relationships, constraints, enums, views, RLS policies, and installed extensions — so changes respect what already exists.

Destructive changes are gated:dropping a table, truncating data, or deleting without a WHERE clause requires confirmation. If your request explicitly asked for it ("drop the orders table"), Theo proceeds; otherwise the editor chat shows an amber Confirm & run card spelling out exactly what would be destroyed — one click approves, Cancel leaves everything untouched. Every schema change lands in the migration history with best-effort revert SQL.

Theo can also read its own trail: db_list_migrations shows the recent history, db_revert_migration undoes an entry via its stored compensating SQL, and slow queries get diagnosed withEXPLAIN (ANALYZE, BUFFERS) before Theo adds an index.

Dev & Production environments

Experiment safely — your live site keeps its own data

Your database splits into two environments built on Neon branching. Dev is where Theo, the editor preview, the SQL runner, and the row grids work by default — experiment freely. Productionis what your published site reads and writes. A schema change or a bulk delete in Dev never touches your visitors' data.

Switch environments with the Dev / Productionpill in the Data tab header. When you're happy with Dev, open Environments & backups on the Overview and click Promote to Production. Promote has two modes:

  • Schema only (default) — replays the schema changes you made in Dev since the last promote onto Production, one migration at a time. Your production data is untouched. The preview shows exactly which pending migrations will replay; if one fails, the replay stops there and re-promoting after a fix resumes from the same point.
  • Full restore — makes Production an exact copy of Dev, including its data. The dialog warns you when production tables hold more rows than Dev, since those rows would be replaced.

Either way the pre-promote production state is kept as an automatic backup. Reset Dev from Production pulls live data the other way when you want to test against real rows.

Environments are rolling out — if you don't see the switcher yet, your project is on the single-database setup and everything else on this page works the same.

Backups & restore

Point-in-time restore + automatic pre-restore backups

Every environment can be rewound to any moment in the last 24 hours — pick a time in the Restore dialog and the branch rolls back to exactly that state. Before ANY restore or promote runs, the current state is preserved as abackup-* branch, so a restore is itself always undoable.

The three most recent backups are kept (older ones prune automatically). Restore from any of them — or delete ones you no longer need — from the same Environments & backups card. Each backup shows its size, and the Overview's storage meter has a Where is it going?breakdown (Production / Dev / Backups) — deleting old backups is the quickest way to free space when you're near your plan's limit.

Background migrations & imports

Long-running SQL no longer hits the request timeout

Big backfills and slow migrations can run as a durable background job with a 4-minute statement budget. Theo dispatches them automatically when a statement times out inline (it re-runs with background: true), and large file imports queue themselves. You get a notification when the job finishes, and the outcome lands in the migration history — Theo verifies withdb_list_migrations before building on it.

Progress is live: the moment a job is dispatched it appears in Schema history as a Running entry with a spinner, and the view refreshes itself until the job flips to applied or failed — no reload needed.

Authentication

Click Auth → Enabledin the Data tab, or ask Theo "add signup and login". Your app then uses:

await window.__auth.signup(email, password, displayName?);
await window.__auth.login(email, password);
const user = await window.__auth.currentUser();
window.__auth.onAuthChange((user) => { /* react to state */ });

Ask Theo to call scope_table_to_userto add a user_id UUID column + index (and optional Postgres RLS policy) so each user only sees their own rows.

Auth and environments: user accounts follow the data. Signups made in the editor preview land in Devas test accounts, while your published site's users and sessions live in Production— the two never mix. The Dev / Production pill also switches which user list the Data tab's Auth views show, and the promote / reset dialogs call out when an operation would replace an environment's users.

Preview toolbar

Address bar, viewport selector, and reload — above every preview

Every Code Canvas preview now has a Bolt/Replit-style toolbar across the top. The address bar accepts any in-project route (“/about”, “/dashboard?tab=stats”) — hit Enter and Theo routes the iframe to that page. If a sibling HTML file matches (“about.html”) the preview swaps instantly; otherwise SPA routers (React Router, Vue Router) pick up the new path via the same pushState +popstate dance the in-preview link clicks use.

Back, Home, and Reload sit next to the address bar. Reload re-mounts the iframe (or re-runs Sandpack) without losing your code state — useful after a manual edit you want to apply in isolation.

The device viewport selector on the right of the toolbar constrains the preview to a fixed width × height — Desktop (fluid), iPhone 16 / 16 Pro / 16 Pro Max, Pixel 10, Galaxy S25, iPad, iPad Pro 13, or Custom dimensions you type yourself. Zoom + / − keeps iPad presets readable on small laptop screens. Selections persist per project, so refreshing the page leaves you in the same frame.

Inside an edit turn

One agent loop, one Project State, one recovery contract

Every Code Canvas chat message runs through a single agent loop: one streaming AI call, one set of tools, one heartbeat, one budget. The model picksupdate_code,patch_code,generate_code, or a DB tool, and the loop short-circuits the moment real code lands so changes ship immediately.

Theo opens every turn with a Project Stateblock: a compact summary of your project's framework, entry file, whether the database is live, every table + auth provider, and whether auth is enabled. That single authoritative snapshot replaces the older stack of competing context blocks so the model never has to guess what's wired and what isn't.

The tier picker above the composer (Theo Code Fast / Theo Code / Theo Code Max) controls which model handles the loop and how long it can run before the heartbeat trips. The picker also exposes a Plan mode for multi-step requests — see the section below.

After a substantial build (3 or more files in a single ad-hoc turn) Theo finishes the chat reply with two extra sections — Key features and Design highlights — enumerating the user-visible deliverables and the visual choices he made. The bubble picks up a subtle accented background so the recap reads like a delivery report. Small CSS / single-file edits and plan-mode turns skip the recap so iterative changes stay terse.

Project credit usage

See what each project costs — live, in the header

A credits pill sits at the top of the editor, just left of the Visual Edit toggle. It shows the running total of AI credits this project has spent. Every time you send a prompt and Theo ships changes, the number ticks up the moment the turn finishes — so you always know roughly what a given build is costing you.

Click the pill to open an itemized breakdown of where your credits went. Each turn is listed newest-first with what it did (a code change, a database step, a design tweak, an auto-fix, a plan step, or an upscale), which tier ran it (Theo Code Fast / Theo Code / Theo Code Max), how many files it touched, and how long ago it happened. The breakdown updates automatically the instant a turn completes.

The breakdown also surfaces a smart suggestion when it spots a cheaper path — for example, if most of your recent spend is going to Theo Code Max, it nudges you toward Theo Code, which handles the majority of changes for a fraction of the credits. Switch tiers any time from the model picker in the composer.

The total is per-project and persists across reloads. Instant CSS tweaks that Theo applies without an AI round-trip don't add to it, and your overall monthly balance still lives in Settings → Billing.

Try-to-fix & Keep going

Free, one-click repair

When the preview throws a runtime error (including Postgres errors from window.__db), a red Try to fix chip appears above the composer. Clicking it sends the recent errors to Theo and routes the fix through a fastpatch_code repair.

We pair Postgres error codes with one-line hints so Theo knows, for example, that42P01means "table doesn't exist — create it before querying". Throttled to 3 attempts per project per minute.

When Theo stalls or finishes a turn without writing any code (for example, a DB-only call to enable_auth with no UI follow-up, or an upstream timeout) the assistant message ends with a small orange Keep going card. Clicking it re-sends a typed resume message so Theo finishes the work without you re-typing anything. The card surfaces a specific reason (timeout, no tool call, provider error, etc.) so you always know whether to wait or try a different tier.

Seed data

Never start with an empty preview

Theo now passes realistic seed_rows with everydb_create_table call, and can calldb_seed_tablelater with a hint like "three fitness customers" or "urgent support tickets". Internal_auth_* tables are never seeded.

Import & export data

Open any table in the Data tab. Use Export to download up to 10,000 rows as a CSV, or Import to upload a CSV whose headers match existing columns. Rows insert one-by-one with parameterized SQL and per-row error reporting.

For bigger or messier data, attach the CSV or JSON file in chat and ask Theo to import it. The db_import_data tool parses it server-side, infers column types (numbers, booleans, timestamps), can create the table for you (adding an idprimary key when the data has none), and inserts in chunked transactions. Up to 2,000 rows import instantly; files up to 50,000 rows / 15MB run as a background job with a notification when done. Replacing a table's data goes through the same confirm gate as any destructive SQL.

Chat imports are all-or-nothing: rows are staged into a temporary table first, and your real table only changes in one final transaction once every row has landed. If anything fails mid-import, the staging table is discarded and your data is exactly as it was — no half-imported tables.

Edit rows inline

Fix a value without writing SQL

In the Tables view, double-click any cellto edit it in place — Enter saves, Escape cancels, and nullable columns get a NULL toggle. Each row also has a delete action with a confirm dialog. Edits run as parameterized UPDATE / DELETE statements keyed on the table's primary key (tables without one show editing as disabled), so a typo fix is one click instead of a SQL round-trip.

The editor matches the column's type: booleans get a true / false picker, timestamps get a date-time picker, JSON columns get a multi-line editor that validates before saving (⌘/Ctrl+Enter commits), and numeric columns get a number input — so you can't accidentally save malformed values.

Plan mode

Review the plan before Theo touches your code

Flip the mode pill above the chat composer from Agent to Plan and send your request. Theo drafts a structured plan first — phases, tasks, tech stack, components — and surfaces it in a side panel anchored to the top-right corner of the preview. Nothing in your code changes until you approve.

Each task starts as queued. You can edit the wording, drop tasks you don't want, or dismiss the plan entirely. When you're ready, hit Execute Plan and Theo runs each task in order — flipping rows to activedone in real time. A task that stops without shipping code surfaces a recovery card on that row so you can keep going manually.

The plan panel can be minimized into a slim pill (e.g. Plan · 3/7 tasks) so it never fights the preview for screen space. Click the pill any time to expand the full task list. Once a plan completes, the mode picker automatically returns to Agent so the next ad-hoc message ships directly.

  • Engine tier sticks. Plan creation runs on a fast planner; execution runs on the tier you picked (Theo Code Fast / Code / Max).
  • Persistence is local-only. Plans rehydrate from your browser for 24h. The server never stores them; the next page reload picks up where you left off in review mode.
  • Per-task recovery. Every task reuses Code Canvas's standard heartbeat, retry, and salvage contract — if Theo stalls on task 5, the rest of the plan stays untouched.

Schema history + revert

The History sub-view lists every schema-changing SQL statement Theo or you applied — with source, tool, and timestamp. Each row shows a best-effort revert button; clicking it runs a compensating DDL (e.g.DROP TABLE,DROP COLUMN) and marks the entry as reverted. Destructive reverts prompt for confirmation.

Theo works from the same ledger: ask "what changed in my database?" and it readsdb_list_migrations; ask it to undo a change anddb_revert_migration runs the stored revert SQL (destructive reverts go through the same confirm card). Background jobs, imports, promotes, and restores are recorded here too, so the ledger doubles as your job history.

Publishing a code project keeps the database behind a signed public query proxy. Enable auth + call scope_table_to_userbefore launch so each visitor only sees their own rows.
Was this article helpful?

Related Articles