Express backend
The Vite + Node stack — a modular Express + TypeScript API with MongoDB or SQL Server, JWT auth, AI, tRPC, jobs, payments, and an optional Vite React frontend.
The Vite + Node stack generates an Express + TypeScript backend with strict typing, zod validation, and a modular folder layout. Choose it at the first nextron create prompt.
Layouts
- API only — the Express backend at the project root.
- Monorepo — a pnpm workspace with
apps/api(the same Express backend) andapps/web(Vite + React + TypeScript + Tailwind CSS v4). The web dev server proxies/api/*to the backend, so no CORS setup is needed in development.
Web app architecture (monorepo)
The apps/web frontend follows the same separation of concerns as the backend, so components stay thin and API access stays in one place:
apps/web/src/
main.tsx # RouterProvider entrypoint
router.tsx # react-router-dom routes (modules inject here)
shared/
lib/api.ts # the HTTP transport — ONLY services import this
components/Layout.tsx # app shell + nav (modules inject links)
modules/
<feature>/
services/ # all API calls for the feature live here
pages/ # routed pages — call services, never `api` directly
components/ # feature UI
store/ # feature state (e.g. auth)- Never call
api()from a component. Components and pages call a service (modules/<feature>/services/*.service.ts); only services import theapitransport. This keeps request/response shapes, endpoints, and error handling in one testable layer. - Routing is react-router-dom. Modules register their pages at the
nextron:web-route-imports/nextron:web-routesmarkers inrouter.tsxand their nav links at thenextron:web-navmarker inLayout.tsx— the same marker mechanism the backend uses. - The
@/alias maps toapps/web/src(configured invite.config.tsandtsconfig.json). - Auth wires a token provider into the transport, so every request automatically carries
Authorization: Bearer <token>once signed in — services never set it by hand.
Project structure
src/
@types/ # global types + Express Request augmentation (rawBody)
config/ # env.ts (zod-validated), db.ts, payment clients
controllers/ # thin request handlers
enums/ # shared enums (HTTP status, ...)
middlewares/ # error handler, zod validation middleware
models/ # Mongoose models or SQL row types + bootstrap SQL
routes/ # routers, aggregated in routes/index.ts
seeders/ # `pnpm seed` entrypoint + seeders
services/ # business logic — the only layer that touches the database
utils/ # asyncHandler, logger
validations/ # zod schemas + inferred input types
index.ts # bootstrap: env → db → express → graceful shutdownConventions the generated code follows (and that AGENTS.md teaches your coding agent):
- Env vars are accessed only through
src/config/env.ts, validated with zod at startup. - Controllers stay thin; business logic lives in
src/services/. - Every request is validated with the
validatemiddleware and schemas fromsrc/validations/. - New routers are registered in
src/routes/index.tsbetween the// nextron:route-importsand// nextron:route-mountsmarkers —nextron adduses the same markers. - Operational errors throw
AppError; the central error middleware formats every response.
Databases
| Choice | What you get |
|---|---|
| MongoDB | Mongoose connection with lifecycle events, a User model, service, and seeder |
| SQL Server | mssql connection pool, a typed query<T>(sql, params) helper, parameterized SQL service, and a seeder that bootstraps the users table |
Both flavors expose the same service surface (findAll, findById, create, update, remove), so controllers and routes are identical either way.
pnpm seed # seeds sample users (creates the table first on SQL Server)Authentication
Choose JWT at the auth prompt (or add it later with nextron add express-auth) to scaffold email/password authentication. It requires a database module — credentials are stored on the same users store, with a hidden passwordHash field/column added automatically.
| Endpoint | Purpose |
|---|---|
POST /api/auth/register | Create a user ({ name, email, password }) → { token, user } |
POST /api/auth/login | Verify credentials ({ email, password }) → { token, user } |
GET /api/auth/me | Return the current user — requires Authorization: Bearer <token> |
Passwords are hashed with bcrypt; tokens are signed with JWT_SECRET and expire after JWT_EXPIRES_IN (default 7d). Protect any route by adding the authenticate middleware — it verifies the Bearer token and attaches the typed user to req.user.
In a monorepo, the web app also gets an auth service, a reactive store (useAuth), /login and /register pages, and a /dashboard guarded by <ProtectedRoute> — all wired into the router automatically.
import { authenticate } from '../middlewares/auth.middleware.js';
router.get('/me/orders', authenticate, listMyOrders);Payments
Select Stripe and/or Polar during setup, or add them later from the API root:
npx @edwinfom/nextron@latest add stripe-express
npx @edwinfom/nextron@latest add polar-express| Endpoint | Module | Purpose |
|---|---|---|
POST /api/payments/stripe/checkout | stripe-express | Create a Stripe Checkout session |
POST /api/payments/stripe/webhook | stripe-express | Signature-verified Stripe webhook |
POST /api/payments/polar/checkout | polar-express | Create a Polar checkout |
POST /api/payments/polar/portal | polar-express | Create a customer-portal session |
POST /api/payments/polar/webhook | polar-express | Signature-verified Polar webhook |
Webhook signature verification relies on the raw request body, which the base template captures as req.rawBody in src/index.ts.
Other modules
Pick these at the "Additional modules" prompt, or add them later with nextron add <module>:
| Module | Adds |
|---|---|
express-ai | A streaming POST /api/ai/chat endpoint on the Vercel AI SDK. Choose the provider (Anthropic, OpenAI, DeepSeek, Google) at setup; it speaks the AI SDK data-stream protocol, so useChat works on the frontend. |
express-trpc | A tRPC v11 router mounted at /api/trpc via the Express adapter. Export AppRouter and import its type in the web app for an end-to-end typed client. |
express-inngest | Inngest's Express handler at /api/inngest plus an example durable function. Run npx inngest-cli@latest dev for the local dev server. |
Each module registers itself at the nextron: route markers in src/routes/index.ts, adds only the packages and env vars it needs, and follows the same controller/service/validation layout as the rest of the backend.
In a monorepo these modules also add their frontend counterparts to apps/web: express-ai adds a /chat page (built on the AI SDK's useChat), and each payment module adds a checkout service + page (/checkout/stripe, /checkout/polar) — routes and nav links are injected automatically.
Commands
pnpm dev # tsx watch (monorepo: runs api + web in parallel)
pnpm build # tsc → dist/
pnpm start # node dist/index.js
pnpm typecheck # tsc --noEmit
pnpm seed # seed sample dataAdding modules
Modules are stack-aware: Next.js modules (auth, trpc, dashboard, ...) cannot be added to an Express project, and *-express modules cannot be added to a Next.js project. In a monorepo, run nextron add from apps/api, where nextron.config.ts lives.
Project structure
Understand the boundaries and responsibilities in a generated Nextron application.
React Native (Expo)
The Expo stack — a React Native app on Expo SDK 56 with Expo Router and NativeWind, standalone or in a monorepo with the same modular Express backend, plus mobile screens for auth, payments, AI, and tRPC.