What is Co-location?
Co-location is the practice of placing related code in close proximity within your project structure. Instead of organizing by technical type, co-location organizes by business domain and usage patterns.Co-location PrincipleCode that changes together should live together. Code that’s used together should be stored together.
Why Co-location Matters
The Problem with Separation
Traditional architecture separates code by technical concerns:- Working on login requires jumping between 4 directories
- No clear boundaries between features
- Hard to move or refactor features as units
- Mental overhead tracking related files
The Co-location Solution
- Everything for authentication is in one place
- Clear feature boundaries
- Easy to refactor or move entire features
- Reduced mental overhead
Co-location Across Frameworks
Next.js Co-location
From the Next.js Scope Rule Architect:- Product listing logic stays with the shop page
- Cart management logic stays with the cart page
- Shared shop utilities stay within the
(shop)route group - Each page has its own loading states and components nearby
- Need to work on cart? Everything’s in
app/(shop)/cart/ - Need to understand shop? Look in
app/(shop)/ - Want to refactor the entire shop feature? It’s all self-contained
Angular Co-location
From the Angular Scope Rule Architect:- All cart components live with the cart feature
- Cart state management (signals) is local
- Cart-specific services and guards are nearby
- Cart types and utilities are together
- Single source of truth for cart functionality
- Easy to test cart as an isolated unit
- Can move or refactor cart without touching other features
- New developers find everything cart-related in one place
Astro Co-location
From the Astro Scope Rule Architect:- Blog pages and their specific components
- Blog utilities for date formatting and excerpts
- Both static components and interactive islands
- Blog-specific helper functions
- Blog functionality is self-contained
- Easy to see what’s static vs. interactive
- Can understand blog feature without looking elsewhere
- Simple to add new blog-specific features
React Co-location
From the React Scope Rule Architect:- Container and presentational components for catalog
- Product fetching and caching logic
- Custom hooks for product operations
- Type definitions for products
- Catalog-specific utility functions
How Co-location Works with the Scope Rule
Co-location and the Scope Rule work together:Example: ProductCard Journey
Let’s trace a component through its lifecycle:- Stage 1: Single Feature
- Stage 2: Two Features
- Stage 3: Multiple Features
Benefits of Co-location
Mental Model Alignment
Code is where you expect it. Working on authentication? Everything you need is in
authentication/.Reduced Context Switching
No jumping between
components/, services/, hooks/, types/ directories. Everything related is nearby.Easier Refactoring
Move features as complete, self-contained units. No hunting for scattered dependencies.
Clear Boundaries
Obvious where one feature ends and another begins. Prevents unintended coupling.
Team Collaboration
Multiple teams can work on different features without stepping on each other’s toes.
Faster Onboarding
New developers understand feature boundaries immediately. No “where do I find…” questions.
Co-location Best Practices
1. Keep Feature Structure Consistent
Each feature should follow the same internal structure:- Next.js
- Angular
- Astro
- React
2. Use Clear Sub-directories
Within features, organize by technical type for clarity:components/- UI componentsservices/- Business logic and API callshooks/- Custom React/framework hooksmodels.tsortypes.ts- Type definitionsutils.ts- Utility functionsconstants.ts- Feature-specific constants
3. Co-locate Tests with Code
- Next to Source
- Test Directory
4. Document Feature Dependencies
If a feature depends on another feature’s code, this might indicate:- Code should be moved to shared/
- Features are too coupled
- Feature boundaries need reconsidering
Common Questions
What if a component needs data from another feature?
What if a component needs data from another feature?
Use shared services or state management. The component itself stays co-located with its feature, but it can import from
shared/services/ or use a global store. The key is the component’s placement follows the Scope Rule.Should I co-locate types that are used across files?
Should I co-locate types that are used across files?
Yes, but apply the Scope Rule. If types are only used within one feature, keep them in that feature’s
models.ts or types.ts. If used by 2+ features, move to shared/types/.What about infrastructure code like API clients?
What about infrastructure code like API clients?
Infrastructure that’s used across features goes in
lib/ or infrastructure/. This includes:- HTTP clients
- Authentication setup
- Database connections
- Logging utilities
Can features have sub-features?
Can features have sub-features?
Yes, in Next.js this is natural with nested routes. In other frameworks, consider whether the sub-feature is truly distinct. If it’s always used with the parent, keep it co-located. If it could be used independently, make it a separate feature.
How deep should co-location go?
How deep should co-location go?
Generally 2-3 levels deep within a feature:Deeper than this might indicate the feature is too complex and should be split.
Anti-Patterns to Avoid
Real-World Example
Let’s see co-location in a real e-commerce scenario:- Before (Separated)
- After (Co-located)
- Need to modify cart? Touch 3+ directories
- Unclear what belongs where
- Hard to refactor or test in isolation
Further Reading
The Scope Rule
Learn how the Scope Rule determines what gets co-located where
Screaming Architecture
Understand how co-location enables architecture that communicates intent
