atomic-bomb
v7.2.4
Published
A small CLI tool to create atoms, molecules and organisms in a NodeJS app
Maintainers
Readme
Atomic Bomb
Atomic Bomb is a small CLI for generating React project structure from atomic design and DDD-style conventions.
It can create:
- atomic components:
atom,molecule,organism,template,page - shared files next to components:
hook,lib - feature modules with their own atomic structure
- domain containers and subdomain folders
- scoped domain files:
api,event,helper,hook,model,page,service,state - structure JSON exports and imports
- recursive generated item removal
Important This tool is for educational purposes.
Install
npm install --global atomic-bombOr install it in a project:
npm install --save-dev atomic-bomb
yarn add -D atomic-bombYou can also run it with npx:
npx atomic-bomb@latest --type atom --name LogoRequirements
Run Atomic Bomb from the root of a project with a package.json.
The CLI checks the configured search package in your project dependencies. For React templates this is usually react.
Quick Start
Configure the platform:
atomic-bomb --platform react-ts
atomic-bomb -p react-tsCreate a component:
atomic-bomb --type atom --name LogoAfter the first configuration, --platform can be omitted. Atomic Bomb reads it from .atomic-bomb.
atomic-bomb --type molecule --name "Button Group"Usage
atomic-bomb --platform [PLATFORM]
atomic-bomb -p [PLATFORM]
atomic-bomb --type atom|molecule|organism|template|page --name [NAME](,[NAME],[NAME])
atomic-bomb --type hook --name [NAME](,[NAME],[NAME])
atomic-bomb --type lib --name [NAME](,[NAME],[NAME])
atomic-bomb --type service --name [NAME](,[NAME],[NAME])
atomic-bomb --type module --name [NAME](,[NAME],[NAME])
atomic-bomb --type module --for [DOMAIN] --name [NAME]
atomic-bomb --type module --for [DOMAIN]/[SUBDOMAIN] --name [NAME]
atomic-bomb --type domain --name [NAME](,[NAME],[NAME])
atomic-bomb --type subdomain --for [DOMAIN] --name [NAME](,[NAME],[NAME])
atomic-bomb --for [MODULE] --type atom|molecule|organism|template|page --name [NAME]
atomic-bomb --module [MODULE] --type hook|lib|service --name [NAME]
atomic-bomb --module [MODULE] --for [DOMAIN] --type atom|molecule|organism|template|page|hook|lib|service --name [NAME]
atomic-bomb --module [MODULE] --for [DOMAIN]/[SUBDOMAIN] --type atom|molecule|organism|template|page|hook|lib|service --name [NAME]
atomic-bomb --for [DOMAIN]/[SUBDOMAIN] --type atom|molecule|organism|template --name [NAME]
atomic-bomb --for [DOMAIN]/[SUBDOMAIN] --type api|event|helper|hook|lib|model|page|service|state --name [NAME]
atomic-bomb --export structure.json
atomic-bomb --from structure.json
atomic-bomb --remove [NAME]
atomic-bomb --clean
atomic-bomb --update
atomic-bomb --type atom --name Button --ai [--prompt PROMPT] [--validate]Platforms
Platforms are pulled from the template repository configured in package.json:
{
"config": {
"templates": "https://github.com/ReneKrewinkel/atomic-bomb-templates.git"
}
}Use:
atomic-bomb --platform react-ts
atomic-bomb -p react-tsThis writes or updates .atomic-bomb without requiring --name. During platform setup, Atomic Bomb also asks whether to configure an AI provider for the future --ai flow.
Available platforms depend on the template repository. See atomic-bomb-templates.
Configuration
Atomic Bomb creates a .atomic-bomb file in the project root.
Example:
{
"search": "react",
"extension": "tsx",
"platform": "react-ts",
"destination": "src/components",
"scss": true,
"ai": {
"enabled": true,
"provider": "openai",
"baseUrl": "https://api.openai.com/v1",
"model": "gpt-5-mini",
"apiKeyEnv": "OPENAI_API_KEY",
"skillPath": ".skills/atomic-bomb/7.0.0/index.md"
}
}Fields:
search: dependency name to check inpackage.jsonextension: component file extension:js,jsx,tsortsxplatform: default platform used when--platformis omitteddestination: component root, usuallysrc/componentsscss: whether_index.scssfiles are created and updatedai: optional provider configuration for--ai
AI fields:
enabled: whether AI-assisted generation is configuredprovider: provider adapter name; platform setup defaults toopenaibaseUrl: provider API base URL; platform setup defaults tohttps://api.openai.com/v1model: provider model name; platform setup defaults togpt-5-miniapiKeyEnv: environment variable that contains the API key; platform setup asks only for this value and defaults toOPENAI_API_KEY; secrets are not stored in.atomic-bombskillPath: installed skill index path, defaulting to.skills/atomic-bomb/<atomic-bomb-version>/index.md
The --ai flag uses the configured provider adapter to read the installed skill files, expand the scaffold plan and complete generated files.
AI-Assisted Generation
Configure the platform and AI provider first:
atomic-bomb -p react-tsDuring platform setup, Atomic Bomb can store provider settings in .atomic-bomb. Provider setup defaults to OpenAI (provider: "openai", baseUrl: "https://api.openai.com/v1", model: "gpt-5-mini") and only asks for the API key environment variable name. The default skillPath is:
.skills/atomic-bomb/<atomic-bomb-version>/index.mdRunning atomic-bomb -p also installs the bundled skill files into the target project:
.skills/atomic-bomb/<atomic-bomb-version>/Refresh the installed skill files without reconfiguring the platform:
atomic-bomb --updateThis replaces .skills/atomic-bomb/<atomic-bomb-version>/ with the bundled skill files from the current Atomic Bomb version. If .atomic-bomb already has AI provider settings, --update preserves them and updates ai.skillPath to the refreshed versioned index.md.
Use --ai on generation commands when you want the configured provider adapter to read those installed skill instructions and determine the component setup before implementation. The openai and openai-compatible provider names use the OpenAI-compatible adapter.
For page and organism requests, Atomic Bomb seeds the scaffold plan with the standard skill-driven composition stack before asking the provider to complete files. A form-like page request will consistently scaffold base atoms such as Label, InputField, Button and Icon, then compose them through ButtonGroup and Form before completing the requested page.
Add --validate to run a post-generation AI validation pass. The provider reviews the completed generated files against the installed skill instructions and checks for bugs, prop/API mismatches, broken imports, accessibility issues and usability gaps. Validation is only valid with --ai; if the provider returns issues, the command fails with the reported findings.
Create an AI-assisted atom:
atomic-bomb --type atom --name Button --aiCreate a composed molecule:
atomic-bomb --type molecule --name "Button Group" --ai --prompt "Use primary and secondary actions with optional icons."Create a page-level feature:
atomic-bomb --type page --name ServiceDesk --ai --prompt "Create a ticket intake screen with title input, save/cancel actions, loading state, and success callback."Create and validate a page-level feature:
atomic-bomb --type page --name ServiceDesk --ai --validate --prompt "Create a ticket intake screen with title input, save/cancel actions, loading state, and success callback."Create a scoped component inside a domain subdomain:
atomic-bomb --for Orders/Sales --type organism --name OrdersTable --aiFor --ai requests, the provider should use the configured skillPath to decide:
- whether existing atoms, molecules or organisms should be reused or extended
- which Atomic Bomb artifacts should be scaffolded
- which
_types_contracts, props and variants are needed - which TypeScript and Sass barrels must be updated
- which token-backed CSS variables and Sass mixins should be used
- which mocks, stories and tests should be completed
- which validation command should run before completion
- whether
--validateshould fail because generated code violates the skill, contains likely bugs or has usability/accessibility problems
The CLI stores the AI intent with the parsed command and exposes the provider configuration. If no adapter exists for the configured provider, the command exits with a clear error.
--prompt and --validate are only valid with --ai. Use --prompt for request-specific instructions that should be combined with the installed skill instructions.
Compatibility
Atomic Bomb remains compatible with existing non-AI generation workflows. Commands that do not pass --ai still scaffold from templates, update barrels, create sidecar files, export/import structure JSON and remove generated items without calling an AI provider.
AI support is opt-in:
--aimust be passed before any provider call is made--promptand--validateare invalid without--ai- the optional
.atomic-bomb.aiblock is ignored by normal scaffolding commands - API keys are read only from the configured environment variable and are not stored in
.atomic-bomb
There are two additive filesystem changes in newer versions:
atomic-bomb -pinstalls bundled skill files into.skills/atomic-bomb/<atomic-bomb-version>/- atomic directory setup creates
src/components/_types_/index.tsorindex.js
Those additions are safe for existing projects, but they can make the generated project tree slightly larger than older Atomic Bomb versions. Use atomic-bomb --update to refresh installed skill files after upgrading Atomic Bomb.
Naming
Atomic Bomb normalizes names by type.
Component and container types use PascalCase:
atommoleculeorganismtemplatepagemoduledomainsubdomain
Non-component file types use camelCase:
apieventhelperhooklibmodelservicestate
Examples:
atomic-bomb --type atom --name "data table"
# DataTable
atomic-bomb --type hook --name "use data"
# useData
atomic-bomb --type service --name "order service"
# orderService
atomic-bomb --for Orders/Sales --type event --name "order created"
# orderCreatedExisting PascalCase component names and existing camelCase non-component names are preserved.
CLI Output
Generated output uses icons for the newer structure types:
hook: 🪝lib: 📚domain: 🏢subdomain: 🗄️
Atomic Components
Create one component:
atomic-bomb --type atom --name Label
atomic-bomb --type molecule --name Header
atomic-bomb --type organism --name Navigation
atomic-bomb --type template --name Dashboard
atomic-bomb --type page --name HomeCreate multiple components:
atomic-bomb --type atom --name Label,Button,InputCreate a multi-word component:
atomic-bomb --type molecule --name "Button Group"Atomic components are created in:
src/components/[type]s/[Name]Example output for a React TypeScript component:
src/components/molecules/ButtonGroup
├── ButtonGroup.interface.tsx
├── ButtonGroup.mock.ts
├── ButtonGroup.stories.tsx
├── ButtonGroup.test.tsx
├── ButtonGroup.tsx
├── _ButtonGroup.style.scss
├── _index.scss
└── index.tsxAtomic directory indexes are created for each component bucket:
src/components
├── index.ts
├── _types_
│ └── index.ts
├── atoms
│ ├── index.tsx
│ └── _index.scss
├── molecules
│ ├── index.tsx
│ └── _index.scss
├── organisms
│ ├── index.tsx
│ └── _index.scss
├── templates
│ ├── index.tsx
│ └── _index.scss
└── pages
├── index.tsx
└── _index.scssWhen extension is tsx or jsx, non-component barrel files use the matching logic extension:
tsx->tsjsx->js
Hooks
Create hooks next to components:
atomic-bomb --type hook --name useDataOutput:
src/hooks
├── index.ts
└── useData
├── index.ts
└── useData.tsThe generated file contains:
export const useData = () => {}
export default useDataLib
Create shared lib files next to components:
atomic-bomb --type lib --name formatDateOutput:
src/lib
├── index.ts
└── formatDate
├── index.ts
└── formatDate.tsThe generated file contains:
export const formatDate = () => {}
export default formatDateDomains
Create a domain directory next to components:
atomic-bomb --type domain --name OrdersOutput:
src/domains
├── index.ts
└── Orders
└── index.tsThe top-level src/domains/index.ts barrel exports every domain using its
domain name as an alias:
export * as Orders from "./Orders"
export * as Billing from "./Billing"Modules
Create a feature module next to components:
atomic-bomb --type module --name "User Manager"Output:
src/modules/UserManager
├── components
│ ├── atoms
│ ├── molecules
│ ├── organisms
│ ├── pages
│ └── templates
├── hooks
├── lib
├── services
└── index.tsThe top-level src/modules/index.ts barrel exports every module using its
module name as an alias:
export * as UserManager from "./UserManager"
export * as OrderManager from "./OrderManager"Use either --for [MODULE] or --module [MODULE] to generate inside it:
atomic-bomb --type atom --name Button --for UserManager
atomic-bomb --type molecule --name UserForm --module UserManager
atomic-bomb --type page --name Users --for UserManager
atomic-bomb --type hook --name useUsers --for UserManager
atomic-bomb --type lib --name userMapper --for UserManager
atomic-bomb --type service --name userService --module UserManagerAtomic types are generated under src/modules/UserManager/components. The
components directory is always lowercase, including its module barrel export:
export * from "./components"Modules support only atomic components, hooks, libs, and services. Hooks, libs, and services are generated in their matching module-level folders. Referencing a module that does not exist creates its structure automatically.
Modules can also belong to a domain or subdomain:
atomic-bomb --type module --name Checkout --for Orders
atomic-bomb --type module --name UserManager --for Orders/SalesThese commands create:
src/domains/Orders/modules/Checkout
src/domains/Orders/Sales/modules/UserManagerGenerate artifacts inside a nested module by combining --module and --for:
atomic-bomb --module Checkout --for Orders --type page --name CheckoutPage
atomic-bomb --module UserManager --for Orders/Sales --type atom --name Button
atomic-bomb --module UserManager --for Orders/Sales --type hook --name useUsers
atomic-bomb --module UserManager --for Orders/Sales --type lib --name userMapper
atomic-bomb --module UserManager --for Orders/Sales --type service --name userServiceEach nested modules/index.ts barrel exports modules using aliases:
export * as Checkout from "./Checkout"
export * as UserManager from "./UserManager"Module component stories include the module in their Storybook title:
title: "modules/UserManager/Components/atoms/Button"
title: "domains/Orders/modules/Checkout/Components/pages/CheckoutPage"
title: "domains/Orders/Sales/modules/UserManager/Components/atoms/Button"Top-level domain and module namespace barrels can be imported and composed directly:
import { DomainName } from "@/domains"
import { ModuleName } from "@/modules"
const App = () => {
return (
<div>
<ModuleName.PageName />
<DomainName.SubdomainName.PageName />
</div>
)
}
export default AppSubdomains
Create a subdomain inside a domain:
atomic-bomb --type subdomain --for Orders --name SalesIf the domain does not exist, it is created.
Output:
src/domains/Orders
├── index.ts
└── Sales
├── api
│ └── index.ts
├── components
│ ├── index.ts
│ ├── atoms
│ │ ├── index.tsx
│ │ └── _index.scss
│ ├── molecules
│ │ ├── index.tsx
│ │ └── _index.scss
│ ├── organisms
│ │ ├── index.tsx
│ │ └── _index.scss
│ ├── templates
│ │ ├── index.tsx
│ │ └── _index.scss
│ └── pages
│ ├── index.tsx
│ └── _index.scss
├── events
│ └── index.ts
├── helpers
│ └── index.ts
├── hooks
│ └── index.ts
├── lib
│ └── index.ts
├── models
│ └── index.ts
├── modules
│ └── index.ts
├── pages
│ └── index.ts
├── services
│ └── index.ts
├── state
│ └── index.ts
└── index.tsThe subdomain index.ts exports every DDD folder:
export * from "./components"
export * from "./hooks"
export * from "./lib"
export * from "./services"
export * from "./state"
export * from "./models"
export * from "./events"
export * from "./helpers"
export * from "./api"
export * from "./pages"Scoped Generation
Use --for [DOMAIN]/[SUBDOMAIN] to create files inside a subdomain.
Atomic component types go into the subdomain components folder:
atomic-bomb --for Orders/Sales --type atom --name Logo
atomic-bomb --for Orders/Sales --type molecule --name FilterBar
atomic-bomb --for Orders/Sales --type organism --name OrdersTable
atomic-bomb --for Orders/Sales --type template --name SalesDashboardExample:
src/domains/Orders/Sales/components/atoms/Logo
├── Logo.interface.tsx
├── Logo.mock.ts
├── Logo.stories.tsx
├── Logo.test.tsx
├── Logo.tsx
├── _Logo.style.scss
├── _index.scss
└── index.tsxScoped domain file types go into their matching folders:
atomic-bomb --for Orders/Sales --type hook --name useOrders
atomic-bomb --for Orders/Sales --type lib --name formatOrder
atomic-bomb --for Orders/Sales --type service --name orderService
atomic-bomb --for Orders/Sales --type event --name orderCreated
atomic-bomb --for Orders/Sales --type helper --name formatOrder
atomic-bomb --for Orders/Sales --type api --name fetchOrders
atomic-bomb --for Orders/Sales --type model --name order
atomic-bomb --for Orders/Sales --type state --name orderState
atomic-bomb --for Orders/Sales --type page --name SalesOverviewExamples:
src/domains/Orders/Sales/hooks/useOrders
├── index.ts
└── useOrders.ts
src/domains/Orders/Sales/services/orderService
├── index.ts
└── orderService.tsEach folder index is updated:
export { default as orderService } from "./orderService"Scoped generation repairs missing subdomain index files when the subdomain already exists.
Scoped component stories include their domain and subdomain in the Storybook title:
title: "domains/Orders/Sales/Components/atoms/Logo"The same convention applies to components rendered directly for a domain:
title: "domains/Orders/Components/atoms/Logo"Generated Documentation
Generated libs, hooks, services, domains, subdomains, modules, and scoped DDD
files include a <name>.mdx file beside their named source file. For example,
src/domains/Orders/Sales/api/fetchOrders/fetchOrders.mdx contains:
import { Meta, Source } from "@storybook/addon-docs/blocks"
import source from "./fetchOrders.ts?raw"
<Meta title="domains/Orders/Sales/api/fetchOrders" />
# api fetchOrders
**File:** `src/domains/Orders/Sales/api/fetchOrders/fetchOrders.ts`
Add Documentation for api / fetchOrders here.
<Source code={source} language="ts" />Existing MDX documentation is preserved when a domain, subdomain, or module is reused for additional generated files.
Pass --ai to ask the configured provider to replace the placeholder with
request-specific documentation based on the generated source:
atomic-bomb --type hook --name useOrders --ai
atomic-bomb --for Orders/Sales --type api --name fetchOrders --ai
atomic-bomb --module UserManager --type service --name userService --aiFor these documented artifacts, AI completion updates the named source and MDX
files without expanding the Atomic Design component scaffold. The provider is
instructed to preserve the MDX Meta, title, file path, and Source blocks
while documenting the purpose, public API, inputs, outputs, usage, and
important behavior.
Remove Generated Items
Remove generated items by name:
atomic-bomb --remove Logo
atomic-bomb --remove orderServiceThe remove command scans generated components, domains, modules,
hooks, and lib folders recursively. It removes every matching item
directory and cleans matching TypeScript and Sass barrel lines such as:
export { default as Logo } from "./Logo"
export * as Orders from "./Orders"@use "./Logo";Clean Unused Items
Scan generator-owned component, domain, module, hook, lib, and service folders for unused paths:
atomic-bomb --cleanThe command lists every proposed deletion and asks for confirmation:
Unused generated paths:
src/components/atoms/OldButton
src/hooks/oldHook.ts
Remove these unused paths? [y/N]:A generated path is considered unused when its name is not referenced by another source file. Barrel files, stories, tests, and mocks do not count as usage. This is a conservative text scan rather than compiler-level dead-code analysis, so review the displayed paths before confirming.
Only y or yes removes the listed paths. Pressing Enter, entering another
answer, or running without an interactive terminal cancels the clean. Matching
TypeScript and Sass barrel references are removed after confirmation.
Export Structure
Export the current generated structure as JSON:
atomic-bomb --export structure.jsonThis exports the directory structure, not file contents.
Example:
{
"version": 1,
"platform": "react-ts",
"items": [
{ "type": "atom", "name": "Logo" },
{ "type": "lib", "name": "formatDate" },
{ "type": "domain", "name": "Orders" },
{ "type": "subdomain", "for": "Orders", "name": "Sales" },
{ "type": "module", "for": "Orders/Sales", "name": "UserManager" },
{
"type": "atom",
"for": "Orders/Sales",
"module": "UserManager",
"name": "Button"
},
{ "type": "service", "for": "Orders/Sales", "name": "orderService" }
]
}Create From Structure
Create all items listed in a structure file:
atomic-bomb --from structure.jsonThe JSON is validated with Zod before generation. Invalid files stop with an error.
Scoped items must use:
{
"type": "service",
"for": "Orders/Sales",
"name": "orderService"
}Module items use for for their owning domain or subdomain. Artifacts inside
the module use a separate module field:
{
"type": "atom",
"for": "Orders/Sales",
"module": "UserManager",
"name": "Button"
}Subdomains use a domain-only for value:
{
"type": "subdomain",
"for": "Orders",
"name": "Sales"
}License
GPL-1.0-only
