Skip to main content
Every Mist app starts as a copy of Fluid’s public starter template, Fluid-WeCommerce/mist-next-app-template on GitHub. When you create an app, Fluid generates your app’s private repository from it. Your repository is a one-time copy. Changes to the template after you create an app don’t reach it. To pull in a later template change, add the template as a Git remote and cherry-pick the commits you want.

What’s in it

The template is a Next.js app written in TypeScript. It uses Drizzle to talk to Postgres and Vitest for tests.

Scripts

The template pins Node 22 in .tool-versions.

Local and production databases

The same code runs against two different databases:
  • Locally, npm run dev uses an embedded Postgres that runs inside Node and saves to a local.db folder in your project. You don’t need to install Postgres. The folder is in .gitignore.
  • In production, the app connects to its own hosted Postgres database through DATABASE_URL, which Fluid sets for you.
lib/db.ts picks the database for you, and both return the same Drizzle client. Your queries don’t change between the two. Data you create locally never reaches production.

Add a table

The template doesn’t run a migration step. Instead, ensureSchema() in lib/ensure-schema.ts runs CREATE TABLE IF NOT EXISTS statements the first time the app needs the database.
1

Define the table

Add the table to lib/schema.ts with Drizzle’s pgTable.
2

Create it on first use

Add a matching CREATE TABLE IF NOT EXISTS statement to ensureSchema().
3

Call ensureSchema first

Call await ensureSchema() before your route’s first query.
For a larger app, switch to real migrations, such as drizzle-kit, rather than growing ensure-schema.ts. The template creates two tables of its own: companies, with one row per installation of your droplet, and webhooks, an audit log of every webhook the app receives. Keep them.

Extend the app

Handle a webhook event

1

Write the handler

Add a file under lib/handlers/, such as order-created.ts, that exports an async function.
2

Register it

In lib/handlers/index.ts, add registerHandler("order.created", handleOrderCreated).
3

Turn on the webhook

In lib/config/droplet.config.ts, set enabled: true on the matching webhook entry.

Declare what your app registers

lib/config/droplet.config.ts lists everything your app registers with a company when the company installs it. Every entry ships with enabled: false. Turn one on only once the route behind it exists.
lib/config/droplet.config.ts
On install, the app registers each enabled entry for that company and saves the IDs. On uninstall, it removes them.