- The build must run in full, at image build time — not split into “compile in the image / generate at runtime”. FrogBot’s
prebuildstep generates the admin import map, andnext buildcompiles the app. Runningnext build --experimental-build-mode generateat container start (as some platform templates do) re-runs webpack in production, which requirestypescriptat runtime and slows cold starts dramatically. - In production, FrogBot does not push your schema automatically the way it does in dev. A fresh production database has no tables until migrations run — see Migrations.
Docker
The template ships a productionDockerfile based on the Next.js with-docker example:
- Package-manager agnostic — it detects your committed lockfile (
pnpm-lock.yaml,package-lock.json, oryarn.lock) and installs with the matching tool. The template ships no lockfile; your firstinstallcreates it. - Standalone output — the build stage sets
NEXT_OUTPUT=standalone(wired up in the template’snext.config.mjs), and the final image contains only Next’s traced server: no package manager, no fullnode_modules. It starts with plainnode server.js(~110 MB image, sub-second boot). - Build isolation — the build stage uses a throwaway
DATABASE_URLand a placeholderFROGBOT_SECRET, so no local data or secrets are baked into the image. Real values come from environment variables at runtime.
Health check
The template answersGET /api/health with 200 and { "status": "ok" } once FrogBot has started, and 503 with { "status": "error" } when it can’t start, logging why. It needs no sign-in, so point your platform’s HTTP health check at it. Dojo, where the Dojo plugin’s frogbot share runs apps, checks this path. The route is src/app/(frogbot)/api/health/route.ts.
Fly.io
Dockerfile and uses it instead of generating its default Next.js two-phase build, so your app gets a fast, single-phase cold start.
For a complete, working setup — persistent volume, migrations, scale-to-zero — see the fly-sqlite example.
Database persistence
The default SQLite database lives in a localfrogbot.db file on the machine’s ephemeral storage. If your machines auto-stop (scale to zero), the data is wiped on restart. Choose one of:
-
Attach a persistent volume and point
DATABASE_URLat it:A volume attaches to one machine at a time, so with SQLite you run a single machine (fly scale count 1). Scale-to-zero still works — the data lives on the volume, not the machine. -
Use a remote database: Postgres, MongoDB, or a hosted SQLite like Turso. Set
DATABASE_URLaccordingly.
Migrations
In development, FrogBot pushes your schema to SQLite automatically on boot. In production it does not — it only applies migrations listed inprodMigrations. Before your first production deploy:
pnpm migrate:create <name> again and commit the new files.
Generated migrations import from the underlying database adapter package, which the template includes as a direct dependency — do not remove it.
Troubleshooting
no such table: users in production
Your production database has no schema. FrogBot only pushes schema automatically in dev; in production you need migrations wired into prodMigrations — see Migrations.
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION during Docker build
Recent pnpm versions refuse packages published within the last 24 hours as a supply-chain protection. If a FrogBot release is newer than that, either wait, pin an older pnpm via the packageManager field in package.json, or relax the policy in pnpm-workspace.yaml (minimumReleaseAge: 0).
Cannot find module 'libsql' (or sharp, pino, drizzle-kit, json-schema-to-typescript)
Only applies to non-standalone deploys (bare VPS running pnpm start): the compiled routes require() a package that FrogBot externalizes from the webpack bundle, but it is not linked at your project root. Add it to dependencies in package.json and rebuild — the template already includes all of them. Standalone Docker images are unaffected: the build includes these packages, and libsql’s native binary for the platform the image is built on. Build the image with the template Dockerfile so dependencies install inside Linux. node_modules copied in from macOS or Windows has no Linux binary, and the server fails with Cannot find module '@libsql/linux-…'.
Installing TypeScript... or Can't resolve '@frogbot-config' at start
A runtime next build step is running (usually a platform template with a two-phase build), and typescript was pruned from the image. Use the template Dockerfile above so the build happens once, in the image, and start runs only node server.js.
Slow cold starts
If your platform starts a build at container boot, your cold start includes a webpack rebuild. Move the build into the image (see Docker) so cold starts are just the standalone server booting.Installation
Scaffold a project and run it locally.
Database
Choose a database adapter that fits your production storage needs.