Next.js gives you a lot of freedom in how you organise things, which is great until you're staring at a messy project wondering where anything lives. Here's the structure I've settled on after building enough projects to know what causes problems.
App router vs pages router
I use the App Router — the newer system introduced in Next.js 13 and properly stable by 15. It uses a folder-based routing system inside the app directory where each folder is a route segment and each page.tsx is the component that renders at that route. Server components by default, client components when you need interactivity. It takes some getting used to but the mental model is cleaner once it clicks.
My folder structure
src/ ├── app/ │ ├── (auth)/ │ │ ├── login/ │ │ └── register/ │ ├── dashboard/ │ ├── api/ │ └── layout.tsx ├── components/ │ ├── ui/ │ └── shared/ ├── lib/ │ ├── db.ts │ ├── auth.ts │ └── utils.ts ├── hooks/ └── types/
Why this layout
The app directory handles routing. Components are split between ui (generic reusable bits like buttons and inputs) and shared (things that are reused but more specific to the project). The lib folder is where all the utility logic lives — database connection, auth helpers, anything that isn't a component. types for TypeScript type definitions. Clean separation that scales without becoming a mess.
(auth) — let you organise routes into groups without affecting the URL. Useful for applying shared layouts to a subset of pages without it showing up in the path.
API routes
For projects with a Rust/Axum backend, the Next.js API routes are mostly just thin proxies. For projects where Next.js is doing everything, I put API handlers in app/api/ using Route Handlers. Each endpoint gets its own folder with a route.ts file — keeps things tidy and easy to find.
TypeScript everywhere
Always TypeScript, never plain JavaScript. The extra setup is trivial and the payoff in caught errors and editor support is enormous. If you're starting a new Next.js project and reaching for .js files, stop. Use TypeScript from day one.