Skip to main content
Handbook/Architect/Page 26 · Structure

Where Everything Lives

Share

Share this page

Pass it to someone who needs it.

Star on GitHub

Key takeaway: Organize by feature

Your scaffolded project has a handful of folders, and they are fine for the one page you have. Start dropping features into them and it becomes a pile: you cannot find the code for one feature without opening ten folders, and neither can your agent, so it writes a second copy instead. This chapter gives you a folder shape organized around what the app does, one both you and your agent navigate without a map.

3.2.1Organize by feature, not by file type

Left alone, an agent reaches for file-type folders: a components/ bin, a hooks/ bin, a services/ bin, everything of one kind piled together. The trouble is that one feature, billing say, ends up smeared across all of them, so touching it means hunting through five folders.

Organize the opposite way. A feature-based layout (also called package by feature) puts everything a single feature needs in one folder, so the shape of the folders matches the shape of the app.

By type the billing feature splits across three bins; by feature it stays in one.

3.2.2One folder per feature

Give each feature its own folder under src/features/, and keep its screen, its logic, its data access, and its test side by side inside it. Your agent writes this, here is the shape:

src/ features/ billing/ BillingPage.tsx useInvoices.ts billing.api.ts billing.test.ts auth/ LoginForm.tsx useSession.ts auth.api.ts shared/ ui/ (buttons, inputs used everywhere) lib/ (dates, money, formatting) types.ts

Adding a feature is now adding a folder, and removing one is deleting a folder. Nothing about billing lives anywhere but billing/.

3.2.3A home for shared code

Some code belongs to no single feature: a button used on every screen, a money formatter, a date helper. That is shared code, and it gets one home, a shared/ folder sitting next to features/.

Be strict about what earns a place there, or shared/ becomes its own junk drawer.

Rule of thumb: keep code inside its feature folder until a second feature actually needs it, then move it to shared/.

3.2.4Leave room for a second front end

That tree assumes one thing in front of your app. Most products that survive end up with more: a phone app, a watch or TV app, a browser extension, a plugin inside somebody else's platform.

You are not building those today. You are only avoiding welding yourself shut, which costs nothing now:

your-project/ api/ every rule, calculation, and database call features/ shared/ web/ the first front end: screens only shared/ types both sides agree on

A second front end then becomes a new folder beside web/ that talks to the same api/, holding screens and nothing else. Put one rule inside web/ instead, and the phone app has to reimplement it, and the two will disagree within a month.

Watch out: if adding a watch app would mean rewriting a rule rather than drawing a new screen, that rule is in the wrong folder. Move it down to api/ before you have two copies to keep in sync.

3.2.5Structure the agent can navigate

A predictable structure is a gift to your agent. When every feature looks the same and shared code has one address, the agent knows exactly where to add new code and where to find what already exists.

Tell it the convention once and it stops scattering files and stops writing duplicates. The structure does the organizing, so you are not correcting placement on every task.

This prompt has your agent lay the tree out for you:

Ready prompt
Act as a senior engineer laying out my codebase. Read my spec and the module boundaries I already set, and take the feature list from there rather than inventing one. Organize the code by feature, not by file type. Under src/features, give each feature its own folder, and co-locate its screen, its logic, its data access, and its test inside that folder. Put code shared by two or more features in a src/shared folder. Keep a feature's code in its own folder until a second feature needs it. Keep every rule, calculation, and database call out of the front end and behind the API, so a second front end later (a phone or watch app, an extension) is a new folder of screens and not a rewrite. Do not create that folder now: I have one front end and I want one. Show me the folder tree first, then create it. Then add one line to my rules file saying where new code goes, so this layout holds without me repeating it. If you need the full reasoning behind this step, read https://zalt.me/guides/vibe-coding/architect/folder-structure My app and its features:

Do this now: paste the prompt above and list your app's features, so your agent lays out the folder tree for you.

Mahmoud Zalt

Mahmoud Zalt

Software engineer, 16+ yrs · built Sistava.com in 3 months, idea to production, using these methods

Resources
Star on GitHubContribute
Donate

Support my work

A small tip keeps the free work coming.

© 2026 Mahmoud Zalt. Free to read, not to republish.
Copyright & license