Development & Deployment
Development happens in the hosted sandbox, against a dev release with its own copy of the database. Each person with edit access gets their own workspace — their own copy of the code, their own dev database — and everyone publishes to the same default branch, which is what builds a new release and promotes it. Both run through the same execution pipeline, the same SDK, and the same schema rules, so code that works in the sandbox works in production.
#How Development Works
#The Sandbox
The hosted sandbox editor is the development environment:
- File tree + Monaco editor
- Live preview
- Terminal / process output
- AI coding agent (Remy)
- TypeScript language server
The sandbox is snapshotted automatically when idle, so work is never lost: it resumes from the latest snapshot.
#The Inner Loop
Backend changes:
- Edit method code in
dist/methods/src/ - Save
- The next method invocation (from the preview or the API) uses the updated code — esbuild transpiles per request, so there is no restart step
Frontend changes, when the app has a web interface:
- Edit React components in
dist/interfaces/web/src/ - Save
- Vite HMR updates the preview instantly
#Schema Sync
When a table definition is added or modified, the change is synced to the dev database automatically. The platform parses the TypeScript, diffs against the current schema, and applies DDL using the same migration rules as production — see Tables & Database.
#The Dev Database
A dev session gets its own database: a snapshot of the live database taken at session start. Dev code writes to that snapshot, never to production.
Reset to live data
POST /dev/manage/reset
Overwrites the dev database with a fresh copy of production data. IDs are preserved, so no reload is needed.
Truncate (empty tables)
POST /dev/manage/reset
Body: { "mode": "truncate" }Keeps the schema and deletes all row data. Scenarios use this to start from empty tables before seeding.
Scenarios
Running a scenario puts the dev database into a specific, repeatable state:
- Truncate all tables
- Execute the seed function (the same
db.push()calls a method would make) - Assign the scenario's declared roles to the dev test user
See Scenarios. To test the app from a particular role's perspective, set the dev test user's roles. That is a real write to the user's row, so auth.userId, requireRole, and role lookups behave exactly as in production — see Auth & Roles for the mechanics.
#Debugging
Console output — console.log, console.warn, and console.error in methods are captured per invocation and surfaced in the editor's process output.
Request logs
GET /apps/{appId}/requests
GET /apps/{appId}/requests/{requestId}Every method execution, including dev, is logged with full input, output, duration, and error info. For a deployed app, mindstudio-prod requests retrieves the same server-side logs, errors, and latency.
Method metrics
GET /apps/{appId}/metrics/summary
GET /apps/{appId}/metrics/methods/{methodId}Aggregated execution metrics: call count, error rate, duration percentiles.
#What Happens on Deploy
Every commit that lands on the default branch deploys. Publishing is what puts one there: the workspace commits its changes and pushes.
git push origin HEAD
Each workspace is a full clone on the default branch, so there is no shared working tree to contend for — several people can publish from several sandboxes. When two of them publish close together the second push is rejected as non-fast-forward; that workspace fetches, merges the release it missed, and pushes again.
From the push on, the platform builds and deploys automatically:
- Parse manifest — read
mindstudio.jsonfrom the commit - Create release — record in Postgres with status
building - Mirror files — copy repo files to S3 for instant editor access
- Compile methods — esbuild bundles each method into a single JS file, extracts npm package dependencies
- Compile interfaces — build the web interface (
npm install && npm run build), generate configs for API/cron/webhook/etc. - Parse table schemas — TypeScript AST → column definitions, diff against live database
- Compute pending effects — roles diff, cron diff, bot command diffs, webhook/email diffs, table DDL
- Apply — create/update roles, sync bot commands, apply DDL to a staging database copy, swap the live pointer
Every step is captured in the build log with timing.
#Release Statuses
building → compiled → live (default branch)
→ preview (feature branch)
→ failed (build error)
live → superseded (new release goes live)| Status | Meaning |
|---|---|
building | Compilation in progress |
compiled | Build succeeded, not yet promoted |
live | Currently serving production traffic |
preview | Feature branch deployment |
failed | Build error (check build log) |
superseded | Was live, replaced by newer release |
dev | Active dev session (not a deploy) |
#Preview Deployments
Push any branch other than the default:
git push origin HEAD:refs/heads/<branch>
Same build pipeline, but the release is marked preview instead of live. Accessible via a branch-specific URL, and it runs against a copy of the data rather than production. Each branch gets its own preview release; pushing the branch again supersedes the previous one.
Preview deployments don't affect the live app — they are how you show work before it ships. A branch sitting at the default branch's tip builds no preview, because the live release already covers that commit.
#Database Migrations
On deploy, the platform:
- Parses the table definition files (TypeScript AST)
- Compares against the current live database schema
- Clones the live database to a staging copy
- Applies the changes to the staging copy — new tables are created; a table with new, dropped, or retyped columns or changed
uniqueconstraints is rebuilt (a table with the declared shape is created, every row is copied across, and it replaces the old one in one transaction); tables removed from the manifest are dropped - Promotes the staging copy to live
Renames are not detected: a renamed column or table is a drop plus an add, so its data does not carry over.
Safety — schema changes are always applied to a clone, never to the live database directly. If the DDL fails, the live database is untouched and the release is marked failed.
Per-release databases — databases are keyed by release ID, so each release gets its own copy:
- The live release has the production database
- A new release clones from live, applies DDL, then becomes the new live database on promotion
- Dev sessions get their own copy (snapshotted from live on session start)
- Rollback is safe because the previous release's database still exists
#Build Logs
Every release has a detailed build log:
✓ Release created from commit a1b2c3d ✓ Compiling 13 methods ✓ Compiled submit-vendor-request (submitVendorRequest) [4.2KB] ✓ Compiled get-dashboard (getDashboard) [3.1KB] ✓ ... ✓ Compiling web interface ✓ Installing NPM packages... ✓ Web interface compiled [47 files] ✓ Roles diff: 2 to create, 0 to delete ✓ Tables diff: 4 to create, 0 to alter ✓ Cron diff: 2 jobs ✓ Release promoted to live (12.4s)
Each phase is timestamped. On failure, the error and context are captured.
Access via the dashboard or API:
GET /apps/{appId}/releases/{releaseId}#Side Effects on Deploy
When a release is promoted to live, the platform applies all pending effects computed during build:
| Effect | What happens |
|---|---|
| Roles | Create new roles, update descriptions, delete removed roles |
| Cron | Upsert scheduled jobs (create/update/remove) |
| Webhooks | Update endpoint registrations |
| Update email trigger routing | |
| Tables | Clone database, apply DDL, promote |
Effects are stored on the release as pendingEffects. Nothing changes in the live system until promotion.
#Post-Deploy Diagnostics
Every live deploy runs an automated Lighthouse audit of the app — performance, accessibility, best-practices, and SEO scores, plus runtime findings (console errors and failed network requests). Pull it via the mindstudio-prod CLI to find concrete issues worth fixing while iterating:
mindstudio-prod diagnostics get— scores + runtime findings + a distilled list of failing audits, with a signed link to the full report.mindstudio-prod diagnostics report— the raw Lighthouse JSON.
The audit runs asynchronously and lands ~30–60s after the release goes live, so it is not ready the moment a deploy finishes. Immediately after deploying, diagnostics get returns {"status":"pending"}; retry shortly after, or use diagnostics get --wait to block until it's ready. Both default to the current live release.
#Rollback
Rollback is a git operation: revert, then publish.
git revert HEAD git push origin HEAD
This creates a new commit that undoes the last change, triggering a new build and deploy. The previous release's database is still available (databases are per-release), so data isn't lost.
For faster rollback without a new build, the platform supports re-promoting a previous release (via the editor dashboard).
#Diagnosing Build Failures
If a build fails:
- Check the build log (
GET /releases/{releaseId}) - Common issues:
- Method compilation error — TypeScript/syntax error in a method file. The error message includes the file and line.
- Web build error — npm install or build command failed. Check the captured stdout/stderr in the build log.
- Table schema error — TypeScript file couldn't be parsed. The table definition must use the expected
defineTable<T>()pattern. - Missing manifest fields — method declared but path doesn't exist, or export doesn't match.
- Fix the issue and push again. Failed releases never affect the live release.