Extending the App

Add a new CRUD module, permission, setting, or scheduled task, following the app's own conventions.

On this page

Extending the App

CB Genesis is a launchpad, not a finished product. These are the same steps its own Users/Roles/Permissions/Settings modules follow - use them as the template for anything new.

Adding a new CRUD module

1
Create the entity

In app/models/<domain>/, extending BaseEntity — see Database & ORM.

2
Create the service

Extending BaseService, marked singleton threadSafe — see the service pattern.

3
Create the handler

Extending BaseSecureHandler, with an @secured annotation — see Handlers & Routing.

4
Add routes

In app/config/Router.bx, near the // @app_routes@ marker.

5
Create views

In app/views/<domain>/, reusing existing _components/ui/ partials.

6
Create an Alpine component

In resources/assets/js/components/<domain>/, then register it in App.js — see Frontend.

7
Add SCSS

In resources/assets/scss/views/, imported from app.scss.

8
Write tests

Unit specs in tests/specs/unit/<domain>/ — see Testing.

Adding a new permission

1
Seed the slug

Add the resource:action slug to resources/database/seeds/AdminData.bx and assign it to the appropriate role(s).

2
Guard the handler

@secured( "resource:action,resource:admin" ) — comma means OR. See Security & Permissions.

3
Gate the view
<bx:if prc.authUser.hasPermission( "resource:action,resource:admin" )>

so the UI never offers something the handler would reject.

4
Re-seed

box migrate seed against an existing database - or grant the permission to a role directly from the Roles admin page.

Adding a setting

Add a new key to the DEFAULTS struct in SettingService.bx. preFlightCheck() seeds it automatically on next boot, and it appears in the /settings admin page with no further wiring — see Configuration.

Customizing layouts

Layouts live in app/layouts/. Selection happens per-handler, typically in preHandler:

function preHandler( event, rc, prc ){
    event.setLayout( "Admin" );
}

Adding a scheduled task

Register tasks in app/config/Scheduler.bx:

task( "My Task" )
    .call( () => getInstance( "MyService" ).doWork() )
    .everyDayAt( "03:00" )
    .when( isClusterReady )
    .withoutOverlaps();

Overriding module configuration

Module configs in app/config/modules/ extend the module's own defaults. Override any key there — changes take effect on the next ?fwreinit.

Edit this page Download Markdown Last updated Sep 1, 2026, 7:55:53 PM