FORM FOLLOWS DOMAIN. DOMAIN COMES FIRST.NODE.JS / REACT
PROJECT STRUCTURE / SCAFFOLDER

STRUCTURE.
START HERE.

@domain-first/project-structure

Clear architecture costs files, contracts and wiring, so under a deadline code lands wherever it is quickest to write. The scaffolder makes the right place the shortest path.

01 / The problem

Architecture loses
to the deadline.

In most TypeScript codebases you choose between convenience and architecture. Clear boundaries mean more files, more contracts and more wiring β€” and every one of them is written by hand.

01

The structure lives in people's heads. Where does a query go? What is a port? The answer is a wiki page or a colleague.

02

Every feature starts with copy-paste. Copy a neighboring folder, rename, fix imports, delete leftovers, add the factory, add the export.

03

Shortcuts accumulate. Under pressure the logic goes where it is quickest to write. Boundaries blur one import at a time.

04

Review is spent on placement. β€œWhy is this in services?” instead of β€œis the rule right?” And a coding agent improvises a new layout every session.

02 / The approach

The clean path
is the shortest one.

The conventions become executable. The CLI asks which bounded context, layer and role a new piece of code has, and generates it in its place β€” with contracts, implementations, test skeletons and wiring that respect the boundaries. Doing it right takes a few prompts; doing it wrong takes extra effort.

The generated files belong to your project. You write the business rules.

03 / Three commands

Scaffold. Teach.
Check.

One package, three binaries.

npx df-psScaffold
  1. First run

    Asks your settings β†’ writes domain-first.project-structure.config.json β†’ exits.

  2. Every next run

    Opens the menu β†’ one operation β†’ files in their place.

npx df-skillsTeach
  1. Run

    Copies the agent skills β†’ .claude/skills or .agents/skills.

  2. After an upgrade

    Run again β†’ the new versions replace the old ones.

npx df-lintCheck
  1. Run

    Checks imports and wiring against the rules β†’ file:line report.

  2. In CI

    Anything found β†’ exit code 1 β†’ the build fails.

04 / df-lint

Boundaries
stay checked.

The scaffolder puts new code in its place. After that the code is edited by people and agents, and an import across a boundary is one autocomplete away. df-lint catches it before review does: it fits CI and pre-commit hooks.

context-isolation

A bounded context importing another one.

shared-layer

The Shared Layer importing a context beyond its errors.

layers

Imports against the layers, e.g. domain importing infrastructure.

dependencies

A module importing or wiring a kind its dependency rules don't allow.

react

Pages, widgets, UI-kit and hooks importing what they shouldn't.

clock

new Date() or Date.now() in domain or application β€” use the clock port.

05 / Your rules

The rules
are a default.

Teams that work differently change them in the config. df-ps offers dependencies and df-lint checks them by the same rules. Kinds and checks you don't mention keep their defaults.

rules.dependencies

What each kind of module may depend on: a list replaces the defaults, add and remove change them.

rules.lint

Which checks run: set a check to false to turn it off.

domain-first.project-structure.config.jsonExample
{
    "rules": {
        "dependencies": {
            "use-cases": { "add": ["use-cases"] },
            "orchestration-queries": { "remove": ["repositories"] },
            "application-services": ["application-ports"]
        },
        "lint": { "clock": false }
    }
}

Defaults for every kind: Dependency rules β†—

06 / Start

Add the scaffolder.

Terminal
npm install --save-dev @domain-first/project-structure
Terminal
npx df-ps

The first run asks for your settings, writes the config and exits. Every next run opens the menu and performs one operation. In a monorepo, run it inside the package you want to scaffold.

Building blocks β†—

Bounded contexts, the shared layer and the five layers.

Package README β†—

Every generator and integration.