Shared Utilities Guide
Guidelines for organizing and using shared hooks, utilities, and types versus domain-specific code.
Shared Utilities Guide
Overview
This guide provides clear rules and examples for organizing shared hooks, utilities, and types in core/shared/ versus domain-specific code in core/domains/. It ensures clean architecture boundaries and prevents mixing domain logic with truly reusable utilities.
Purpose & Scope
This guide helps developers make correct decisions about where to place code, maintaining the distinction between:
- Generic, reusable utilities that belong in
core/shared/ - Domain-specific logic that belongs in
core/domains/[domain]/
Shared Hooks (core/shared/hooks/)
What Belongs Here
Generic React hooks that:
- Are truly reusable across multiple features/domains
- Contain no business logic or domain knowledge
- Don't depend on domain types or APIs
Examples of Shared Hooks
What DOESN'T Belong Here
Domain-specific hooks that should stay in core/domains/[domain]/hooks.ts:
Shared Utilities (core/shared/utils/)
What Belongs Here
General-purpose JavaScript/TypeScript functions that:
- Have no domain-specific logic
- Don't depend on React or domain types
- Are useful across multiple features/domains
Organization
Examples of Shared Utilities
What DOESN'T Belong Here
Domain-specific utilities that should stay in domain folders:
Shared Types (core/shared/types/)
What Belongs Here
TypeScript types that:
- Are used across multiple domains
- Define generic cross-domain patterns (not component-specific props)
- Represent common API response patterns
- Define application-wide constants
Important: Component-specific props (like ButtonProps, CardProps) should be co-located with their components following the Feature Implementation Decision Tree, not placed in shared types.
Organization
Examples of Shared Types
What DOESN'T Belong Here
Domain-specific types that should stay in domain folders:
Component-specific types that should be co-located with components:
Migration Checklist
When reviewing existing code to implement this structure:
Step 1: Audit Current Code
- List all hooks in the project
- List all utility functions
- List all type definitions
Step 2: Categorize by Domain
- Identify which hooks are domain-specific
- Identify which utilities are domain-specific
- Identify which types are domain-specific
Step 3: Move Generic Code to Shared
- Move truly generic hooks to
shared/hooks/ - Move general utilities to
shared/utils/ - Move cross-domain types to
shared/types/
Step 4: Keep Domain Code in Domains
- Ensure domain hooks stay in
domains/[domain]/hooks.ts - Keep domain utilities in domains (if needed)
- Keep domain types in
domains/[domain]/types.ts
Step 5: Update Imports
- Fix all import paths
- Ensure no circular dependencies
- Update barrel exports
Best Practices
Naming Conventions
All files must follow our File Naming Conventions:
- Hooks: Always prefix with
use(e.g.,useDebounce) - Utils: Use descriptive verb/noun combinations (e.g.,
formatDate) - Types: Use PascalCase for interfaces/types (e.g.,
ButtonProps)
File Organization
- Keep files focused on a single responsibility
- Group related utilities in the same file
- Use barrel exports for clean imports
Documentation
Testing
- Write unit tests for all shared utilities
- Test edge cases and error conditions
- Ensure utilities work in isolation
Common Pitfalls
1. Domain Logic in Shared
❌ Wrong: Putting business logic in shared utilities
✅ Correct: Keep domain logic in domains
2. Over-Abstraction
❌ Wrong: Creating overly generic utilities
✅ Correct: Create specific, useful utilities
3. Circular Dependencies
❌ Wrong: Shared utilities depending on domains
✅ Correct: Keep shared utilities independent