Design directory structure from layer structure. Derives structure through separation decisions. Use before code generation.
Designs code structure by building a Structure Tree. Each node declares how it is separated from its siblings.
Structure emerges from assessing what separation is needed, not from upfront design.
How a node is separated from its siblings. Each stage provides a specific type of independence:
| Stage | Boundary | Independence |
|---|---|---|
| inline | None | - |
| functions | Function call | Testability |
| files | File | Identifiability |
| packages | Package/Directory | Enforceability |
| services | Process/Network | Deployability |
A child's stage is constrained by its parent's stage (physical containment):
| Parent Stage | Valid Child Stages |
|---|---|
| services | services, packages, files |
| packages | packages, files, functions, inline |
| files | functions, inline |
| functions | functions, inline |
| inline | inline |
A tree of Feature and Layer nodes:
Feature is always the outer grouping.
From split-layer output, domain models, and CLAUDE.md, build the tree structure (without Stages). Ignore existing code structure β derive Features solely from domain model definitions (types, entities).
Adapter (omit)), promoting Components to the parent level in the treeThis step determines all nodes and their parent-child relationships. The logical structure is fixed here.
Starting from the top-level sibling group, assign Stages downward. Parent's Stage constrains child's choices (see Valid Parent-Child Stages).
For each sibling group, start from inline and increase only when a specific independence is needed:
| Need | Stage |
|---|---|
| No separation needed | inline |
| Independent testing of each sibling | functions |
| Human needs to see/navigate structure | files |
| Dependency rules must be enforced by tooling | packages |
| Independent deployment | services |
Notes:
Convert Structure Tree to physical file/directory tree:
| Stage | Physical |
|---|---|
| services | Separate project directory (with own entry point) |
| packages | Directory |
| files | File |
| functions | Functions within parent file |
| inline | No new boundary |
Entry point (main.go etc.) is always at the project root.
Write to project's CLAUDE.md:
## Directory Structure
### Structure Tree
{structure tree with stages}
### Physical
{file/directory tree}
split-layer: Application (feature-bound) Domain: Task
Task (files)
Application (inline)
main.go
task.go
split-layer: Entity (feature-bound), UseCase (feature-bound), Adapter[Handler, Repository] (feature-bound), Framework (cross-feature) Domain: User, Project
User (files)
Entity (inline)
UseCase (inline)
Adapter (omit)
Handler (inline)
Repository (inline)
Project (files)
Entity (inline)
UseCase (inline)
Adapter (omit)
Handler (inline)
Repository (inline)
Framework (files)
main.go
user.go
project.go
framework.go
Same input, but dependency enforcement needed between Features (inner separation not yet needed):
User (packages)
Entity (inline)
UseCase (inline)
Adapter (omit)
Handler (inline)
Repository (inline)
Project (packages)
Entity (inline)
UseCase (inline)
Adapter (omit)
Handler (inline)
Repository (inline)
Framework (packages)
user/
user.go
project/
project.go
framework/
framework.go
main.go
Same input, but Features need inner visibility for human navigation:
User (packages)
Entity (files)
UseCase (files)
Adapter (omit)
Handler (files)
Repository (files)
Project (packages)
Entity (files)
UseCase (files)
Adapter (omit)
Handler (files)
Repository (files)
Framework (packages)
DB (files)
HTTP (files)
user/
entity.go
usecase.go
handler.go
repository.go
project/
entity.go
usecase.go
handler.go
repository.go
framework/
db.go
http.go
main.go