Skip to content

Extend the platform

You extend the platform by implementing a port — the ports are the extension surface. Ports live in packages/platform-domain/**/ports/ (infrastructure-free); your adapter lives in apps/api/**/adapters/.

  • Generic (any future consumer would want it) → goes in packages/platform-ingestion/. Example: a new source reader, a new port.
  • Consumer-specific (only one app cares) → goes in the consumer’s directory. Example: classifieds-listing parsing, bookmark-tag derivation.

Implement INode — or extend SelfSourcingNode when the node selects its own work rather than reading the items handed to it — and register it in the NodeRegistry with a NodeDescriptor. Most nodes register unconditionally and resolve their credential (an LLM, Gmail, Notion, … Connector) per run, failing clearly at that point when the owning user has no connected channel of that scheme; a node whose integration this deployment cannot wire at all is left unregistered, so it is absent from the palette rather than present and permanently red.

Implement IDispatchTarget (packages/platform-domain/src/dispatch/ports/IDispatchTarget.ts) and add its scheme to DESTINATION_SCHEMES (packages/platform-domain/src/connector/Destination.ts — the canonical vocabulary shared by the workflow templates and buildWork). The dispatch step (DispatchStep) routes by config.destination’s URI scheme, threading context.metadata.userId/orgId into the destination config for owner-scoping.

Implement ISourceReader in packages/platform-ingestion/. The consumer seam is IContentHandler — a consumer app implements it to translate BaseContent into its own entity.

Implement ILlmClient and add the models to the catalog. Every AI consumer reaches the model through the AI gateway, which resolves the channel, applies the default, meters the call and fails it over — so adding a provider is an adapter plus a catalog entry, not a code change in any step. Anthropic (default) and Cline (fallback) are the two today.

  • TypeScript + Bun; checks are bun run typecheck / bun run lint / bun run test:unit.
  • Keep the domain package infrastructure-free (no drizzle-orm, pg-boss, fs, http).
  • Import from the @viite-ai/platform-domain barrel, not deep relative paths.