Catalog npm
PACKAGE EXPLORERView in registry

02-rbor

npm

CLI tool for scaffolding opinionated, Clean Architecture-inspired React frontends with dependency graph analysis

architectureclean-architectureclidependency-graphdomain-drivenfrontendrborreactscaffolding
Versions collected4
Direct dependencies16From release 0.2.2
Last observed20 Oct, 16:54 UTC

README

Current package documentation

02-rBOR CLI

npm version CI License: MIT

recusrive Branching Orchestration Rendering

A CLI tool for building frontend applications following the 02-rBOR architecture pattern. Generate domain-driven feature modules with proper layering, enforce architectural rules, and analyze dependency graphs — with SVG visualization out of the box.

🤔 What is rBOR?

rBOR is an opinionated folder architecture for React apps. Instead of organizing by file type (components/, hooks/, services/ at the root), rBOR organizes by domain — each feature gets its own self-contained folder with every layer it needs.

The idea: a user feature shouldn't scatter its files across 6 different top-level folders. Everything related to user lives under domains/user/, with a single barrel export (index.tsx) as the public API.

Each domain follows a strict downward dependency rule inspired by the Dependency Inversion Principle:

  ┌─────────────────────────────┐
  │  Page (route)               │  composes components
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Component (UI)             │  renders data from hooks
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Hook — data / action       │  React Query fetching & mutations
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Hook — controller          │  creates service, wires methods
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Method (pure logic)        │  receives service as 1st param
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Service (HTTP layer)       │  extends BaseService
  └──────────────┬──────────────┘
                 ▼
  ┌─────────────────────────────┐
  │  Infrastructure (shared)    │  BaseService, ServiceFactory
  └─────────────────────────────┘

Control flows upward — each layer orchestrates the layer below it.
Dependencies flow downward — lower layers are completely independent of what consumes them.

This means:

  • Infrastructure (BaseService, ServiceFactory) knows nothing about any domain.
  • Service extends BaseService — depends only on infrastructure.
  • Method receives a service object as its first argument — depends only on services.
  • Hook (controller) creates the service via ServiceFactory, passes it to methods — depends on methods & infrastructure.
  • Hook (data/action) consumes the controller hook for fetching or mutations — depends on the controller.
  • Component renders data from hooks — depends only on hooks.
  • Page composes components — depends only on components.

Lower layers never import from higher layers. This keeps your business logic testable, your services reusable, and your UI replaceable.

📦 Installation

npm install -g 02-rbor
rbor init
rbor domain <domain-name>

Tip: If you prefer not to install globally, use npx — it works without any install:

npx 02-rbor init
npx 02-rbor domain <domain-name>

All commands work with npx 02-rbor <command>, for example:

npx 02-rbor domain user
npx 02-rbor validate
npx 02-rbor deps domains/user -f svg

🚀 Quick Start

1. Initialize your project

rbor init

This creates a .rborrc.json configuration file with your project defaults.

2. Generate your first domain

# Interactive mode — prompts for name and HTTP client
rbor domain

# Or pass the name directly
rbor domain user --http axios

This generates a complete domain structure:

domains/user/
├── index.tsx              # Barrel export (public API)
├── __test__/              # Test directory
├── components/
│   └── User.tsx           # Main component
├── hooks/
│   ├── useUser.ts         # Controller hook (creates service, wires methods)
│   ├── useUserData.ts     # Data hook (React Query)
│   └── useUserAction.ts   # Action hook (mutations)
├── methods/
│   └── user-logic.ts      # Pure async functions (React-independent)
├── schema/
│   └── user-schema.ts     # Validation schema (zod)
├── services/
│   └── user-service.ts    # Domain service (HTTP layer)
├── types/
│   └── user-types.ts      # TypeScript types
└── utils/
    ├── constant/
    │   ├── user-constants.ts
    │   └── user-endpoints.ts
    └── helper/
        └── user-helpers.ts

What each folder does

FolderPurposeRules
components/React UI. Renders data, handles user interaction.Can import from hooks/. Nothing else in the domain.
hooks/Wiring layer. Connects React to your domain logic.useUser creates the service object and passes it to methods. useUserData and useUserAction provide React Query scaffolds for fetching and mutations.
methods/Pure business logic. Every function receives the service as its first argument — no React, no hooks, no global state.Can import from services/ and utils/. Must stay framework-free so it's easy to test and reuse.
services/HTTP layer. Extends BaseService to get an axios (or fetch/ky) instance. Exposes typed get, post, put, delete methods with URL param substitution.Can import from infrastructure/ and utils/.
schema/Validation schemas (zod by default). Define the shape of your domain data for form validation, API response parsing, etc.Pure data definitions — no side effects.
types/TypeScript interfaces and types for this domain.Pure type definitions.
utils/constant/Endpoint paths and domain-specific constants (timeouts, config values, feature flags).Pure values — no logic.
utils/helper/Domain-specific utility functions (formatters, transformers, parsers).Pure functions — no React, no service calls.
__test__/Tests for this domain.Mirrors the folder structure above.
index.tsxBarrel export — the only file other parts of your app should import from.Re-exports the component and anything else that's part of the public API.

How data flows

  ┌──────────────────────────────┐
  │  Component  (User.tsx)       │  UI — renders data
  └──────────────┬───────────────┘
                 │ uses hooks
                 ▼
  ┌──────────────────────────────┐
  │  useUserData / useUserAction │  React Query — fetching & mutations
  └──────────────┬───────────────┘
                 │ consumes controller
                 ▼
  ┌──────────────────────────────┐
  │  useUser  (controller hook)  │  creates service, wires methods
  │                              │  ServiceFactory.create('USER')
  └───────┬──────────────┬───────┘
          │              │
          ▼              ▼
  ┌──────────────┐  ┌────────────────────┐
  │  user-logic  │  │  ServiceFactory    │
  │  (methods)   │  │  (infrastructure)  │
  └──────┬───────┘  └────────────────────┘
         │ calls service
         ▼
  ┌──────────────────────────────┐
  │  UserService                 │  extends BaseService
  │  self-registers with Factory │
  └──────────────┬───────────────┘
                 │
                 ▼
  ┌──────────────────────────────┐
  │  BaseService                 │  axios instance, interceptors,
  │  (infrastructure)            │  base URL, timeout
  └──────────────────────────────┘

Dependency Inversion in practice:

  • Lower layers are stable abstractions — they define contracts (BaseService, ServiceFactory registry) that don't change when features change.
  • Higher layers are volatile details — UI, state management, and wiring change frequently.
  • Each layer only depends on the layer directly below it, never sideways or upward.
  • ServiceFactory never imports domain services — each service self-registers via ServiceFactory.register() at the bottom of its file. The controller hook triggers registration by importing the service file.
  • hook-data and hook-action are independent siblings — both depend on the controller hook, but never on each other.

3. Add endpoints and constants

cd domains/user
rbor endpoint users/:id/profile    # → USERS_ID_PROFILE
rbor constant timeout=3000         # → TIMEOUT = 3000

4. Analyze dependencies

# Who imports this file?
rbor deps domains/user/components/User.tsx -d reverse -f svg -o deps.svg

# What does this file import?
rbor deps src/app/App.tsx -d forward -f tree

5. Validate architecture

rbor validate

📚 Commands

CommandDescription
rbor initInitialize .rborrc.json configuration
rbor domain [name]Generate a domain (interactive if no name given)
rbor endpoint <path>Add an endpoint to the current domain
rbor constant <key=value>Add a constant to the current domain
rbor listList all domains with metadata
rbor validateValidate architecture rules
rbor deps <path>Analyze dependency graph
rbor davinciCredits

rbor init

Initialize rBOR configuration in your project.

rbor init [options]

Options:
  --http <client>               HTTP client (axios, fetch, ky)
  --domains-path <path>         Path to domains folder
  --infrastructure-path <path>  Path to infrastructure folder
  --force                       Overwrite existing config

Creates .rborrc.json:

{
  "http": "axios",
  "domainsPath": "domains",
  "infrastructurePath": "infrastructure",
  "schema": { "library": "zod" }
}

rbor domain [name]

Generate a new domain with the full 02-rBOR structure.

# Interactive mode (prompts for name, HTTP client, confirmation)
rbor domain

# Direct mode
rbor domain auth
rbor domain products --http ky

What it generates:

  • ✅ Component with TypeScript + JSX
  • ✅ Three-hook pattern (controller, data, action)
  • ✅ Pure domain logic (methods receive service, stay React-free)
  • ✅ Service layer with HTTP client integration
  • ✅ Validation schemas (zod)
  • ✅ Type definitions
  • ✅ Constants and endpoint files
  • ✅ Barrel export (index.tsx)

Hook pattern:

Three hooks are generated per domain:

  • use<Domain> — Controller hook. Creates a service object and wires up all methods:
  • use<Domain>Data — Data hook. Fetches server state using React Query (commented scaffold).
  • use<Domain>Action — Action hook. Mutation actions via React Query (commented scaffold).

The controller hook wires up services and methods:

export const useUser = () => {
  const service = ServiceFactory.create('USER') as UserService;

  return {
    getList: () => getUserList(service),
    getById: (id: string) => getUserById(service, id),
    create: (data: unknown) => createUser(service, data),
    update: (id: string, data: unknown) => updateUser(service, id, data),
    remove: (id: string) => deleteUser(service, id),
  };
};

Note: If you need access to the Redux store or other global state, access it in the hook and pass values down to your methods. Methods should remain pure async functions.


rbor endpoint <path>

Add an API endpoint constant to an existing domain. Run from inside domains/<domain>/.

rbor endpoint users/:id/profile

Generates ALL_CAPS keys and appends to utils/constant/<domain>-endpoints.ts:

export const AUTH_ENDPOINTS = {
  LOGIN: '/login',
  USERS_ID_PROFILE: '/users/:id/profile',
} as const;

rbor constant <key=value>

Add a constant to the current domain's constants file. Run from inside domains/<domain>/.

rbor constant timeout=3000        # → export const TIMEOUT = 3000;
rbor constant maxRetries=5        # → export const MAX_RETRIES = 5;
rbor constant api-url=https://x   # → export const API_URL = 'https://x';
rbor constant debug=true          # → export const DEBUG = true;

Auto-detects value types — numbers and booleans stay unquoted, strings get wrapped in quotes.


rbor list

List all domains with metadata.

rbor list    # or: rbor ls

rbor validate

Enforce 02-rBOR architectural rules.

rbor validate          # or: rbor lint
rbor validate --strict # treat warnings as errors

What it checks:

  • ❌ No cross-domain imports — Domains must not import from each other
  • ❌ Downward-only dependencies — Page → Component → Hook (data/action) → Hook (controller) → Method → Service → Infrastructure
  • ❌ Sibling isolation — hook-data and hook-action must be independent (no importing each other)
  • ❌ No React in methods layer — Pure logic must be framework-free
  • ⚠️ Barrel exports — Every domain should have an index.tsx
  • ⚠️ Circular dependencies — Warns about import cycles

rbor deps <path>

Analyze dependency graphs for any file or directory. Traces imports forward (what does this file use?) or reverse (who imports this file?) and renders the result in five different formats — from quick terminal summaries to full SVG diagrams you can open in a browser.

rbor deps <path> [options]

Flags

FlagShortDescriptionDefault
--direction <dir>-dforward (imports) or reverse (importers)forward
--format <fmt>-fOutput format: summary, tree, json, dot, svgsummary
--output <file>-oWrite output to a file instead of stdout(stdout)
--depth <n>Maximum traversal depth10
--include-externalInclude external npm packages in the graphfalse
--include-testsInclude test files (*.test.*, *.spec.*)false
--include-typesInclude type-only imports (import type { ... })true
--aliases <mapping>Path aliases, e.g. "@/=src/,@utils/=src/utils/"(auto-detected from tsconfig)

Alias auto-detection: If your project has a tsconfig.json with compilerOptions.paths, aliases are read automatically. Use --aliases to add extras or override.

Direction

--direction forward (default) — "What does this file import?"

          ┌──────────┐
          │ App.tsx  │
          │ (entry)  │
          └────┬─────┘
               │
     ┌─────────┼──────────┐
     ▼         ▼          ▼
 router.ts  store.ts  utils.ts

--direction reverse — "Who imports this file?"

 Layout.tsx  Main.tsx  test.tsx
     │         │          │
     └─────────┼──────────┘
               ▼
          ┌──────────┐
          │ App.tsx  │
          │ (target) │
          └──────────┘

Use forward to understand what a file depends on. Use reverse to see a file's consumers — useful for gauging blast radius before a refactor.

Output Formats

summary (default) — Grouped table view in the terminal. Shows imports and importers categorized by file type, plus stats.

═══════════════════════════════════════════════════════════════
  FILE SUMMARY: useUser.ts
  Path: domains/user/hooks/useUser.ts
═══════════════════════════════════════════════════════════════

📥 IMPORTS (what this file depends on)
  🔨 method        user-logic.ts
  🏗️ infrastructure ServiceFactory.ts
  📝 type          user-types.ts

📤 IMPORTED BY (what depends on this file)
  📊 hook-data     useUserData.ts
  ⚡ hook-action   useUserAction.ts

📊 STATS
  Nodes: 5  │  Edges: 4  │  Circular: 0
═══════════════════════════════════════════════════════════════

tree — ASCII tree in the terminal. Respects --depth to control how deep the traversal goes.

📦 domains/user/hooks/useUser.ts
├── 🔨 domains/user/methods/user-logic.ts
│   └── ⚙️ domains/user/services/user-service.ts
│       └── 🏗️ infrastructure/BaseService.ts
├── 🏗️ infrastructure/ServiceFactory.ts
└── 📝 domains/user/types/user-types.ts

json — Full structured output. Contains nodes, edges, metadata, and stats. Pipe to jq or consume in scripts.

rbor deps domains/user -f json | jq '.stats'
rbor deps domains/user -f json -o deps.json
{
  "nodes": [
    { "id": "domains/user/hooks/useUser.ts", "type": "internal", "category": "hook-controller" }
  ],
  "edges": [
    {
      "source": "domains/user/hooks/useUser.ts",
      "target": "domains/user/methods/user-logic.ts",
      "importType": "static"
    }
  ],
  "metadata": { "direction": "forward", "circularDependencies": [] },
  "stats": { "nodeCount": 5, "edgeCount": 4 }
}

dot — Graphviz DOT format. Use if you have Graphviz installed locally or want to paste into an online viewer.

rbor deps domains/user -f dot -o deps.dot
dot -Tpng deps.dot -o deps.png          # render with Graphviz

svg — Renders the DOT graph to an SVG image using @viz-js/viz (bundled, no external install needed). This is the richest format — color-coded nodes, labeled edges, and circular dependency highlighting.

rbor deps domains/user -f svg -o deps.svg
# Open deps.svg in your browser or VS Code

SVG/DOT node colors:

  ┌────────────────────────────┐
  │  🟣 Entry point (purple)   │
  │  🔵 Internal file (blue)   │
  │  🟢 External package (green)│
  │  🟡 Dynamic import (amber) │
  │  ⚪ Built-in module (grey) │
  └────────────────────────────┘

Circular Dependency Detection

All formats detect and report circular imports. In SVG/DOT output they're visually highlighted:

  Normal edge:              Circular edge:

  ┌────────┐                ┌────────┐
  │  A.ts  │                │  A.ts  │ (red border)
  └───┬────┘                └───┬────┘
      │                         │
      ▼                         ▼ ⚠ circular (red edge)
  ┌────────┐                ┌────────┐
  │  B.ts  │                │  B.ts  │ (red border)
  └────────┘                └────────┘

  🔴 Red borders — nodes involved in a cycle
  🔴 Red edges   — the circular import itself, labeled "⚠ circular"
  📋 Legend box   — appears in the bottom-left with the cycle count

The summary and tree formats print (circular) inline when a cycle is encountered.

Recipes

# Quick overview of a domain's internal structure
rbor deps domains/auth -f tree --depth 3

# Full SVG graph saved to file
rbor deps domains/auth -f svg -o auth-deps.svg

# Reverse lookup: who depends on this service?
rbor deps domains/auth/services/auth-service.ts -d reverse -f tree

# Include npm packages in the graph
rbor deps src/App.tsx -f svg --include-external -o full-deps.svg

# Shallow analysis (immediate imports only)
rbor deps domains/auth/hooks/useAuth.ts -f summary --depth 1

# JSON for scripting / CI pipelines
rbor deps domains/auth -f json -o deps.json

# Custom aliases (on top of tsconfig auto-detection)
rbor deps src/App.tsx --aliases "@shared/=src/shared/,@lib/=lib/"

⚙️ Configuration

.rborrc.json

{
  "http": "axios",
  "domainsPath": "domains",
  "infrastructurePath": "infrastructure",
  "schema": { "library": "zod" }
}
OptionDescriptionValues
httpDefault HTTP clientaxios, fetch, ky
domainsPathWhere to generate domainsAny path
infrastructurePathShared infrastructure dirAny path
schema.libraryValidation libraryzod, yup, none

CLI flags always override config values.


🏗️ Architecture Philosophy

02-rBOR is built on the Dependency Inversion Principle — higher layers control the flow, lower layers remain independent abstractions.

The Layer Model

Layer 0  │  type, schema, constant, config, util     ← importable by anyone (pure data)
Layer 1  │  infrastructure (BaseService, Factory)     ← independent, no domain knowledge
Layer 2  │  service (extends BaseService)             ← depends only on infrastructure
Layer 3  │  method (pure async functions)             ← depends on service, no React
Layer 4  │  hook-controller (useUser)                 ← wires service + methods
Layer 5  │  hook-data / hook-action                   ← consumes controller, independent siblings
Layer 6  │  component (User.tsx)                      ← renders from hooks
Layer 7  │  page (route)                              ← composes components

Each layer can import from the same layer or below, never above. hook-data and hook-action are at the same level but must stay independent — both consume the controller, neither consumes the other.

Why this works

  1. Feature Containerization — Each domain is self-contained with a single barrel export. The rest of the app imports from 'domains/user', never from 'domains/user/services/user-service'.
  2. Downward Dependencies — Complexity flows down: Page → Component → Hook → Method → Service → Infrastructure. Upper layers orchestrate lower layers, never the reverse.
  3. Layer Separation — React stays in the component and hook layers. Methods are pure async functions that receive a service object and return data. You can unit test them without rendering anything.
  4. No Cross-Domain Imports — domains/auth must never import from domains/user. Shared logic goes in infrastructure/.
  5. Service as a Parameter — Methods don't create their own HTTP clients. They receive the service object from the hook, making them easy to mock and test.
  6. Sibling Isolation — useUserData (fetching) and useUserAction (mutations) are independent. They both depend on useUser (the controller), but never on each other. This prevents tangled state flows between reads and writes.

Infrastructure (shared across all domains)

infrastructure/
├── BaseService.ts       # Abstract class — creates axios instance, interceptors, base CRUD methods
├── ServiceFactory.ts    # Registry-based factory — services self-register, factory never imports domain code
└── generateURL.ts       # URL builder — replaces :params and appends ?query strings
  • BaseService — Every domain service extends this. It creates an axios instance with configured baseURL, timeout, and request/response interceptors. Exposes protected get, post, put, delete methods that all domain services inherit.
  • ServiceFactory — A registry-based factory. Each domain service calls ServiceFactory.register('KEY', () => new DomainService()) at the bottom of its own file. The factory never imports domain code — it just stores creators and instantiates on demand via ServiceFactory.create('KEY'). This keeps infrastructure fully independent (Dependency Inversion).
  • generateURL — Utility for URL parameter substitution (/users/:id → /users/42) and query string building.

🧪 Testing

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report

💡 Examples

# Full domain setup
rbor domain auth --http axios
cd domains/auth
rbor endpoint auth/login
rbor endpoint auth/logout
rbor endpoint auth/refresh
rbor constant session-timeout=1800000

# Generate more domains
rbor domain user
rbor domain products --http ky

# Analyze and validate
rbor validate --strict
rbor deps domains/auth -d forward -f svg -o auth-deps.svg
rbor list

📄 License

MIT © 02-davinci-01


rendered to reality by 02-davinci-01

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 4

Collected releases
VersionPublishedDirect dependenciesOpen version
0.2.2Registry latest20 Feb 202616
0.2.120 Feb 202616
0.2.020 Feb 202616
0.1.018 Feb 202616

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
02-davinci-01/02-rbor

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 16:54 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:cae8688b969179f1d3c97fd37fdb7da6e59ffc082779c25cb485559b4bce701d