frontend-structure-standards
GitHub定义前端项目结构标准,指导文件夹布局、模块边界划分及文件分解。规范基于领域驱动的组织方式,明确API、组件、页面、Hook和类型的存放位置,确保代码的可维护性与可扩展性。
Trigger Scenarios
Install
npx skills add AjayIrkal23/agentic-mercy-10x --skill frontend-structure-standards -g -y
SKILL.md
Frontmatter
{
"name": "frontend-structure-standards",
"schema": 1,
"category": "backend",
"surfaces": [
"backend"
],
"triggers": {
"paths": [
"\/router\/",
"\/routes\/",
"\/store\/",
"reducer.",
"redux",
"route.ts",
"route.tsx",
"routes.ts",
"selector.",
"slice.",
"src\/schemas\/",
"src\/types\/"
],
"intents": [
"backend"
],
"keywords": [
"app-owned",
"boundaries",
"component",
"decisions",
"decomposition",
"file",
"folder",
"frontend",
"hook",
"layout",
"live",
"maintainable",
"module",
"modules",
"needs",
"organize",
"plan",
"should",
"standards",
"structure",
"types",
"work"
]
},
"platforms": [
"linux",
"darwin",
"windows"
],
"token-cost": 2585,
"description": "ALWAYS invoke when frontend work needs decisions about folder layout, module boundaries, file decomposition, or where app-owned frontend types should live. MUST use to plan frontend component, hook, and module boundaries and organize maintainable frontend modules.",
"disable-model-invocation": false
}
FRONTEND STRUCTURE STANDARDS
- OBJECTIVE
- Maintain clean, scalable, production-grade code
- Preserve business logic and existing patterns
- Ensure maintainability, performance, and correctness
- MODULARITY RULES
- Files should remain small and focused
- When a file grows large:
- Extract UI subcomponents
- Extract hooks for logic
- Extract helpers/utilities
- Parent components should orchestrate, not contain heavy logic
- PROJECT STRUCTURE
Use domain-based organization. Confirmed against 3 reference codebases (site-sync-vista, MARKETING REPORT AUTOMATION, GO_UDP admin/user dashboards) — all React/Vite/Tailwind/Redux Toolkit, all domain-first.
Example:
src/
api/
components/
pages/
hooks/hooks/useX.ts is equally normal until a domain accumulates several)
store/
Rules:
- One domain per folder
- Do not mix domains
- Domain folder names are kebab-case by default (
credit-report,loco-event-packets,realtime-locos) — PascalCase domain folders exist as legacy drift in older code; don't introduce new PascalCase domain folders, but don't rename existing ones as a side effect of unrelated work - A dedicated
services/<domain>/layer is optional and uncommon — most repos fold that logic straight intoapi/<domain>/or intostore/<domain>/api.ts(RTK Query); only addservices/when there's real orchestration beyond a single HTTP call - By default, route entry parents live under
src/pages/<domain>/<route>/index.tsx— if the repo uses a file-based router (e.g. TanStack Router), route files instead live flat undersrc/routes/with dot-segmented filenames mirroring the URL (_app.alerts.config.$id.edit.tsx) and a generated route tree; don't hand-nest folders to imitatepages/under a file-based router - Page files should orchestrate route concerns and compose feature UI, not own large UI trees
- Route-owned UI and related subcomponents should live under
src/components/<domain>/<feature>/* - Feature-owned hooks may live under
src/components/<domain>/<feature>/hooks/*when the logic is only used by that feature - Shared hooks used across multiple features may live under
src/hooks/<domain>/* - Shared domain support can stay in a repo's established shared folder pattern
- No API calls directly in components
src/types/<domain>/...is the canonical home for app-owned frontend types- Feature-specific UI prop/state contracts should use focused files such as
src/types/<domain>/<feature>-ui.tsinstead of inline component ownership - Root global CSS belongs in
src/index.cssand should stay a thin shell - Domain-shared non-module CSS belongs in
src/styles/<domain>/index.css - Feature-local styling belongs in
src/components/<domain>/<feature>/*.module.css - CSS Modules must be imported directly by the owning component, not routed through domain CSS or root CSS
- Tailwind utilities should own layout, spacing, sizing, typography, breakpoints, and common state classes by default
- CSS Modules are the escape hatch for pseudo-elements, keyframes, layered backgrounds, complex selectors, and feature-local skins — and a genuinely optional one: two of the three reference codebases ship zero
.module.cssfiles and rely on Tailwind + shadcn/ui primitives alone, so don't add a CSS Module just to have one - Once a repo has domain and feature style ownership, monolithic app CSS files are a structural violation
- Repo-local docs may override this default when a project intentionally uses a different layout
Example style topology:
src/ index.css styles/ theme/ index.css superadmin/ index.css components/ theme/ theme-toggle.tsx theme-toggle.module.css superadmin/ login/ superadmin-login-page.tsx superadmin-login-page.module.css
- TYPE OWNERSHIP
Frontend type ownership must mirror the backend pattern.
Canonical layout:
src/ types/ dashboard/ dashboard-hero.ts endpoint-snapshot.ts readiness/ status.ts api/ error.ts theme/ theme.ts
Rules:
- Put all app-owned frontend
typeandinterfacedeclarations insrc/types/<domain>/... - Components, hooks, API modules, store modules, and services must import custom types instead of declaring them inline
- This applies to all frontend types, including component props, domain models, API contracts, store contracts, and app/theme types
- Keep one domain folder per concern and one focused file per boundary
- Use focused UI-type files such as
src/types/<domain>/<feature>-ui.tsfor feature component props, dialog state, and other feature-local UI contracts - Do not create catch-all
types.tsdumping grounds - If a file currently owns types such as
src/app/theme-types.ts,src/api/types.ts, orsrc/store/<domain>/types.ts, move that ownership undersrc/types/<domain>/...unless the file itself already lives there
Anti-patterns:
- No
interface Propsor equivalent custom prop contracts inside component files - No feature-local dialog/page state interfaces inside
.tsxfiles when a focusedsrc/types/<domain>/<feature>-ui.tsfile should own them - No response or store contracts inside API modules, slice files, selector files, thunk files, hooks, or services
- No app-owned types left beside implementation files just because the type is small
- COMPONENT DESIGN
Components must:
- Be reusable and focused
- Separate UI and logic
- Move repeated logic to hooks
- Move repeated UI to shared components
- Keep page and feature-shell components as thin orchestrators that delegate local state, query wiring, and dialog logic to hooks where appropriate
Performance discipline:
- Use React.memo when useful
- Use useMemo / useCallback for expensive or stable logic
Avoid:
- Large monolithic components
- Heavy calculations inside render
- Large inline functions in JSX
- Inline custom type ownership in
.tsxfiles
- API LAYER RULES
- Centralize API calls in api/ or services/
- Do not call APIs directly inside UI
- Normalize responses and type them
- Centralize error handling
- Keep API request and response contracts in
src/types/<domain>/..., not inside API modules
- STATE MANAGEMENT (IF USED)
Redux Toolkit is the confirmed default across all 3 reference codebases. Plain React Context is only used for genuinely cross-cutting concerns (auth/session, theme) — never for domain/feature state. No Zustand or bare Context-as-store observed.
Recommended structure (either variant is fine — match whatever the repo already uses):
store/
-- or --
redux/slices/<Domain>/
<Domain>Slice.ts
thunks.ts (optional — createAsyncThunk calling into api/
Rules:
- One domain per slice
- No UI logic in store
- Access state through selectors
- Side effects only in thunks, RTK Query endpoints, or hooks
- Keep store-facing contracts in
src/types/<domain>/..., not instore/<domain>/types.ts - A shared base file (e.g.
store/api/baseApi.ts+errorTransform.ts/listResponseTransform.ts) centralizes the RTK Query base query and response shaping once — domainapi.tsfiles callinjectEndpointsagainst it rather than each configuring their own base query
Use global state only for:
- Auth/session
- Shared data
- Cached server data
- Configuration
- CONTEXT AWARENESS
Before writing code:
- Review existing components, hooks, and services
- Review existing
src/types/<domain>/...ownership before adding new types - Reuse logic when possible
- Avoid duplication and circular dependencies
Never assume context.
- PERFORMANCE PRINCIPLES
Prefer:
- Memoization
- Lazy loading
- Pagination or virtualization for large lists
Avoid:
- Large global state
- Unnecessary re-renders
- TYPESCRIPT & NAMING
Naming:
- Components → PascalCase
- Hooks → useCamelCase
- Functions → camelCase
- Files → match export
- Type files → named for the owning UI boundary or contract, not generic
types
Avoid:
- any unless unavoidable
- inconsistent naming
- hidden type ownership inside implementation files
- CODE SAFETY
Do NOT:
- Change API response shapes
- Modify business logic without instruction
- Invent a colocated type pattern when a central domain type file should own the contract
You MAY:
- Improve readability
- Extract helpers
- Reduce duplication
- FILE SIZE LIMIT
- No manually maintained frontend source file should be more than 250 lines.
- If a touched file exceeds 250 lines, it must be optimized and broken into:
- Subcomponents
- Custom hooks
- Utility/helper files
- Domain type files when inline contracts are contributing to file growth
- Service/API layer separation where applicable
- Large frontend source files are considered a structural issue and must be refactored before adding more behavior unless the user explicitly scopes that cleanup out.
- FINAL CHECK
- Structure is consistent
- Components are modular
- No direct API calls in UI
- No duplication
- App-owned frontend types live in
src/types/<domain>/... - Components, hooks, API modules, and stores import types instead of declaring them inline
src/index.csscontains only Tailwind import, domain CSS imports, and global base/reset rules- Domain
index.cssfiles stay thin and shared - Feature-local visuals live in colocated CSS Modules imported by the owner
- Imports are valid
- Code compiles logically
ABSOLUTE RULE
If unsure: Inspect existing code first. Never guess patterns.
Version History
- 581d130 Current 2026-07-19 09:08


