This documentation is synthesized from deep code analysis of the Reactium framework source code and reference implementations. All examples are drawn from actual framework code.
- Framework Overview
- Core Architecture
- SDK Components
- Domain-Driven Design (DDD) Artifacts
- Routing System
- State Management
- Component Patterns
- Build System
- Extensibility Points
- Best Practices
Reactium is a full-stack React framework that provides:
- Universal (isomorphic) rendering - SSR and SPA in one codebase
- Convention-over-configuration approach via Domain-Driven Design
- Powerful hook-based extensibility system
- Dynamic component and route registration
- Built on top of React, Express, and Webpack
Reactium-Core-Plugins/
└── reactium_modules/@atomic-reactor/
├── reactium-core/ # Core framework implementation
└── [other plugins...]
reactium-sdk-core/ # Foundation SDK (browser + server utilities)
CLI/ # Command-line interface tool
File: Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/package.json
{
"reactium": {
"version": "5.0.0"
}
}File: Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/index.mjs
The server bootstrap follows this sequence:
-
Global Initialization (
server-globals.mjs)- Creates
global.ReactiumBootobject combining SDK core + server modules - Sets
global.rootPath,global.PORT,global.TLS_PORT - Initializes logging system via
reactium.log.cjs
- Creates
-
Boot Hook Discovery (
boot-hooks.mjs)- Scans for
reactium-boot.{js,mjs,cjs}files in:src/reactium_modules/node_modules/**/reactium-plugin/
- Dynamically imports and executes boot hooks
- Runs
sdk-inithook for final initialization
- Scans for
-
Server Setup (
index.mjs)// Middleware registration via ReactiumBoot.Server.Middleware ReactiumBoot.Server.Middleware.register('morgan', { name: 'morgan', use: morgan(format), order: ReactiumBoot.Enums.priority.highest, });
-
SSR Renderer (
server/renderer/index.mjs)- Registers hooks for collecting assets:
Server.AppStyleSheetsServer.AppScriptsServer.AppHeadersServer.AppBindingsServer.AppGlobals
- Assembles HTML via
server/template/feo.js
- Registers hooks for collecting assets:
Logging System (reactium.log.cjs):
// Provides global logging functions
global.DEBUG();
global.INFO();
global.BOOT();
global.WARN();
global.ERROR();
// Controlled by process.env.LOG_LEVELFile: learning/src/app/main.js (application entry point)
import { Shell } from '@atomic-reactor/reactium-core/app/shell';
__webpack_public_path__ = window.resourceBaseUrl || '/assets/js/';
await Shell();Client-side initialization flow:
-
Manifest Loading (
src/manifest.js)- Generated at build-time by
manifest-tools.js - Contains dynamic imports for all DDD artifacts
- Example structure:
export const allRoutes = { HelloWorld: [ () => import( './app/components/HelloWorld/reactium-route-helloworld.js' ), ], }; export const allHooks = { HookTester: [ () => import( './app/components/HookTester/reactium-hooks-hooktester.js' ), ], };
- Generated at build-time by
-
Hook Loading (
reactium-hooks-App.js)Hook.register('plugin-init', async () => { await deps().loadAll('allHooks'); }); Hook.register('routes-init', async (routesRegistry) => { const allRoutes = await deps().loadAllDefaults('allRoutes'); allRoutes.forEach((route) => { Reactium.Routing.register(route); }); });
-
Component Registration
// In reactium-hooks-*.js files Hook.register('plugin-init', async () => { const { MyComponent } = await import('./MyComponent'); Component.register('MyComponent', MyComponent); });
File: Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/webpack.config.js
// WebpackSDK provides extensible configuration
sdk.mode = config.mode;
sdk.target = 'web';
sdk.entry = config.entries; // From application config
sdk.output = {
publicPath: '/assets/js/',
path: path.resolve(rootPath, 'dest'),
filename: '[name].js',
asyncChunks: true,
};
// Code splitting for dynamic imports
sdk.setCodeSplittingOptimize(env);
// Babel integration for module resolution
sdk.addRule('js-babel-loader', {
test: /\.jsx?$/,
loader: 'babel-loader',
});Babel Module Resolution (babel.config.js):
// Managed by ReactiumBabel.ModuleAliases registry
plugins: [
[
'module-resolver',
{
alias: {
manifest: './src/manifest',
appdir: './src/app',
},
},
],
];Source: reactium-sdk-core/src/core/Hook.ts
The Hook system is the foundation for extensibility:
class HookSDK {
register(
name: string,
callback: Function,
order: number,
id?: string,
): string;
unregister(id: string): void;
run(name: string, ...params: any[]): Promise<any>; // Async hooks via ActionSequence
runSync(name: string, ...params: any[]): any; // Sync hooks
}Hook Properties:
name: Hook identifiercallback: Function to executeorder: Priority (higher = earlier execution)id: Unique identifier for the hook instancedomain: Grouping/namespace
Example Usage:
// File: learning/src/app/components/HookTester/reactium-hooks-hooktester.js
import { Hook, Enums } from '@atomic-reactor/reactium-core/sdk';
Hook.register(
'plugin-init',
async () => {
const { HookTester } = await import('./HookTester');
Component.register('HookTester', HookTester);
},
Enums.priority.normal,
'plugin-init-HookTester',
);ActionSequence Pattern: Async hooks execute sequentially, allowing data to flow through the chain:
// Each hook receives output from previous hook
await Hook.run('my-hook', initialData);
// Hook 1: receives initialData, returns modified data
// Hook 2: receives modified data from Hook 1, returns further modifications
// ...Source: reactium-sdk-core/src/core/Registry.ts
Generic in-memory database for managing collections:
class Registry<ItemT> {
register(id: string, item: ItemT): void;
unregister(id: string): void;
get(id: string): ItemT | undefined;
list: ItemT[];
protect(id: string): void; // Prevent unregistration
subscribe(callback: (registry: this) => void): () => void;
// Modes: CLEAN (default) or HISTORY (tracks changes)
}Use Cases:
- Components:
Reactium.Component(RegisteredComponents instance) - Zones:
ZoneRegistryfor UI extensibility - Middleware:
Server.Middlewarefor Express middleware - Routes:
Reactium.Routingroute management
Source: reactium-sdk-core/src/core/Pulse/index.ts
Advanced task scheduling with lifecycle management:
class PulseTask<Params extends any[]> {
constructor(options: PulseTaskOptions<Params>);
start(): void;
stop(): void;
now(): Promise<any>; // Execute immediately
reset(): void;
retry(): void;
onSuccess(callback: Function): void;
onError(callback: Function): void;
}
interface PulseTaskOptions<Params> {
ID: string;
callback: (...params: Params) => any | Promise<any>;
attempts?: number; // Retry count
autostart?: boolean;
delay?: number; // ms delay before execution
repeat?: number; // Repeat interval in ms (-1 = infinite)
}Example:
import { Pulse } from '@atomic-reactor/reactium-core/sdk';
const task = Pulse.register({
ID: 'data-sync',
callback: async () => {
const data = await fetchData();
return data;
},
delay: 1000,
repeat: 5000, // Every 5 seconds
attempts: 3,
});
task.onSuccess((result) => console.log('Success:', result));
task.onError((error) => console.error('Error:', error));Source: reactium-sdk-core/src/browser/Handle.ts, useHandle.ts, useRegisterHandle.ts
Global component communication system:
// ReactiumHandle singleton
class Handle {
register(ID: Path, value: any): void;
unregister(ID: Path): void;
get(ID: Path): any;
subscribe(callback: (handles: object) => void): () => void;
}Provider Hook:
// File: reactium-sdk-core/src/browser/useRegisterHandle.ts
function useRegisterHandle<HandleType>(
ID: Path,
cb: () => HandleType,
deps: DependencyList = [],
): void;Consumer Hook:
// File: reactium-sdk-core/src/browser/useHandle.ts
function useHandle<HandleType>(ID: Path): HandleType | undefined;Example:
// Provider component
import { useRegisterHandle } from '@atomic-reactor/reactium-core/sdk';
export const DataProvider = () => {
useRegisterHandle(
'app-data',
() => ({
user: { name: 'John' },
settings: { theme: 'dark' },
}),
[],
);
return null;
};
// Consumer component
import { useHandle } from '@atomic-reactor/reactium-core/sdk';
export const UserDisplay = () => {
const appData = useHandle('app-data');
return <div>{appData?.user.name}</div>;
};Source: reactium-sdk-core/src/browser/ReactiumSyncState.ts, useSyncState.ts
Event-driven, observable state management:
class ReactiumSyncState<T extends object> extends EventTarget {
get(path?: Path, defaultValue?: any): any;
set(path: Path | T, value?: any): void;
del(path: Path): void;
reset(): void;
has(path: Path): boolean;
extend(prop: string, method: Function): void;
// Events: 'before-set', 'set', 'change', 'before-del', 'del'
}Hook Usage:
import { useSyncState } from '@atomic-reactor/reactium-core/sdk';
const MyComponent = () => {
const state = useSyncState({
count: 0,
user: { name: 'Alice' },
});
const increment = () => {
state.set('count', state.get('count') + 1);
};
// Dynamic method extension
state.extend('doubleCount', function () {
return this.get('count') * 2;
});
return (
<div>
<p>Count: {state.get('count')}</p>
<p>Double: {state.doubleCount()}</p>
<button onClick={increment}>Increment</button>
</div>
);
};useRegisterSyncHandle:
import {
useRegisterSyncHandle,
useSyncHandle,
} from '@atomic-reactor/reactium-core/sdk';
// Provider
const AppState = () => {
const state = useRegisterSyncHandle('app-state', {
theme: 'light',
user: null,
});
return <div>App State Provider</div>;
};
// Consumer (reactive)
const ThemeDisplay = () => {
const state = useSyncHandle('app-state');
return <div>Theme: {state.get('theme')}</div>;
};Source: reactium-sdk-core/src/browser/Zone.tsx, Zones.ts
Pluggable UI system for extensible layouts:
// ZoneRegistry singleton
class Zones {
addComponent(registration: ComponentRegistration): void;
removeComponent(ID: Path): void;
getZoneComponents(zone: string): ComponentRegistration[];
addFilter(zone: string, filter: FilterFunction): void;
addMapper(zone: string, mapper: MapperFunction): void;
addSort(zone: string, sorter: SortFunction): void;
subscribe(zone: string, callback: Function): () => void;
}
interface ComponentRegistration {
id: string;
zone: string;
component: React.ComponentType | string;
order?: number;
[key: string]: any; // Additional props passed to component
}Zone Component Usage:
import { Zone } from '@atomic-reactor/reactium-core/sdk';
const Layout = () => (
<div>
<header>
<Zone zone='header-widgets' />
</header>
<main>
<Zone zone='sidebar' />
<Zone zone='content' />
</main>
</div>
);
// Register components to zones
import { ZoneRegistry, Enums } from '@atomic-reactor/reactium-core/sdk';
ZoneRegistry.addComponent({
id: 'UserMenu',
zone: 'header-widgets',
component: UserMenuComponent,
order: Enums.priority.high,
});
ZoneRegistry.addComponent({
id: 'SearchWidget',
zone: 'header-widgets',
component: SearchComponent,
order: Enums.priority.normal,
});PassThrough Mode:
// Custom rendering control
<Zone zone='my-zone' passThrough>
{({ components }) => (
<div className='custom-layout'>
{components.map((comp) => (
<div key={comp.id} className='widget'>
{React.createElement(comp.component, comp)}
</div>
))}
</div>
)}
</Zone>Memory Cache (reactium-sdk-core/src/core/MemoryCache.ts):
import { Cache } from '@atomic-reactor/reactium-core/sdk';
Cache.set('user.profile', { name: 'John' }, 60000); // 60s TTL
const profile = Cache.get('user.profile');
// Path-based subscriptions
Cache.subscribe('user', (event, key, value) => {
console.log('User cache changed:', key, value);
});Prefs (localStorage) (reactium-sdk-core/src/browser/Prefs.ts):
import { Prefs } from '@atomic-reactor/reactium-core/sdk';
Prefs.set('user.theme', 'dark');
const theme = Prefs.get('user.theme', 'light');
Prefs.clear('user.theme');Fullscreen API (reactium-sdk-core/src/browser/Fullscreen.ts):
import { Fullscreen } from '@atomic-reactor/reactium-core/sdk';
Fullscreen.expand(); // Enter fullscreen
Fullscreen.collapse(); // Exit fullscreen
Fullscreen.toggle(); // Toggle state
const isFS = Fullscreen.isExpanded();Reactium organizes code by domain (feature/module) rather than file type.
File: manifest/manifest-tools.js
const regenManifest = (manifest) => {
// 1. Scan directories based on patterns
const files = find(patterns, {
directories: sourceMappings,
});
// 2. Map to domains using fileToDomain()
// 3. Generate src/manifest.js with dynamic imports
};Pattern: (routes?|reactium-routes?.*?)\.jsx?$
File: learning/src/app/components/Greeter/reactium-route-greeter.js
import { Greeter as component } from './Greeter';
export default [
{
id: 'route-Greeter-1',
exact: true,
component,
path: ['/greeter'],
},
];Integration:
- Discovered by
manifest-tools.js - Listed in
src/manifest.jsunderallRoutes - Loaded by
routes-inithook inreactium-hooks-App.js - Registered via
Reactium.Routing.register() register-routehook processescomponentfor dynamic resolution
Purpose: Bootstrap hooks (client + server)
File: learning/src/app/components/HookTester/reactium-hooks-hooktester.js
(async () => {
const { Hook, Enums, Component, ZoneRegistry } = await import(
'@atomic-reactor/reactium-core/sdk'
);
Hook.register(
'plugin-init',
async () => {
const { HookTester } = await import('./HookTester');
const { Salutation } = await import('./Salutation');
const { default: ZoneComponent } = await import('./ZoneComponent');
Component.register('HookTester', HookTester);
Component.register('Salutation', Salutation);
ZoneRegistry.addComponent({
id: 'ZoneComponentInHookTester',
zone: 'my-test-zone',
component: ZoneComponent,
message: 'This component is rendered in a Zone!',
order: Enums.priority.neutral,
});
},
Enums.priority.normal,
'plugin-init-HookTester',
);
})();Integration:
- Discovered by
manifest-tools.js - Listed in
src/manifest.jsunderallHooks - Loaded by
dependencies.loadAll('allHooks')duringplugin-inithook
Purpose: Server-side initialization
Pattern: Files executed during server boot
Example:
// reactium-boot.js
import { Hook } from '@atomic-reactor/reactium-core/sdk';
Hook.register('Server.Middleware', async (app) => {
app.use('/api', customMiddleware);
});
Hook.register('Server.Init', async () => {
// Initialize database connections, etc.
});Integration:
- Discovered by
boot-hooks.mjs - Dynamically imported during server startup
- Executed before
sdk-inithook
Purpose: Utility functions and AJAX requests
Integration:
- Discovered by
manifest-tools.js - Listed in
src/manifest.jsunderallServices - Loaded by
dependencies.load()and stored independencies.services
Purpose: Per-domain configuration
Example:
export default {
name: 'MyDomain', // Explicit domain name
version: '1.0.0',
// ... other config
};Integration:
- Discovered by
manifest-tools.js - Processed by
manifest/processors/domains.js - Generates
src/domains.jsmanifest - Used for domain name overrides in manifest generation
Purpose: Domain-specific Sass styles
Integration:
- Processed by Gulp
dddStylesPartialtask - Dynamically generates SCSS partials with priority-based ordering
Purpose: Hook-driven Webpack configuration
Example:
import { ReactiumWebpack } from '@atomic-reactor/reactium-core';
ReactiumWebpack.Hook.registerSync('webpack-config', (sdk) => {
// Add custom loader
sdk.addRule('my-loader', {
test: /\.custom$/,
use: 'my-custom-loader',
});
// Add plugin
sdk.addPlugin('MyPlugin', new MyWebpackPlugin());
});Integration:
- Discovered by
WebpackSDKconstructor - Executed during Webpack configuration assembly
Purpose: Custom build tasks
Example:
export default (gulp, config, gulpConfig) => {
gulp.task('my-custom-task', () => {
// Custom build logic
});
};Integration:
- Discovered and required by
gulp.bootup.js
Purpose: Universal Module Definition bundles for runtime loading
Use Case: Service workers, runtime plugins
Source: Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/sdk/routing/index.js
{
// Core react-router properties
path: string | string[], // URL path(s)
exact?: boolean, // Exact path matching
component: React.ComponentType | string,
strict?: boolean,
sensitive?: boolean,
// Reactium extensions
id?: string, // Auto-generated if not provided
order?: number, // Matching priority (default: 0)
loadState?: AsyncFunction, // SSR/data fetching
handleId?: string, // Handle system ID for loadState data
persistHandle?: boolean, // Keep handle on route change
transitions?: boolean, // Enable transition states
transitionStates?: Array<{ // Custom transition sequence
state: string,
active: 'current' | 'previous'
}>
}File: learning/src/app/components/DataLoader/DataLoader.jsx
export const DataLoader = ({ className }) => {
const handle = useSyncHandle(DataLoader.handleId);
const loadedData = handle ? handle.get('data') : null;
const isLoading = handle.get('loading', true);
return (
<div className={className}>
<h1>Data Loader</h1>
{isLoading && <p>Loading...</p>}
{loadedData && (
<div>
<h2>Data:</h2>
<pre>{JSON.stringify(loadedData, null, 2)}</pre>
</div>
)}
</div>
);
};
// Static loadState method
DataLoader.loadState = async ({ route, params, search }) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
data: {
message: 'This data was loaded from loadState!',
timestamp: Date.now(),
routeId: route.id,
routeParams: params,
queryParams: search,
},
loading: false,
});
}, 1000);
});
};
// Static handleId for data storage
DataLoader.handleId = 'DataLoaderHandle';Route Registration:
// File: learning/src/app/components/DataLoader/reactium-route-dataloader.js
import { DataLoader as component } from './DataLoader';
import { Enums } from '@atomic-reactor/reactium-core/sdk';
export default [
{
id: 'route-DataLoader-1',
exact: true,
component,
path: '/data-loader',
order: Enums.priority.high,
},
];
// Note: loadState and handleId are on the component, not the route objectSource: Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/app/reactium-hooks-App.js
// 1. routes-init hook
Hook.register(
'routes-init',
async (routesRegistry) => {
const allRoutes = await deps().loadAllDefaults('allRoutes');
const globalRoutes = window.routes || global.routes || [];
[...allRoutes, ...globalRoutes].forEach((route) => {
Reactium.Routing.register(route);
});
},
Enums.priority.core,
);
// 2. register-route hook (processes each route)
Hook.register(
'register-route',
async (route) => {
// Dynamic component resolution
if (typeof route.component === 'string') {
route.component = hookableComponent(route.component);
}
},
Enums.priority.core,
);Best for: Single-component state with event-driven updates
import { useSyncState } from '@atomic-reactor/reactium-core/sdk';
const Counter = () => {
const state = useSyncState({ count: 0, history: [] });
// Listen to specific events
state.addEventListener('set', (e) => {
console.log('State changed:', e.data);
});
const increment = () => {
const newCount = state.get('count') + 1;
state.set('count', newCount);
// Update nested path
state.set('history', [...state.get('history'), newCount]);
};
return (
<div>
<p>Count: {state.get('count')}</p>
<button onClick={increment}>Increment</button>
<p>History: {state.get('history').join(', ')}</p>
</div>
);
};Best for: Cross-component communication
// Provider component
const AppDataProvider = () => {
useRegisterHandle(
'app-data',
() => ({
user: null,
settings: { theme: 'light' },
notifications: [],
}),
[],
);
return null;
};
// Consumer (non-reactive)
const UserInfo = () => {
const appData = useHandle('app-data');
return <div>{appData?.user?.name || 'Guest'}</div>;
};Best for: Global state with reactive updates
// Provider
const ThemeProvider = () => {
const state = useRegisterSyncHandle('app-theme', {
mode: 'light',
colors: { primary: '#007bff' },
});
// Expose methods
state.extend('toggleMode', function () {
const current = this.get('mode');
this.set('mode', current === 'light' ? 'dark' : 'light');
});
return null;
};
// Consumer (reactive - re-renders on state changes)
const ThemeToggle = () => {
const theme = useSyncHandle('app-theme');
return (
<button onClick={() => theme.toggleMode()}>
Current: {theme.get('mode')}
</button>
);
};Best for: Performance optimization
import { useSelectHandle } from '@atomic-reactor/reactium-core/sdk';
const UserName = () => {
// Only re-renders when 'user.name' changes
const { selected: userName } = useSelectHandle(
'app-data',
'user.name',
'Guest',
);
return <div>Hello, {userName}</div>;
};
// Or with callback selector
const UserRole = () => {
const { selected: role } = useSelectHandle(
'app-data',
(state) => state.get('user.role'),
'user',
);
return <div>Role: {role}</div>;
};File: learning/src/app/components/Hello/Hello.jsx
import { useSyncState } from '@atomic-reactor/reactium-core/sdk';
import React from 'react';
import { Link } from 'react-router-dom';
export const Hello = ({ className }) => {
const state = useSyncState({ content: 'Hello Reactium' });
return (
<div className={className}>
<h1>{state.get('content')}</h1>
<nav>
<ul>
<li>
<Link to='/user/123'>User Page</Link>
</li>
<li>
<Link to='/data-loader'>Data Loader</Link>
</li>
</ul>
</nav>
</div>
);
};
Hello.defaultProps = {
className: 'hello',
};
export default Hello;Usage in routes:
export default [
{
id: 'my-route',
path: '/page',
component: 'MyComponent', // String reference
},
];Registration:
// In reactium-hooks-*.js
Hook.register('plugin-init', async () => {
const { MyComponent } = await import('./MyComponent');
Component.register('MyComponent', MyComponent);
});Resolution:
// Automatic via register-route hook
route.component = hookableComponent('MyComponent');import { useHookComponent } from '@atomic-reactor/reactium-core/sdk';
const DynamicRenderer = ({ componentName }) => {
const DynamicComp = useHookComponent(componentName, DefaultComponent);
return <DynamicComp />;
};// Register to zone
ZoneRegistry.addComponent({
id: 'sidebar-widget-1',
zone: 'sidebar',
component: MySidebarWidget,
order: Enums.priority.high,
// Additional props
title: 'My Widget',
canClose: true,
});
// Layout component
const Layout = () => (
<div className='layout'>
<aside>
<Zone zone='sidebar' />
</aside>
</div>
);
// Widget receives all props
const MySidebarWidget = ({ title, canClose, ...props }) => (
<div className='widget'>
<h3>{title}</h3>
{canClose && <button>Close</button>}
</div>
);File: manifest/manifest-tools.js
Process:
- Pattern Discovery: Scan directories for DDD artifacts
- Domain Mapping: Use
fileToDomain()to map files to domains - Template Processing: Use Handlebars to generate
src/manifest.js - Dynamic Imports: Create
req: () => import(...)functions
Generated Manifest Structure:
// src/manifest.js
export const allHooks = {
HelloWorld: [
() =>
import('./app/components/HelloWorld/reactium-hooks-helloworld.js'),
],
DataLoader: [
() =>
import('./app/components/DataLoader/reactium-hooks-dataloader.js'),
],
};
export const allRoutes = {
HelloWorld: [
() =>
import('./app/components/HelloWorld/reactium-route-helloworld.js'),
],
DataLoader: [
() =>
import('./app/components/DataLoader/reactium-route-dataloader.js'),
],
};
export const allServices = {
/* ... */
};File: gulp.tasks.js
Key Tasks:
mainManifest: Generate src/manifest.jsdomainsManifest: Generate src/domains.jsstyles:compile: Compile SassdddStylesPartial: Generate style partials
Custom Gulp Tasks:
// reactium-gulp.js in your domain
export default (gulp, config, gulpConfig) => {
gulp.task('my-custom-task', () => {
return gulp
.src('src/**/*.custom')
.pipe(customProcessor())
.pipe(gulp.dest('public/'));
});
// Hook into existing task
gulp.task('build', gulp.series('my-custom-task', 'default'));
};WebpackSDK Methods:
sdk.addRule(id, rule);
sdk.addPlugin(id, plugin);
sdk.addAlias(key, path);
sdk.addIgnore(id, pattern);
sdk.addExtension(ext);
sdk.setCodeSplittingOptimize(env);Example Extension:
// reactium-webpack.js
import { ReactiumWebpack } from '@atomic-reactor/reactium-core';
ReactiumWebpack.Hook.registerSync('webpack-config', (sdk) => {
// Add SVG loader
sdk.addRule('svg-loader', {
test: /\.svg$/,
use: ['@svgr/webpack'],
});
// Add environment plugin
sdk.addPlugin(
'env',
new webpack.EnvironmentPlugin({
API_URL: 'https://api.example.com',
}),
);
});reactium-boot.js:
import { Hook } from '@atomic-reactor/reactium-core/sdk';
// Add Express middleware
Hook.register('Server.Middleware', async (app, options) => {
app.use('/api/custom', customApiHandler);
});
// Initialize backend services
Hook.register('Server.Init', async () => {
await connectToDatabase();
});
// SSR asset injection
Hook.register('Server.AppGlobals', async (AppGlobals, req, res) => {
AppGlobals.register('myData', {
value: { foo: 'bar' },
});
});reactium-hooks.js:
import {
Hook,
Component,
ZoneRegistry,
} from '@atomic-reactor/reactium-core/sdk';
Hook.register('plugin-init', async () => {
// Register components
const { MyComp } = await import('./MyComp');
Component.register('MyComp', MyComp);
// Add to zones
ZoneRegistry.addComponent({
id: 'my-zone-comp',
zone: 'header',
component: MyComp,
order: 100,
});
});
// Custom hooks
Hook.register('app-ready', () => {
console.log('Application is ready!');
});reactium-webpack.js:
import { ReactiumWebpack } from '@atomic-reactor/reactium-core';
ReactiumWebpack.Hook.registerSync('webpack-config', (sdk) => {
sdk.addRule('markdown', {
test: /\.md$/,
use: 'raw-loader',
});
});reactium-gulp.js:
export default (gulp) => {
gulp.task('process-assets', () => {
return gulp
.src('assets/**/*')
.pipe(customProcessor())
.pipe(gulp.dest('public/assets'));
});
};DO:
src/app/components/UserProfile/
├── UserProfile.jsx # Main component
├── reactium-route-userprofile.js # Routes
├── reactium-hooks-userprofile.js # Registration & hooks
├── _reactium-style.scss # Styles
├── services.js # API calls
└── domain.js # Configuration
DON'T:
src/components/
├── UserProfile.jsx
src/routes/
├── userProfile.js
src/styles/
├── UserProfile.scss
DO:
Hook.register(
'plugin-init',
async () => {
const { MyComponent } = await import('./MyComponent');
Component.register('MyComponent', MyComponent);
},
Enums.priority.normal,
'plugin-init-MyComponent', // Unique ID
);DON'T:
Hook.register('plugin-init', () => {
// Sync import in async hook
import('./MyComponent').then(/* ... */);
});Use useSyncState when:
- State is component-local
- Need event-driven updates
- Want dynamic method extension
Use Handle system when:
- State needs to be shared across components
- Non-reactive access is sufficient
Use useSyncHandle when:
- Need reactive global state
- Want automatic re-renders on state changes
Use useSelectHandle when:
- Only care about specific state slice
- Want to optimize re-renders
loadState for routes:
MyComponent.loadState = async ({ route, params, search }) => {
const data = await fetchData(params.id);
return { data, loading: false };
};
MyComponent.handleId = 'my-component-data';useAsyncEffect for component-level:
import { useAsyncEffect } from '@atomic-reactor/reactium-core/sdk';
const MyComponent = () => {
const [data, setData] = useState(null);
useAsyncEffect(async (isMounted) => {
const result = await fetchData();
if (isMounted()) {
setData(result);
}
}, []);
return /* ... */;
};DO:
// Define semantic zones
<Zone zone="header-actions" />
<Zone zone="main-content" />
<Zone zone="sidebar-widgets" />
// Register with priorities
ZoneRegistry.addComponent({
id: 'user-menu',
zone: 'header-actions',
component: UserMenu,
order: Enums.priority.highest // Show first
});DON'T:
// Generic zones
<Zone zone="zone1" />
<Zone zone="zone2" />Generate components:
npx reactium component -n UserProfile -d src/app/components -H -r /user/:id --unattendedFlags:
-n, --name: Component name-d, --destination: Parent directory-r, --route: Route path(s)-H, --hooks: Generate reactium-hooks file-s, --style: Generate style file-u, --unattended: Skip prompts
Cypress for route testing:
// cypress/e2e/dataloader.cy.js
describe('DataLoader Component', () => {
it('should display loaded data', () => {
cy.visit('http://localhost:3000/data-loader');
cy.get('[data-cy="loading"]').should('be.visible');
cy.wait(1500);
cy.get('[data-cy="data-loaded"]').should('be.visible');
cy.get('[data-cy="loading"]').should('not.exist');
});
});const DynamicPage = () => {
const componentName = useParams().component;
const Component = useHookComponent(componentName);
return <Component />;
};// Provider
const ApiService = () => {
useRegisterHandle(
'api',
() => ({
async fetch(endpoint) {
return await fetch(`/api/${endpoint}`).then((r) => r.json());
},
}),
[],
);
return null;
};
// Consumer
const DataDisplay = () => {
const api = useHandle('api');
const [data, setData] = useState(null);
useEffect(() => {
api.fetch('users').then(setData);
}, []);
return /* ... */;
};import { useScrollToggle } from '@atomic-reactor/reactium-core/sdk';
const Modal = ({ isOpen }) => {
useScrollToggle(isOpen); // Disables scroll when open
return isOpen ? <div className='modal'>...</div> : null;
};import { breakpoint } from '@atomic-reactor/reactium-core/sdk';
const ResponsiveComponent = () => {
const [bp, setBp] = useState(breakpoint());
useEffect(() => {
const handleResize = () => setBp(breakpoint());
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return <div>Current breakpoint: {bp}</div>; // xs, sm, md, lg, xl
};All examples reference actual source files:
Core Framework:
Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/reactium-sdk-core/src/CLI/
Learning Project:
learning/src/app/- Application componentslearning/src/manifest.js- Generated manifestlearning/cypress/e2e/- Cypress tests
Build System:
manifest/manifest-tools.js- Manifest generationgulp.tasks.js- Gulp task definitionswebpack.config.js- Webpack configuration
This documentation provides comprehensive coverage of the Reactium framework based on actual source code analysis. For deeper exploration:
- Examine the SDK source:
reactium-sdk-core/src/ - Study core implementations:
Reactium-Core-Plugins/reactium_modules/@atomic-reactor/reactium-core/ - Review reference plugins:
Reactium-Admin-Plugins/andReactium-GraphQL-Plugin/ - Build and test: Use the
learning/directory for hands-on practice
All patterns documented here are verified through actual code implementation and Cypress testing.