I'm building a reusable Next.js boilerplate and am trying to choose an architecture that stays practical without creating duplicate code. In a React and Express project, I typically use Web → API → Service → Repository → Database, which makes it straightforward to replace the web client with Android or iOS later. With Next.js, I'm considering Web → Server Action → Service → Repository → Database using Prisma, and then adding a separate API layer only if another client actually becomes necessary. I'm concerned that supporting both server actions and API routes could mean maintaining two adapters that perform the same work. Do you generally use server actions first, skip them in favor of route handlers, or organize the application another way? Should I follow YAGNI and wait until another client exists before adding an API?
4 Answers
Don’t design around a hypothetical mobile app. Keep the business rules in shared service modules, and make server actions or route handlers thin adapters around those services. If a mobile client or another integration becomes real, add an API at that point instead of maintaining two interfaces from day one.
Next.js is convenient for applications where the UI and backend are closely integrated, but complex API-heavy systems may be clearer as a dedicated backend plus a separate client. Server actions are useful for operations initiated directly by the Next.js UI; route handlers or a standalone API make more sense when the same capabilities must serve mobile apps, third parties, or several frontends.
A layered structure like API → service → repository → database isn’t automatically over-engineering. Keeping persistence behind a repository can make testing and future database changes easier. The important part is to avoid adding layers that don’t provide a clear boundary or benefit in your current application.
For a larger product, a monorepo can work well: separate the web and server apps, then share packages for validation, database access, authentication, API clients, UI components, and utilities. A typed validation layer and a shared API contract are especially useful when multiple clients are expected. I’d still start with only the packages and boundaries you actually need.

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