Feature Implementation Decision Tree
A step-by-step guide to determine where and how to implement new features, functions, and code in the codebase
Feature Implementation Decision Tree
Overview
This guide provides a systematic approach to determine where to place new code, when to create new structures, and how to implement features consistently. By following this decision tree, you'll maintain our codebase's clarity and ensure that every developer's code looks like it was written by a single person.
Why this matters: Consistent code placement reduces cognitive load, speeds up development, and makes code reviews more focused on logic rather than structure. Studies show that developers spend up to 60% of their time understanding existing code - clear organization dramatically reduces this overhead.
Quick Decision Flow
Pro tip: Bookmark this page! Most placement decisions can be made in under 2 minutes using this flow. If you're spending more time than that, it's likely an edge case worth discussing with the team.
UI Component Decision Tree
Understanding our three-layer UI architecture is crucial for maintaining clean separation of concerns:
Detailed Decision Process
Step 1: Identify the Code Type
First, understand what you're building. This categorization drives all subsequent decisions:
| Code Type | Description | Key Questions |
|---|---|---|
| UI Component | Visual elements users interact with | Does it render JSX? Does it have styles? |
| Business Logic | Core application functionality | Does it manage data? Does it implement business rules? |
| Utility Function | Helper functions and tools | Is it a pure function? Is it reusable? |
| Navigation | Screen routing and navigation logic | Does it handle screen transitions? |
| Configuration | App settings and constants | Is it app-wide configuration? |
| API Integration | Backend communication | Does it fetch/send data to servers? |
Learning moment: This categorization aligns with the Separation of Concerns principle. By clearly identifying what type of code you're writing, you ensure each piece has a single, well-defined responsibility.
Step 2: Determine Scope
Understanding scope helps maintain proper code organization and reusability:
The 3+ Rule Explained:
- Code used by 3 or more features should be shared to avoid duplication
- Code used by 1-2 features can remain feature-specific to avoid premature abstraction
- This threshold balances reusability with simplicity
Real-world example: A formatCurrency() function used in checkout, product listing, and order history should be in core/shared/utils/. A calculateCheckoutTax() function only used in checkout should stay in features/checkout/utils/.
Step 3: Apply Location Rules
Now that you know the type and scope, here's exactly where your code belongs:
UI Component Placement
Our three-layer architecture ensures clean separation and maximum reusability:
Component Guidelines by Layer
Foundation Components ✨
- Purpose: Basic building blocks of your UI
- Characteristics:
- Single responsibility
- Zero business logic
- Use design tokens exclusively
- Highly reusable
- Examples: Button, Input, Text, Icon, Card
- Think of them as: LEGO blocks - simple, combinable, universal
Pattern Components 🎨
- Purpose: Common UI patterns built from foundation components
- Characteristics:
- Composed from foundation components
- Handle complex UI interactions
- Domain-agnostic (no business logic)
- Reusable across different contexts
- Examples: Modal, Form, DataTable, Accordion, Tabs
- Think of them as: Pre-built LEGO structures - save time, ensure consistency
Business Components 💼
- Purpose: Domain-aware components used across multiple features
- Characteristics:
- Can use domain hooks for data
- Encapsulate business logic
- Shared by 3+ features
- Handle their own loading/error states
- Examples: ProductCard, UserAvatar, OrderStatus, PricingDisplay
- Think of them as: Smart components that understand your business
Why this architecture? This three-layer approach prevents business logic from leaking into presentational components, maximizes reusability, and makes it crystal clear where each component belongs. It's based on proven patterns from companies like Airbnb and Shopify.
Step 4: Check Existing Patterns
Before creating anything new, always look for existing patterns:
Important: Creating new patterns without checking existing ones is a major source of inconsistency. When in doubt, ask: "Have we solved this problem before?"
Common Scenarios
Let's walk through real decisions you'll face daily:
Scenario 1: Creating a New UI Component
Question: "I need to create a button that shows a loading spinner. Where does it go?"
Decision Process:
- Is it a basic component with single responsibility? → YES
- Does it contain business logic? → NO
- Answer: Create in
ui/foundation/Button/
Scenario 2: Creating a Product Display Component
Question: "I need a component to display product information with price, image, and add to cart."
Decision Process:
- Does it use domain data (Product)? → YES
- Contains business logic (pricing, cart)? → YES
- Used by multiple features? → YES (catalog, search, recommendations)
- Answer: Create in
ui/business/ProductCard/
Scenario 3: Creating a Modal Pattern
Question: "I need a reusable modal component for forms and confirmations."
Decision Process:
- Is it composed from other components? → YES
- Is it domain-agnostic? → YES
- Is it a common UI pattern? → YES
- Answer: Create in
ui/patterns/Modal/
Special Cases
When to Create Business Components
Create a business component when ALL of these are true:
- (Do ✅) It works with domain entities (Product, User, Order)
- (Do ✅) It's used by 3+ features
- (Do ✅) It contains business logic or calculations
- (Do ✅) It needs domain hooks for data
Examples that qualify:
ProductCard- displays product with pricing logicUserAvatar- shows user with online statusOrderStatusBadge- shows order state with business rules
Examples that don't qualify:
- (Don't ❌)
Button- just styling variations → Foundation - (Don't ❌)
LoadingSpinner- no business logic → Foundation - (Don't ❌)
CheckoutForm- feature-specific → Feature component
When to Create Pattern Components
Create a pattern component when:
- (Do ✅) It's a common UI pattern (Modal, Tabs, Accordion)
- (Do ✅) It's composed from foundation components
- (Do ✅) It's completely domain-agnostic
- (Do ✅) It handles complex UI interactions
Examples:
DataTable- complex table with sorting/filteringDatePicker- date selection interfaceWizard- multi-step form navigation
When to Create Foundation Components
Create a foundation component when:
- (Do ✅) It's an atomic building block
- (Do ✅) It has single responsibility
- (Do ✅) It's purely presentational
- (Do ✅) It only uses design tokens for styling
Examples:
Button,Input,Text- basic elementsCard,Surface- layout componentsIcon,Avatar- simple display components
Feature Development Checklists
Pre-Development Checklist
Before writing any code, ensure:
- ADR created for significant architectural decisions
- File placement determined using the decision tree above
- Dependencies identified - What domains/features will you integrate with?
- Performance requirements defined - Response time, memory usage, etc.
- Security implications assessed - Auth requirements, data sensitivity
- Similar features reviewed - Check existing patterns to follow
- API contracts defined - If creating new endpoints
- Error scenarios mapped - Happy, sad, mad, and bad paths
During Development Checklist
While implementing, verify:
- Following naming conventions exactly as documented
- Code aligns with patterns from similar features
- Error handling matches team standards
- Documentation written alongside code (not after!)
- Tests written for all new functionality
- Design tokens used for all UI styling
- No magic numbers/strings - Use constants
- Accessibility considered - ARIA labels, keyboard navigation
Pre-Merge Checklist
Before creating PR:
- All checklist items verified above
- Documentation updated in same PR
- No TypeScript errors - Run
npx tsc --noEmit - Linting passes - Run
npm run lint - Tests passing with >90% coverage
- Bundle size checked - No unexpected increases
- Performance tested - No regressions
- Code review self-check using team template
Enforcement Checklist
Use this final checklist before committing any code:
- Code is in the correct location per this guide
- UI components are in the right layer (foundation/patterns/business)
- Foundation components use design tokens exclusively
- Business components use domain hooks appropriately
- File naming conventions are followed exactly
- Imports use correct path aliases (@/)
- Tests are co-located with code
- Barrel exports (index.ts) are updated
- No code duplication with existing components
Quick Reference Card
For AI Assistants
AI Instructions: Follow this decision tree exactly. Each file placement decision should be traceable through this guide.
When implementing features:
- Always determine the component layer first (foundation/patterns/business)
- Foundation components must have zero business logic
- Patterns must be composed from foundation only
- Business components should use domain hooks
- Check for existing similar components before creating new ones
- Follow the exact folder structure shown above
Related Documents
- UI Architecture Overview - Deep dive into our UI layers
- Project Structure - Complete codebase organization
- File Naming Conventions - Naming standards
- Domain Architecture Guide - Understanding domains
- component-development - Best practices