From e4f67062ab90adf2f90a74eac6540ca05057ecb3 Mon Sep 17 00:00:00 2001 From: Chris Jayden Date: Wed, 22 Jul 2026 08:44:37 +0200 Subject: [PATCH 01/21] docs: design Trakoo agent skill --- .../2026-07-22-trakoo-agent-skill-design.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md diff --git a/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md b/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md new file mode 100644 index 0000000..a4d917a --- /dev/null +++ b/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md @@ -0,0 +1,121 @@ +# Trakoo Agent Skill Design + +## Goal + +Add a consumer-facing Agent Skill that helps application developers integrate and use Trakoo correctly. The skill must be installable from this repository with the `skills` CLI and useful across TypeScript frameworks without duplicating the full documentation site. + +## Research Summary + +Popular TypeScript projects use three recurring structures: + +- Better Auth publishes a broad integration guide plus narrower feature skills in a dedicated repository. +- Vercel AI SDK keeps a focused consumer skill in the main repository and tells agents to verify version-sensitive APIs against installed package documentation and source. +- tRPC and CopilotKit use routers and many specialized skills for larger API surfaces. + +Trakoo is compact enough that a routed skill pack would add navigation and maintenance overhead without improving the common integration flow. A focused core skill with on-demand reference files provides the best balance of discoverability, context size, and coverage. + +## Package Structure + +```text +skills/trakoo/ +├── SKILL.md +└── references/ + ├── providers.md + └── frameworks.md +``` + +`skills/trakoo/SKILL.md` is the installable entry point discovered by the `skills` CLI. It contains the integration workflow, core invariants, a concise working example, verification guidance, and pointers to the two references. + +`references/providers.md` contains the provider capability and dependency matrix, selection guidance, routing patterns, Proxy transport, custom providers, and provider-specific constraints. + +`references/frameworks.md` contains framework detection and integration guidance for Next.js, SvelteKit, and framework-neutral browser/server TypeScript projects. It focuses on file placement, environment-variable boundaries, navigation tracking, and server lifecycle rather than restating framework documentation. + +## Triggering and Scope + +The skill should trigger when developers: + +- Mention Trakoo or its package entry points. +- Add typed, provider-agnostic analytics to a TypeScript application. +- Configure a Trakoo provider such as PostHog, OpenPanel, Bento, Pirsch, EmitKit, Visitors, or Proxy. +- Define typed events, identify users, route events between providers, or troubleshoot Trakoo client/server integration. + +The skill is for applications consuming Trakoo. It does not govern development of the Trakoo repository itself, releases, or changes to Trakoo internals. + +## Integration Workflow + +When activated, the skill guides the agent through this sequence: + +1. Inspect the consuming project to detect its package manager, framework, client/server boundaries, installed Trakoo version, and existing analytics dependencies. +2. Determine whether the integration needs browser tracking, server tracking, or both, and choose providers based on the events and delivery guarantees required. +3. Install `trakoo` and only the optional provider SDKs required by the chosen configuration. +4. Define a central typed event collection before adding tracking calls. Preserve exact event names with `as const satisfies` and pass its type to each analytics factory. +5. Create browser and server analytics modules using their environment-specific entry points. Keep secrets and server providers out of browser bundles. +6. Add tracking at authoritative locations: interactions and navigation in the browser; payments, signups, jobs, and other critical events on the server. +7. Apply lifecycle rules: identify once and reset on logout in the browser; pass user context per server event; await critical server events and flush or shut down before short-lived runtimes exit. +8. Configure multi-provider routing, Proxy delivery, or custom providers only when the application requirements call for them. +9. Run the consuming project’s formatter, type checker, and relevant tests. Resolve type or import failures using the installed package declarations and official Trakoo documentation rather than guessing. + +## Core Correctness Rules + +- Import shared event types from `trakoo`, browser APIs from `trakoo/client`, server APIs from `trakoo/server`, and providers from `trakoo/providers/client` or `trakoo/providers/server`. +- Do not import server providers, secrets, or server-only environment variables into browser code. +- Keep a single browser analytics instance per session. Treat server analytics as stateless across users. +- Call client `identify()` after authentication and `reset()` on logout. +- Pass user context explicitly to server tracking calls. +- Await critical server events and call `shutdown()` in short-lived/serverless execution paths, preferably from `finally`. +- Use routing rules for provider-specific constraints rather than sending every event and method to every provider. +- Do not invent provider packages or options. Verify version-sensitive details against installed types, source, or official documentation. + +## Error Handling + +The skill should diagnose common integration failures before proposing broad changes: + +- Wrong entry point or client/server code mixed in one module. +- Missing optional provider dependency. +- Event collection type not supplied to an analytics factory. +- Event name or property shape that does not match the typed collection. +- Browser user state not reset after logout. +- Server event not awaited or provider queue not flushed. +- Provider requirements not met, such as Bento lacking an identified email, Pirsch server tracking lacking request context, or Visitors identification without persistence and consent. +- Mutually exclusive provider routing options combined in one configuration. + +When the installed package API differs from the repository documentation, the installed package declarations are authoritative for generated code. The agent should explain the version mismatch and avoid silently upgrading unless the user requests it. + +## Testing and Evaluation + +The skill is a reference/integration skill, so evaluation should use realistic application tasks rather than discipline-pressure scenarios. Before writing the skill, establish baseline agent behavior without it for representative prompts. After writing it, rerun the same prompts with the skill and compare correctness. + +Initial scenarios should cover: + +1. A Vite or framework-neutral browser app adding typed PostHog tracking and user lifecycle handling. +2. A Next.js application tracking a critical server event while keeping credentials server-only and flushing correctly. +3. A multi-provider setup routing anonymous page views and identified lifecycle events to providers with different requirements. + +Objective checks include correct import paths, a typed event collection, environment-safe configuration, required optional dependencies, correct client/server lifecycle behavior, and a verification step. Test artifacts should stay outside the installable skill directory unless they provide ongoing value to maintainers. + +## Documentation and Installation + +The repository README should gain a short Agent Skill section with the installation command: + +```bash +npx skills add multiplehats/trakoo --skill trakoo +``` + +The section should state that the skill helps coding agents integrate typed Trakoo analytics and link to `skills/trakoo/SKILL.md`. The skill itself links to the official Trakoo documentation for details likely to change. + +## Success Criteria + +- `npx skills add multiplehats/trakoo --skill trakoo` discovers the skill from the repository layout. +- The `SKILL.md` frontmatter satisfies the Agent Skills specification and clearly triggers for Trakoo consumer integration tasks. +- The main skill stays concise and delegates provider/framework detail to explicit on-demand references. +- Examples use only public exports and valid configuration from the current repository. +- Baseline-versus-skill evaluations show improved correctness for typed events, import boundaries, provider dependencies, and runtime lifecycle. +- Repository formatting and validation checks pass. + +## Out of Scope + +- Contributor instructions for modifying Trakoo itself. +- A dedicated MCP server or live documentation service. +- Separate installable skills for each provider or framework. +- Automated migration from other analytics libraries. +- Publishing a separate skills repository. From 41be03b371ef036d1a867a4421ccbc5565374130 Mon Sep 17 00:00:00 2001 From: Chris Jayden Date: Wed, 22 Jul 2026 09:07:16 +0200 Subject: [PATCH 02/21] docs: expand agent skill framework coverage --- docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md b/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md index a4d917a..d445cb5 100644 --- a/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md +++ b/docs/superpowers/specs/2026-07-22-trakoo-agent-skill-design.md @@ -28,7 +28,7 @@ skills/trakoo/ `references/providers.md` contains the provider capability and dependency matrix, selection guidance, routing patterns, Proxy transport, custom providers, and provider-specific constraints. -`references/frameworks.md` contains framework detection and integration guidance for Next.js, SvelteKit, and framework-neutral browser/server TypeScript projects. It focuses on file placement, environment-variable boundaries, navigation tracking, and server lifecycle rather than restating framework documentation. +`references/frameworks.md` contains framework detection and integration guidance for Next.js, SvelteKit, TanStack Start, Astro, and framework-neutral browser/server TypeScript projects. It focuses on file placement, environment-variable boundaries, navigation tracking, and server lifecycle rather than restating framework documentation. ## Triggering and Scope From ba4a074e0d5cd79138cd4b9a34a9cbac41da8096 Mon Sep 17 00:00:00 2001 From: Chris Jayden Date: Wed, 22 Jul 2026 09:12:22 +0200 Subject: [PATCH 03/21] docs: plan Trakoo agent skill implementation --- .../plans/2026-07-22-trakoo-agent-skill.md | 770 ++++++++++++++++++ 1 file changed, 770 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-22-trakoo-agent-skill.md diff --git a/docs/superpowers/plans/2026-07-22-trakoo-agent-skill.md b/docs/superpowers/plans/2026-07-22-trakoo-agent-skill.md new file mode 100644 index 0000000..c92d0fe --- /dev/null +++ b/docs/superpowers/plans/2026-07-22-trakoo-agent-skill.md @@ -0,0 +1,770 @@ +# Trakoo Agent Skill Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add and validate an installable consumer-facing Trakoo Agent Skill with concise core guidance and on-demand provider and framework references. + +**Architecture:** Place one discoverable skill at `skills/trakoo/SKILL.md`; keep provider and framework detail in two references that are loaded only when relevant. Protect the package with a Vitest contract test, document installation in the root README, and compare realistic agent outputs with and without the skill before considering it complete. + +**Tech Stack:** Agent Skills open specification, Markdown/YAML frontmatter, skills CLI, TypeScript, Vitest, pnpm. + +## Global Constraints + +- The skill serves applications consuming Trakoo, not contributors changing Trakoo internals. +- The install command is exactly `npx skills add multiplehats/trakoo --skill trakoo`. +- The core skill must use public exports from `trakoo`, `trakoo/client`, `trakoo/server`, `trakoo/providers/client`, and `trakoo/providers/server` only. +- Keep browser providers and public environment values separate from server providers and secrets. +- Cover Next.js, SvelteKit, TanStack Start, Astro, and framework-neutral TypeScript. +- Do not add runtime dependencies to the Trakoo package. +- Treat installed package declarations as authoritative when a consumer's installed version differs from current repository docs. +- Keep generated evaluation outputs under `.context/`; do not commit them. + +## File Map + +- Create `skills/trakoo/SKILL.md`: discovery metadata, core integration workflow, invariants, one end-to-end example, and verification. +- Create `skills/trakoo/references/providers.md`: provider selection, optional dependencies, constraints, routing, Proxy, and custom providers. +- Create `skills/trakoo/references/frameworks.md`: framework detection, file placement, environment boundaries, navigation tracking, and server lifecycle. +- Create `test/agent-skill.test.ts`: repository-level contract for discovery metadata, required guidance, references, framework coverage, and README installation copy. +- Modify `readme.md`: short Agent Skill installation section. +- Create `.context/trakoo-skill-evals/evals/evals.json`: local evaluation prompts and assertions; this remains gitignored. + +--- + +### Task 1: Capture baseline agent behavior + +**Files:** +- Create (gitignored): `.context/trakoo-skill-evals/evals/evals.json` +- Create (gitignored): `.context/trakoo-skill-evals/iteration-1/*/without_skill/outputs/response.md` + +**Interfaces:** +- Consumes: Current public Trakoo source and documentation; no skill guidance. +- Produces: Three baseline responses and a stable assertion set used by Task 6. + +- [ ] **Step 1: Create the evaluation set before authoring the skill** + +Write `.context/trakoo-skill-evals/evals/evals.json` with this exact structure: + +```json +{ + "skill_name": "trakoo", + "evals": [ + { + "id": 1, + "name": "typed-vite-posthog", + "prompt": "I have a Vite React TypeScript app using pnpm. Add Trakoo with PostHog browser analytics. Define typed signup and CTA-click events, identify after login, reset after logout, and tell me how to verify it. Return the exact files and commands you would use.", + "expected_output": "Uses pnpm, posthog-js, a central as-const-satisfies event collection, trakoo/client and trakoo/providers/client, AppEvents on the factory, client-safe VITE_ values, identify/reset lifecycle, and typecheck verification.", + "files": [], + "assertions": [ + "Installs trakoo and posthog-js with pnpm", + "Defines a central typed event collection with as const satisfies", + "Uses trakoo/client and trakoo/providers/client imports", + "Passes AppEvents to createClientAnalytics", + "Uses only client-public environment values", + "Calls identify after login and reset after logout", + "Includes a typecheck or build verification command" + ] + }, + { + "id": 2, + "name": "nextjs-critical-server-event", + "prompt": "In a Next.js TypeScript app, use Trakoo and PostHog to record a subscription purchase on the server. The browser must never receive the PostHog secret. Include typed events, user context, error-safe flushing, and exact imports. Return the files you would add.", + "expected_output": "Uses posthog-node and server-only imports, shares the event type safely, awaits tracking, passes user context, and shuts down in finally without leaking the secret.", + "files": [], + "assertions": [ + "Uses trakoo/server and trakoo/providers/server imports", + "Installs or names posthog-node rather than posthog-js for server delivery", + "Keeps the provider key in an unprefixed server environment variable", + "Passes AppEvents to createServerAnalytics", + "Awaits the purchase tracking call", + "Passes explicit user context", + "Calls shutdown in a finally block" + ] + }, + { + "id": 3, + "name": "routed-bento-pirsch", + "prompt": "Configure Trakoo for a SaaS app that wants anonymous privacy-friendly page views in Pirsch and identified lifecycle events in Bento. Explain the client/server split, required packages, provider routing, and the important delivery constraints. Include a minimal configuration.", + "expected_output": "Routes page views away from Bento, requires email identification for Bento, describes Pirsch request context for server hits, and does not invent SDK dependencies.", + "files": [], + "assertions": [ + "States that Bento requires identified users with email", + "Routes or excludes pageView from Bento", + "States that Pirsch server events need request IP and User-Agent context", + "Names @bentonow/bento-node-sdk only for Bento server usage", + "Does not require an extra Pirsch package", + "Uses valid client or server provider aggregate imports" + ] + } + ] +} +``` + +- [ ] **Step 2: Run all three baseline prompts in fresh contexts without the skill** + +Dispatch one fresh subagent per evaluation. Tell each subagent to inspect this repository for Trakoo's current public API, answer its assigned prompt, and save only its final response under: + +```text +.context/trakoo-skill-evals/iteration-1//without_skill/outputs/response.md +``` + +Expected: Three response files exist; at least one misses or mishandles a lifecycle, import-boundary, dependency, or provider-constraint assertion. Record exact misses in each evaluation directory's `baseline-findings.md`. + +For each evaluation directory, also write `eval_metadata.json` with `eval_id`, `eval_name`, the exact prompt, and its assertion array from `evals.json`. When each subagent completes, immediately save the notification's token and duration values to `without_skill/timing.json`: + +```json +{ + "total_tokens": 0, + "duration_ms": 0, + "total_duration_seconds": 0 +} +``` + +Replace each zero with the actual completion values; zeros are invalid final timing data. + +- [ ] **Step 3: Confirm no tracked files were created** + +Run: `git status --short` + +Expected: No `.context/` paths appear. + +--- + +### Task 2: Add the discoverable core skill + +**Files:** +- Create: `test/agent-skill.test.ts` +- Create: `skills/trakoo/SKILL.md` + +**Interfaces:** +- Consumes: Public Trakoo types and factories plus the provider/framework references created in later tasks. +- Produces: Skill `trakoo` and contract-test helpers reused by Tasks 3–5. + +- [ ] **Step 1: Write the failing discovery and core-guidance tests** + +Create `test/agent-skill.test.ts`: + +```ts +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; + +const read = (relativePath: string) => + readFileSync( + fileURLToPath(new URL(`../${relativePath}`, import.meta.url)), + "utf8", + ); + +describe("Trakoo Agent Skill", () => { + it("has discoverable metadata and core integration rules", () => { + const skill = read("skills/trakoo/SKILL.md"); + + expect(skill).toMatch(/^---\nname: trakoo\ndescription: Use when /); + expect(skill).toContain("trakoo/client"); + expect(skill).toContain("trakoo/server"); + expect(skill).toContain("trakoo/providers/client"); + expect(skill).toContain("trakoo/providers/server"); + expect(skill).toContain("as const satisfies"); + expect(skill).toContain("createClientAnalytics"); + expect(skill).toContain("createServerAnalytics"); + expect(skill).toContain("shutdown()"); + expect(skill).toContain("references/providers.md"); + expect(skill).toContain("references/frameworks.md"); + }); +}); +``` + +- [ ] **Step 2: Run the focused test and verify RED** + +Run: `pnpm vitest run test/agent-skill.test.ts` + +Expected: FAIL with `ENOENT` for `skills/trakoo/SKILL.md`. + +- [ ] **Step 3: Write the minimal core skill** + +Create `skills/trakoo/SKILL.md` with: + +````markdown +--- +name: trakoo +description: Use when adding, configuring, or troubleshooting Trakoo analytics in TypeScript applications, including typed events, browser or server tracking, PostHog, OpenPanel, Bento, Pirsch, EmitKit, Visitors, Proxy, provider routing, user identification, or framework integration. +--- + +# Trakoo Integration + +Trakoo is a typed, provider-agnostic analytics library. Preserve its central event contract and its browser/server boundary; those two choices prevent most integration errors. + +## Start by inspecting the application + +Before editing, detect the package manager, framework, installed `trakoo` version, browser/server entry points, existing analytics dependencies, and available verification commands. Determine whether each requested event is a browser interaction, an authoritative server event, or both. + +Use the consuming project's installed Trakoo declarations as the source of truth. If they differ from current official docs, explain the version mismatch; do not silently upgrade or invent an API. + +Read [references/providers.md](references/providers.md) when choosing or configuring providers, routing events, using Proxy, or building a custom provider. Read only the matching section of [references/frameworks.md](references/frameworks.md) for Next.js, SvelteKit, TanStack Start, Astro, or framework-neutral integration. + +## Integration workflow + +1. Install `trakoo` with the project's package manager, plus only the selected providers' optional SDKs. +2. Define the event collection before adding tracking calls. +3. Put browser and server analytics in separate modules with environment-specific imports. +4. Add tracking where the event becomes true: interactions in browser handlers; payments, signups, jobs, and other authoritative outcomes on the server. +5. Apply identity and delivery lifecycle rules. +6. Run the project's formatter, type checker, relevant tests, and build when it checks environment boundaries. + +## Typed event contract + +```ts +import type { CreateEventDefinition, EventCollection } from "trakoo"; + +export const appEvents = { + ctaClicked: { + name: "cta_clicked", + category: "engagement", + properties: {} as { location: "hero" | "pricing" }, + }, + purchaseCompleted: { + name: "purchase_completed", + category: "conversion", + properties: {} as { + orderId: string; + amount: number; + currency: string; + }, + }, +} as const satisfies EventCollection< + Record> +>; + +export type AppEvents = typeof appEvents; +``` + +Object keys organize source code; each `name` is the stable value sent to providers. Keep names stable after release and type properties narrowly. + +## Browser module + +```ts +import { createClientAnalytics } from "trakoo/client"; +import { PostHogClientProvider } from "trakoo/providers/client"; +import type { AppEvents } from "./events"; + +export const analytics = createClientAnalytics({ + providers: [ + new PostHogClientProvider({ + token: import.meta.env.VITE_POSTHOG_KEY, + }), + ], +}); +``` + +Create one browser instance per session. Call `analytics.identify(userId, traits)` after authentication and `analytics.reset()` on logout. Browser tracking is normally fire-and-forget; do not block navigation on non-critical analytics. + +## Server module and critical event + +```ts +import { createServerAnalytics } from "trakoo/server"; +import { PostHogServerProvider } from "trakoo/providers/server"; +import type { AppEvents } from "./events"; + +const analytics = createServerAnalytics({ + providers: [ + new PostHogServerProvider({ apiKey: process.env.POSTHOG_API_KEY! }), + ], +}); + +try { + await analytics.track( + "purchase_completed", + { orderId, amount, currency }, + { userId, user: { email } }, + ); +} finally { + await analytics.shutdown(); +} +``` + +Server analytics is stateless across users: pass user context with each event. Await critical events. In serverless or other short-lived runtimes, call `shutdown()` before exit, preferably in `finally`; use the platform's `waitUntil` only for explicitly non-critical work. + +## Import and lifecycle reference + +| Concern | Correct pattern | +|---|---| +| Shared types | `trakoo` | +| Browser factory | `trakoo/client` | +| Server factory | `trakoo/server` | +| Browser providers | `trakoo/providers/client` | +| Server providers | `trakoo/providers/server` | +| Browser identity | `identify()` after login; `reset()` on logout | +| Server identity | Context on every call | +| Critical server delivery | Await `track()` and then `shutdown()` | + +Never import a server provider, secret, or unprefixed server environment variable into browser code. Do not use a nonexistent `trakoo/providers` aggregate. + +## Verification + +Use the consuming project's commands. At minimum, run its type checker and the narrowest relevant tests; run its production build when client/server bundling or environment variables changed. Recheck installed declarations when an import, option, event property, or provider constructor fails. + +## Common mistakes + +- Tracking first and defining events later, which loses useful type pressure. +- Omitting `AppEvents` from an analytics factory. +- Sharing stateful browser identity logic with stateless server analytics. +- Sending every method and event to providers with different requirements instead of routing them. +- Installing all optional provider SDKs instead of only those selected. +- Forgetting logout reset, request user context, or short-lived-runtime shutdown. +```` + +- [ ] **Step 4: Run the focused test** + +Run: `pnpm vitest run test/agent-skill.test.ts` + +Expected: PASS. + +- [ ] **Step 5: Commit the core skill** + +```bash +git add test/agent-skill.test.ts skills/trakoo/SKILL.md +git commit -m "feat: add Trakoo agent skill" +``` + +--- + +### Task 3: Add provider reference guidance + +**Files:** +- Modify: `test/agent-skill.test.ts` +- Create: `skills/trakoo/references/providers.md` + +**Interfaces:** +- Consumes: The core skill's link to `references/providers.md`. +- Produces: Provider selection and advanced routing guidance. + +- [ ] **Step 1: Add a failing provider-reference test** + +Add this test inside the existing `describe` block: + +```ts + it("covers every public provider and its delivery constraints", () => { + const providers = read("skills/trakoo/references/providers.md"); + + for (const name of [ + "PostHog", + "OpenPanel", + "Bento", + "Pirsch", + "EmitKit", + "Visitors", + "Proxy", + "BaseAnalyticsProvider", + ]) { + expect(providers).toContain(name); + } + expect(providers).toContain("@bentonow/bento-node-sdk"); + expect(providers).toContain("IP address and User-Agent"); + expect(providers).toContain("methods"); + expect(providers).toContain("excludeEvents"); + expect(providers).toContain("eventPatterns"); + }); +``` + +- [ ] **Step 2: Run the focused test and verify RED** + +Run: `pnpm vitest run test/agent-skill.test.ts` + +Expected: FAIL with `ENOENT` for `references/providers.md`. + +- [ ] **Step 3: Create the provider reference** + +Create `skills/trakoo/references/providers.md` with these exact sections and facts: + +````markdown +# Provider Reference + +Read the selected provider's installed constructor types and official Trakoo provider page before generating final code. Install only dependencies required by the selected side. + +## Capability and dependency matrix + +| Provider | Browser | Server | Extra dependency | Use and constraints | +|---|---:|---:|---|---| +| PostHog | Yes | Yes | Browser: `posthog-js`; server: `posthog-node` | General product analytics. Keep the server key out of browser code. | +| OpenPanel | Yes | Yes | Browser: `@openpanel/web`; server: `@openpanel/sdk` | Product and web analytics across both runtimes. | +| Bento | Yes | Yes | Browser: none; server: `@bentonow/bento-node-sdk` | Identified lifecycle/email events. An email is required; route anonymous page views elsewhere. | +| Pirsch | Yes | Yes | None | Privacy-first analytics. Server hits require the visitor IP address and User-Agent request context. | +| EmitKit | No | Yes | `@emitkit/js` when required by the installed version | Server-side event notifications; verify its current constructor from installed types. | +| Visitors | Yes | No | None | Privacy-friendly web analytics. Identification needs persistence and appropriate consent; page views are automatic. | +| Proxy | Yes | Ingestion helpers | None | First-party batching from `ProxyProvider` to `createProxyHandler` or `ingestProxyEvents`. It is transport, not an analytics vendor. | + +## Choose by event semantics + +- Use browser providers for interaction, navigation, and other non-critical UI events. +- Use server providers for payments, confirmed signups, jobs, and events that must survive blockers or navigation. +- Pair providers when one handles anonymous measurement and another handles identified lifecycle automation. +- Use Proxy when keys must stay server-side, request context is required, or first-party delivery is important. + +## Routing + +Each provider entry can be a provider instance or a routing object: + +```ts +providers: [ + new PostHogClientProvider({ token: publicPosthogKey }), + { + provider: new BentoClientProvider({ siteUuid: publicBentoSiteUuid }), + methods: ["identify", "track"], + eventPatterns: ["user_*", "subscription_*"], + }, +] +``` + +Use one method selector: `methods` or `exclude`. Use one event selector: `events`, `excludeEvents`, or `eventPatterns`. If mutually exclusive options are combined, Trakoo warns and applies precedence; remove the ambiguity instead of relying on precedence. + +## Provider constraints + +### Bento + +Call client `identify()` with a valid email before sending Bento events. Exclude `pageView` or restrict Bento to `identify` and `track`; send anonymous traffic to PostHog, Pirsch, or another suitable provider. + +### Pirsch + +No extra package is required. A server event without the original IP address and User-Agent cannot be attributed and is skipped. Proxy browser events through a server endpoint when that request context is needed. + +### Visitors + +Visitors is browser-only. `pageView()` does not send a duplicate because its script tracks page loads automatically. Non-scalar custom properties are dropped. `identify()` requires persistence and, where applicable, explicit consent. + +### Proxy + +Import `ProxyProvider` from `trakoo/providers/client`; import `createProxyHandler` or `ingestProxyEvents` from `trakoo/providers/server`. Keep the endpoint same-origin when the goal is first-party delivery. Configure batch size and interval only when defaults do not meet the application's delivery needs. + +## Custom providers + +Extend `BaseAnalyticsProvider` from the environment-specific provider export and implement the `AnalyticsProvider` contract. Preserve Trakoo's event `action`, properties, and context; do not put vendor-specific behavior into shared event definitions. + +## Verification + +Typecheck constructor options against the installed provider types. Exercise one representative event per routing branch and confirm excluded events or methods do not reach that provider. For buffered server SDKs, verify the handler flushes before exit. +```` + +- [ ] **Step 4: Run the focused test and commit** + +Run: `pnpm vitest run test/agent-skill.test.ts` + +Expected: PASS. + +```bash +git add test/agent-skill.test.ts skills/trakoo/references/providers.md +git commit -m "docs: add Trakoo provider skill reference" +``` + +--- + +### Task 4: Add framework integration guidance + +**Files:** +- Modify: `test/agent-skill.test.ts` +- Create: `skills/trakoo/references/frameworks.md` + +**Interfaces:** +- Consumes: The core skill's link to `references/frameworks.md`. +- Produces: Framework-specific browser/server boundary and navigation guidance. + +- [ ] **Step 1: Add a failing framework-reference test** + +Add this test inside the existing `describe` block: + +```ts + it("covers supported framework boundaries", () => { + const frameworks = read("skills/trakoo/references/frameworks.md"); + + for (const name of [ + "Next.js", + "SvelteKit", + "TanStack Start", + "Astro", + "Framework-neutral", + ]) { + expect(frameworks).toContain(name); + } + expect(frameworks).toContain("router.subscribe(\"onResolved\""); + expect(frameworks).toContain("astro:page-load"); + expect(frameworks).toContain("PUBLIC_"); + expect(frameworks).toContain("VITE_"); + }); +``` + +- [ ] **Step 2: Run the focused test and verify RED** + +Run: `pnpm vitest run test/agent-skill.test.ts` + +Expected: FAIL with `ENOENT` for `references/frameworks.md`. + +- [ ] **Step 3: Create the framework reference** + +Create `skills/trakoo/references/frameworks.md` with this structure and guidance: + +````markdown +# Framework Integration Reference + +Read only the section matching the consuming project. Framework APIs evolve; confirm routing hooks and server boundaries against the installed framework version before editing. + +## Detection + +| Signal | Framework | +|---|---| +| `next.config.*` plus `next` dependency | Next.js | +| `svelte.config.*` plus `@sveltejs/kit` | SvelteKit | +| `@tanstack/react-start` and its Vite/Rsbuild plugin | TanStack Start | +| `astro.config.*` plus `astro` | Astro | +| Browser entry plus server/API entry without the above | Framework-neutral TypeScript | + +## Shared rules + +- Keep `events.ts` environment-neutral and import only types from `trakoo`. +- Put `createClientAnalytics` and browser providers in a browser-only module. +- Put `createServerAnalytics`, server providers, and secrets in a server-only module. +- Track a business event where it becomes authoritative, not merely where navigation happens. +- Use the framework's public-variable convention only for browser-safe provider identifiers. + +## Next.js + +Use a client component for browser initialization, identity lifecycle, and navigation effects. Browser values use `NEXT_PUBLIC_*`; unprefixed values remain server-only. Put critical tracking in route handlers, server actions, or other server-only modules. Await critical events and call `shutdown()` in `finally` before a short-lived request exits. Verify with `next build` because it catches accidental server imports in client bundles. + +## SvelteKit + +Initialize browser analytics only in browser-executed code such as `onMount`; keep server providers in `+page.server.ts`, `+server.ts`, hooks, or other server-only modules. Use `$env/static/public` or `$env/dynamic/public` for client-safe values and private `$env/*/private` modules only on the server. Use the installed SvelteKit navigation API for page views and avoid double-counting the initial navigation. + +## TanStack Start + +Place browser analytics in client-executed application code and server analytics inside `createServerFn` handlers or server routes. With Vite, expose only browser-safe identifiers through `VITE_*`; keep secrets unprefixed and read them inside the per-request server handler, especially on edge runtimes. Subscribe to completed navigation for page views and clean up the subscription: + +```ts +const unsubscribe = router.subscribe("onResolved", ({ toLocation }) => { + analytics.pageView({ path: toLocation.pathname, url: toLocation.href }); +}); +``` + +Use the framework's lifecycle to call `unsubscribe()` when the owner is disposed. + +## Astro + +Initialize client analytics in a processed `