@todayai-labs/tck-host
Browser-side host runtime. Manifest registry, widget loader, layout grid, patch dispatcher, agent channel, two-tier mount surface.
The browser-side host runtime. A host app (today-platform-web, the workbench, the native WebView shell) wires up a single TodayHost and consumes it through React. tck-host owns the doc store, the patch dispatcher, the manifest registry, the widget loader, the layout canvas, the bus the agent talks on, and the <WidgetMount> mount primitive.
Widgets do not import this package — it's host-only, and the bundler enforces that absence at build time.
The package is split into multiple subpaths to keep the import graph minimal per consumer-class — a Next.js server module evaluating getHostHeadNodes must not transitively reach createContext, and an import-map-served mountHost must not drag in the full React component graph. The split is structurally enforced by __tests__/export-safety.test.ts; see the design memo for the rationale.
Subpaths
@todayai-labs/tck-host (root)
The core runtime. Safe to import anywhere a client React runtime exists.
| Export | What it does |
|---|---|
TodayHost | The host root. Owns registry + loader + dispatcher + docStore + canvas state. See § TodayHost. |
TodayHostOptions | Constructor options: storage, loaderOptions, onSizeMismatch. |
WidgetInstance | Immutable per-mount metadata returned by host.mountWidget / host.restoreWidget. |
SizeMismatchPolicy | 'warn' | 'throw' — see container contract. |
TodayWidgetCanvas | React component: the grid surface. Drag-to-move, tile chrome. |
TodayWidgetCanvasProps | Props + types for canvas tile rendering (WidgetTileRenderArgs, CanvasTileDragBindings). |
TodayFeedStack | React component: the feed surface (linear column of full-width cards). |
TodayFeedStackProps | Props + types for feed card rendering (FeedCardRenderArgs). |
WidgetLoader | Given a bundle URL → WidgetModule. Verifies named exports, ABI label, manifest schema. |
WidgetLoaderOptions, WidgetModule, ModuleMap, DEFAULT_HOST_ABI | Loader plumbing. |
WidgetLoadError | Loader-side rejection (malformed bundle / missing exports / failed manifest validation). |
WidgetAbiError | manifest.engines.abi does not match the host's ABI label. |
WidgetSizeError | Mount offered a size not in manifest.sizes. See container contract. |
WidgetMount | Low-level shadow-DOM mount primitive (also re-exported by /bootstrap). |
WidgetMountProps, WidgetMountFallbackControls | <WidgetMount> types. |
PatchDispatcher | Single sequencer per doc. Applies RFC-6902 patches; rejects stale baseVersion; idempotent on patchId. |
PatchDispatcherOptions | Dispatcher tuning. |
ManifestRegistry | In-memory {manifestId → RegisteredWidget} index. |
RegisteredWidget | Registry entry shape. |
DocStore, ephemeralStorage | Per-instance JSON-doc snapshots; pluggable storage backends. |
DocSnapshot, DocStorage | Storage backend contract. |
migrateDoc, MigrationError | Forward-only state migrations on schemaVersion mismatch. |
WidgetErrorBoundary | Per-widget React error boundary. Chrome-level "Reload widget" + "Reset to defaults". |
AgentChannelImpl, makeWidgetAgentChannel | Host-side agent bus implementation. |
| Layout helpers | DEFAULT_GRID, canPlaceAt, canvasWidth, effectiveFootprint, findFirstFreeSlot, gridCssVars, pointerToGridPosition, widgetPixelSize, TodayGridConfig. |
@todayai-labs/tck-host/bootstrap
Tier-1 mount components — closed-contract single-widget surfaces. Client React only.
| Export | What it does |
|---|---|
TodayHostBoundary | React provider exposing the host + docStore to descendant <TodayWidget> mounts. |
TodayHostBoundaryProps | Props. |
TodayWidget | Closed-contract widget mount; accepts {src, instanceId} OR {devModule, instanceId}. No loadModule escape hatch — every module flows through WidgetLoader.parseModule. See Tier 1 mount surface. |
TodayWidgetProps | Discriminated-union prop shape. |
TodayWidgetMountedInfo | onMounted callback payload. |
WidgetMount | Low-level shadow-DOM primitive (re-exported from root). |
@todayai-labs/tck-host/server
SSR-head slice. Safe to import in server modules — does not call createContext or touch the DOM.
| Export | What it does |
|---|---|
getHostHeadNodes | Returns <link> / <script type="importmap"> / <html data-theme> React elements for the host's <head>. |
@todayai-labs/tck-host/mount
Client-imperative slice — mountHost only. Safe to import anywhere; no React, no createContext.
| Export | What it does |
|---|---|
mountHost(document, options) | Installs document-level host concerns: CSS <link>, importmap, data-theme attribute. Returns a MountHostControl. |
MountHostControl | { setTheme, dispose } — runtime theme flips + cleanup. |
MountHostOptions | { theme: 'light' | 'dark' | 'system', hostCssUrl? }. |
HostBootstrapError | Thrown when mountHost cannot verify the import-map's presence on the document. |
@todayai-labs/tck-host/vite
Vite plugin: build-time importmap injection. For no-SSR Vite hosts (workbench, tck-preview) — the dev-server equivalent of getHostHeadNodes.
| Export | What it does |
|---|---|
hostImportMapPlugin() | Vite plugin. Reads tck-shared-deps's manifest.json at transformIndexHtml, injects <script type="importmap"> before any module script. |
@todayai-labs/tck-host/messages
Cross-window message types for <TodayWidget>'s iframe-mode bridge. Internal-protocol; typed shapes only.
@todayai-labs/tck-host/style.css
Default host stylesheet (preflight + theme tokens + the [data-theme='dark'] variant binding). Import once at the host app's root, or copy alongside tck-shared-deps's output for serving over importmap-resolved URLs.
import '@todayai-labs/tck-host/style.css'TodayHost
The canvas-tier API. Use this when building a Tier-2 host (workbench, drag-canvas, persisted layout); for embedding surfaces, prefer <TodayWidget> from /bootstrap.
import { TodayHost, ephemeralStorage } from '@todayai-labs/tck-host'
const host = new TodayHost({
storage: ephemeralStorage, // or an idb-keyval-backed DocStorage
loaderOptions: { loadModule: (url) => import(url) },
onSizeMismatch: 'warn', // or 'throw' for debug surfaces
})
host.registerWidget({
manifest: parsedManifest,
bundleUrl: 'https://.../widget.mjs',
cssUrl: 'https://.../widget.css',
})
const instance = await host.mountWidget({
manifestId: 'com.example.counter',
position: { col: 0, row: 0 },
size: '2x1', // optional; defaults to manifest.defaultSize
seedState: { count: 0 }, // optional; defaults to manifest.defaultState
})Methods:
registerWidget/mountWidget/restoreWidget/resetWidget/removeWidgetmoveWidget(instanceId, position)/resizeWidget(instanceId, size)setTransient(instanceId, transient)— flip the suggestion / pinned bitsetAmbientWidgetCss(css)— for unbundled (workspace dev) widgetslist()/get(instanceId)/subscribeLayout(fn)submitPatch({instanceId, baseVersion, patch})— build envelope + dispatch + handle stale rebasepublishAgent(message)— broadcast onto the agent bus
Source
- Package:
packages/tck-host - Reference Tier-2 host:
apps/host-playground - Reference Tier-1 consumer:
today-platform-web/apps/web/src/canvas-boot/ - Host-side ABI contract: Platform ABI § Host-side ABI contract
- Two-tier mount design: Platform ABI § Mount tiers
@todayai-labs/tck
Widget-author SDK. Types, hooks, primitives, patch helpers. Compiled INTO the widget bundle.
@todayai-labs/tck-host-native
Bundle-artifact package for non-Vite native hosts (macOS / iOS / iPadOS / visionOS). Ships dist/ with harness.html + importmap-resolved shared deps for WebView consumers.