Composability & Architecture
Because CellUI components execute exactly once, you don't have to rethink how JavaScript works just to build a UI. CellUI allows you to compose your applications the exact same way you would compose any vanilla JS library.
Small-Scale Composability
At a small scale, composability in CellUI means writing simple, pure functions.
You do not need "Render Props", "Higher Order Components", or complex children APIs. If you want to embed a Component into another Component, you just call it!
Example: A Reusable Card
import { view } from '@cmj/cellui';
// 1. A pure function that takes regular arguments
function Card(title: string, content: Node | DocumentFragment) {
return view`
<div class="card">
<h2 class="card-title">${title}</h2>
<div class="card-body">
${content}
</div>
</div>
`;
}
// 2. Composing it elsewhere
function App() {
return view`
<main>
${Card("User Profile", UserDetails())}
${Card("Settings", SettingsMenu())}
</main>
`;
}Large-Scale Composability (Substrates)
As your application grows—perhaps you are building a dashboard with 100+ components—passing data via function arguments (prop drilling) becomes tedious.
At a large scale, you should compose your application architectures using Substrates.
A Substrate is an isolated dependency-injection container. It allows an entire "tree" of CellUI components to share a decentralized memory layer.
Pattern: The "Feature Module"
Instead of building one monolithic app, break your app into modular "Features" that each manage their own memory Substrate.
import { Substrate, signal, view } from '@cmj/cellui';
// 1. Create an isolated Context for the Dashboard feature
const DashboardContext = new Substrate('analytics-dashboard');
export function AnalyticsDashboard() {
// 2. The Root component initializes the data into the Substrate
DashboardContext.infuse('date-range', signal('7D'));
return view`
<div class="dashboardLayout">
${SidebarControls()}
${ChartCanvas()}
</div>
`;
}
// 3. Deeply nested children extract the data directly
function ChartCanvas() {
// No props needed! We pull it straight from the closest Substrate layer.
const dateRange = DashboardContext.extract<string>('date-range');
return view`
<canvas id="chart">Drawing chart for ${dateRange}...</canvas>
`;
}