--- name: frontend-architecture description: How to organize frontend code — separation of concerns (UI / logic / data / type), file responsibility, state tiers, API services, schema validation, and framework conventions for React/Next and Vue. Structural rules, not visual design. when_to_use: "When structuring a frontend codebase or reviewing how frontend code is organized — where logic, API calls, state, types, and validation should live; component vs hook/composable boundaries; Next.js server/client split; Vue Composition API. NOT for visual design (use frontend-design) and NOT for React/Next performance rules (use nextjs-react-expert)." allowed-tools: Read, Write, Edit, Glob, Grep --- # Frontend Architecture > How to organize frontend code so it scales. Separation of concerns over file-type folders. > Applies to React/Next and Vue. For directory layout, follow [app-builder](../app-builder/scaffolding.md). For visual design, see [frontend-design](../frontend-design/SKILL.md). For React/Next performance, see [nextjs-react-expert](../nextjs-react-expert/SKILL.md). --- ## 1. Separation of Concerns — the core rule Split code into four layers by responsibility. A unit of code does ONE of these, not several: | Layer | Holds | Lives in | |-------|-------|----------| | **UI** | Rendering, markup, presentational state | `components/` | | **Logic** | State, effects, data transforms, reusable UI logic | `hooks/` (React) · `composables/` (Vue) | | **Data** | API calls, fetch/axios, cache keys | `lib/` / service files (`*.api.ts`) | | **Type** | TypeScript types, domain models | `types.ts` / `*.types.ts` | | **Validation** | Form/data schemas | `*.schema.ts` (zod/yup/valibot) | > **Directory layout** (top-level folders) follows the project's scaffolding skill — do not invent a competing structure here. This skill is about *which layer code belongs to*, not where the folders sit. --- ## 2. File Responsibility & Size One clear responsibility per file. Size is a **signal, not a hard limit** — a clear 230-line file beats a 90-line file that fetches, validates, renders, and juggles modals + toasts. | File type | Comfortable range | |-----------|-------------------| | UI component | 80–180 lines | | Page / screen | 100–220 lines | | Hook / composable | 40–150 lines | | API service | 50–200 lines | | Type / schema | flexible | Split a file when it mixes UI + API + business logic + validation + state. Don't split a coherent file just to hit a number. --- ## 3. Components render UI; logic goes elsewhere Components should primarily render. Push fetching/state/transforms into a hook or composable. ```tsx // ❌ Component owns the data layer function ProductList() { const [products, setProducts] = useState([]) useEffect(() => { fetch('/api/products').then(r => r.json()).then(setProducts) }, []) return