Modules are the unit of deployment. Everything lives in a module.
{
"name": "sales",
"version": "1.0.0",
"label": "Sales Management",
"depends": ["base", "crm"],
"category": "Sales",
"table": { "prefix": "sale" },
"models": ["models/*.json"],
"apis": ["apis/*.json"],
"processes": ["processes/*.json"],
"agents": ["agents/*.json"],
"views": ["views/*.json"],
"templates": ["templates/*.html"],
"scripts": ["scripts/*"],
"data": ["data/*.json"],
"i18n": ["i18n/*.json"],
"menu_visibility": "app",
"include_menus": [
{"module": "base", "views": ["user_list"]}
],
"permissions": {
"sales.order.read": "Read orders",
"sales.order.create": "Create orders"
},
"groups": {
"sales.user": { "label": "Sales / User", "implies": ["base.user"] },
"sales.manager": { "label": "Sales / Manager", "implies": ["sales.user"] }
},
"menu": [
{ "label": "Sales", "icon": "shopping-cart", "children": [
{ "label": "Orders", "view": "order_list" }
]}
],
"settings": {
"default_currency": { "type": "string", "default": "USD" }
}
}The "table" field configures database table naming for all models in the module:
"table": { "prefix": "crm" }With prefix crm, model contact → table crm_contact. Without prefix, table name = model name.
Models can override the module prefix:
// model JSON — direct table name
{ "name": "log", "table": "custom_log", ... }
// model JSON — different prefix
{ "name": "log", "table": { "prefix": "sys" }, ... }
// model JSON — clear module prefix
{ "name": "setting", "table": { "prefix": "" }, ... }Resolution order: model direct name → model prefix → module prefix → model name as-is.
modules/sales/
├── module.json # Module definition
├── models/ # Model definitions
├── apis/ # API definitions
├── processes/ # Process + workflow definitions
├── agents/ # Agent definitions
├── views/ # View definitions
├── templates/ # HTML templates
├── scripts/ # TypeScript/Python plugins
├── data/ # Demo/seed data
└── i18n/ # Translations
Modules can depend on other modules. The engine resolves dependencies automatically using topological sort.
"depends": ["base", "crm"]baseis always available (embedded in binary)- Circular dependencies are detected and rejected
The engine resolves module files from 3 layers, highest priority first:
Layer 1: Project → ./modules/base/models/user.json (user override)
Layer 2: Global → ~/.bitcode/modules/base/... (shared across projects)
Layer 3: Embedded → [binary]/base/... (default fallback)
Resolution is per-file. If ./modules/base/models/user.json exists in the project, it overrides the embedded version. All other base files fall back to embedded.
- Base module is embedded in the engine binary via Go
embed.FS ModuleFSinterface abstracts file access (DiskFS, EmbedFS, LayeredFS)LayeredFScomposes multiple FS layers with priority-based per-file resolution- Engine discovers modules across all layers, deduplicates, resolves dependencies
Extract embedded module files to your project for customization. Similar to Laravel's artisan vendor:publish.
bitcode publish base # Publish entire base module
bitcode publish base --models # Publish only models
bitcode publish base --views # Publish only views
bitcode publish base --templates # Publish only templates
bitcode publish base models/user.json # Publish single file
bitcode publish base --force # Overwrite existing files
bitcode publish base --dry-run # Preview without writing
bitcode publish --list # List publishable modulesDefault behavior: skip existing files (no overwrite). Use --force to overwrite.
Control where a module's menu appears:
"menu_visibility": "app"| Value | Behavior |
|---|---|
"app" |
Menu appears in app views sidebar (default) |
"admin" |
Menu only appears in admin panel |
The base module uses "menu_visibility": "admin" — its menu (Users, Roles, Permissions, Settings) only appears in the admin panel, not in the app sidebar.
Import menu items from other modules into your module's sidebar:
"include_menus": [
{"module": "base", "views": ["user_list", "role_list"]},
{"module": "hrm", "views": ["employee_list"]}
]views— array of specific view names to include. Omit to include all.- Included items are merged into matching menu groups of the importing module.
- Use case: CRM module wants to show "Users" link from base module in its sidebar.
bitcode module list # List available modules
bitcode module create my-module # Scaffold new module
bitcode publish base # Extract embedded module to project
bitcode publish --list # List publishable modulesEmbedded in the engine binary. Always available. Provides: user, role, group, permission, record_rule, audit_log, setting models + auth API + default templates.
Config: GLOBAL_MODULE_DIR env var sets the global module directory (default: ~/.bitcode/modules).
Views saved from the admin editor are versioned in the view_revisions database table. Each save creates a new revision. Rollback restores a previous revision's content to the file.
Settings:
view_revision_limit: Maximum revisions to keep per view.0= unlimited, default:50.