per-project widget snippet: route by data-project#7
Conversation
…atch each project now has its own snippet (visible on the project detail page) with `data-project="<projectId>"` baked in. feedback from a project's widget routes there directly, no URL-pattern matching needed. schema: - ingestEvents: optional projectId field. set when the snippet declared `data-project`; the HTTP route validates team ownership before persisting, so the parser can trust it. widget (widget/src/index.ts): - reads `data-project` from the script tag - includes `projectId` in every POST body ingest (convex): - http.ts: validates posted projectId belongs to the team via new `verifyProjectInTeam` internal query; silently drops it on mismatch (falls back to URL-pattern matching). - ingest.recordWidget: accepts + persists optional projectId on the ingestEvent row. - parserDb.persistItems: prefers ingestEvent.projectId over URL pattern matching. emits routedBy: "snippet" | "url-pattern" | "router" in the audit log. ui: - ProjectDetail's "no events yet" card now renders the actual snippet for that project (team secret + project id baked in), with a one-click copy button. when the team secret hasn't been created yet, it points users to settings instead. - OnboardingTab widget step: drop the inline team-only snippet. it now nudges users toward `projects → install the widget` and keeps just the secret create/rotate button. backward compatible: existing widget installs without `data-project` keep routing via URL patterns. URL patterns stay configurable in the project edit form. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.
Reviewed by Cursor Bugbot for commit 80ed5c8. Configure here.
| </button> | ||
| </div> | ||
| ); | ||
| } |
There was a problem hiding this comment.
New SnippetBlock duplicates existing CodeBlock component
Low Severity
SnippetBlock in ProjectsTab.tsx duplicates the existing CodeBlock in OnboardingTab.tsx — both render a pre with code content and a copy button using identical clipboard logic (navigator.clipboard.writeText + setTimeout to reset "copied" state after 1400ms). Extracting a shared component would avoid inconsistent bug fixes and styling drift.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 80ed5c8. Configure here.
per-project widget snippet (#7) made URL-pattern routing the fallback path. with no legacy projects to migrate, ripping it out: - schema.projects: drop urlPatterns, description columns - projects.upsert: drop urlPatterns + description args (60 → 50 LOC) - projects.ts: drop resolveProjectFromUrl + matchUrl + globMatch + helpers (~70 LOC) - parserDb.persistItems: drop URL-pattern fallback + widgetUrl arg. routedBy enum is now just "snippet" | "router". - parser.ts: drop the widgetUrl wiring through to persistItems - ProjectsTab: drop urlPatterns: [] / description: "" from upsert calls (create + edit) widget events without data-project (misconfigured snippet, deleted project) flow through to the semantic router, same as granola/zoom.


Summary
Each project gets its own widget snippet (visible on the project detail page) with `data-project=""` baked in. Feedback from a project's widget routes there directly — URL-pattern matching becomes a fallback for snippets that don't declare a project.
Why
What changed
Test plan
Backward compatibility
🤖 Generated with Claude Code
Note
Medium Risk
Changes widget ingestion and routing by persisting an optional
projectIdand preferring it over URL-pattern matching, which can affect where feedback is attributed. Includes schema + HTTP ingest updates, so regressions could mis-route or drop project tagging if validation or snippet usage is incorrect.Overview
Adds per-project widget installation snippets and routing. The widget now reads an optional
data-projectattribute and postsprojectIdwith each/ingest/widgetevent.On the backend,
ingestEventsgains optionalprojectId; the widget HTTP route validates that postedprojectIdbelongs to the team (otherwise ignores it) and persists it on the ingest event. The parser then prefers this storedprojectIdfor routing, falling back to URL-pattern matching, and audit logging now recordsroutedByassnippetvsurl-patternvsrouter.UI updates shift onboarding guidance away from a single team snippet and surface a per-project snippet (with copy button) on the project detail page, prompting users to create the team widget secret first.
Reviewed by Cursor Bugbot for commit 80ed5c8. Bugbot is set up for automated code reviews on this repo. Configure here.