Tech Stack
Core technologies and architectural decisions for the StarterApp foundation.
The technology stack prioritizes type safety, real-time capabilities, and developer efficiency. Each component addresses specific production requirements while maintaining compatibility with modern development workflows.
AI-First Architecture
The codebase implements context engineering patterns that enable AI-assisted development. Focused file scopes, explicit type contracts, and centralized documentation in /llms/
allow AI agents to generate production-grade code.
Framework and Runtime
Next.js 15
Next.js 15 ↗ provides the application framework with React Server Components as the default rendering strategy. The App Router enables file-based routing with layouts, error boundaries, and loading states. Server Components execute on the server and send rendered HTML with minimal client JavaScript to browsers.
The framework supports parallel routes for concurrent data fetching, streaming with Suspense boundaries, and partial prerendering for static shells with dynamic content. Middleware runs at the edge for security headers and request routing.
export const revalidate = 0;
export const dynamic = "force-dynamic";
export const fetchCache = "force-no-store";
export default async function DashboardPage() {
const session = await getCurrentSession();
// Server Component fetches data server-side
return <DashboardContent session={session} />;
}
React 19
React 19 ↗ powers the component layer with Server Components, the use()
hook for async operations, and improved hydration. Client Components opt in with 'use client'
directives. Server Actions handle mutations without explicit API routes.
TypeScript
TypeScript ↗ enforces compile-time type checking with strict configuration. The compiler prohibits implicit any types, requires explicit return types, and enforces null checking. Type inference flows from Convex schemas through database queries to UI components.
Monorepo Architecture
Turborepo
Turborepo ↗ orchestrates builds with caching and task parallelization. The build system rebuilds only affected packages when files change. Remote caching shares build artifacts across team members.
The monorepo structure separates concerns while enabling code sharing:
apps/marketing
Public-facing marketing site with static CSP and ISR support.
apps/dashboard
Authenticated application with nonce-based CSP and real-time features.
packages/*
Shared libraries for auth, billing, security, UI, and environment configuration.
convex/
Backend data layer with queries, mutations, actions, and schema definitions.
pnpm Workspaces
pnpm ↗ manages package dependencies with content-addressable storage. Workspace packages reference each other through @workspace/*
aliases. The lockfile ensures deterministic installs across environments.
// Workspace imports use aliases, never relative paths
import { getCurrentSession } from "@workspace/app-shell/lib/auth/server";
import { secureUserJson } from "@workspace/security";
import { loadServerEnv } from "@workspace/env/server";
Data Layer
Convex
Convex ↗ provides real-time data synchronization through reactive queries. When data changes, connected clients receive updates without polling. The platform handles WebSocket connections, offline sync, and optimistic updates automatically.
Schema definitions use TypeScript with automatic type generation. Queries and mutations execute as serverless functions with ACID transactions and automatic retries. The system includes built-in pagination, indexing, and search.
Define schema in convex/schema.ts
with table definitions and indexes
Write queries and mutations using builders (userQuery
, userMutation
, userAction
)
Subscribe from components via useQuery(api.namespace.functionName)
Changes propagate instantly to all subscribed clients
Pro Tip
Custom builders in convex/_helpers/builders.ts
auto-inject authentication context and billing integration. Use userQuery
for authenticated reads, userMutation
for writes, and userAction
for external side effects.
Authentication
BetterAuth
BetterAuth ↗ integrates with Convex for session management and OAuth flows. The library stores sessions in Convex tables and provides session validation without external HTTP requests.
Authentication patterns use the getToken(createAuth)
approach for server-side session retrieval. Google OAuth is configured by default.
export async function getCurrentSession(): Promise<UserSession | null> {
const createAuth = await getCreateAuthFunction();
const token = await getToken(createAuth);
if (!token) return null;
const user = await fetchQuery(api.auth.getCurrentUser, {}, { token });
return user ? { user, session: { ... } } : null;
}
Protected Routes
Protected pages must export cache-disabling flags: export const revalidate = 0; export const dynamic = 'force-dynamic'; export const fetchCache = 'force-no-store';
Billing and Payments
UseAutumn + Stripe
UseAutumn ↗ wraps Stripe for subscription management and usage-based billing. The integration provides React hooks for checkout flows and customer portal access. Webhook verification handles payment events with idempotency.
Configuration in autumn.config.ts
defines products, features, and pricing tiers. The npx atmn push
command synchronizes local configuration to the Autumn service.
export const premiumExport = userAction({
args: { format: v.literal("csv") },
handler: async (ctx, args) => {
// ctx.check() and ctx.track() auto-injected by userAction builder
await ctx.check({ featureId: "exports" });
const exportUrl = await generateExport(args.format);
await ctx.track({ featureId: "exports", value: 1 });
return { url: exportUrl };
},
});
Pro Tip
BetterAuth user IDs map directly to Autumn customer IDs without additional identity resolution. The @workspace/auth/server
bridge provides auth.api.getSession()
compatibility for UseAutumn.
Security and Validation
Content Security Policy
Middleware enforces CSP headers with different policies per application:
Zod
Zod ↗ validates data at system boundaries with runtime type checking. Schemas define contracts for user input, API responses, environment variables, and database mutations. Validation errors include detailed messages for debugging.
export const serverEnv = createEnv({
server: {
APP_BASE_URL: z.string().url(),
GOOGLE_CLIENT_ID: z.string().min(1),
GOOGLE_CLIENT_SECRET: z.string().min(1),
BETTER_AUTH_SECRET: z.string().min(1),
},
runtimeEnv: process.env,
});
Styling and UI
Tailwind CSS
Tailwind CSS ↗ provides utility-first styling with automatic class sorting and unused style purging. The configuration supports dark mode through CSS variables without layout shift. Design tokens for spacing, colors, and typography maintain consistency.
Component library in packages/ui/src/components/
uses Radix UI ↗ primitives for accessible, unstyled components. Tailwind utilities apply styling while Radix handles interactions and ARIA attributes.
AI Development Support
The architecture enables AI-assisted workflows through deliberate structural decisions:
AI Workflow Overview
Develop features through AI-assisted patterns using context documents and templates.
Template System
Production-ready code patterns for authentication, billing, and data operations.