Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vibefollow.com/llms.txt

Use this file to discover all available pages before exploring further.

For events that aren’t part of the canonical lifecycle set, use events.track(). The name is accepted as-is — the backend validates only that it’s a non-empty string.

Single events

await vf.events.track('dashboard_created', 'usr_42', {
  source: 'wizard',
  workspaceId: 'ws_3',
});
The first argument is the event name. The second is the external user ID. The third is an optional properties bag — anything JSON-serialisable.
The 9 canonical lifecycle names work through track() as well, but prefer the typed helpers in vf.users.* for autocomplete and type safety.

Naming conventions

Use dashboard_created, not DashboardCreated. Stable across audience filters and triggers.
Renaming an event breaks any audience filter that already references the old name. Treat event names like database column names — pick once, live with it.
Use workspaceId, not workspace_id. The backend normalises both to the same column, but consistency in your own code is worth holding the line on.

Batch tracking

For high-volume work — backfilling historical events, syncing from a data warehouse, replaying a Segment export — use events.batch() to amortise HTTP overhead:
const batch = vf.events.batch({ maxSize: 100, maxAgeMs: 5_000 });

for (const row of historicalEvents) {
  batch.track(row.name, row.userId, row.properties);
}

// Drain on shutdown.
await batch.flush();
The batch auto-flushes when:
  • The queue reaches maxSize events (default 100), or
  • maxAgeMs has elapsed since the first queued event (default 5000), or
  • You call flush() explicitly.
Always await batch.flush() before process exit. Lambda-style runtimes that freeze the event loop will lose any queue still in memory.

Trade-offs

events.track()events.batch()
LatencyPer-event POSTBuffered, drains in one POST
Failure modeSingle event failsFull batch retried
Use whenReal-time interactive flowBackfills, sync jobs, write-heavy paths
Batches are not idempotent across drains — if the POST fails midway through retries, the batch may be partially accepted server-side. Re-emit conservatively or set a retention-policy filter on your end to dedupe by event ID.

Reserved names

Reserved-name routing is an API-side concern, not the SDK’s. Custom names that happen to collide with a future reserved name will be rejected at validation with ValidationError — you’ll know immediately.
The current reserved set is the 9 canonical lifecycle names. Treat anything Vibefollow ships with as reserved.