DocsChoosing A Stack

Open documentation actions

Choosing a Stack

Pick a frontend, backend, database and ORM, auth provider, and deployment target, and see which choices constrain the others.

Five choices shape a stack: frontend, backend, database with ORM, auth provider, and deployment target. Each one narrows the rest. The Stack Builder and the CLI reject combinations that do not work, so they decide the exact matrix; this page explains how to pick deliberately.

Frontend

FamilyFrameworksChoose it when
React SPAtanstack-router, react-router, react-viteYou want client-rendered React with a separate backend.
React fullstacknext, tanstack-start, vinext, redwoodYou want SSR or RSC in one deployable unit.
Vue / NuxtnuxtYou prefer Vue with an integrated server.
Svelte / Solidsvelte, solid, solid-startYou want compiler-first frameworks with fine-grained reactivity.
Content / edgeastro, qwik, freshYou lead with content or want minimal client JavaScript.
AngularangularYou want Angular's batteries-included framework and built-in HttpClient.

Four constraints come from the frontend:

  • tRPC only works with React-based frontends. Use --api orpc for Nuxt, Svelte, Solid, and SolidStart.
  • --backend self pairs with fullstack frontends (next, vinext, tanstack-start, astro, nuxt, svelte, solid-start) and requires --runtime none.
  • Qwik ships its own server, so it takes --backend none --api none. Angular takes --api none.
  • Astro needs --astro-integration <react|vue|svelte|solid|none>. Workers support depends on the pair you choose.

Unsure? Take tanstack-router with a hono backend. That is the scaffolded default and works across runtimes.

Backend

BackendCharacterNote
honoSmall, fast, runs on Bun, Node, and Workers.The default; broadest runtime support.
expressThe classic Node framework.Largest ecosystem, Node runtime.
fastifyHigh-throughput Node framework with schemas.Good for JSON APIs.
elysiaBun-first framework with end-to-end types.Best on the Bun runtime.
fetsFetch-API framework with OpenAPI.Standards-based handlers.
effectEffect-based HTTP platform.Pairs with the --effect capability flags.
nestjsOpinionated, decorator-driven framework.Requires --runtime node.
adonisjsFull MVC framework with its own tooling.Requires --runtime node.
nitroUniversal server toolkit.Deploys to many targets.
encoreBackend framework with built-in infrastructure.Encore.ts workflow.
convexReactive backend-as-a-service.Owns database and API choices and auto-adjusts them.
selfThe frontend serves its own API.Needs --runtime none and a fullstack frontend.

Start with hono for portability, elysia if you are all-in on Bun, nestjs or adonisjs for structured Node apps, and convex when you want managed realtime data. You can also layer Effect onto another backend with --effect effect or --effect effect-full.

Database and ORM

--database accepts sqlite, postgres, mysql, mongodb, edgedb, redis, or none. Relational engines cover most apps; pick Postgres unless you have a reason not to.

ORMSQLitePostgresMySQLMongoDB
drizzleYesYesYesNo
prismaYesYesYesYes
kyselyYesYesYesNo
mikroormYesYesYesNo
typeormYesYesYesNo
sequelizeYesYesYesNo
mongooseNoNoNoYes

MongoDB pairs with prisma or mongoose. --db-setup layers hosted configuration onto the engine choice: Turso, Neon, Prisma Postgres, PlanetScale, MongoDB Atlas, Supabase, Upstash, Cloudflare D1, or Docker. Create the database in the provider's dashboard, then paste its connection string into .env.

Auth

ProviderHostingNote
better-authSelf-hostedOwns tables in your database; needs a compatible ORM.
better-auth-organizationsSelf-hostedBetter Auth plus organizations and teams plugin.
nextauthSelf-hostedAuth.js; strongest fit for Next.js.
clerkHostedDrop-in components and hosted user management.
stack-authHostedGenerous free tier.
supabase-authHostedPairs naturally with Supabase Postgres.
auth0Hosted IdPEnterprise identity provider.
workosHosted IdPAuthKit and enterprise SSO.
kindeHosted IdPHosted auth and feature flags.

Three pairing rules matter:

  • Better Auth needs an adapter. It works with drizzle, prisma, kysely, and mongoose; mikroorm, typeorm, and sequelize have none, so pair them with --auth none.
  • Some payments require it too. Polar needs Better Auth plus a web frontend.
  • Hosted providers read keys from environment variables, and the scaffold writes every required key into .env.example.

Own the data with better-auth when you already use a supported ORM. Take clerk or stack-auth for the fastest hosted setup and auth0, workos, or kinde when enterprise SSO decides.

Other ecosystems expose native helpers instead: Go uses --auth go-better-auth or --go-auth, Python uses --python-auth, Rust uses --rust-auth, Java uses --java-auth, and Elixir uses --elixir-auth.

Deployment

Deployment is a stack section, not a separate step. --web-deploy and --server-deploy control whether platform files are emitted during creation:

FlagValues
--web-deployvercel cloudflare fly railway render netlify docker sst none
--server-deployvercel cloudflare fly railway render netlify docker sst none
TargetBest fit
DockerSelf-hosting, reproducible production images, local service orchestration.
VercelSupported React, Nuxt, SvelteKit, Solid, and serverless deployments.
CloudflareWorkers runtime stacks and edge-first Hono servers.
Fly.ioDocker-backed hosting with regional placement and long-running services.
RailwayGit-connected builds with managed services.
RenderBlueprint-driven deploys via render.yaml; web and server deploy separately.
NetlifyStatic and SSR web frontends, or Hono APIs running on Node.js Functions.
SSTAWS infrastructure as code for TypeScript workflows.

Fullstack frontends usually deploy through the web app rather than a separate server target, and Convex or Encore manage their own platform path. Before deploying, set production environment variables, run migrations against the production database, and keep test credentials out of source control.

To change a target on an existing project, run add --dry-run --web-deploy <target> or the --server-deploy equivalent and review the plan first. See Add and Remove Capabilities.

Every accepted value lives in the generated tables on CLI Create.

GitHub Sponsors