Event sources
An event source is a live, read-only feed of dated items one package contributes to another package’s event grid. The shipped example: with both packages installed, the boards package feeds every card’s due date to the calendar, where each shows as an all-day item that opens the card when clicked.
Where a sidebar slot contributes UI, an event source contributes data — the host owns all rendering, plus a per-source visibility toggle in its sidebar. Contributed items cannot be dragged or edited on the host’s grid; a press navigates to the item’s own app via its href.
Contributor side
Declare the source in the manifest and export a hook module:
const manifest = {
// ...
eventSources: [
{
target: 'calendar', // host package slug
id: 'boards-due', // unique per target, [a-z0-9-] only
label: 'Card due dates', // the host's sidebar toggle text
module: 'calendar-source', // package-exports subpath
color: 'graphite', // optional; host resolves the key
},
],
}
Add the matching literal entry to package.json exports ("./calendar-source": "./tinycld/boards/calendar-source.ts"). The module exports a single hook:
import type { EventSourceItem, EventSourceRange } from '@tinycld/core/lib/event-sources/types'
export function useEventSource({ start, end }: EventSourceRange): {
items: EventSourceItem[]
isLoading: boolean
} {
// Typically one useOrgLiveQuery over your own collections, mapped to
// { id, title, start, end, allDay, href } items within [start, end].
}
The host mounts the hook inside a collector component and calls it on every render, so it must obey the rules of hooks — a live query is the expected implementation. Items re-render on the host’s grid as your data changes, which is what makes the feed live rather than a snapshot.
The contract types live in @tinycld/core/lib/event-sources/types — the contributor never imports the host. An absent host leaves the contribution silently inactive, so a partial workspace still typechecks and runs (the same lean-shell rule as every cross-package feature).
Host side
A host declares eventSourceHost: true in its manifest and consumes packageEventSources[<own slug>] from @tinycld/core/lib/event-sources/registry, resolving each source’s module with loadEventSourceModule (or the useEventSourceModule hook) and mounting one collector component per source. Calendar is the reference implementation: EventSourcesHost.tsx (collectors), useSourceEvents.ts (merge + press routing), EventSourceToggles.tsx (sidebar visibility).
Validation
Generation fails fast on the mistakes that would otherwise surface as a silently empty grid: a contribution targeting a present package that doesn’t declare eventSourceHost, a duplicate (target, id) pair, or an id outside [a-z0-9-] (the host embeds ids in synthetic event identifiers). A contribution targeting an absent package is only a warning — that’s the normal partial-checkout case.
Like sidebar slots, event sources are static and bundled-only: the generator emits a lazy load thunk into tinycld.config.ts, so a contributor’s module is code-split and never in the host’s import graph. Runtime-installed packages cannot contribute event sources.