{"id":"d2352dc1-9c45-4131-994d-7465451088e0","shortId":"X6Cps9","kind":"skill","title":"feature-slicing","tagline":"Proactively apply when creating new features/components/pages or setting up frontend project structure. Triggers on FSD, feature slicing, frontend architecture, layer structure, module boundaries, scalable frontend, slice organization. Use when restructuring React/Next.js/Vue/Rem","description":"# Feature-Sliced Design Architecture\n\nFrontend architecture methodology with strict layer hierarchy and import rules for scalable, maintainable applications. FSD organizes code by **business domain** rather than technical role.\n\n> **Official Docs:** [feature-sliced.design](https://feature-sliced.design) | **GitHub:** [feature-sliced](https://github.com/feature-sliced)\n\n---\n\n## THE IMPORT RULE (Critical)\n\n**Modules can ONLY import from layers strictly below them. Never sideways or upward.**\n\n```\napp → pages → widgets → features → entities → shared\n ↓      ↓        ↓          ↓          ↓         ✓\n ✓      ✓        ✓          ✓          ✓      (external only)\n```\n\n| Violation | Example | Fix |\n|-----------|---------|-----|\n| Cross-slice (same layer) | `features/auth` → `features/user` | Extract to `entities/` or `shared/` |\n| Upward import | `entities/user` → `features/auth` | Move shared code down |\n| Shared importing up | `shared/` → `entities/` | Shared has NO internal deps |\n\n**Exception:** `app/` and `shared/` have no slices, so internal cross-imports are allowed within them.\n\n---\n\n## Layer Hierarchy\n\n| Layer | Purpose | Has Slices | Required |\n|-------|---------|------------|----------|\n| `app/` | Initialization, routing, providers, global styles | No | Yes |\n| `pages/` | Route-based screens (one slice per route) | Yes | Yes |\n| `widgets/` | Complex reusable UI blocks (header, sidebar) | Yes | No |\n| `features/` | User interactions with business value (login, checkout) | Yes | No |\n| `entities/` | Business domain models (user, product, order) | Yes | No |\n| `shared/` | Project-agnostic infrastructure (UI kit, API client, utils) | No | Yes |\n\n**Minimal setup:** `app/`, `pages/`, `shared/` — add other layers as complexity grows.\n\n---\n\n## Quick Decision Trees\n\n### \"Where does this code go?\"\n\n```\nCode Placement:\n├─ App-wide config, providers, routing    → app/\n├─ Full page / route component            → pages/\n├─ Complex reusable UI block              → widgets/\n├─ User action with business value        → features/\n├─ Business domain object (data model)    → entities/\n└─ Reusable, domain-agnostic code         → shared/\n```\n\n### \"Feature or Entity?\"\n\n| Entity (noun) | Feature (verb) |\n|---------------|----------------|\n| `user` — user data model | `auth` — login/logout actions |\n| `product` — product info | `add-to-cart` — adding to cart |\n| `comment` — comment data | `write-comment` — creating comments |\n| `order` — order record | `checkout` — completing purchase |\n\n**Rule:** Entities represent THINGS with identity. Features represent ACTIONS with side effects.\n\n### \"Which segment?\"\n\n```\nSegments (within a slice):\n├─ ui/      → React components, styles\n├─ api/     → Backend calls, data fetching, DTOs\n├─ model/   → Types, schemas, stores, business logic\n├─ lib/     → Slice-specific utilities\n└─ config/  → Feature flags, constants\n```\n\n**Naming:** Use purpose-driven names (`api/`, `model/`) not essence-based (`hooks/`, `types/`).\n\n---\n\n## Directory Structure\n\n```\nsrc/\n├── app/                    # App layer (no slices)\n│   ├── providers/          # React context, QueryClient, theme\n│   ├── routes/             # Router configuration\n│   └── styles/             # Global CSS, theme tokens\n├── pages/                  # Page slices\n│   └── {page-name}/\n│       ├── ui/             # Page components\n│       ├── api/            # Loaders, server actions\n│       ├── model/          # Page-specific state\n│       └── index.ts        # Public API\n├── widgets/                # Widget slices\n│   └── {widget-name}/\n│       ├── ui/             # Composed UI\n│       └── index.ts\n├── features/               # Feature slices\n│   └── {feature-name}/\n│       ├── ui/             # Feature UI\n│       ├── api/            # Feature API calls\n│       ├── model/          # State, schemas\n│       └── index.ts\n├── entities/               # Entity slices\n│   └── {entity-name}/\n│       ├── ui/             # Entity UI (Card, Avatar)\n│       ├── api/            # CRUD operations\n│       ├── model/          # Types, mappers, validation\n│       └── index.ts\n└── shared/                 # Shared layer (no slices)\n    ├── ui/                 # Design system components\n    ├── api/                # API client, interceptors\n    ├── lib/                # Utilities (dates, validation)\n    ├── config/             # Environment, constants\n    ├── routes/             # Route path constants\n    └── i18n/               # Translations\n```\n\n---\n\n## Public API Pattern\n\nEvery slice MUST expose a public API via `index.ts`. External code imports ONLY from this file.\n\n```typescript\n// entities/user/index.ts\nexport { UserCard } from './ui/UserCard';\nexport { UserAvatar } from './ui/UserAvatar';\nexport { getUser, updateUser } from './api/userApi';\nexport type { User, UserRole } from './model/types';\nexport { userSchema } from './model/schema';\n```\n\n```typescript\n// ✅ Correct\nimport { UserCard, type User } from '@/entities/user';\n\n// ❌ Wrong\nimport { UserCard } from '@/entities/user/ui/UserCard';\n```\n\n**Avoid wildcard exports** — they expose internals and harm tree-shaking:\n```typescript\n// ❌\nexport * from './ui';\n\n// ✅\nexport { UserCard } from './ui/UserCard';\n```\n\n---\n\n## Cross-Entity References (@x Notation)\n\nWhen entities legitimately reference each other, use the `@x` notation:\n\n```\nentities/\n├── product/\n│   ├── @x/\n│   │   └── order.ts    # API specifically for order entity\n│   └── index.ts\n└── order/\n    └── model/types.ts  # Imports from product/@x/order\n```\n\n```typescript\n// entities/product/@x/order.ts\nexport type { ProductId } from '../model/types';\n\n// entities/order/model/types.ts\nimport type { ProductId } from '@/entities/product/@x/order';\n```\n\n**Guidelines:** Keep cross-imports minimal. Consider merging entities if references are extensive.\n\n---\n\n## Anti-Patterns\n\n| Anti-Pattern | Problem | Fix |\n|--------------|---------|-----|\n| Cross-slice import | `features/a` → `features/b` | Extract shared logic down |\n| Generic segments | `components/`, `hooks/` | Use `ui/`, `lib/`, `model/` |\n| Wildcard exports | `export * from './button'` | Explicit named exports |\n| Business logic in shared | Domain logic in `shared/lib` | Move to `entities/` |\n| Single-use widgets | Widget used by one page | Keep in page slice |\n| Skipping public API | Import from internal paths | Always use `index.ts` |\n| Making everything a feature | All interactions as features | Only reused actions |\n\n---\n\n## TypeScript Configuration\n\n```json\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    }\n  }\n}\n```\n\n---\n\n## Reference Documentation\n\n| File | Purpose |\n|------|---------|\n| [references/LAYERS.md](references/LAYERS.md) | Complete layer specifications, flowcharts |\n| [references/PUBLIC-API.md](references/PUBLIC-API.md) | Export patterns, @x notation, tree-shaking |\n| [references/IMPLEMENTATION.md](references/IMPLEMENTATION.md) | Code patterns: entities, features, React Query |\n| [references/NEXTJS.md](references/NEXTJS.md) | App Router integration, page re-exports |\n| [references/MIGRATION.md](references/MIGRATION.md) | Incremental migration strategy |\n| [references/CHEATSHEET.md](references/CHEATSHEET.md) | Quick reference, import matrix |\n\n## Resources\n\n### Official Sources\n- **Official Documentation**: https://feature-sliced.design\n- **GitHub Organization**: https://github.com/feature-sliced\n- **Official Examples**: https://github.com/feature-sliced/examples\n- **Specification**: https://feature-sliced.design/docs/reference\n\n### Community\n- **Awesome FSD**: https://github.com/feature-sliced/awesome (curated articles, videos, tools)","tags":["feature","slicing","robust","skills","ccheney","agent-skills","clean-architecture","domain-driven-design","drizzle-orm","feature-sliced-design","hexagonal-architecture","mermaid-diagrams"],"capabilities":["skill","source-ccheney","skill-feature-slicing","topic-agent-skills","topic-clean-architecture","topic-domain-driven-design","topic-drizzle-orm","topic-feature-sliced-design","topic-hexagonal-architecture","topic-mermaid-diagrams","topic-modern-javascript","topic-postgres","topic-skills","topic-slack-block-kit","topic-slack-mrkdwn"],"categories":["robust-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/ccheney/robust-skills/feature-slicing","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add ccheney/robust-skills","source_repo":"https://github.com/ccheney/robust-skills","install_from":"skills.sh"}},"qualityScore":"0.469","qualityRationale":"deterministic score 0.47 from registry signals: · indexed on github topic:agent-skills · 39 github stars · SKILL.md body (7,640 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T00:57:20.778Z","embedding":null,"createdAt":"2026-04-18T22:18:42.980Z","updatedAt":"2026-05-02T00:57:20.778Z","lastSeenAt":"2026-05-02T00:57:20.778Z","tsv":"'/api/userapi':513 '/button':646 '/docs/reference':768 '/entities/product':601 '/entities/user':531 '/entities/user/ui/usercard':536 '/feature-sliced':759 '/feature-sliced)':74 '/feature-sliced/awesome':774 '/feature-sliced/examples':764 '/model/schema':523 '/model/types':519,595 '/src':701 '/ui':551 '/ui/useravatar':508 '/ui/usercard':504,555 'action':254,284,317,399,694 'ad':292 'add':220,289 'add-to-cart':288 'agnost':206,268 'allow':146 'alway':681 'anti':617,620 'anti-pattern':616,619 'api':210,331,358,396,407,427,429,446,463,464,481,489,576,676 'app':92,134,156,217,237,242,369,370,731 'app-wid':236 'appli':5 'applic':53 'architectur':22,39,41 'articl':776 'auth':282 'avatar':445 'avoid':537 'awesom':770 'backend':332 'base':167,363 'baseurl':699 'block':179,251 'boundari':26 'busi':58,188,195,256,259,341,650 'call':333,430 'card':444 'cart':291,294 'checkout':191,306 'client':211,465 'code':56,121,232,234,269,493,723 'comment':295,296,300,302 'communiti':769 'compileropt':698 'complet':307,708 'complex':176,224,248 'compon':246,329,395,462,636 'compos':415 'config':239,348,471 'configur':381,696 'consid':609 'constant':351,473,477 'context':376 'correct':525 'creat':7,301 'critic':78 'cross':104,143,557,606,625 'cross-ent':556 'cross-import':142,605 'cross-slic':103,624 'crud':447 'css':384 'curat':775 'data':262,280,297,334 'date':469 'decis':227 'dep':132 'design':38,460 'directori':366 'doc':65 'document':703,753 'domain':59,196,260,267,654 'domain-agnost':266 'driven':356 'dtos':336 'effect':320 'entiti':96,112,127,194,264,273,274,310,435,436,439,442,558,563,572,580,611,660,725 'entities/order/model/types.ts':596 'entities/product':589 'entities/user':117 'entities/user/index.ts':500 'entity-nam':438 'environ':472 'essenc':362 'essence-bas':361 'everi':483 'everyth':685 'exampl':101,761 'except':133 'explicit':647 'export':501,505,509,514,520,539,549,552,591,643,644,649,714,737 'expos':486,541 'extens':615 'extern':98,492 'extract':110,630 'featur':2,19,36,70,95,184,258,271,276,315,349,418,419,422,425,428,687,691,726 'feature-nam':421 'feature-sl':1,35,69 'feature-sliced.design':66,67,754,767 'feature-sliced.design/docs/reference':766 'features/a':628 'features/auth':108,118 'features/b':629 'features/components/pages':9 'features/user':109 'fetch':335 'file':498,704 'fix':102,623 'flag':350 'flowchart':711 'frontend':13,21,28,40 'fsd':18,54,771 'full':243 'generic':634 'getus':510 'github':68,755 'github.com':73,758,763,773 'github.com/feature-sliced':757 'github.com/feature-sliced)':72 'github.com/feature-sliced/awesome':772 'github.com/feature-sliced/examples':762 'global':160,383 'go':233 'grow':225 'guidelin':603 'harm':544 'header':180 'hierarchi':46,150 'hook':364,637 'i18n':478 'ident':314 'import':48,76,82,116,124,144,494,526,533,584,597,607,627,677,747 'increment':740 'index.ts':405,417,434,453,491,581,683 'info':287 'infrastructur':207 'initi':157 'integr':733 'interact':186,689 'interceptor':466 'intern':131,141,542,679 'json':697 'keep':604,670 'kit':209 'layer':23,45,84,107,149,151,222,371,456,709 'legitim':564 'lib':343,467,640 'loader':397 'logic':342,632,651,655 'login':190 'login/logout':283 'maintain':52 'make':684 'mapper':451 'matrix':748 'merg':610 'methodolog':42 'migrat':741 'minim':215,608 'model':197,263,281,337,359,400,431,449,641 'model/types.ts':583 'modul':25,79 'move':119,658 'must':485 'name':352,357,392,413,423,440,648 'never':88 'new':8 'notat':561,571,717 'noun':275 'object':261 'offici':64,750,752,760 'one':169,668 'oper':448 'order':200,303,304,579,582 'order.ts':575 'organ':30,55,756 'page':93,164,218,244,247,387,388,391,394,402,669,672,734 'page-nam':390 'page-specif':401 'path':476,680,700 'pattern':482,618,621,715,724 'per':171 'placement':235 'proactiv':4 'problem':622 'product':199,285,286,573,586 'productid':593,599 'project':14,205 'project-agnost':204 'provid':159,240,374 'public':406,480,488,675 'purchas':308 'purpos':152,355,705 'purpose-driven':354 'queri':728 'querycli':377 'quick':226,745 'rather':60 're':736 're-export':735 'react':328,375,727 'react/next.js/vue/rem':34 'record':305 'refer':559,565,613,702,746 'references/cheatsheet.md':743,744 'references/implementation.md':721,722 'references/layers.md':706,707 'references/migration.md':738,739 'references/nextjs.md':729,730 'references/public-api.md':712,713 'repres':311,316 'requir':155 'resourc':749 'restructur':33 'reus':693 'reusabl':177,249,265 'role':63 'rout':158,166,172,241,245,379,474,475 'route-bas':165 'router':380,732 'rule':49,77,309 'scalabl':27,51 'schema':339,433 'screen':168 'segment':322,323,635 'server':398 'set':11 'setup':216 'shake':547,720 'share':97,114,120,123,126,128,136,203,219,270,454,455,631,653 'shared/lib':657 'side':319 'sidebar':181 'sideway':89 'singl':662 'single-us':661 'skill' 'skill-feature-slicing' 'skip':674 'slice':3,20,29,37,71,105,139,154,170,326,345,373,389,410,420,437,458,484,626,673 'slice-specif':344 'sourc':751 'source-ccheney' 'specif':346,403,577,710,765 'src':368 'state':404,432 'store':340 'strategi':742 'strict':44,85 'structur':15,24,367 'style':161,330,382 'system':461 'technic':62 'theme':378,385 'thing':312 'token':386 'tool':778 'topic-agent-skills' 'topic-clean-architecture' 'topic-domain-driven-design' 'topic-drizzle-orm' 'topic-feature-sliced-design' 'topic-hexagonal-architecture' 'topic-mermaid-diagrams' 'topic-modern-javascript' 'topic-postgres' 'topic-skills' 'topic-slack-block-kit' 'topic-slack-mrkdwn' 'translat':479 'tree':228,546,719 'tree-shak':545,718 'trigger':16 'type':338,365,450,515,528,592,598 'typescript':499,524,548,588,695 'ui':178,208,250,327,393,414,416,424,426,441,443,459,639 'updateus':511 'upward':91,115 'use':31,353,568,638,663,666,682 'user':185,198,253,278,279,516,529 'useravatar':506 'usercard':502,527,534,553 'userrol':517 'userschema':521 'util':212,347,468 'valid':452,470 'valu':189,257 'verb':277 'via':490 'video':777 'violat':100 'wide':238 'widget':94,175,252,408,409,412,664,665 'widget-nam':411 'wildcard':538,642 'within':147,324 'write':299 'write-com':298 'wrong':532 'x':560,570,574,716 'x/order':587,602 'x/order.ts':590 'yes':163,173,174,182,192,201,214","prices":[{"id":"b3a0556e-25dd-4c6c-852d-2ad0cf41b380","listingId":"d2352dc1-9c45-4131-994d-7465451088e0","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"ccheney","category":"robust-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:18:42.980Z"}],"sources":[{"listingId":"d2352dc1-9c45-4131-994d-7465451088e0","source":"github","sourceId":"ccheney/robust-skills/feature-slicing","sourceUrl":"https://github.com/ccheney/robust-skills/tree/main/skills/feature-slicing","isPrimary":false,"firstSeenAt":"2026-04-18T22:18:42.980Z","lastSeenAt":"2026-05-02T00:57:20.778Z"}],"details":{"listingId":"d2352dc1-9c45-4131-994d-7465451088e0","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"ccheney","slug":"feature-slicing","github":{"repo":"ccheney/robust-skills","stars":39,"topics":["agent-skills","clean-architecture","domain-driven-design","drizzle-orm","feature-sliced-design","hexagonal-architecture","mermaid-diagrams","modern-javascript","postgres","skills","slack-block-kit","slack-mrkdwn","slack-work-objects"],"license":"mit","html_url":"https://github.com/ccheney/robust-skills","pushed_at":"2026-04-27T15:23:12Z","description":"Robust skills for Agents","skill_md_sha":"dc66f0e3f6a1632f6842ee975eaf12e5c58a065b","skill_md_path":"skills/feature-slicing/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/ccheney/robust-skills/tree/main/skills/feature-slicing"},"layout":"multi","source":"github","category":"robust-skills","frontmatter":{"name":"feature-slicing","description":"Proactively apply when creating new features/components/pages or setting up frontend project structure. Triggers on FSD, feature slicing, frontend architecture, layer structure, module boundaries, scalable frontend, slice organization. Use when restructuring React/Next.js/Vue/Remix projects, organizing frontend code, fixing import violations, or migrating legacy codebases. Feature-Sliced Design (FSD) architecture for frontend projects."},"skills_sh_url":"https://skills.sh/ccheney/robust-skills/feature-slicing"},"updatedAt":"2026-05-02T00:57:20.778Z"}}