nextjs-architecture
Next.js Architecture Enforcement
<output_language>
Default all user-facing deliverables, saved artifacts, reports, plans, generated docs, summaries, handoff notes, commit/message drafts, and validation notes to Korean, even when this canonical skill file is written in English.
Preserve source code identifiers, CLI commands, file paths, schema keys, JSON/YAML field names, API names, package names, proper nouns, and quoted source excerpts in their required or original language.
Use a different language only when the user explicitly requests it, an existing target artifact must stay in another language for consistency, or a machine-readable contract requires exact English tokens. If a localized template or reference exists (for example *.ko.md or *.ko.json), prefer it for user-facing artifacts.
</output_language>
Overview
Enforces official Next.js architecture rules before code changes. Validate that the target is actually a Next.js project, determine whether App Router is in use, then apply strict rules for routing, Server and Client Component boundaries, server-first data fetching, Server Actions, Route Handlers, Proxy, and environment setup.
This skill is official-first. Treat the Next.js documentation as the source of truth. If a repo-local convention is stricter than the framework, label it clearly instead of silently presenting it as a framework rule.
OPERATING MODE: This skill is self-contained. Do not block on external orchestration just to apply architecture rules. If the user wants exhaustive verification, keep verifying. Otherwise proceed with this skill's own validation flow.
IMPORTANT: App Router is the default path for this skill. If the repo is Pages Router only, apply only the shared platform and boundary checks and do not force App Router-only file conventions unless the user is migrating or explicitly adding app/.
IMPORTANT: Prefer Server Actions for internal UI writes, especially forms and app-originated mutations. Use Route Handlers when the surface is genuinely HTTP-native, such as webhooks, feeds, CORS-sensitive endpoints, or machine-readable/public endpoints.
IMPORTANT: Treat every Server Action as a reachable POST entry point. Validation, authentication, authorization, and return-value filtering must happen inside the action or the delegated server-only data layer, not only in the page that renders the form.
Quick Surface Chooser
Use this table before reading the full gates:
| If the task sounds like... | Default surface | Do not default to... |
|---|---|---|
Add a form or internal app mutation in App Router |
Server Action | route.ts |
Add a webhook, feed, CORS endpoint, or public machine-readable endpoint |
Route Handler | Server Action |
Fetch initial page data for UI |
Server Component | Client-first fetching without a real need |
Need redirect logic before render across many requests |
next.config.* or Proxy, with Proxy last |
Server Action |
Client Component imports DB code or private env |
move the code behind a server-only boundary | leaving secrets in client-reachable code |
Pages Router only repo and no migration requested |
shared Next.js safety checks only | forcing App Router file conventions |
If the task matches one of these rows, start there, then read the linked rule file in Step 2 for detail.
Trigger Examples
Positive
Audit this Next.js app before I add more App Router routes.Refactor a Next.js feature so Server Components, client boundaries, caching, and server actions follow the official docs.Add a Next.js Route Handler or Server Action and keep the architecture compliant.
Negative
Create a generic React architecture guide.Review a Remix or TanStack Start app.
Boundary
-
Make a tiny copy-only text change in a Next.js page.Direct editing can be enough if no architectural boundary is affected, but touched files still need a quick boundary check. -
This repo is Pages Router only and I am not migrating to App Router.This skill still applies for shared Next.js platform, env, and boundary checks, but App Router-specific file rules must be relaxed.
Step 1: Project Validation
Before any work, confirm a Next.js project and detect router mode:
rg -n '"next"' package.json
find . -maxdepth 3 \( -path './app' -o -path './src/app' -o -path './pages' -o -path './src/pages' \)
test -f next.config.ts -o -f next.config.mjs -o -f next.config.js
Interpretation:
- No
nextdependency found: stop, this skill does not apply. app/orsrc/app/present: full App Router mode.pages/orsrc/pages/present without App Router: shared Next.js mode only.- Mixed
app/andpages/: prefer App Router rules for touchedapp/code and avoid breaking legacypages/code without explicit migration intent.
Step 2: Read Architecture Rules
Load the detailed rules reference:
REQUIRED: Read architecture-rules.md in this skill directory before writing code.
Then read the relevant rule files for the change:
rules/routes.md- App Router structure, special files, route groups, private folders, and segment boundariesrules/execution-model.md- Server vs Client Components,use client, providers, serializable props, andserver-onlyrules/data-fetching.md- server data fetching, streaming, cache intent, dynamic rendering triggers, and revalidationrules/server-actions.md-use server, validation, auth, authz, DAL delegation, revalidation, redirect ordering, and side-effect rulesrules/route-handlers.md- whenroute.tsis justified, method handling, caching defaults, and HTTP-only surfacesrules/platform.md- environment variables,next.config.*,typedRoutes, Proxy, and deployment-sensitive setup
If framework behavior may have drifted, also read:
references/official/nextjs-docs.md- official doc map for the rules this skill depends on
Step 3: Pre-Change Validation Checklist
Before writing any code, verify the planned change against these gates:
Brownfield Adoption Rule
- Do not treat every untouched legacy deviation as an immediate project-wide failure.
- Safety and boundary issues still block immediately, especially in touched files.
- Legacy
pages/code can remain in place when the task is local and non-migratory. - Any file you touch should be brought into compliance unless that would require a materially risky migration.
Gate 1: Routing and File Conventions
| Check | Rule |
|---|---|
page.tsx, layout.tsx, loading.tsx, error.tsx, not-found.tsx, or route.ts placed outside the expected segment structure? |
BLOCKED |
route.ts and page.tsx created at the same route segment? |
BLOCKED |
App Router feature work done in pages/ even though app/ already exists for that surface? |
BLOCKED unless explicitly requested |
| Route groups or private folders used without understanding URL impact? | WARNING. (group) does not affect URL, _folder stays private |
| Segment needs loading/error/not-found UX but no boundary exists? | WARNING. Add loading.tsx, error.tsx, or not-found.tsx intentionally |
Gate 2: Server and Client Boundaries
| Check | Rule |
|---|---|
Interactive component missing 'use client'? |
BLOCKED |
'use client' added high in the tree without need? |
BLOCKED. Keep client boundaries as narrow as possible |
Client Component imports server-only code, secrets, DB clients, or process.env private values? |
BLOCKED |
Server-only helper missing import 'server-only' or equivalent protected placement? |
WARNING. Add a clear server-only boundary |
| Client Component props include broad DB records or non-serializable values? | BLOCKED |
| Context provider placed at the document root when a deeper boundary works? | WARNING. Render providers as deep as possible |
Gate 3: Data Fetching and Caching
| Check | Rule |
|---|---|
| Initial page data fetched in a Client Component when a Server Component can do it? | BLOCKED unless there is a real client-only need |
Layout reads uncached runtime data and blocks same-segment loading.tsx without a closer <Suspense> boundary? |
BLOCKED |
| Cache behavior is accidental or unclear? | BLOCKED. Choose and explain the cache strategy |
| Sensitive or privileged reads happen outside a DAL/server-only module without justification? | WARNING for prototypes, BLOCKED for production-oriented code |
Mutation completes without revalidatePath, revalidateTag, redirect, or another freshness strategy where the UI depends on new data? |
BLOCKED |
Gate 4: Server Actions
| Check | Rule |
|---|---|
Internal UI mutation or form submit implemented with route.ts even though a Server Action fits? |
BLOCKED unless real HTTP semantics are required |
| Action trusts form data, params, headers, or search params without validation or re-verification? | BLOCKED |
| Action relies only on page-level auth checks? | BLOCKED. Re-authorize inside the action |
| Action returns raw database rows or broad internal objects? | BLOCKED |
| Action performs DB or secret-heavy work directly when a server-only DAL exists or should exist? | WARNING for small code, BLOCKED for repeated domain logic |
Action mutates during rendering instead of from an explicit action path (form, event, transition)? |
BLOCKED |
redirect() called before required revalidation? |
BLOCKED. Revalidate first, then redirect |
Gate 5: Route Handlers and Proxy
| Check | Rule |
|---|---|
Internal UI mutation implemented as route.ts even though a Server Action fits better? |
BLOCKED unless real HTTP semantics are required |
| Route Handler used for webhooks, feeds, CORS, or public machine endpoints? | ALLOWED |
Route Handler uses NextResponse.next() to forward like Proxy? |
BLOCKED |
Proxy added when redirects, rewrites, headers, or render-time logic would be enough? |
BLOCKED. Proxy is last resort |
proxy.ts not placed at project root or src/ root level next to app or pages? |
BLOCKED |
| Proxy matcher is missing or too broad for the actual need? | BLOCKED |
Gate 6: Platform and Environment
| Check | Rule |
|---|---|
.env* files assumed to load from src/? |
BLOCKED. They belong at project root |
Client code reads non-NEXT_PUBLIC_ env vars? |
BLOCKED |
| Runtime client env needed but treated as build-time inlined config? | BLOCKED. Expose via server path/API instead |
Multi-proxy or reverse-proxy deployment uses Server Actions without checking serverActions.allowedOrigins needs? |
WARNING |
| Next config toggles caching, routing, or server action behavior without clear intent? | BLOCKED |
Typed route safety would materially reduce routing mistakes but typedRoutes is ignored in a TypeScript codebase? |
WARNING. Consider enabling it intentionally |
Step 3.5: Auto-Remediation Policy
Auto-fix directly when the issue is local, reversible, and low-risk.
- narrow an overly broad
'use client'boundary - add
loading.tsx,error.tsx, ornot-found.tsxfor a touched segment - move privileged reads into a server-only helper or DAL
- add
server-onlymarkers and tighten client props - add missing revalidation after a Server Action mutation
- move a misused internal
route.tsmutation to a Server Action when the change is small and local - tighten Proxy matcher scope or move simple redirects into
next.config.* - correct
.env/NEXT_PUBLIC_usage and explicit config wiring
Do not auto-apply broad or potentially breaking migrations without explicit justification.
- mass route tree rewrites
- Pages Router to App Router migrations across large surfaces
- sweeping cache model changes
- turning many Route Handlers into Server Actions in one pass
- deployment-sensitive Server Action origin or encryption-key changes
Step 4: Implementation
Carry these acceptance criteria into the active task:
- [ ] Next.js project mode validated before editing
- [ ] App Router rules applied only where they actually fit
- [ ] Routing files live in the correct route segment structure
- [ ] Server and Client Component boundaries are explicit and minimal
- [ ] Client code cannot reach server-only data, env, or modules
- [ ] Data fetching and caching strategy is intentional
- [ ] Server Actions are the default surface for internal UI writes
- [ ] Server Actions validate input, re-authorize, and return minimal data
- [ ] Route Handlers exist only for real HTTP-native needs
- [ ] Proxy is used only when simpler surfaces are insufficient
- [ ] Environment handling and next.config setup are boundary-safe
Step 5: Post-Change Verification
After writing code, verify:
- project mode still matches the edited surface (
app/,pages/, or mixed) - route segment file placement is valid
'use client'boundaries are as small as possible- client code does not import server-only modules or private env
- data freshness after mutations is explicit (
revalidatePath,revalidateTag, redirect flow, or documented alternative) - Route Handlers and Proxy usage are still justified
next.config.*, env loading, and deployment-sensitive settings remain coherent
Quick Reference: App Router Shape
app/
├── layout.tsx
├── page.tsx
├── dashboard/
│ ├── page.tsx
│ ├── loading.tsx
│ ├── error.tsx
│ ├── not-found.tsx
│ ├── _components/
│ └── _lib/
├── api/
│ └── webhooks/
│ └── route.ts
└── (marketing)/
└── about/
└── page.tsx
Key meaning:
(group)organizes routes without affecting the URL_folderis a private implementation folder and does not become a route segmentroute.tsis for HTTP handling, not page UIloading.tsx,error.tsx, andnot-found.tsxare route-segment boundaries, not general-purpose components
More from alpoxdev/hypercore
bug-fix
[Hyper] Analyze bugs, present repair options, then implement and verify the user-selected fix path. Routes simple bugs directly; tracks complex multi-phase investigations via .hypercore/bug-fix/ JSON flow.
47tanstack-start-architecture
[Hyper] Enforce TanStack Start architecture in existing Start projects, especially route structure, server functions, loader/client-server boundaries, importProtection, hooks, SSR/hydration, and hypercore conventions. Use before structural code changes, route work, server function work, or architecture audits in TanStack Start codebases.
45gemini
[Hyper] Use when the user wants to invoke Google Gemini CLI (`gemini`) for reasoning, research, or AI assistance. Trigger phrases: \"use gemini\", \"ask gemini\", \"run gemini\", \"call gemini\", \"gemini cli\", \"Google AI\", \"Gemini reasoning\", or when users request Google's Gemini models, research with web search, plan-mode review, or want to resume a previous Gemini session. Do not use for generic writing, runbook cleanup, or local edits that do not require the Gemini CLI.
45crawler
[Hyper] Investigate websites with Playwriter plus CDP to choose a crawl strategy, capture API/auth evidence, document findings under `.hypercore/crawler/[site]/`, and generate crawler code only after discovery is grounded.
45research
[Hyper] Produce a multi-source, source-backed markdown research report for fact-finding, comparisons, market/trend analysis, or evidence-backed recommendations across live web, official docs, GitHub, and local repo sources. Use when synthesis and citations are needed, not for one-source lookups.
45genius-thinking
[Hyper] Generate and prioritize differentiated ideas for stuck product, strategy, or innovation problems when ordinary brainstorming is too shallow. Saves structured multi-file analysis under .hypercore/genius-thinking/[topic-slug]/ with phase tracking.
44