Enterprise

AI Rules for Fullstack Teams

Fullstack teams own the entire stack from database to UI. AI rules must encode the boundaries between layers, shared type safety, API contract patterns, and the conventions that prevent full-stack features from becoming unmaintainable.

6 min read·July 5, 2025

Fullstack teams own every layer. AI rules enforce boundaries so features stay organized from database to UI.

Shared types, tRPC contracts, server/client boundaries, service layers, and optimistic updates

Fullstack: One Team, Every Layer

Fullstack teams build features from database to UI: data model, API endpoint, business logic, and frontend component — all in one PR. The advantage: one team owns the full feature. The risk: without clear boundaries, fullstack code becomes tangled — frontend logic leaks into the backend, backend types are duplicated in the frontend, and a change in one layer breaks another. AI rules for fullstack teams enforce: clear layer separation, shared types across the stack, and consistent patterns at each layer.

The modern fullstack stack: Next.js (App Router with Server Components, Server Actions, and API routes), Remix (loaders and actions), SvelteKit (server load functions), or Nuxt (server routes and composables). These frameworks blur the line between frontend and backend — Server Components run on the server but look like React components. AI rule: 'Understand the framework's server/client boundary. Next.js: Server Components (server-only), Client Components (browser), Server Actions (server functions called from the client). Generate code on the correct side of the boundary.'

The fullstack AI rules: types are defined once and shared, API contracts are explicit (tRPC, Zod schemas, or OpenAPI), business logic lives in a separate layer (not in components or API handlers), and database queries never run in client code.

Shared Types and API Contracts

Type safety across the stack: in a TypeScript fullstack app, the same types should describe: the database schema (Drizzle/Prisma types), the API request/response (inferred from the schema or defined as shared types), and the frontend props (derived from the API response). AI rule: 'Define types once. Drizzle: export the inferred type (typeof articles.$inferSelect). Use that type in the API handler and the frontend component. Never re-define the same shape in multiple places. Type changes propagate automatically across the stack.'

tRPC pattern: end-to-end type safety without code generation. The backend defines procedures with input/output schemas (Zod). The frontend calls procedures with full type inference. AI rule: 'tRPC project: define procedures in the router. Use Zod for input validation. The client gets full type safety automatically. Never bypass tRPC with raw fetch calls — that loses type safety. The AI generates tRPC procedures for new endpoints, not REST routes.'

For non-tRPC projects: use Zod schemas as the single source of truth. Define the schema once (shared/schemas/user.ts), use it for: API input validation (parse the request body), API response typing (infer the TypeScript type from the schema), and frontend form validation (same schema validates client-side). AI rule: 'Zod schemas in a shared directory. Used by both server and client. One schema = one source of truth for the data shape.'

💡 One Zod Schema = Three Validations

Define a Zod schema once: const userSchema = z.object({ name: z.string().min(1), email: z.string().email() }). Use it for: (1) client-side form validation (instant feedback), (2) server-side API validation (security), (3) TypeScript type inference (type User = z.infer<typeof userSchema>). One schema, three uses, zero duplication. When the schema changes: all three update automatically. The AI should always generate shared schemas, not duplicate validation logic.

Layer Boundaries and Data Flow

Server vs client boundary: AI rule: 'In Next.js App Router: Server Components are the default (server-rendered, no client JavaScript). Add "use client" only when the component needs: browser APIs, event handlers (onClick, onChange), state (useState), or effects (useEffect). The AI should generate Server Components by default and only add "use client" when required. This minimizes client-side JavaScript.'

Business logic layer: AI rule: 'Business logic (validation, calculations, transformations, authorization) lives in a separate layer — not in API handlers and not in UI components. Pattern: handlers call service functions, services contain business logic, services call repositories for data access. The AI generates: thin handlers (parse input, call service, format response), service functions (business logic), and data access functions (database queries). This separation makes business logic testable without HTTP or UI.'

Data flow: AI rule: 'Data flows in one direction: database → server → client. The client never directly queries the database. Server Actions and API routes are the boundary. The client sends user input to the server, the server validates and processes it, and the server returns the result. The AI must never generate database imports or queries in client components or files without "use server" directives.'

⚠️ Database Queries in Client Components = Security Breach

In Next.js: importing a database client in a file without 'use server' can accidentally expose the database connection to the client bundle. The AI must ensure: database imports only exist in server-only files (Server Components, Server Actions, API routes). Client Components (files with 'use client') must never import database modules. Use the server-only package to enforce this: import 'server-only' at the top of files that should never be bundled for the client.

Fullstack Feature Development Patterns

Feature structure: AI rule: 'Fullstack features organized by domain: features/users/ contains: schema.ts (Zod schema, shared), service.ts (business logic, server), api.ts or route.ts (API handler, server), and components/ (UI components, client). All related code in one directory. The AI generates the full feature structure when creating a new feature, not just one layer.'

Form handling: the most common fullstack pattern. AI rule: 'Form data flow: client (form component with validation) → server (Server Action or API endpoint with same Zod validation) → database (validated data inserted/updated). Client-side validation: for instant UX feedback. Server-side validation: for security (client validation can be bypassed). Same Zod schema for both. The AI generates both client and server validation from the shared schema.'

Optimistic updates: update the UI immediately, then sync with the server. If the server rejects the update: revert the UI. AI rule: 'For actions where latency matters (like, bookmark, toggle): use optimistic updates. Pattern: update the UI state immediately, send the request to the server, if the server returns an error: revert the UI state and show an error message. TanStack Query: useMutation with onMutate (optimistic update) and onError (rollback). The AI generates optimistic patterns for user-facing actions where instant feedback matters.'

ℹ️ Feature Folders Keep Fullstack Changes in One PR

With layer-based folders (api/users.ts, components/UserProfile.tsx, schemas/user.ts): a fullstack feature change touches 3+ directories. PR reviews hop between unrelated files. With feature folders (features/users/ containing schema.ts, service.ts, api.ts, UserProfile.tsx): the entire feature is in one directory. The PR changes are co-located. Reviewers see the full picture. Deleting a feature: remove one folder.

Fullstack AI Rules Summary

Summary of AI rules for fullstack teams building end-to-end features.

  • Shared types: define once (Zod schema or Drizzle inferred type). Used by server and client
  • tRPC: end-to-end type safety. Procedures with Zod input. Never bypass with raw fetch
  • Server Components: default in Next.js. Add 'use client' only when browser APIs needed
  • Business logic: separate service layer. Not in handlers, not in components. Testable independently
  • Data flow: database → server → client. Client never queries database directly
  • Feature structure: organized by domain. Schema + service + API + components in one directory
  • Forms: same Zod schema for client and server validation. Both are required
  • Optimistic updates: instant UI feedback for user actions. Revert on server error