I'm building a reusable Next.js boilerplate and I'm trying to decide how much architecture to introduce up front. In a React and Express project, I typically use a layered structure like Web → API → Service → Repository → Database, which makes it fairly easy to replace the web client with an Android or iOS app later.
With Next.js, I'm considering using server actions as the web-facing layer: Web → Server Action → Service → Repository → Database, with Prisma handling database access. If mobile clients are added later, I could introduce an API that also calls the same services. My concern is ending up with duplicate logic in server actions and API handlers.
Would it be better to use API routes from the beginning and have both the web and mobile clients consume them? Or should server actions be the default for a web-only application, with an API added only when another client actually becomes necessary? I'm looking for a practical Next.js architecture that stays reusable without being over-engineered.
4 Answers
Don’t design around a hypothetical mobile client. Keep your business rules in shared service modules, and make both server actions and route handlers thin adapters around those services. If another client becomes a real requirement, add an API at that point. That keeps the initial application simple without preventing a clean expansion later.
Next.js doesn’t require you to choose one universal architecture. Server actions are convenient for mutations that belong closely to the web application, while route handlers or a separate API are better when external clients need a stable contract. Either way, put authorization and business logic below those entry points so the choice of transport doesn’t duplicate core behavior.
For a product that genuinely targets web and mobile, a shared workspace can work well: separate client and server applications, shared database and validation packages, a reusable API client, authentication utilities, and common UI components. That approach is useful when multiple clients are already part of the plan, but it’s probably more structure than a web-only project needs on day one.
A layered structure like Web → API → Service → Repository → Database isn’t automatically over-engineering. Small, well-defined abstractions can make testing and future changes easier, especially around data access. The important part is avoiding layers that only pass arguments through without adding a useful boundary.

Related Questions
How To: Running Codex CLI on Windows with Azure OpenAI
Set Wordpress Featured Image Using Javascript
How To Fix PHP Random Being The Same
Why no WebP Support with Wordpress
Replace Wordpress Cron With Linux Cron
Customize Yoast Canonical URL Programmatically