Skip to content

Hexagonal architecture

The platform follows strict hexagonal architecture (ports and adapters). This is what keeps the domain testable and lets you extend the platform without forking it.

flowchart TD
    ui["User interfaces<br/>CLI · Web UI · REST API"]
    app["Application layer<br/>Use cases · services · orchestration"]
    domain["Domain layer<br/>Entities · Ports / interfaces"]
    infra["Infrastructure layer<br/>Adapters: DB · API · file system"]

    ui --> app --> domain --> infra
  • Ports (interfaces) live in packages/platform-domain/**/ports/. The domain package is infrastructure-free — no drizzle-orm, pg-boss, fs, or http imports.
  • Adapters (concrete implementations) live in apps/api/**/adapters/.

For example, the job runtime defines IJobRepository, IJobRunner, and IWorkflowStep as ports; DrizzleJobRepository, PgBossJobRunner, and the concrete steps are adapters.

The ports are the extension surface. You extend the platform by implementing one:

Implement……to add
IWorkflowStep / BaseWorkflowStepa new pipeline step
IExportTargeta new export destination
ISourceReadera new ingestion source
ILlmClienta new LLM provider

See Extend the platform for a worked example.