Two halves, one section
Building an extension — the groups from Extension model through Shipping an extension. These describe the public surface: the contracts infapost/foundation that Core undertakes not to break within a major version.
Everything there is a promise.
Core internals and Contributing to Core describe how Core is built: its
domains, its runtime, the decisions that shape it. Nothing there is a promise —
it is refactored freely.
What the platform is made of
Three Composer packages plus a standalone Go service. The split is not organisational tidiness — it is what makes the platform extensible without freezing its internals.fapost/core
The platform itself: domains, flow engine, admin panels, and the Vue builder.
This is the application an operator deploys.
fapost/foundation
The public contract layer for Solutions, Plugins, and external integrations.
Everything an extension is allowed to depend on.
fapost/support
Reusable primitives: the ULID trait, a base model, model concerns, and the
builder schema field classes.
gateway
An optional Go service that accepts, verifies, and queues provider webhooks
without involving PHP.
fapost/core
Thirteen domains underapp/Domains, the flow engine, the Filament admin and
assistant panels, and the Inertia + Vue flow builder. It depends on both packages
below.
Core is where a Feature lives — a capability that belongs to the product
surface and releases with the platform. Anything narrower belongs outside it; see
Choosing an extension type.
fapost/foundation
Node handlers, data accessors, channel and messaging interfaces, RAG adapters, the plugin and solution lifecycle base classes, and the DTOs that travel between them. This package is the extension boundary. A Solution or Plugin depends onfapost/foundation and never on App\…, which is what lets Core refactor its
own internals without breaking anything built on top.
It has no FaPost dependencies of its own — only PHP 8.4, illuminate/support,
psr/http-message, and spatie/laravel-data.
fapost/support
Primitives with no domain meaning.HasUlidPrimaryKey, a BaseModel, concerns
for computed attributes and utilities — and the field classes that describe a
node’s configuration form: TextField, SelectField, StatePickerField,
ObjectArrayField and the rest, assembled into a Schema of Sections.
fapost/support depends on fapost/foundation. The arrow runs one way and never
back toward Core.
Both packages live in their own repositories under
fapost-lab. During development they are
checked out into
packages/ and symlinked into vendor/; in production they
resolve from git like any other dependency. See
Development setup.gateway
A Go service ingateway/, shipped inside the Core repository rather than as a
Composer package, because it is not PHP.
It sits in front of webhook ingress: rate-limits by channel, resolves the routing
entry from Redis, verifies the provider’s signature, claims an idempotency key,
and pushes the job — about a millisecond, with no PHP process involved. It knows
nothing about any particular platform; each channel adapter publishes a
declarative ingress spec describing how its webhook is signed, and both the
Go and PHP implementations are held to the same golden file so they cannot drift.
It is optional. Without it, webhooks go to the Laravel route exactly as they
always have. See Webhook gateway.
Where to start
Local setup
Get a checkout running on your machine.
Extension model
Feature, Solution, or Plugin — and how they differ.