Docs / SDK / Modules

Modules

A module bundles a workspace shell, entity types, inspectors, commands, and hotkeys into a self-contained unit. The workspace switcher lets users switch between modules like tabs.

Module definition

A ModuleDef is pure data -- no React, no side effects. It describes everything about a module: its workspace layout, entity types, commands, and hotkeys. Use the defineModule() builder to create one:

import { defineModule } from "@substrateui/substrate/modules";
import { workspaceShell, menuBar, toolBar, canvasSlot, dockZone, standardFileMenu } from "@substrateui/substrate/workspace";
import { entityType } from "@substrateui/substrate/entities";

const myModule = defineModule("inventory", "Inventory", {
  icon: "package",
  accent: "orange",
  description: "Track products, stock levels, and warehouse locations.",
  order: 4,

  workspace: workspaceShell({
    menuBar: menuBar([standardFileMenu()]),
    canvas: canvasSlot("data-grid"),
    dockZones: [
      dockZone("left", [
        { id: "categories", label: "Categories", icon: "tags" },
      ], { defaultSize: 220 }),
    ],
  }),

  entities: [
    entityType("product", {
      name: "Product",
      namePlural: "Products",
      icon: "box",
      accent: "orange",
      module: "inventory",
      displayField: "name",
      statuses: [
        { id: "in-stock", label: "In Stock", color: "green", default: true },
        { id: "low-stock", label: "Low Stock", color: "yellow" },
        { id: "out-of-stock", label: "Out of Stock", color: "red" },
        { id: "discontinued", label: "Discontinued", color: "neutral", terminal: true },
      ],
    }),
  ],

  commands: [
    { id: "inventory.restock", label: "Restock", icon: "package-plus", category: "Inventory" },
    { id: "inventory.adjust", label: "Adjust Quantity", icon: "hash", category: "Inventory" },
  ],

  hotkeys: [
    { id: "inventory.new-product", shortcut: "N", label: "New Product", commandId: "entity.create" },
  ],
});

Module registry

Combine modules into a registry with createModuleRegistry(). The registry flattens all entity types, commands, and hotkeys across modules for cross-module lookup:

import { createModuleRegistry } from "@substrateui/substrate/modules";
import { financeModule, crmModule, projectMgmtModule } from "@substrateui/templates";
import { myModule } from "./my-module";

const registry = createModuleRegistry(
  financeModule,
  crmModule,
  projectMgmtModule,
  myModule,
);

// Access resolved registries
import { resolveEntityRegistry, resolveCommandRegistry } from "@substrateui/substrate/modules";

const entities = resolveEntityRegistry(registry);
// entities.typeById.get("contact") → EntityTypeDef

const commands = resolveCommandRegistry(registry);
// commands.byId.get("inventory.restock") → CommandDef

Built-in templates

Substrate ships with 7 template modules that demonstrate real-world workspace patterns. Each is a complete ModuleDef you can use directly, extend, or use as a reference:

ModuleIDEntities
Financefinanceaccount, journal-entry, invoice, vendor, payment, budget, fund
CRMcrmcontact, company, deal, activity
Project Managementproject-mgmtproject, task, sprint, milestone
Design Tooldesign-toolscene, asset, layer, component
Data Platformdata-platformdataset, pipeline, query, notebook
Adminadminuser, role, team, audit-log
Agent Opsagent-opsagent, workflow, run, skill, tool

Import individual modules or use allTemplateModules to load all 7:

import { allTemplateModules } from "@substrateui/templates";
import { createModuleRegistry } from "@substrateui/substrate/modules";

// Load every template module
const registry = createModuleRegistry(...allTemplateModules);

Registry helpers

Resolved registries flatten all definitions across modules into efficient lookup maps:

FunctionReturns
createModuleRegistry(...modules)ModuleRegistry
resolveEntityRegistry(registry)ResolvedEntityRegistry
resolveCommandRegistry(registry)ResolvedCommandRegistry
resolveHotkeyRegistry(registry)ResolvedHotkeyRegistry
getModule(registry, moduleId)ModuleDef | undefined
getSortedModules(registry)ModuleDef[]