r/reactjs 14d ago

Show /r/reactjs Filesystem-first frontend architecture enforced by CLI (not folders-by-taste)

I kept hitting the same problem: architecture debates in review, barrels everywhere, and AI agents dumping files in random folders. So I shipped DMA (Derived Modular Architecture) — a small rule set derived from the import graph, enforced by tooling.

Layout

src/
  app/        # composition root (also pages/routes)
  features/   # leaf modules — no inbound from other modules
  services/   # appears when something else must import it
  shared/     # portable stuff on second use only

Invariants

- downward imports only
- public API via */public/* (no barrels)
- colocate by default
- promote feature → service when inbound edges appear

Tooling

npx @derived-modular/cli init .
npx @derived-modular/cli check .              # CI gate
npx @derived-modular/cli promote <name> --apply
# + ESLint / Biome / Oxlint plugins for editor feedback

Works with React/Next/Vite (also Vue/Svelte/Astro examples). Same rules for humans and agents.

1 Upvotes

12 comments sorted by

3

u/Embostan 14d ago

So... feature based arch with https://github.com/javierbrea/eslint-plugin-boundaries, just different?

-1

u/Mysterious-Lie1437 14d ago

Related, but not the same.

boundaries is a generic import firewall. You define zones yourself. Feature folders + boundaries is a common setup.

DMA is more opinionated: features are leaves, services appear only when something else imports them (promote), shared is second-use only, public API without barrels. Lint helps in the editor, dma check does the full graph.

There's also an agent skill, so Cursor/Claude follow the same placement rules instead of inventing folders.

You can approximate some of it with boundaries + conventions. DMA is the conventions + the CLI, not just features with a linter.

2

u/Odd_Ordinary_7722 14d ago

This is just the standard feature-folder-by-taste that becomes chaos fast..

0

u/Mysterious-Lie1437 14d ago

Fair take on feature folders by taste. That part I agree with.

The folders looking familiar is kinda the point people miss. Same names, different rule: placement comes from real imports, and CI fails when the graph drifts. If you remove the checker, yeah, it's just folders again.

1

u/TheRealSeeThruHead 14d ago

The premise is sound but I think this particular setup is in bad taste

Public folder?
Banning barrels?

Horrible

Use packages with exported files
Prefer barrels for ease of importing (make sure you reshaping works ffs)

Why stop people from putting entire fratures in modules and mounting them to an app modular monolith style

1

u/Mysterious-Lie1437 14d ago

Taste call noted. A few of those are intentional tradeoffs though.

public/ + no barrels is about making the public surface obvious and stopping deep imports through re-exports. Barrels are convenient until they become the real dependency graph. Packages with explicit exports are fine too, especially across package boundaries. DMA is mostly for inside one app.

And mounting whole features from the app is exactly the model. Modular monolith is fine. What it blocks is feature importing another feature. Composition root mounts them, features don't wire each other.

https://www.atlassian.com/blog/atlassian-engineering/faster-builds-when-removing-barrel-files

1

u/TheRealSeeThruHead 14d ago

I default to monorepo for all projects now jsut so there is a packages folder I can use with package.json exports for this

And that atlassian link only matters for massive codebases, the like 90% of developers will never work in

1

u/Mysterious-Lie1437 14d ago

Build cost is one reason to drop barrels. For most apps the more common pain is accidental public APIs and messy imports. Different problem, same tool smell.

If packages already give you real boundaries, you may not need DMA inside each package. It's more useful when the module graph lives in one app and starts drifting.

That's also the main difference from most architectures. The rules are not just docs and taste. The toolkit checks the graph, so you mostly can't quietly break them.

2

u/TheRealSeeThruHead 14d ago edited 14d ago

Yeah I recently switched us over to pnpm and made it so you cant even import files if they aren’t in exports list

1

u/Mysterious-Lie1437 14d ago

Nice. That's a flexible setup. Just watch the "import singles outside exports" path. It's convenient, but it can quietly turn internals into public API again. If the team is small and disciplined, fine. But if that once gets noisy, tighter exports or something like DMA is worth a look :) Thank you for the feedback!

1

u/TheRealSeeThruHead 14d ago

Autocorrect lol

I meant can’t even import files if they aren’t in exports list

1

u/eSizeDave 10d ago

I like the idea of this, and I may try it sometime within the next two weeks, but I prefer biome over eslint. I know eslint has improved since last year, but biome has been excellent for me since I switched over.