:8080 by
default. It is a client of the ConnectRPC API
and nothing else. Every button maps to an RPC you can call yourself, so
anything you do here is scriptable later.


The Filament web app
- A connection is a configured connector. Credentials plus connection-scoped settings, saved once and reused.
- A pipeline is a graph of connections. Edges route resources from a source to a sink, each carrying a read mode and a write mode.
- A run is one execution of a pipeline route, tracked from request to verified write.
Observability
The landing page. Records and bytes moved, run durations, and success rate over a timeframe you pick, plus a feed of recent runs across every pipeline. The charts come from the metrics service, which aggregates the same run rows the rest of the app reads.

Observability, the landing page
Connections
Sources and Sinks each list what you have already connected. A card carries the connector it uses, how many pipelines depend on it, and its current version, which is the optimistic lock that keeps concurrent edits from overwriting each other.

Saved sources


The connector catalog
cdc.
Two details worth knowing:
- Scope. Connections hold connection-scoped fields only, the ones that describe reaching the system. Pipeline-scoped fields like a destination schema are set later, per pipeline.
- Secrets. Secret-typed fields are extracted on save and stored through the configured secrets provider. Reads return them masked, and editing leaves a stored secret in place unless you submit a new value.
Pipelines
The list view shows each pipeline with its schedule, recent run outcomes, and last duration. Opening one gives you the canvas, the history, and the settings.

The pipelines list
Canvas
The canvas edits the pipeline graph. Nodes are connections and edges route selected resources between them. Standard sources let you choose full or incremental reads and an appropriate destination write mode. CDC sources use the connection’s change stream and let the route append events or merge them into current state. Incremental reads may also need a cursor column. Replication modes explains the valid combinations. Edits are validated as you work. Unmet requirements appear on the edge itself, so a table without a primary key blocks an upsert route before you save rather than failing at run time. Saving creates a new immutable pipeline version. In-flight runs keep executing against the version they started with.

The pipeline canvas
History
Every run, newest first, with per-resource record and byte tallies and a final status. An active run streams, so progress arrives as the engine publishes it rather than on a poll. Statuses map directly to engine states. A failed run that saved resumable progress entersPARTIAL and continues from its last checkpoint when
requested again. See
Runs and recovery.


Run history
Settings
Name and description, a cron schedule with a timezone and an overlap policy, and the worker configuration that sizes the machines runs execute on. Metadata edits apply in place and do not create a version.

Pipeline settings
Contributing to the web app
For contributors, the web app lives inui/ as a React 18 and TypeScript app
built with Vite:
- Routing and data. TanStack Router with file-based routes in
src/routes/, and TanStack Query for server state. API calls go through ConnectRPC’s web transport withconnect-querybindings. - Generated types.
src/gen/holds the protobuf-generated TypeScript. Never edit it by hand.pnpm codegen(orjust genat the repo root) regenerates it withbufafter a proto change. - Design system. Components, tokens, and theming come from
@galaxy-io/dls. The app mounts its stylesheet andGalaxyThemeProviderinmain.tsx. Browse the catalog at storybook.getgalaxy.io before building anything new. - Styling and the canvas. Component-local styles use Linaria. The canvas
is built on
@xyflow/react. Icons are Phosphor, with project SVGs compiled bypnpm assets. - Formatting. Biome formats and lints the UI.
embedui tag,
which just binaries and the published images do. For development, just ui
runs Vite on :5173 against a local API. See
Local development for the
rest of the workflow.