GenerateSaaS

Tech Stack

Review the full GenerateSaaS stack and the reasoning behind each technology choice.

A Nuxt 4 frontend (apps/web-nuxt) talks to one shared Hono backend (@repo/api); all cross-cutting logic lives in @repo/* workspace packages. Every feature is gated by a flag in @repo/config (packages/config/src/index.ts). Versions below are read straight from the repo's package.json files.

The stack by layer

LayerTechWhy
FrontendNuxt ^4.4.4 + Vue ^3.5.33File-based routing, SSR by default, first-class i18n.
BackendHono RPC (@repo/api)Tiny web-standard router; method-chained routes infer types into the Nuxt client.
AuthBetter Auth (@repo/auth)Always-on plugins: email/password, social OAuth, 2FA, passkeys, API keys, organizations.
BillingStripe or Polar (@repo/payments)Provider chosen by config.payment.provider (default stripe); plugged into Better Auth.
DataDrizzle ORM + Postgres (@repo/database)Type-safe queries/migrations over the pg driver; Postgres is the portable default.
JobsInngest ^4.2.6 (packages/runtime/src/inngest.ts)Durable background jobs, retries, crons - no queue infra to run.
UIshadcn/ui (reka-ui + shadcn-nuxt) + Tailwind CSS v4, Phosphor iconsComponents you own, utility CSS, one icon set (Ph* in Vue).
CacheRedis (ioredis, @repo/runtime)Backs the cache and rate-limiter; TTLs centralized in cacheConfig.
ValidationZod + @hono/standard-validatorOne schema language shared across API routes and forms.
Toolingpnpm 11.1.2 workspaces + Turborepo ^2.9.8Fast installs, shared catalog, cached build/lint/check-types/test.
LanguageTypeScript (strict) + VitestOne language end to end; no any, full type safety from DB to UI.

Frontend details

The Nuxt app is a thin shell over the shared backend and packages.

  • Data fetching: SSR by default via useAsyncData + authClient.useSession(ssrFetch); authClient.useSession() + <ClientOnly> for marketing/user-only UI. See Data fetching.
  • Clients: its own typed Hono client (hc<AppType> in apps/web-nuxt/app/utils/api.ts) and Better Auth client (apps/web-nuxt/app/utils/auth.ts).
  • Platform modules: fonts (@nuxt/fonts), images (@nuxt/image), theming (@nuxtjs/color-mode), SEO (@nuxtjs/seo), and i18n (@nuxtjs/i18n ^10.3.0). See i18n.
  • UI extras: tables use TanStack Table (@tanstack/vue-table), charts use Unovis (@unovis/vue), the editor is Tiptap (@tiptap/vue-3).

Feature flags

Capabilities are toggled in @repo/config (packages/config/src/index.ts), not hard-wired - disabled features are hidden everywhere.

FlagDefaultGates
config.auth.socialProviders["google","github","facebook","discord","x"]Social OAuth providers. See Authentication.
config.payment.provider"stripe"Billing provider - stripe or polar. See Payments.
config.apiDocstrueThe hono-openapi + Scalar reference UI. See API.
config.performanceMonitor.enabledtrueThe Hono request logger.

Backend @repo/* packages target web-standard APIs (crypto.randomUUID, node: imports, Uint8Array) so the same code deploys to Node, Vercel, and Docker. Cloudflare Workers is not a target.

Frequently asked questions

Why Hono instead of a Nuxt server route? Hono gives full RPC type inference into the Nuxt client and keeps the backend portable to a standalone server. Routes must stay method-chained (.get().post()) to preserve that inference.

Can I swap Postgres or Redis? Postgres is the recommended default; Drizzle keeps queries portable, but Postgres-specific features may need adjustment. Redis is not optional - REDIS_URL is a required env var, and Redis backs caching, the rate limiter, and the distributed mutex. See Caching.

Where do exact versions live? In each package.json - apps/web-nuxt/package.json for the frontend and the root package.json for monorepo tooling. Bump them with pnpm add, never by editing the lockfile.

On this page