Skip to main content
A map, not a manual: each entry names what Core uses, the major version it is on, and why. The deeper pages are linked rather than repeated. Versions are those in composer.json, package.json and their lock files; when this page and a lock file disagree, the lock file is right.

Backend

Development-only: Telescope, Pail, ide-helper, Ray and Laravel Boost.

Data

How tenant context is held and switched: Tenant-aware execution. Why migrations are pure DDL: Migration isolation. Why keys are ULIDs in uuid columns: ID strategy.

Queues and realtime

Workers are long-lived, which is what Long-lived worker safety is about. Turning websockets on: Realtime.

Console front end

The staff console — platform administration and the per-assistant screens — is an Inertia application in Vue. Core has no Filament or Livewire: neither is in composer.json, so in Core’s CI a reference to either fails phpstan’s unknown-class checks. The PHPat rule NoFilamentTest bites only where Filament is installed — a local Core checkout with the SaaS overlay. Translations come from Laravel’s lang/ files (en, ru, uk) and reach a page as shared Inertia props, one namespace per page — there is no separate front-end i18n library. Admin UI language and content language are different things; see Multilingual. Solution screens are prebuilt bundles that import Vue, Inertia and @fapost/ui from the console through an import map, so a Solution never ships its own copy. See Console UI.

The flow builder

The builder in resources/js/builder is a separate Vite entry with its own root view and stylesheet. It is still Inertia and Vue, but the canvas holds a lot of client state, so it keeps it in Pinia stores rather than in page props. Node configuration forms are rendered from the schema a handler declares, not written per node — see Builder UI. resources/js/tma is a third entry: a small Vue Router app served as a Telegram Mini App for forms.

Extensions

Core is extended from outside, never by forking it. Briefly:
  • fapost/foundation — the public contracts a Solution or Plugin builds against; Core implements them.
  • fapost/support — primitives with no domain meaning, including the builder schema field classes.
  • Solutions and Plugins — separate Composer packages, added to a checkout with a composer overlay that leaves Core’s own composer.json untouched.
  • The SaaS operator package — the control plane of the hosted service (billing, onboarding), a separate repository on top of Core and never part of it. Its operator panel is built on Filament and lives in that package, not in Core.
Where each thing belongs: Extension model. Working on the packages locally: Development setup. Which way dependencies may point: Dependency direction.

Gateway and images

The gateway in gateway/ is an optional Go service (Go 1.27, go-redis 9) in front of webhook ingress: it verifies, deduplicates and queues provider webhooks without a PHP process. See Webhook gateway. A release publishes three images from .github/workflows/publish-images.yml: core and web come from one docker/Dockerfile; its dev target is the local development image, built from the same base. Running them: Docker Compose.

Quality

CI runs the PHP job twice — on SQLite, what a developer runs locally, and on PostgreSQL, where schema-per-tenant switching and partitioned tables actually behave as in production — with a real Redis beside both. The front-end job type-checks, tests and runs the same production build the web image does. How to run all of it: Testing and architecture checks. Agents working on Core use Jig for task routing and project knowledge.

Running it locally

Docker or a local install, and the commands for both: Local setup.