Listen to this lesson
Course: Advanced App Building with AI | Pathway: Builder | Tier: Pro | Level: Advanced Estimated Reading Time: 15 minutes
When you built your first AI-powered app, the architecture mostly chose itself. A single Next.js project, one database, a couple of API routes. That works for a prototype. It does not work when you need to ship something that other people depend on.
This lesson covers the decisions you need to make before writing a single line of code — the ones that determine whether your project is pleasant to maintain at six months or a nightmare at three.
These are the choices that experienced developers agonise over. And they are the choices where AI assistants are most likely to mislead you.
A monorepo puts multiple packages or applications in one Git repository. A single app is exactly what it sounds like — one project, one repo.
A practical example: the Lalapanzi.ai platform uses a Turborepo monorepo. The Next.js web app, the UI component library, the database package, and the AI utilities all live in one repository. When someone changes the database schema, they can update the app that uses it in the same commit. No version mismatches. No "which package version is deployed?"
apps/
web/ # Next.js app
packages/
ui/ # Shared components
database/ # Drizzle ORM schema
ai/ # AI utilities
config/ # Shared configuration
Ask Claude or ChatGPT to set up a project and they will often default to whatever is most common in their training data. That means you might get a monorepo when you need a single app, or vice versa. AI assistants are not good at weighing trade-offs that depend on your team size, deployment constraints, and future plans.
The rule: Decide your architecture based on your actual situation. Then tell the AI what you decided. Do not ask the AI to decide for you.
For full-stack web applications in 2026, the realistic options are:
| Framework | Best for | Watch out for |
|---|---|---|
| Next.js (App Router) | Full-stack apps with SSR, API routes, and React | Complexity of server components, caching behaviour |
| Remix / React Router v7 | Apps with heavy form handling and progressive enhancement | Smaller ecosystem than Next.js |
| SvelteKit | Performance-critical apps, smaller bundle sizes | Smaller talent pool, fewer third-party integrations |
| Nuxt (Vue) | Teams already using Vue | Vue ecosystem is strong but narrower |
| Astro | Content-heavy sites with islands of interactivity | Not suited for highly interactive apps |
Next.js has the largest representation in AI training data. When you ask an AI to build a web app, it will almost certainly generate Next.js code. This creates a feedback loop — more people use Next.js with AI, more Next.js code enters training data, AI gets better at Next.js.
This is not a bad thing. Next.js is genuinely capable. But be aware that AI recommendations of Next.js are partly a reflection of training data frequency, not an objective assessment of your needs.
If you are starting a new Next.js project in 2026, use the App Router. The Pages Router still works and is still supported, but new features and improvements go to the App Router. AI assistants sometimes generate Pages Router code because there is more of it in older training data. If you see getServerSideProps or pages/api/, that is Pages Router. Redirect the AI.
The App Router introduces React Server Components (RSC). This is where most developers get confused and where AI-generated code is most likely to be subtly wrong.
Server Components (the default) run on the server. They can:
useState, useEffect, or browser APIsClient Components (marked with 'use client') run in the browser. They can:
// Server Component (default) -- runs on the server
import { db } from '@/lib/database';
export default async function CoursePage() {
const courses = await db.query.courses.findMany();
return (
<div>
{courses.map(course => (
<CourseCard key={course.id} course={course} />
))}
</div>
);
}
// Client Component -- runs in the browser
'use client';
import { useState } from 'react';
export function SearchFilter({ onSearch }: { onSearch: (q: string) => void }) {
const [query, setQuery] = useState('');
return (
<input
value={query}
onChange={(e) => {
setQuery(e.target.value);
onSearch(e.target.value);
}}
/>
);
}
The common AI mistake: Generating a Server Component that uses useState or useEffect. It will compile, but it will crash at runtime or silently fail. Always check that interactive code is in a 'use client' file.
AI coding assistants are transformative for architecture at the implementation level — generating boilerplate, scaffolding routes, writing configuration files. But they are unreliable at the decision level.
For every architectural choice, ask yourself:
Here is a production-ready Next.js App Router structure. This is opinionated — adjust it to your needs — but it covers the common cases:
src/
├── app/
│ ├── (public)/ # Routes that don't require auth
│ │ ├── page.tsx # Homepage
│ │ └── about/
│ ├── (protected)/ # Routes that require sign-in
│ │ └── dashboard/
│ ├── api/ # API routes
│ │ └── webhooks/
│ └── layout.tsx # Root layout
├── components/
│ ├── ui/ # Generic UI components (buttons, cards)
│ ├── layout/ # Nav, footer, sidebar
│ └── features/ # Feature-specific components
├── lib/
│ ├── db.ts # Database client
│ ├── auth.ts # Auth utilities
│ └── ai.ts # AI client setup
├── types/ # TypeScript type definitions
└── middleware.ts # Auth middleware, redirects
The route groups (public) and (protected) are a Next.js convention. The parentheses mean the folder name does not appear in the URL — it is purely for organisation and applying different layouts or middleware.
Take an app idea you want to build (or one you have already started). Write a one-page architecture document that answers:
Do not use AI for this exercise. The point is to practise making these decisions yourself.
1. When should you use a monorepo?
a) Always, because it is more professional b) When you have multiple packages that share code and you want atomic changes across them c) When AI recommends it for your project
Answer: b) Monorepos add value when packages share code (types, utilities, components) and you want to change them together. They add overhead otherwise.
2. What is the most common AI mistake with React Server Components?
a) Generating too many components b) Using hooks like useState or useEffect in a Server Component c) Making components too small
Answer: b) Server Components cannot use React hooks or browser APIs. AI assistants frequently generate Server Components with client-side code, which will fail at runtime.
3. For architectural trade-off decisions (e.g., which database to use), you should:
a) Ask the AI to recommend the best option b) Make the decision yourself based on your constraints, then use AI to implement it c) Always pick the most popular option
Answer: b) AI does not know your budget, team skills, deployment environment, or user base. Trade-off decisions require context that only you have. Use AI for implementation once you have decided.