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
| Layer | Tech | Why |
|---|---|---|
| Frontend | Nuxt ^4.4.4 + Vue ^3.5.33 | File-based routing, SSR by default, first-class i18n. |
| Backend | Hono RPC (@repo/api) | Tiny web-standard router; method-chained routes infer types into the Nuxt client. |
| Auth | Better Auth (@repo/auth) | Always-on plugins: email/password, social OAuth, 2FA, passkeys, API keys, organizations. |
| Billing | Stripe or Polar (@repo/payments) | Provider chosen by config.payment.provider (default stripe); plugged into Better Auth. |
| Data | Drizzle ORM + Postgres (@repo/database) | Type-safe queries/migrations over the pg driver; Postgres is the portable default. |
| Jobs | Inngest ^4.2.6 (packages/runtime/src/inngest.ts) | Durable background jobs, retries, crons - no queue infra to run. |
| UI | shadcn/ui (reka-ui + shadcn-nuxt) + Tailwind CSS v4, Phosphor icons | Components you own, utility CSS, one icon set (Ph* in Vue). |
| Cache | Redis (ioredis, @repo/runtime) | Backs the cache and rate-limiter; TTLs centralized in cacheConfig. |
| Validation | Zod + @hono/standard-validator | One schema language shared across API routes and forms. |
| Tooling | pnpm 11.1.2 workspaces + Turborepo ^2.9.8 | Fast installs, shared catalog, cached build/lint/check-types/test. |
| Language | TypeScript (strict) + Vitest | One 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>inapps/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.
| Flag | Default | Gates |
|---|---|---|
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.apiDocs | true | The hono-openapi + Scalar reference UI. See API. |
config.performanceMonitor.enabled | true | The 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.