Skip to content

Commit 017e398

Browse files
amortemousqueclaude
andcommitted
πŸ“ Add router integration pipeline design spec
Design for a fully automated Claude Code skill pipeline that generates draft Browser SDK router integration PRs from framework public docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 65cb22a commit 017e398

1 file changed

Lines changed: 227 additions & 0 deletions

File tree

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Router Integration Pipeline β€” Design Spec
2+
3+
## Overview
4+
5+
A fully automated Claude Code skill pipeline that generates draft Browser SDK router integration PRs from framework public documentation. The pipeline fetches framework router docs, analyzes concepts, maps them to existing SDK patterns, generates a complete package with tests, and opens a draft PR β€” with no human intervention until the PR is ready for review.
6+
7+
## Invocation
8+
9+
```
10+
/router:pipeline <framework> <doc-url> [<doc-url>...]
11+
```
12+
13+
Example:
14+
```
15+
/router:pipeline svelte https://svelte.dev/docs/kit/routing
16+
```
17+
18+
## Architecture
19+
20+
### Approach: Hybrid β€” Orchestrator + Stage Skills
21+
22+
Six skills total: one orchestrator that chains five stage skills sequentially. Each stage produces a durable markdown artifact in `docs/integrations/<framework>/`. Individual stage skills can be re-run independently.
23+
24+
### Pipeline Flow
25+
26+
```
27+
/router:pipeline
28+
β”‚
29+
β”œβ”€ /router:fetch-docs β†’ 01-router-concepts.md
30+
β”‚ └─ EXIT if incompatible framework
31+
β”‚
32+
β”œβ”€ /router:analyze β†’ 02-sdk-mapping.md
33+
β”‚ └─ EXIT if critical concepts unmapped
34+
β”‚
35+
β”œβ”€ /router:design β†’ 03-design-decisions.md
36+
β”‚
37+
β”œβ”€ /router:generate β†’ 04-generation-manifest.md + packages/rum-<framework>/
38+
β”‚
39+
└─ /router:pr β†’ Draft PR on GitHub
40+
```
41+
42+
No human gates. Early exits produce an `EXIT.md` alongside whatever artifacts were written.
43+
44+
## Artifacts
45+
46+
All artifacts live in `docs/integrations/<framework>/`.
47+
48+
### Source Reference Convention
49+
50+
Every factual claim in every artifact is inline-linked to its source β€” either an external doc URL or an internal file path with line range. Unsourced claims are explicitly marked as *inferred: \<reasoning\>*.
51+
52+
Example:
53+
```markdown
54+
Routes use [`:param` syntax](https://svelte.dev/docs/kit/routing#dynamic-parameters)
55+
for dynamic segments, equivalent to Angular's
56+
[`:id` in route config path](packages/rum-angular/src/domain/angularRouter/startAngularView.ts#L15-L28).
57+
```
58+
59+
### `01-router-concepts.md` (Stage 1 output)
60+
61+
Structured extraction from framework docs:
62+
63+
- **Route definition format** β€” config object, file-based, decorators
64+
- **Dynamic segment syntax** β€” `:id`, `[id]`, `{id}`, etc.
65+
- **Catch-all/wildcard syntax** β€” `*`, `**`, `[...slug]`, etc.
66+
- **Navigation lifecycle hooks** β€” which events fire and when
67+
- **Navigation lifecycle timing** β€” specifically: where in the lifecycle do redirects resolve, and where do data fetches (loaders/resolvers) execute? The SDK wants to start a view as early as possible but after redirects and before both data fetches (loaders/resolvers) and component rendering, so that all resource loading and rendering work is attributed to the correct view. If no single hook satisfies all three constraints (after redirects, before data fetches, before render), document the trade-off and rank the options. Reference how existing integrations solve this: Angular uses [`GuardsCheckEnd`](packages/rum-angular/src/domain/angularRouter/provideDatadogRouter.ts) (after guards/redirects, before resolvers), Vue uses [`afterEach`](packages/rum-vue/src/domain/router/vueRouter.ts) (after everything), React uses [`subscribe`](packages/rum-react/src/domain/reactRouter/createRouter.ts) (after state change).
68+
- **Route matching model** β€” nested vs flat, outlets, layouts
69+
- **Programmatic navigation API** β€” how router exposes state
70+
- **`compatible`** β€” boolean flag. `false` if the framework lacks a client-side route tree, dynamic segments, or navigation lifecycle events
71+
72+
### `02-sdk-mapping.md` (Stage 2 output)
73+
74+
Maps each framework concept to its SDK equivalent by reading reference implementations ([rum-angular](packages/rum-angular/), [rum-react](packages/rum-react/), [rum-vue](packages/rum-vue/)):
75+
76+
- Navigation event β†’ equivalent of Angular's [`GuardsCheckEnd`](packages/rum-angular/src/domain/angularRouter/provideDatadogRouter.ts), Vue's [`afterEach`](packages/rum-vue/src/domain/router/vueRouter.ts), React's [`subscribe`](packages/rum-react/src/domain/reactRouter/createRouter.ts)
77+
- Dynamic segment syntax β†’ `computeViewName` normalization strategy
78+
- Catch-all handling β†’ substitution approach
79+
- Route tree shape β†’ traversal algorithm
80+
- Framework DI/plugin model β†’ wrapping strategy (provider, hook, wrapper, plugin install)
81+
- Peer dependencies needed
82+
- Concepts marked `unmapped` if no SDK equivalent exists (with severity: `critical` or `minor`)
83+
84+
### `03-design-decisions.md` (Stage 3 output)
85+
86+
Design document covering:
87+
88+
- Architecture decisions with rationale
89+
- Public API surface (what the user imports and calls)
90+
- File structure plan
91+
- Test strategy and edge cases to cover
92+
- Trade-offs and alternatives considered
93+
94+
### `04-generation-manifest.md` (Stage 4 output)
95+
96+
Listing of every generated file:
97+
98+
- File path
99+
- Purpose (one line)
100+
- Which reference file it was modeled after (linked)
101+
- Deviations from the reference pattern and why
102+
103+
### `EXIT.md` (on early exit only)
104+
105+
Written when the pipeline exits before completion:
106+
107+
- Which stage failed or exited
108+
- Reason with source links supporting the exit decision
109+
- List of artifacts produced before exit
110+
111+
## Stage Details
112+
113+
### Stage 1: `/router:fetch-docs`
114+
115+
**Input:** Framework name + doc URL(s)
116+
**Output:** `01-router-concepts.md`
117+
118+
Fetches and parses the provided URLs. Extracts the structured summary described above. Performs compatibility check β€” flags frameworks that lack standard routing concepts (no client-side route tree, no dynamic segments, no navigation events). Examples of incompatible frameworks: Shopify Hydrogen (server-only loaders), Salesforce Lightning (proprietary component model).
119+
120+
### Stage 2: `/router:analyze`
121+
122+
**Input:** `01-router-concepts.md` + reference implementations in `packages/rum-angular/`, `packages/rum-react/`, `packages/rum-vue/`
123+
**Output:** `02-sdk-mapping.md`
124+
125+
Reads reference implementations to understand the common contract:
126+
- [Plugin interface](packages/rum-core/src/domain/plugins.ts) β€” `RumPlugin` with `onInit`/`onRumStart`
127+
- [Public API](packages/rum-core/src/boot/rumPublicApi.ts) β€” `startView()` method
128+
- `computeViewName()` implementations across all three reference packages
129+
- Navigation event subscription patterns
130+
131+
Maps each concept from Stage 1 to an SDK equivalent. Exits if critical concepts (navigation event, route tree access) have no mapping.
132+
133+
### Stage 3: `/router:design`
134+
135+
**Input:** `01-router-concepts.md` + `02-sdk-mapping.md`
136+
**Output:** `03-design-decisions.md`
137+
138+
Produces the design document. Synthesizes the mapping into concrete decisions: which files to create, what the public API looks like, how tests are structured. References both the framework docs and the SDK patterns that informed each decision.
139+
140+
### Stage 4: `/router:generate`
141+
142+
**Input:** All previous artifacts + reference implementations
143+
**Output:** `packages/rum-<framework>/` + `04-generation-manifest.md`
144+
145+
Generates the package structure:
146+
147+
```
148+
packages/rum-<framework>/
149+
β”œβ”€β”€ src/
150+
β”‚ β”œβ”€β”€ entries/
151+
β”‚ β”‚ └── main.ts
152+
β”‚ β”œβ”€β”€ domain/
153+
β”‚ β”‚ β”œβ”€β”€ <framework>Plugin.ts
154+
β”‚ β”‚ β”œβ”€β”€ <framework>Plugin.spec.ts
155+
β”‚ β”‚ β”œβ”€β”€ <framework>Router/
156+
β”‚ β”‚ β”‚ β”œβ”€β”€ start<Framework>View.ts
157+
β”‚ β”‚ β”‚ β”œβ”€β”€ start<Framework>View.spec.ts
158+
β”‚ β”‚ β”‚ β”œβ”€β”€ types.ts
159+
β”‚ β”‚ β”‚ └── <integration-point>.ts
160+
β”‚ β”‚ └── error/
161+
β”‚ β”‚ β”œβ”€β”€ add<Framework>Error.ts
162+
β”‚ β”‚ └── add<Framework>Error.spec.ts
163+
β”‚ └── test/
164+
β”‚ └── initialize<Framework>Plugin.ts
165+
β”œβ”€β”€ package.json
166+
β”œβ”€β”€ tsconfig.json
167+
└── README.md
168+
```
169+
170+
**Code generation approach:** The agent reads reference implementations as examples (not templates). It uses `02-sdk-mapping.md` and `03-design-decisions.md` to determine the specific logic for:
171+
- `<integration-point>.ts` β€” shaped by which navigation hook to subscribe to
172+
- `computeViewName()` β€” shaped by dynamic segment and catch-all syntax
173+
- Plugin exposure β€” shaped by framework DI/plugin model
174+
175+
**Test generation:** Derived from two sources:
176+
1. Common edge cases shared across all routers (from reference spec files): static paths, single/nested dynamic segments, empty/layout routes, catch-all/wildcard, duplicate navigation filtering, initial navigation
177+
2. Framework-specific cases from `01-router-concepts.md`
178+
179+
### Stage 5: `/router:pr`
180+
181+
**Input:** Generated package + all artifacts
182+
**Output:** Draft PR on GitHub
183+
184+
- Creates branch: `<user>/<framework>-router-integration`
185+
- Two commits:
186+
1. `πŸ“ Add <framework> router integration design docs`
187+
2. `✨ Add <framework> router integration package`
188+
- Opens draft PR with body structured from `03-design-decisions.md`:
189+
- Summary of what was generated
190+
- Key design decisions
191+
- Link to `docs/integrations/<framework>/` for full artifact trail
192+
193+
## Scope Boundaries
194+
195+
### In scope
196+
- Conventional SPA/SSR frontend frameworks with standard routing: route tree, dynamic params, navigation lifecycle (e.g. Svelte, Remix, Solid, Ember)
197+
- Router integration (view tracking via `startView`)
198+
- Error handler integration (following reference pattern)
199+
- Unit tests for view name computation and navigation filtering
200+
201+
### Out of scope
202+
- Non-conventional frameworks (Shopify Hydrogen, Salesforce Lightning, etc.) β€” pipeline exits early
203+
- E2E tests β€” not generated, left for human follow-up
204+
- Publishing/release automation
205+
- Modifications to existing packages or rum-core
206+
207+
## Skill Location
208+
209+
Skills live in `.claude/skills/router-integration/`:
210+
211+
```text
212+
.claude/skills/router-integration/
213+
β”œβ”€β”€ pipeline.md # /router:pipeline β€” orchestrator
214+
β”œβ”€β”€ fetch-docs.md # /router:fetch-docs
215+
β”œβ”€β”€ analyze.md # /router:analyze
216+
β”œβ”€β”€ design.md # /router:design
217+
β”œβ”€β”€ generate.md # /router:generate
218+
└── pr.md # /router:pr
219+
```
220+
221+
## Stage Input Convention
222+
223+
Each stage skill reads its inputs from the filesystem β€” no arguments are passed between skills except through the orchestrator's context:
224+
225+
- **Orchestrator** receives `<framework>` and `<doc-url>` as arguments, writes them to `docs/integrations/<framework>/00-pipeline-input.md`
226+
- **Stage skills** read from `docs/integrations/<framework>/` for previous artifacts and from `packages/rum-angular/`, `packages/rum-react/`, `packages/rum-vue/` for reference implementations
227+
- **Framework name** is derived from the directory name

0 commit comments

Comments
Β (0)