← All posts

Adding Drizzle to the TanStack CLI, three databases at once

By ·

Before this, scaffolding a TanStack app gave you no database story at all. You picked your framework, your router, your add-ons — and then wired up persistence by hand, every time.

This added Drizzle ORM as a first-class add-on, with support for Postgres, MySQL, and SQLite.

Why this one was harder than it looks

A CLI add-on isn't a library you import. It's a set of templates that must produce correct, working code for every combination of choices a user can make — and the moment you support three drivers, most of the interesting files stop being static.

Each driver needs its own:

  • client constructionsrc/db/index.ts connects differently per driver
  • schema syntax — Drizzle's column builders are driver-specific; a Postgres schema is not a MySQL schema
  • configdrizzle.config.ts needs the right dialect and credentials shape
  • environment variables — appended to .env.local, and the connection string format differs

Everything became an EJS template branching on the selected driver, plus an info.json describing the add-on to the CLI engine and a package.json.ejs pulling in the right driver package — pg, mysql2, or a SQLite driver — rather than all three.

The demo route mattered

The add-on also ships a working demo route. That sounds cosmetic, but it's the part that proves the scaffold is real: it exercises the client, the schema, and the config together. If any of the three templates got a driver-specific detail wrong, the demo route is where you'd find out — before the user did.

There's an irony here I enjoy: a later PR of mine was about making sure demo files like this one get properly removed when you opt out.

What I'd tell someone writing a CLI add-on

The hard part is not the feature. It's the combinatorics. Every option you add multiplies the states your templates must produce valid output for, and the failure mode is silent — a scaffold that looks fine and doesn't run.

Templating a schema is easy. Templating three schemas that each have to be idiomatic for their dialect is where the actual work is.

Merged as TanStack/cli#207.