Architecture

The modern app/public split, the full project tree, and how a request flows from browser to database and back.

On this page

Architecture

CBGenesis follows ColdBox's modern template layout: application code is fully separated from the public webroot, so nothing under app/ is ever directly web-accessible.

Layered overview

flowchart TD
    A["Browser Request"] --> B

    subgraph B["public/ โ€” Webroot"]
        B1["Application.bx โ€” entry point, bootstraps ColdBox + ORM"]
        B2["index.bxm โ€” front controller"]
        B3["includes/ โ€” Vite compiled assets"]
    end

    B --> C

    subgraph C["app/ โ€” Application code (not web-accessible)"]
        C1["config/ โ€” ColdBox, Router, CacheBox, WireBox, Scheduler"]
        C2["handlers/ โ€” Controllers, auth, admin, audit log"]
        C3["models/ โ€” Entities, Services"]
        C4["views/ + layouts/ โ€” BXM templates"]
        C5["email_templates/ โ€” Token-based email bodies"]
        C6["interceptors/ โ€” Audit logging hook"]
    end

    C --> D

    subgraph D["resources/ โ€” Source assets"]
        D1["assets/js/ โ€” Alpine components + stores"]
        D2["assets/scss/ โ€” Bootstrap + custom SCSS"]
        D3["database/ โ€” Migrations + seeders"]
    end

    D --> E

    subgraph E["lib/ โ€” Dependencies (not source-controlled)"]
        E1["coldbox/, testbox/, modules/ โ€” qb, cbsecurity, cborm, ..."]
    end
Why the split?

Anything an attacker could otherwise browse to directly - handler source, config, view templates - simply doesn't live under the webroot. app/Application.bx is a one-line abort; guard, kept only so the framework convention holds even if a web server is ever misconfigured to serve app/ directly.

Request lifecycle

Every request enters through public/Application.bx, which bootstraps ColdBox before handing off to the router and, eventually, your handler:

sequenceDiagram
    Browser->>+public/Application.bx: HTTP Request
    public/Application.bx->>+ColdBox Bootstrap: loadColdbox()
    ColdBox Bootstrap->>+Main Handler: onRequestStart
    Main Handler->>+Router: Match route
    Router->>+Target Handler: Dispatch event
    Target Handler->>+Service Layer: Business logic
    Service Layer->>+ORM / qb: Data access
    Target Handler->>+View / Layout: Render response
    View / Layout-->>-Browser: HTML + Vite assets

Main.bx (app/handlers/Main.bx) is the implicit-event handler wired up in app/config/Coldbox.bx:

  • onAppInit - runs settingService.preFlightCheck(), seeding any missing app settings into the database
  • onRequestStart - loads prc.settings and prc.authUser for every request
  • onException - the app-wide exception handler

Interceptors

app/config/Coldbox.bx registers three application interceptors, in this order:

app/interceptors/AuditLogger.bx writes to the audit trail on four interception points:

PointRecorded
postAuthenticationA successful sign-in
preLogoutA sign-out
cbSecurity_onInvalidAuthenticationA request that required a session and had none
cbSecurity_onInvalidAuthorizationAn authenticated user missing the required permission

app/interceptors/RateLimiter.bx fires on preProcess - before routing, before any handler - and throttles five unauthenticated Auth actions (login, register, forgot/reset password, invitation activation) by client IP. See Rate limiting for the settings and how it works.

app/interceptors/SSOAuthorization.bx handles cbSSO's CBSSOAuthorization interception point. It connects a verified provider identity to the local user model, enforces login-versus-linking policy, provisions users when allowed, and creates the cbauth session. See Single sign-on for the callback flow and the reason cbGenesis uses a custom handler instead of cbSSO's generic cbAuth integration.

Add your own to the variables.interceptors array in Coldbox.bx; they fire in declaration order.

Scheduled tasks

app/config/Scheduler.bx registers three daily background tasks, each onOneServer() and withNoOverlaps() so a multi-instance deployment runs each one exactly once:

TaskRunsDeletesGoverned by
Purge Expired API Tokens03:00user_api_tokens rows past their expirationToken lifetime set at issue time from cbApiTokenMaxValidityMonths (default 12 months) - see App Settings
Purge Expired Remember Tokens03:15user_remember_tokens rows past their expirationFixed expiration set when the token is issued (SecurityService/RememberTokenService)
Purge Old Audit Logs03:30audit_logs rows older than the retention windowcbAuditLogRetentionDays (default 90; 0 disables the purge) - see App Settings

All three call a purgeExpiredTokens()/purgeOlderThan() method on the owning service rather than querying the table directly, so the same purge logic is reachable (and testable) outside the scheduler. Add a new task the same way - see Extending the App.

Full project tree

cbgenesis/
โ”œโ”€โ”€ app/                      Application code
โ”‚   โ”œโ”€โ”€ Application.bx        Abort-only gate (prevents direct /app access)
โ”‚   โ”œโ”€โ”€ config/
โ”‚   โ”‚   โ”œโ”€โ”€ Coldbox.bx        Framework settings, environments, logging
โ”‚   โ”‚   โ”œโ”€โ”€ Router.bx         All application routes
โ”‚   โ”‚   โ”œโ”€โ”€ CacheBox.bx       Cache regions (default, template, sessions, rateLimit)
โ”‚   โ”‚   โ”œโ”€โ”€ WireBox.bx        DI container configuration
โ”‚   โ”‚   โ”œโ”€โ”€ Scheduler.bx      Scheduled tasks
โ”‚   โ”‚   โ””โ”€โ”€ modules/          Per-module settings (cbsecurity, cbauth, cborm, ...)
โ”‚   โ”œโ”€โ”€ handlers/              Controllers (Auth, Dashboard, Users, Roles, ...)
โ”‚   โ”œโ”€โ”€ layouts/                Admin, AuthCenter, AuthSplit, Main
โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”‚   โ”œโ”€โ”€ BaseEntity.bx      ORM base: timestamps, soft delete, memento
โ”‚   โ”‚   โ”œโ”€โ”€ BaseService.bx     Service base: cborm + qb + cache + validation
โ”‚   โ”‚   โ”œโ”€โ”€ security/            Role, Permission, APIToken, RememberToken,
โ”‚   โ”‚   โ”‚                        Passkey, UserActionToken, SecurityService, ...
โ”‚   โ”‚   โ””โ”€โ”€ system/              User, Setting, AuditLog + their services
โ”‚   โ”œโ”€โ”€ views/                  BXM templates, one folder per handler
โ”‚   โ”‚   โ””โ”€โ”€ _components/        Reusable UI partials (app, auth, ui)
โ”‚   โ”œโ”€โ”€ email_templates/       Token-based email body templates
โ”‚   โ”œโ”€โ”€ helpers/               ApplicationHelper.bxm โ€” global view helpers
โ”‚   โ””โ”€โ”€ interceptors/           AuditLogger, RateLimiter, SSOAuthorization
โ”œโ”€โ”€ public/
โ”‚   โ”œโ”€โ”€ Application.bx         Entry point โ€” ColdBox + ORM bootstrap
โ”‚   โ”œโ”€โ”€ index.bxm               Front controller placeholder
โ”‚   โ””โ”€โ”€ includes/               Vite production build output
โ”œโ”€โ”€ resources/
โ”‚   โ”œโ”€โ”€ assets/js/              Alpine entry, stores, components
โ”‚   โ”œโ”€โ”€ assets/scss/            Bootstrap + custom SCSS
โ”‚   โ””โ”€โ”€ database/
โ”‚       โ”œโ”€โ”€ migrations/         Schema migrations (cfmigrations)
โ”‚       โ””โ”€โ”€ seeds/              AdminData seeder
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ specs/integration/      Full HTTP-level specs
โ”‚   โ””โ”€โ”€ specs/unit/             Entity + service specs
โ”œโ”€โ”€ lib/                        Dependencies (gitignored, installed by `box install`)
โ”œโ”€โ”€ runtime/                    BoxLang engine config (boxlang.json)
โ”œโ”€โ”€ server.json                 CommandBox server config (engine, webroot, aliases)
โ”œโ”€โ”€ box.json                    Package manifest โ€” deps, scripts
โ”œโ”€โ”€ package.json                 NPM โ€” Alpine, Bootstrap, Vite, ESLint
โ”œโ”€โ”€ vite.config.mjs              Vite + coldbox-vite-plugin
โ””โ”€โ”€ .env.example                  Environment template

The stack

LayerTechnology
RuntimeBoxLang 1.0+ (JVM)
FrameworkColdBox HMVC (bleeding edge)
CLI / ServerCommandBox + BoxLang MiniServer
Dependency InjectionWireBox
Securitycbsecurity + cbauth (session-based + JWT)
DatabaseMySQL, MariaDB, PostgreSQL, and MSSQL via Hibernate ORM (cborm); all four database targets are supported and covered by the project's database testing workflow
Query Builderqb (fluent SQL)
Migrationscfmigrations
Validationcbvalidation
Emailcbmailservices
Serializationmementifier
FrontendBootstrap 5.3 ยท Alpine.js 3.x ยท Vite 6
IconsPhosphor Duotone
TooltipsTippy.js
Edit this page Download Markdown Last updated Nov 1, 2026, 6:21:18 PM