StarterApp Docs

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.

apps/dashboard/app/(dashboard)/page.tsx
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:

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.

Import Pattern
// 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.

packages/app-shell/src/lib/auth/server.ts
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.

convex/_helpers/builders.ts Integration
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.

packages/env/src/server.ts
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:

Additional Tooling