FORM FOLLOWS DOMAIN. DOMAIN COMES FIRST.NODE.JS / REACT
DOMAIN → STRUCTURE → REACT

YOUR FEATURE.
YOUR REACT.

@domain-first/project-structure

Scaffold hooks, UI-kit components, pages and widgets. Keep each React feature in a predictable place, with the right boundary between behavior and rendering.

01Hooks, components and pages
02Three widget architectures
03Nested paths and module moves
01 / SETUP

Give React a place.

Project Structure scaffolds the React presentation layer inside your existing project. Install the CLI, run it and enable React during setup. The configuration flag is useReact. Then select Scaffold React module in the main menu.

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

React modules live under <rootFolder>/presentation/react. The examples below use src as the root folder. React and your application tooling are configured separately.

02 / MODULES

Build the pieces you need.

New shared hook

Generate a reusable app-wide hook. Enter debounce or use-debounce; the generator adds the use- prefix only once.

New UI-kit component

Generate a typed component and a public index. With Storybook configured, you also get a story skeleton ready for your examples. Reuse these visual building blocks across pages and widgets.

New page

Generate a page component with typed props. Compose widgets into a screen and connect it to your app’s routing.

New widget

Generate a feature-sized module. Choose how its behavior and rendering should be organized: monolithic, with separated UI, or headless.

src/presentation/reactGenerated structure
hooks/use-debounce.ts
ui-kit/button/button.tsx
ui-kit/button/index.ts
pages/orders-page.tsx
widgets/order-list/
03 / WIDGETS / MONOLITHIC

One widget. One place.

Choose New widget → monolithic for a small module whose props and rendering can stay together. The generator creates the widget component and re-exports it through an index. You implement the behavior inside that frame.

widgets/order-listGenerated structure
order-list/
  order-list-widget.tsx
  index.ts
WHEN TO CHOOSE IT

A compact feature with one presentation and little internal coordination is a good starting point for a monolithic widget.

04 / WIDGETS / SEPARATED UI

Behavior here. Rendering there.

STORYBOOK STORIES, FROM THE START

Generate the UI. Get the story skeleton too. With Storybook configured (storybookFramework), every new UI-kit component and widget with separated UI comes with a generated .stories.tsx file. The story is already in place: fill it with your props, states and scenarios.

Choose New widget → with separated ui when the feature needs a clear boundary between orchestration and appearance. The widget connects the UI-model hook to the rendering component; shared types describe the contract between them.

widgets/order-listGenerated structure
order-list/
  order-list-widget.tsx
  types.ts
  hooks/
    use-order-list-ui-model.ts
  ui/
    order-list-widget-ui.tsx
  index.ts

Keep state and event logic in the UI model, and render from its contract in the UI component. With Storybook configured, the generated story lives alongside the UI at ui/order-list-widget-ui.stories.tsx.

05 / WIDGETS / HEADLESS

One behavior. Different views.

Choose New widget → headless when the consumer should provide the rendering component. The generated widget has types and a UI-model hook, but receives its view through the UI prop.

widgets/order-listGenerated structure
order-list/
  order-list-widget.tsx
  types.ts
  hooks/
    use-order-list-ui-model.ts
  index.ts

This keeps the behavior reusable while the caller chooses the presentation. For example, the same feature can be presented as a list or a compact panel by supplying different UI components.

THE DISTINCTION

Separated UI gives the widget its own rendering component. Headless lets the consumer supply that component.

06 / NESTED PATHS

Let the path describe the feature.

Page and widget names accept slash-separated paths. Enter admin/panel/users to group a module under a meaningful hierarchy. This nests folders; you compose widgets inside other widgets in your React code.

New page → admin/panel/usersGenerated structure
src/presentation/react/pages/admin/panel/
  admin-panel-users-page.tsx

Component: AdminPanelUsersPage
New widget → admin/panel/usersGenerated structure
src/presentation/react/widgets/admin/panel/users/
  admin-panel-users-widget.tsx
  index.ts

Component: AdminPanelUsersWidget

The widget folder uses the final segment, users. File and component names use the entire path. A generated story uses the title Widgets/Admin/Panel/Users. Use lowercase names with hyphens inside each segment, such as sales/order-details.

07 / EVOLVE

Move the module with its feature.

Choose Move or rename page or Move or rename widget, select a module and enter its new slash-separated name. A widget moves with its whole folder, including assets. A page moves with matching companion files.

The CLI updates generated names, story titles and project imports, including relative paths and configured aliases. You can organize the feature as it grows without manually relocating every file.

STORYBOOK

Add integration → Storybook (React + Vite) prepares Storybook configuration and scripts. Future UI-kit components and widgets with separated UI can include stories. The CLI prints dependency installation commands for you to run.

Continue with the Project Structure guide ↗ for domain scaffolding, setup and other integrations.