How to Organize Features
Features are organized by domain, then split into modules. Every module lives in
src/features/<domain>/modules/<module>/.
Structure
src/features/<domain>/
modules/
<module>/
<module>.tsx # Module component
components/ # Sub-components used only by this module
hooks/ # Hooks scoped to this module
hooks/ # Hooks shared across modules in the domain
utils/ # Domain helpers
types/ # Domain types
constants/ # Domain constantsExample: notifications domain
src/features/notifications/
modules/
notification-dropdown/
notification-dropdown.tsx
components/
notification-preview.tsx
hooks/
use-notification-dropdown.ts
notification-list/
notification-list.tsx
components/
notification-item.tsx
invitation-item.tsx
hooks/
use-notification-list.ts
hooks/
use-unread-count.ts
utils/
index.tsRules
-
Always nest inside
<domain>/modules/<module>/. Even single-file modules get their own folder.src/features/settings/modules/profile-tab/profile-tab.tsx, notsrc/features/settings/profile-tab.tsx. -
Pages belong in
src/routes/. Route files import module components. Features never contain "page" files. -
Hooks are scoped to where they're used:
- Module-level:
<module>/hooks/when only that module uses it - Domain-level:
<domain>/hooks/when shared across modules in the same domain - Global:
src/hooks/when truly app-wide
- Module-level:
-
Sub-components go in
<module>/components/. Anything a module renders but doesn't export lives next to it. -
No flat files at the domain level. Only shared folders like
modules/,hooks/,utils/,types/,constants/. -
Keep module code colocated. Components, hooks, types, queries, schemas, and tests all live inside the module folder they belong to. Don't move things to a global
components/orhooks/just because of file kind.
Adding a new module
- Create the folder:
src/features/<domain>/modules/<module>/ - Add your component:
<module>.tsx - Add
components/,hooks/, types, or helpers in subfolders as needed - Import the component from a route file in
src/routes/
Every purchase and sponsorship funds my 8+ years of work on open source given freely to the community. It keeps the lights on, funds new packs, and keeps the ecosystem alive. Even a small tier means a lot. Thank you!
