SetuConvex and Clerk#1
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds Clerk and Convex skill documentation, evaluation cases, helper scripts, and reference pages for backend API access, CLI workflows, custom UI, Next.js patterns, organizations, setup, testing, webhooks, quickstart, auth setup, component creation, migrations, and performance auditing. ChangesClerk skill suite
Convex skill suite
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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.
Actionable comments posted: 28
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json (1)
1-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPin major versions instead of "latest" for template stability.
Using
"latest"for all dependencies makes this template vulnerable to breaking changes from major version releases. Pin to known-compatible major versions (e.g.,"next": "^15.0.0","@clerk/nextjs": "^6.0.0") and document the compatibility matrix in the skill README.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json around lines 1 - 17, The template dependencies are using "latest", which makes the Next.js/Clerk starter unstable across major releases. Update the dependency entries in package.json for next, react, react-dom, and `@clerk/nextjs` to pinned compatible major ranges, and keep the devDependencies aligned as well. Use the package.json dependency block as the source of truth, and document the supported version matrix in the skill README so template consumers know which versions are intended to work together.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.agents/skills/clerk-backend-api/scripts/extract-tag-endpoints.sh:
- Around line 38-48: The issue is that several variables in the tag endpoint
extraction script are declared but never used, adding dead state without
affecting behavior. Clean up the script by removing the unused declarations in
the main parser setup and first-pass scan, and keep only the symbols actually
used by the endpoint discovery flow in extract-tag-endpoints.sh so the logic
stays clear and maintainable.
In @.agents/skills/clerk-custom-ui/core-3/custom-sign-up.md:
- Around line 169-170: The Hook API / Sign-Up Methods reference is missing the
lower-level OTP flow used by the complete example, so update the documentation
to include signUp.create() and the finalize() callback shape. Add a create()
entry alongside password(), sso(), web3(), and update() in the API section, or
add a clear cross-reference explaining that OTP sign-up uses the signUp.create({
emailAddress/phoneNumber }) plus verifications.* pattern shown in the example,
and document the navigate({ session, decorateUrl }) finalize signature so
readers can locate the full flow.
In @.agents/skills/clerk-nextjs-patterns/references/api-routes.md:
- Around line 40-48: The GET route is using the old synchronous params shape,
which breaks in Next.js 15. Update the handler signature to treat params as a
Promise and await it inside GET before reading orgId, matching the async params
pattern used in the existing nextjs-patterns reference. Keep the auth and
db.orgs.findUnique logic the same, but read orgId from the awaited params object
rather than from a synchronous destructure.
In @.agents/skills/clerk-nextjs-patterns/references/server-actions.md:
- Around line 43-51: The deleteProject server action is treating Clerk’s has()
as async even though it returns a boolean synchronously. Update the logic in
deleteProject to call has({ permission: 'org:project:delete' }) directly without
await, and keep the surrounding auth() flow and permission check otherwise
unchanged so the intent is clear.
In @.agents/skills/clerk-nextjs-patterns/SKILL.md:
- Around line 119-126: The Common Pitfalls markdown table is breaking because
the regex in the Fix column contains unescaped pipe characters that GitHub
parses as extra columns. Update the table entry in SKILL.md so the matcher regex
is either escaped with literal pipes or replaced with a short reference to the
full matcher example, keeping the table structure intact and readable.
In
@.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/app/layout.tsx:
- Line 1: The auth conditional rendering in the Clerk layout is using the wrong
component API: `Show` with a `when` prop is not part of `@clerk/nextjs`. Update
the `app/layout.tsx` implementation to use Clerk’s `SignedIn` and `SignedOut`
components instead, and adjust the surrounding `ClerkProvider`, `SignInButton`,
`SignUpButton`, and `UserButton` usage so the sign-in/sign-up UI only renders
for signed-out users and the user menu only renders for signed-in users.
In @.agents/skills/clerk-orgs/evals/evals.json:
- Around line 100-124: The eval entries are out of ascending order, with the
item identified by id 9 placed before the item identified by id 8. Reorder the
objects in the evals array so the billing permissions eval (id 8) comes before
the membership-required eval (id 9), keeping all prompt, expected_output,
scaffold, and expectations content unchanged.
In @.agents/skills/clerk-orgs/references/nextjs-patterns.md:
- Around line 37-42: The OrgPage component is using synchronous params even
though Next.js 15 expects page params to be a Promise. Update OrgPage to accept
params as a Promise and await it before reading slug, matching the pattern
already used in the API route example with await params. Keep the auth() and
redirect logic the same, but ensure params is resolved first so OrgPage does not
access params.slug directly.
In @.agents/skills/clerk-orgs/references/roles-permissions.md:
- Around line 106-112: The JSX example is using a nonexistent Clerk <Show>
component for role-based rendering, so update the documentation snippet to use
the Clerk <Protect> component instead. In the roles-permissions example, replace
the <Show when={{ role: 'org:admin' }}> pattern with the correct <Protect> usage
for org role checks, and keep the admin panel conditional tied to the
role/permission props supported by Clerk.
In @.agents/skills/convex-create-component/SKILL.md:
- Line 106: Standardize the example imports in the Convex component docs by
using the same module specifier style everywhere: update the `mutation`/`query`
import from `./_generated/server.js` and the related `_generated/api` and
`./components/notifications/convex.config.js` examples so they either all
include `.js` or all omit it consistently. Make the change in the affected code
snippets referenced by `mutation`, `query`, and `api` imports to keep the
examples uniform for ESM/TypeScript Convex projects.
In @.agents/skills/convex-performance-audit/references/hot-path-rules.md:
- Around line 14-16: The table of contents entry is out of sync with the
document structure: the TOC item for the fourth section does not match the
actual heading in hot-path-rules.md. Update the TOC entry near the top so it
matches the section title used by the corresponding “## 4” heading, and keep the
numbering/label consistent with the existing section names in the document.
In @.claude/skills/clerk-backend-api/scripts/api-specs-context.sh:
- Around line 8-10: The GitHub API fetch in api-specs-context.sh needs to fail
fast and handle missing versions safely. Update the curl calls used around the
version listing and latest-spec fetch to use the existing api-specs context
logic with curl -f so HTTP errors stop the script, and add a guard after
computing latest to verify the filtered version list is non-empty before
building the final RAW_BASE URL. Reference the version-selection flow and latest
variable so the fix applies consistently across the related curl/JSON parsing
steps.
In @.claude/skills/clerk-backend-api/scripts/execute-request.sh:
- Around line 51-64: The scope validation in execute-request.sh is using loose
substring matching for CLERK_BAPI_SCOPES, so values like rewrite or predelete
can pass incorrectly. Update the POST|PUT|PATCH and DELETE checks to compare
exact comma-separated scope tokens instead of wildcard substring tests, using
the existing scope validation logic in execute-request.sh to locate the affected
conditionals. Keep the DELETE requirement enforcing both write and delete
exactly, and preserve the current admin bypass behavior.
In @.claude/skills/clerk-backend-api/scripts/extract-tags.js:
- Around line 6-14: Harden the tag parsing in extract-tags.js by tightening the
tags section detection and making indentation handling more tolerant. In the
main line-processing loop, update the `tags:` state transition so it only
matches a real top-level section header rather than any occurrence in the file,
and adjust the `inTags` exit logic so blank lines do not prematurely stop
extraction. Also relax the `line.match(...)` pattern used to capture tag names
so `name` entries with varying YAML indentation still match reliably, while
keeping the existing `console.log` behavior in the same loop.
In @.claude/skills/clerk-backend-api/SKILL.md:
- Around line 261-272: The bulk invitation rate limit is inconsistent between
the Clerk backend API skill docs and the org invitations reference, so reconcile
the two sources to the correct Clerk limit. Update the rate-limits table in
SKILL.md and the bulk invitations section in invitations.md to use the same
verified value, and ensure the related symbols/sections for bulk invitations and
rate limits remain aligned across both documents.
In @.claude/skills/clerk-cli/references/auth.md:
- Around line 9-14: The Backend API base URL in the auth reference is outdated
and conflicts with the BAPI implementation used by execute-request.sh. Update
the BAPI row in the auth.md table to use the current Clerk Backend API host,
https://api.clerk.com/v1/, so it matches the default used for backend requests.
In @.claude/skills/clerk-custom-ui/core-3/custom-sign-up.md:
- Around line 182-200: The sign-up completion flow is using an invalid Clerk
Core 3 API: signUp.finalize() should not receive a navigate callback with
session and decorateUrl, and decorateUrl is not available from useSignUp. Update
the completion logic in the sign-up flow to match Clerk’s supported behavior by
removing this custom finalize navigation block and relying on the normal
post-attemptVerification() flow or standard routing for session completion,
using the existing signUp and router references only where supported.
In @.claude/skills/clerk-nextjs-patterns/evals/evals.json:
- Around line 48-54: The eval assertions are too broad for the requested
middleware behavior, which can cause false failures. Update the assertions in
evals.json so they only verify the intended Clerk middleware setup:
createRouteMatcher import, public routes for / and /sign-in, auth.protect() for
non-public routes inside clerkMiddleware, and keeping the clerkMiddleware
wrapper. Remove the /profile and /api expectations unless you split them into
separate explicit eval cases tied to those routes.
In @.claude/skills/clerk-nextjs-patterns/references/server-actions.md:
- Around line 7-18: The server action example is missing the import for
revalidatePath, so the snippet is not self-consistent. Update the createPost
example to include revalidatePath alongside the existing auth import from
`@clerk/nextjs/server`, keeping the rest of the server action flow unchanged.
In
@.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json:
- Around line 5-15: Replace the “latest” dependency entries in the template’s
package.json with pinned minimum version ranges so the scaffold is reproducible
and stable across evals. Update the dependency declarations for next, react,
react-dom, `@clerk/nextjs`, typescript, `@types/react`, and `@types/react-dom` to
explicit caret versions, and add a packageManager field or equivalent lockfile
note in the same package.json to make the intended install tool/version clear.
Keep the changes localized to the template manifest so the basic-auth scaffold
remains consistent when generated.
In @.claude/skills/clerk-orgs/evals/evals.json:
- Around line 100-111: The eval IDs in the clerk-orgs evals fixture are out of
sequence, with ID 8 appearing after ID 9, so reorder the objects in the JSON
array to keep the IDs sequential. Update the eval entry ordering around the
affected item in the evals data so ID 8 comes before ID 9, without changing the
actual prompt or expectation content.
In @.claude/skills/clerk-orgs/references/nextjs-patterns.md:
- Around line 37-39: The OrgPage example is using params synchronously, which is
not compatible with Next.js 15’s async dynamic APIs. Update the OrgPage server
component signature to accept params as a Promise, await it before reading slug,
and keep the auth() check and redirect logic the same so the example matches the
Next.js 15 pattern used elsewhere in this document.
In @.claude/skills/clerk-setup/evals/evals.json:
- Line 52: The eval entry for the Clerk React SPA package name is incorrect and
will break installs because `@clerk/react` does not exist. Update the string in
the eval definition so it references the actual package name
`@clerk/clerk-react`, and make sure the surrounding Clerk setup evals stay
consistent with the intended React SPA path.
- Line 12: The middleware filename convention is inconsistent between this eval
entry and the referenced strategy docs, so standardize the wording to a single
Next.js version mapping. Update the eval text around the clerkMiddleware export
to match the canonical convention used by references/middleware-strategies.md,
and make sure all mentions of middleware.ts and proxy.ts are aligned across the
setup docs so they no longer conflict.
In @.claude/skills/clerk-setup/SKILL.md:
- Around line 295-301: The markdown table in SKILL.md is broken by unescaped
pipe characters inside the matcher regex examples. Update the affected table
rows so the `matcher` values in the Clerk setup guidance render safely in
markdown, either by escaping the `|` characters as `\|` or by reformatting those
examples outside inline code, while keeping the content under the same table
entries.
In @.claude/skills/clerk-webhooks/SKILL.md:
- Line 140: The Slack webhook call in fetch currently relies on a non-null
assertion for SLACK_WEBHOOK_URL, which can mask a missing configuration at
runtime. Update the webhook-sending logic in the Slack webhook helper to
validate SLACK_WEBHOOK_URL before calling fetch, and fail with a clear, explicit
error if it is unset. Use the existing webhook send path around fetch and the
surrounding Slack webhook handling code to keep the check close to where the URL
is consumed.
- Around line 189-204: The organizationMembership.created handler is incorrectly
creating a workspace for every new member, which duplicates workspace setup
already handled elsewhere. Update the logic in the
organizationMembership.created branch so it only creates the team_members record
and removes the db.workspaces.create call; keep workspace creation in the
organization.created flow instead. Use the organizationMembership.created
handler and the db.team_members.create/db.workspaces.create calls as the key
symbols to locate and fix this.
In @.claude/skills/convex-performance-audit/references/subscription-cost.md:
- Around line 96-98: The point-in-time read example in the snapshot loading
effect does not handle query failures, so add rejection handling around the
client.query(api.items.snapshot) call inside the useEffect and surface or log
the error instead of leaving the component silently empty. Keep the existing
setItems success path, and update the snapshot example to use proper error
handling in the same effect so failures are explicitly managed.
---
Outside diff comments:
In
@.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json:
- Around line 1-17: The template dependencies are using "latest", which makes
the Next.js/Clerk starter unstable across major releases. Update the dependency
entries in package.json for next, react, react-dom, and `@clerk/nextjs` to pinned
compatible major ranges, and keep the devDependencies aligned as well. Use the
package.json dependency block as the source of truth, and document the supported
version matrix in the skill README so template consumers know which versions are
intended to work together.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 289fa82e-bd6c-4194-8e9e-e927caad425f
⛔ Files ignored due to path filters (18)
.agents/skills/convex-create-component/assets/icon.svgis excluded by!**/*.svg.agents/skills/convex-migration-helper/assets/icon.svgis excluded by!**/*.svg.agents/skills/convex-performance-audit/assets/icon.svgis excluded by!**/*.svg.agents/skills/convex-quickstart/assets/icon.svgis excluded by!**/*.svg.agents/skills/convex-setup-auth/assets/icon.svgis excluded by!**/*.svg.claude/skills/convex-create-component/assets/icon.svgis excluded by!**/*.svg.claude/skills/convex-migration-helper/assets/icon.svgis excluded by!**/*.svg.claude/skills/convex-performance-audit/assets/icon.svgis excluded by!**/*.svg.claude/skills/convex-quickstart/assets/icon.svgis excluded by!**/*.svg.claude/skills/convex-setup-auth/assets/icon.svgis excluded by!**/*.svgconvex/_generated/ai/ai-files.state.jsonis excluded by!**/_generated/**convex/_generated/ai/guidelines.mdis excluded by!**/_generated/**convex/_generated/api.d.tsis excluded by!**/_generated/**convex/_generated/api.jsis excluded by!**/_generated/**convex/_generated/dataModel.d.tsis excluded by!**/_generated/**convex/_generated/server.d.tsis excluded by!**/_generated/**convex/_generated/server.jsis excluded by!**/_generated/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (140)
.agents/skills/clerk-backend-api/SKILL.md.agents/skills/clerk-backend-api/evals/evals.json.agents/skills/clerk-backend-api/scripts/api-specs-context.sh.agents/skills/clerk-backend-api/scripts/execute-request.sh.agents/skills/clerk-backend-api/scripts/extract-endpoint-detail.sh.agents/skills/clerk-backend-api/scripts/extract-tag-endpoints.sh.agents/skills/clerk-backend-api/scripts/extract-tags.js.agents/skills/clerk-cli/SKILL.md.agents/skills/clerk-cli/references/agent-mode.md.agents/skills/clerk-cli/references/auth.md.agents/skills/clerk-cli/references/recipes.md.agents/skills/clerk-custom-ui/SKILL.md.agents/skills/clerk-custom-ui/core-2/custom-sign-in.md.agents/skills/clerk-custom-ui/core-2/custom-sign-up.md.agents/skills/clerk-custom-ui/core-3/custom-sign-in.md.agents/skills/clerk-custom-ui/core-3/custom-sign-up.md.agents/skills/clerk-custom-ui/core-3/show-component.md.agents/skills/clerk-nextjs-patterns/SKILL.md.agents/skills/clerk-nextjs-patterns/evals/evals.json.agents/skills/clerk-nextjs-patterns/references/api-routes.md.agents/skills/clerk-nextjs-patterns/references/caching-auth.md.agents/skills/clerk-nextjs-patterns/references/middleware-strategies.md.agents/skills/clerk-nextjs-patterns/references/server-actions.md.agents/skills/clerk-nextjs-patterns/references/server-vs-client.md.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/app/layout.tsx.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/app/page.tsx.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/proxy.ts.agents/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/tsconfig.json.agents/skills/clerk-orgs/SKILL.md.agents/skills/clerk-orgs/evals/evals.json.agents/skills/clerk-orgs/references/enterprise-sso.md.agents/skills/clerk-orgs/references/invitations.md.agents/skills/clerk-orgs/references/nextjs-patterns.md.agents/skills/clerk-orgs/references/roles-permissions.md.agents/skills/clerk-setup/SKILL.md.agents/skills/clerk-setup/evals/evals.json.agents/skills/clerk-testing/SKILL.md.agents/skills/clerk-webhooks/SKILL.md.agents/skills/clerk-webhooks/evals/evals.json.agents/skills/clerk-webhooks/references/frameworks.md.agents/skills/convex-create-component/SKILL.md.agents/skills/convex-create-component/agents/openai.yaml.agents/skills/convex-create-component/references/advanced-patterns.md.agents/skills/convex-create-component/references/hybrid-components.md.agents/skills/convex-create-component/references/local-components.md.agents/skills/convex-create-component/references/packaged-components.md.agents/skills/convex-migration-helper/SKILL.md.agents/skills/convex-migration-helper/agents/openai.yaml.agents/skills/convex-migration-helper/references/migration-patterns.md.agents/skills/convex-migration-helper/references/migrations-component.md.agents/skills/convex-performance-audit/SKILL.md.agents/skills/convex-performance-audit/agents/openai.yaml.agents/skills/convex-performance-audit/references/function-budget.md.agents/skills/convex-performance-audit/references/hot-path-rules.md.agents/skills/convex-performance-audit/references/occ-conflicts.md.agents/skills/convex-performance-audit/references/subscription-cost.md.agents/skills/convex-quickstart/SKILL.md.agents/skills/convex-quickstart/agents/openai.yaml.agents/skills/convex-setup-auth/SKILL.md.agents/skills/convex-setup-auth/agents/openai.yaml.agents/skills/convex-setup-auth/references/auth0.md.agents/skills/convex-setup-auth/references/clerk.md.agents/skills/convex-setup-auth/references/convex-auth.md.agents/skills/convex-setup-auth/references/workos-authkit.md.agents/skills/convex/SKILL.md.claude/skills/clerk-backend-api/SKILL.md.claude/skills/clerk-backend-api/evals/evals.json.claude/skills/clerk-backend-api/scripts/api-specs-context.sh.claude/skills/clerk-backend-api/scripts/execute-request.sh.claude/skills/clerk-backend-api/scripts/extract-endpoint-detail.sh.claude/skills/clerk-backend-api/scripts/extract-tag-endpoints.sh.claude/skills/clerk-backend-api/scripts/extract-tags.js.claude/skills/clerk-cli/SKILL.md.claude/skills/clerk-cli/references/agent-mode.md.claude/skills/clerk-cli/references/auth.md.claude/skills/clerk-cli/references/recipes.md.claude/skills/clerk-custom-ui/SKILL.md.claude/skills/clerk-custom-ui/core-2/custom-sign-in.md.claude/skills/clerk-custom-ui/core-2/custom-sign-up.md.claude/skills/clerk-custom-ui/core-3/custom-sign-in.md.claude/skills/clerk-custom-ui/core-3/custom-sign-up.md.claude/skills/clerk-custom-ui/core-3/show-component.md.claude/skills/clerk-nextjs-patterns/SKILL.md.claude/skills/clerk-nextjs-patterns/evals/evals.json.claude/skills/clerk-nextjs-patterns/references/api-routes.md.claude/skills/clerk-nextjs-patterns/references/caching-auth.md.claude/skills/clerk-nextjs-patterns/references/middleware-strategies.md.claude/skills/clerk-nextjs-patterns/references/server-actions.md.claude/skills/clerk-nextjs-patterns/references/server-vs-client.md.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/app/layout.tsx.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/app/page.tsx.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/package.json.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/proxy.ts.claude/skills/clerk-nextjs-patterns/templates/nextjs-basic-auth/tsconfig.json.claude/skills/clerk-orgs/SKILL.md.claude/skills/clerk-orgs/evals/evals.json.claude/skills/clerk-orgs/references/enterprise-sso.md.claude/skills/clerk-orgs/references/invitations.md.claude/skills/clerk-orgs/references/nextjs-patterns.md.claude/skills/clerk-orgs/references/roles-permissions.md.claude/skills/clerk-setup/SKILL.md.claude/skills/clerk-setup/evals/evals.json.claude/skills/clerk-testing/SKILL.md.claude/skills/clerk-webhooks/SKILL.md.claude/skills/clerk-webhooks/evals/evals.json.claude/skills/clerk-webhooks/references/frameworks.md.claude/skills/convex-create-component/SKILL.md.claude/skills/convex-create-component/agents/openai.yaml.claude/skills/convex-create-component/references/advanced-patterns.md.claude/skills/convex-create-component/references/hybrid-components.md.claude/skills/convex-create-component/references/local-components.md.claude/skills/convex-create-component/references/packaged-components.md.claude/skills/convex-migration-helper/SKILL.md.claude/skills/convex-migration-helper/agents/openai.yaml.claude/skills/convex-migration-helper/references/migration-patterns.md.claude/skills/convex-migration-helper/references/migrations-component.md.claude/skills/convex-performance-audit/SKILL.md.claude/skills/convex-performance-audit/agents/openai.yaml.claude/skills/convex-performance-audit/references/function-budget.md.claude/skills/convex-performance-audit/references/hot-path-rules.md.claude/skills/convex-performance-audit/references/occ-conflicts.md.claude/skills/convex-performance-audit/references/subscription-cost.md.claude/skills/convex-quickstart/SKILL.md.claude/skills/convex-quickstart/agents/openai.yaml.claude/skills/convex-setup-auth/SKILL.md.claude/skills/convex-setup-auth/agents/openai.yaml.claude/skills/convex-setup-auth/references/auth0.md.claude/skills/convex-setup-auth/references/clerk.md.claude/skills/convex-setup-auth/references/convex-auth.md.claude/skills/convex-setup-auth/references/workos-authkit.md.claude/skills/convex/SKILL.mdAGENTS.mdCLAUDE.mdapp/layout.tsxapp/sign-in/[[...sign-in]]/page.tsxapp/sign-up/[[...sign-up]]/page.tsxpackage.jsonproxy.tsskills-lock.json
| let currentPath = null; | ||
| let currentMethod = null; | ||
| let blockStart = -1; | ||
| let blockLines = []; | ||
| let inPaths = false; | ||
| let inComponents = false; | ||
|
|
||
| // First pass: locate the "paths:" and "components:" top-level keys | ||
| let pathsStart = -1; | ||
| let pathsEnd = -1; | ||
| let componentsStart = -1; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Several declared variables are never used (blockStart, inPaths, inComponents, componentsStart, params, inParams). componentsStart is computed in the first pass but the components section is never actually walked, so $ref'd schemas are only surfaced by name, not expanded. This matches the documented intent (a discovery helper), so it's not a defect — just dead state that can be dropped for clarity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/clerk-backend-api/scripts/extract-tag-endpoints.sh around
lines 38 - 48, The issue is that several variables in the tag endpoint
extraction script are declared but never used, adding dead state without
affecting behavior. Clean up the script by removing the unused declarations in
the main parser setup and first-pass scan, and keep only the symbols actually
used by the endpoint discovery flow in extract-tag-endpoints.sh so the logic
stays clear and maintainable.
| // For email OTP: change create({ phoneNumber }) to create({ emailAddress }) | ||
| const error = await signUp.create({ phoneNumber }) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Document signUp.create() in the Hook API section or verify Core 3 API.
The complete example uses signUp.create({ phoneNumber }) (line 170) and signUp.finalize({ navigate: ({ session, decorateUrl }) => ... }) (line 184), but the "Hook API" and "Sign-Up Methods" sections only document password(), sso(), web3(), and update(). Readers may not find create() or the exact finalize() callback shape in the API reference above.
Add create() to the Sign-Up Methods section, or add a cross-reference note that OTP flows use the lower-level create() + verifications.* pattern shown in the complete example.
Also applies to: 183-184
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/clerk-custom-ui/core-3/custom-sign-up.md around lines 169 -
170, The Hook API / Sign-Up Methods reference is missing the lower-level OTP
flow used by the complete example, so update the documentation to include
signUp.create() and the finalize() callback shape. Add a create() entry
alongside password(), sso(), web3(), and update() in the API section, or add a
clear cross-reference explaining that OTP sign-up uses the signUp.create({
emailAddress/phoneNumber }) plus verifications.* pattern shown in the example,
and document the navigate({ session, decorateUrl }) finalize signature so
readers can locate the full flow.
| export async function GET(req: Request, { params }: { params: { orgId: string } }) { | ||
| const { userId, orgId } = await auth(); | ||
| if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 }); | ||
| if (orgId !== params.orgId) return Response.json({ error: 'Forbidden' }, { status: 403 }); | ||
|
|
||
| const orgData = await db.orgs.findUnique({ where: { id: orgId } }); | ||
| return Response.json(orgData); | ||
| } | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Fix Next.js 15 async params pattern.
Line 40 destructures params synchronously: { params }: { params: { orgId: string } }. In Next.js 15, params is a Promise that must be awaited. This pattern will throw a runtime error.
Your clerk-orgs/references/nextjs-patterns.md (line 78) already shows the correct pattern: { params }: { params: Promise<{ slug: string }> } with const { slug } = await params. Apply the same fix here:
-export async function GET(req: Request, { params }: { params: { orgId: string } }) {
+export async function GET(req: Request, { params }: { params: Promise<{ orgId: string }> }) {
const { userId, orgId } = await auth();
if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 });
- if (orgId !== params.orgId) return Response.json({ error: 'Forbidden' }, { status: 403 });
+ const { orgId: paramOrgId } = await params;
+ if (orgId !== paramOrgId) return Response.json({ error: 'Forbidden' }, { status: 403 });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export async function GET(req: Request, { params }: { params: { orgId: string } }) { | |
| const { userId, orgId } = await auth(); | |
| if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 }); | |
| if (orgId !== params.orgId) return Response.json({ error: 'Forbidden' }, { status: 403 }); | |
| const orgData = await db.orgs.findUnique({ where: { id: orgId } }); | |
| return Response.json(orgData); | |
| } | |
| ``` | |
| export async function GET(req: Request, { params }: { params: Promise<{ orgId: string }> }) { | |
| const { userId, orgId } = await auth(); | |
| if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 }); | |
| const { orgId: paramOrgId } = await params; | |
| if (orgId !== paramOrgId) return Response.json({ error: 'Forbidden' }, { status: 403 }); | |
| const orgData = await db.orgs.findUnique({ where: { id: orgId } }); | |
| return Response.json(orgData); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/clerk-nextjs-patterns/references/api-routes.md around lines
40 - 48, The GET route is using the old synchronous params shape, which breaks
in Next.js 15. Update the handler signature to treat params as a Promise and
await it inside GET before reading orgId, matching the async params pattern used
in the existing nextjs-patterns reference. Keep the auth and db.orgs.findUnique
logic the same, but read orgId from the awaited params object rather than from a
synchronous destructure.
| export async function deleteProject(projectId: string) { | ||
| const { userId, has } = await auth(); | ||
| if (!userId) throw new Error('Unauthorized'); | ||
|
|
||
| const canDelete = await has({ permission: 'org:project:delete' }); | ||
| if (!canDelete) throw new Error('Missing permission'); | ||
|
|
||
| await db.projects.delete({ where: { id: projectId } }); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
has() is synchronous — remove await.
has() returns a boolean synchronously. Using await suggests it returns a Promise, which is incorrect and may confuse readers.
🛠️ Proposed fix
export async function deleteProject(projectId: string) {
const { userId, has } = await auth();
if (!userId) throw new Error('Unauthorized');
- const canDelete = await has({ permission: 'org:project:delete' });
+ const canDelete = has({ permission: 'org:project:delete' });
if (!canDelete) throw new Error('Missing permission');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export async function deleteProject(projectId: string) { | |
| const { userId, has } = await auth(); | |
| if (!userId) throw new Error('Unauthorized'); | |
| const canDelete = await has({ permission: 'org:project:delete' }); | |
| if (!canDelete) throw new Error('Missing permission'); | |
| await db.projects.delete({ where: { id: projectId } }); | |
| } | |
| export async function deleteProject(projectId: string) { | |
| const { userId, has } = await auth(); | |
| if (!userId) throw new Error('Unauthorized'); | |
| const canDelete = has({ permission: 'org:project:delete' }); | |
| if (!canDelete) throw new Error('Missing permission'); | |
| await db.projects.delete({ where: { id: projectId } }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/clerk-nextjs-patterns/references/server-actions.md around
lines 43 - 51, The deleteProject server action is treating Clerk’s has() as
async even though it returns a boolean synchronously. Update the logic in
deleteProject to call has({ permission: 'org:project:delete' }) directly without
await, and keep the surrounding auth() flow and permission check otherwise
unchanged so the intent is clear.
| | Symptom | Cause | Fix | | ||
| |---------|-------|-----| | ||
| | `undefined` userId in Server Component | Missing `await` | `await auth()` not `auth()` | | ||
| | Auth not working on API routes | Missing matcher | Add `'/(api|trpc)(.*)'` to `proxy.ts` (Next.js <=15: `middleware.ts`) | | ||
| | Cache returns wrong user's data | Missing userId in key | Include `userId` in `unstable_cache` key | | ||
| | Mutations bypass auth | Unprotected Server Action | Check `auth()` at start of action | | ||
| | Wrong HTTP error code | Confused 401/403 | 401 = not signed in, 403 = no permission | | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Fix markdown table rendering for regex with pipe characters.
The Common Pitfalls table at line 122 contains a regex with unescaped | characters inside the Fix column. These pipes are interpreted as column delimiters, breaking table rendering. Escape the pipes as \| or replace the inline code with a reference to the full matcher example.
📝 Proposed fix
Replace the inline regex with a concise reference:
-| Auth not working on API routes | Missing matcher | Add `'/(api|trpc)(.*)'` to `proxy.ts` (Next.js <=15: `middleware.ts`) |
+| Auth not working on API routes | Missing matcher | Add the API matcher `'/(api|trpc)(.*)'` to your middleware config (see `references/middleware-strategies.md`) |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | Symptom | Cause | Fix | | |
| |---------|-------|-----| | |
| | `undefined` userId in Server Component | Missing `await` | `await auth()` not `auth()` | | |
| | Auth not working on API routes | Missing matcher | Add `'/(api|trpc)(.*)'` to `proxy.ts` (Next.js <=15: `middleware.ts`) | | |
| | Cache returns wrong user's data | Missing userId in key | Include `userId` in `unstable_cache` key | | |
| | Mutations bypass auth | Unprotected Server Action | Check `auth()` at start of action | | |
| | Wrong HTTP error code | Confused 401/403 | 401 = not signed in, 403 = no permission | | |
| | Symptom | Cause | Fix | | |
| |---------|-------|-----| | |
| | `undefined` userId in Server Component | Missing `await` | `await auth()` not `auth()` | | |
| | Auth not working on API routes | Missing matcher | Add the API matcher `'/(api|trpc)(.*)'` to your middleware config (see `references/middleware-strategies.md`) | | |
| | Cache returns wrong user's data | Missing userId in key | Include `userId` in `unstable_cache` key | | |
| | Mutations bypass auth | Unprotected Server Action | Check `auth()` at start of action | | |
| | Wrong HTTP error code | Confused 401/403 | 401 = not signed in, 403 = no permission | |
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 122-122: Table column count
Expected: 3; Actual: 4; Too many cells, extra data will be missing
(MD056, table-column-count)
🪛 SkillSpector (2.2.3)
[warning] 143: [E1] External Transmission: Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Remediation: Verify the destination URL is trusted and necessary. Remove or replace with documented APIs. Ensure no secrets, tokens, or PII are transmitted.
(Data Exfiltration (E1))
[warning] 164: [E1] External Transmission: Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Remediation: Verify the destination URL is trusted and necessary. Remove or replace with documented APIs. Ensure no secrets, tokens, or PII are transmitted.
(Data Exfiltration (E1))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/clerk-nextjs-patterns/SKILL.md around lines 119 - 126, The
Common Pitfalls markdown table is breaking because the regex in the Fix column
contains unescaped pipe characters that GitHub parses as extra columns. Update
the table entry in SKILL.md so the matcher regex is either escaped with literal
pipes or replaced with a short reference to the full matcher example, keeping
the table structure intact and readable.
| "expected_output": "Installs @clerk/react, wraps app with ClerkProvider, no middleware needed for SPA", | ||
| "files": [], | ||
| "expectations": [ | ||
| "Installs @clerk/react (not @clerk/nextjs or @clerk/clerk-react)", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Incorrect package name for React SPA.
Line 52 expects @clerk/react, but the actual npm package is @clerk/clerk-react. There is no @clerk/react package. This will cause installation failures.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/clerk-setup/evals/evals.json at line 52, The eval entry for
the Clerk React SPA package name is incorrect and will break installs because
`@clerk/react` does not exist. Update the string in the eval definition so it
references the actual package name `@clerk/clerk-react`, and make sure the
surrounding Clerk setup evals stay consistent with the intended React SPA path.
| | Missing `await` on `auth()` | In Next.js 15+, `auth()` is async: `const { userId } = await auth()` | | ||
| | Exposing `CLERK_SECRET_KEY` | Never use the secret key in client code; only `NEXT_PUBLIC_*` keys are safe | | ||
| | Missing middleware matcher | Include API routes: `matcher: ['/((?!.*\\..*|_next).*)', '/']` | | ||
| | ClerkProvider placement | Must be inside `<body>` in root layout (Core 2: could wrap `<html>`) | | ||
| | Auth routes not public | Allow `/sign-in`, `/sign-up` in middleware config | | ||
| | Landing page requires auth | To keep "/" public, exclude it: `matcher: ['/((?!.*\\..*|_next|^/$).*)', '/api/(.*)']` | | ||
| | Wrong import path | Server code uses `@clerk/nextjs/server`, client uses `@clerk/nextjs` | |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix table rendering — unescaped | in code spans breaks markdown parsers.
The | characters inside matcher regex character classes are interpreted as column delimiters by some markdown renderers, corrupting the table layout. Escape them as \| or reformat without inline code backticks.
| Missing middleware matcher | `Include API routes: matcher: ['/((?!.*\\..*\|_next).*)', '/']` |
| Landing page requires auth | `To keep "/" public, exclude it: matcher: ['/((?!.*\\..*\|_next\|^/$).*)', '/api/(.*)']` |🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 297-297: Table column count
Expected: 2; Actual: 3; Too many cells, extra data will be missing
(MD056, table-column-count)
[warning] 300-300: Table column count
Expected: 2; Actual: 4; Too many cells, extra data will be missing
(MD056, table-column-count)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/clerk-setup/SKILL.md around lines 295 - 301, The markdown
table in SKILL.md is broken by unescaped pipe characters inside the matcher
regex examples. Update the affected table rows so the `matcher` values in the
Clerk setup guidance render safely in markdown, either by escaping the `|`
characters as `\|` or by reformatting those examples outside inline code, while
keeping the content under the same table entries.
| }) | ||
|
|
||
| // Step 5: Post notification to Slack channel | ||
| await fetch(process.env.SLACK_WEBHOOK_URL!, { |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Validate SLACK_WEBHOOK_URL before use.
The non-null assertion ! hides a missing-env failure. If the variable is unset, fetch(undefined) throws an unhelpful error at runtime.
- await fetch(process.env.SLACK_WEBHOOK_URL!, {
+ const slackUrl = process.env.SLACK_WEBHOOK_URL
+ if (!slackUrl) throw new Error('Missing SLACK_WEBHOOK_URL')
+ await fetch(slackUrl, {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await fetch(process.env.SLACK_WEBHOOK_URL!, { | |
| const slackUrl = process.env.SLACK_WEBHOOK_URL | |
| if (!slackUrl) throw new Error('Missing SLACK_WEBHOOK_URL') | |
| await fetch(slackUrl, { |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/clerk-webhooks/SKILL.md at line 140, The Slack webhook call
in fetch currently relies on a non-null assertion for SLACK_WEBHOOK_URL, which
can mask a missing configuration at runtime. Update the webhook-sending logic in
the Slack webhook helper to validate SLACK_WEBHOOK_URL before calling fetch, and
fail with a clear, explicit error if it is unset. Use the existing webhook send
path around fetch and the surrounding Slack webhook handling code to keep the
check close to where the URL is consumed.
| if (evt.type === 'organizationMembership.created') { | ||
| // Extract organization ID, user ID, and role from payload | ||
| const { organization, public_user_data, role } = evt.data | ||
| const orgId = organization.id | ||
| const userId = public_user_data.user_id | ||
|
|
||
| // Add to team_members table | ||
| await db.team_members.create({ | ||
| data: { orgId, userId, role }, | ||
| }) | ||
|
|
||
| // Create workspace record for new member | ||
| await db.workspaces.create({ | ||
| data: { orgId, userId, createdAt: new Date() }, | ||
| }) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove or correct the workspace creation in organizationMembership.created.
Creating a workspace record inside the membership handler means every new member triggers a duplicate workspace creation. Workspaces should be created once in the organization.created handler (already shown above), not per-member.
if (evt.type === 'organizationMembership.created') {
// Extract organization ID, user ID, and role from payload
const { organization, public_user_data, role } = evt.data
const orgId = organization.id
const userId = public_user_data.user_id
// Add to team_members table
await db.team_members.create({
data: { orgId, userId, role },
})
-
- // Create workspace record for new member
- await db.workspaces.create({
- data: { orgId, userId, createdAt: new Date() },
- })
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (evt.type === 'organizationMembership.created') { | |
| // Extract organization ID, user ID, and role from payload | |
| const { organization, public_user_data, role } = evt.data | |
| const orgId = organization.id | |
| const userId = public_user_data.user_id | |
| // Add to team_members table | |
| await db.team_members.create({ | |
| data: { orgId, userId, role }, | |
| }) | |
| // Create workspace record for new member | |
| await db.workspaces.create({ | |
| data: { orgId, userId, createdAt: new Date() }, | |
| }) | |
| } | |
| if (evt.type === 'organizationMembership.created') { | |
| // Extract organization ID, user ID, and role from payload | |
| const { organization, public_user_data, role } = evt.data | |
| const orgId = organization.id | |
| const userId = public_user_data.user_id | |
| // Add to team_members table | |
| await db.team_members.create({ | |
| data: { orgId, userId, role }, | |
| }) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/clerk-webhooks/SKILL.md around lines 189 - 204, The
organizationMembership.created handler is incorrectly creating a workspace for
every new member, which duplicates workspace setup already handled elsewhere.
Update the logic in the organizationMembership.created branch so it only creates
the team_members record and removes the db.workspaces.create call; keep
workspace creation in the organization.created flow instead. Use the
organizationMembership.created handler and the
db.team_members.create/db.workspaces.create calls as the key symbols to locate
and fix this.
| useEffect(() => { | ||
| client.query(api.items.snapshot).then(setItems); | ||
| }, []); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add error handling to the point-in-time read example.
The useEffect fetches data but doesn't handle rejection, so a failed query would leave the component silently empty and the error would be unhandled.
useEffect(() => {
- client.query(api.items.snapshot).then(setItems);
+ client.query(api.items.snapshot)
+ .then(setItems)
+ .catch(err => console.error('Failed to load snapshot:', err));
}, []);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useEffect(() => { | |
| client.query(api.items.snapshot).then(setItems); | |
| }, []); | |
| useEffect(() => { | |
| client.query(api.items.snapshot) | |
| .then(setItems) | |
| .catch(err => console.error('Failed to load snapshot:', err)); | |
| }, []); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/convex-performance-audit/references/subscription-cost.md
around lines 96 - 98, The point-in-time read example in the snapshot loading
effect does not handle query failures, so add rejection handling around the
client.query(api.items.snapshot) call inside the useEffect and surface or log
the error instead of leaving the component silently empty. Keep the existing
setItems success path, and update the snapshot example to use proper error
handling in the same effect so failures are explicitly managed.
Summary by CodeRabbit