[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-convex-auth":3,"mdc--ww9dro-key":34,"related-org-convex-auth":258,"related-repo-convex-auth":437},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":32,"mdContent":33},"auth","add authentication to Convex applications","Add sign-in (passkeys by default, OAuth\u002Fpassword optional) to the current Convex app, wired correctly incl. auth.config.ts. TRIGGER on a login\u002Fauth request for an existing app.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"convex","Convex","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fconvex.png","get-convex",[13,16,17,20],{"name":14,"slug":4,"type":15},"Auth","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Authentication","authentication",{"name":21,"slug":22,"type":15},"OAuth","oauth",2,"https:\u002F\u002Fgithub.com\u002Fget-convex\u002Fconvex-codex-plugin","2026-07-18T05:12:54.443056","Apache-2.0",0,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":31},[],"Codex plugin for the hosted Convex MCP server","https:\u002F\u002Fgithub.com\u002Fget-convex\u002Fconvex-codex-plugin\u002Ftree\u002FHEAD\u002Fplugins\u002Fconvex\u002Fskills\u002Fauth","---\nname: \"auth\"\ndescription: \"Add sign-in (passkeys by default, OAuth\u002Fpassword optional) to the current Convex app, wired correctly incl. auth.config.ts. TRIGGER on a login\u002Fauth request for an existing app.\"\nlicense: \"Apache-2.0\"\n---\n\n# Add sign-in to the app\n\nInstall and wire @convex-dev\u002Fauth for the current app: a provider (passkeys by default, or OAuth\u002Fpassword), the server config, the client hooks, and a sign-in UI — correctly, including the auth.config.ts that's the #1 real-world auth footgun.\n\n## Steps\n1. Install @convex-dev\u002Fauth (pinned build) and add it to convex.config.ts. With pnpm, also `pnpm add jose` (it won't hoist otherwise); you need it for step 3.\n2. Add the provider in convex\u002Fauth.ts (Passkey by default; Password or OAuth like Google on request).\n3. Generate the auth keys HEADLESSLY. Do NOT run the interactive `npx @convex-dev\u002Fauth` wizard: it needs a login\u002FTTY and hangs in non-interactive, anonymous, or CI runs (the #1 auth time-sink). Generate JWT_PRIVATE_KEY + JWKS deterministically with `jose`:\n   node -e 'import(\"jose\").then(async({generateKeyPair,exportPKCS8,exportJWK})=>{const k=await generateKeyPair(\"RS256\",{extractable:true});const priv=await exportPKCS8(k.privateKey);const pub=await exportJWK(k.publicKey);process.stdout.write(JSON.stringify({JWT_PRIVATE_KEY:priv.trimEnd().replace(\u002F\\n\u002Fg,\" \"),JWKS:JSON.stringify({keys:[{use:\"sig\",...pub}]})}))})' > .auth-keys.json\n   Then set JWT_PRIVATE_KEY and JWKS (from .auth-keys.json) plus SITE_URL on the deployment. Prefer the Convex MCP `envSet` tool, one call per var, to avoid shell-quoting the multi-line key. CLI fallback: use the NAME=VALUE form (`npx convex env set \"JWT_PRIVATE_KEY=$JWT\"`), NEVER `env set JWT_PRIVATE_KEY \"$JWT\"` (the value starts with `-----BEGIN` and the CLI parses the leading `-` as an unknown flag). SITE_URL is the dev URL (e.g. http:\u002F\u002Flocalhost:3000). Delete .auth-keys.json after.\n4. Write convex\u002Fauth.config.ts (the silently-always-signed-out bug lives here if it's wrong).\n5. Wire the client: ConvexAuthProvider, the sign-in component, and route guards. If you import shadcn\u002Fui primitives (button, input, textarea, label, and so on), add them first with `npx shadcn@latest add \u003Cname>`; a missing @\u002Fcomponents\u002Fui\u002F* is a hard build error.\n6. Verify a sign-in round-trips before declaring done.\n\n## Rules\n- Generate JWT_PRIVATE_KEY\u002FJWKS with `jose` (extractable RS256; PKCS8 newlines to spaces; JWKS = {keys:[{use:\"sig\", ...publicJwk}]}). Do NOT run the interactive `npx @convex-dev\u002Fauth` wizard: it hangs headless\u002Fanonymous. Set the vars via the MCP `envSet` tool or the NAME=VALUE CLI form.\n- Always write auth.config.ts: a missing\u002Fincorrect one makes the app silently always-signed-out with no error.\n- Passkeys by default; only switch to password\u002FOAuth on explicit request.\n- Install any shadcn\u002Fui primitive you import up front (`npx shadcn@latest add ...`); a missing @\u002Fcomponents\u002Fui\u002F* is a hard build failure.\n- Verify a real sign-in works before finishing.\n",{"data":35,"body":36},{"name":4,"description":6,"license":26},{"type":37,"children":38},"root",[39,48,54,61,187,193],{"type":40,"tag":41,"props":42,"children":44},"element","h1",{"id":43},"add-sign-in-to-the-app",[45],{"type":46,"value":47},"text","Add sign-in to the app",{"type":40,"tag":49,"props":50,"children":51},"p",{},[52],{"type":46,"value":53},"Install and wire @convex-dev\u002Fauth for the current app: a provider (passkeys by default, or OAuth\u002Fpassword), the server config, the client hooks, and a sign-in UI — correctly, including the auth.config.ts that's the #1 real-world auth footgun.",{"type":40,"tag":55,"props":56,"children":58},"h2",{"id":57},"steps",[59],{"type":46,"value":60},"Steps",{"type":40,"tag":62,"props":63,"children":64},"ol",{},[65,80,85,164,169,182],{"type":40,"tag":66,"props":67,"children":68},"li",{},[69,71,78],{"type":46,"value":70},"Install @convex-dev\u002Fauth (pinned build) and add it to convex.config.ts. With pnpm, also ",{"type":40,"tag":72,"props":73,"children":75},"code",{"className":74},[],[76],{"type":46,"value":77},"pnpm add jose",{"type":46,"value":79}," (it won't hoist otherwise); you need it for step 3.",{"type":40,"tag":66,"props":81,"children":82},{},[83],{"type":46,"value":84},"Add the provider in convex\u002Fauth.ts (Passkey by default; Password or OAuth like Google on request).",{"type":40,"tag":66,"props":86,"children":87},{},[88,90,96,98,104,106,112,114,120,122,128,130,136,138,144,146,152,154,162],{"type":46,"value":89},"Generate the auth keys HEADLESSLY. Do NOT run the interactive ",{"type":40,"tag":72,"props":91,"children":93},{"className":92},[],[94],{"type":46,"value":95},"npx @convex-dev\u002Fauth",{"type":46,"value":97}," wizard: it needs a login\u002FTTY and hangs in non-interactive, anonymous, or CI runs (the #1 auth time-sink). Generate JWT_PRIVATE_KEY + JWKS deterministically with ",{"type":40,"tag":72,"props":99,"children":101},{"className":100},[],[102],{"type":46,"value":103},"jose",{"type":46,"value":105},":\nnode -e 'import(\"jose\").then(async({generateKeyPair,exportPKCS8,exportJWK})=>{const k=await generateKeyPair(\"RS256\",{extractable:true});const priv=await exportPKCS8(k.privateKey);const pub=await exportJWK(k.publicKey);process.stdout.write(JSON.stringify({JWT_PRIVATE_KEY:priv.trimEnd().replace(\u002F\\n\u002Fg,\" \"),JWKS:JSON.stringify({keys:",{"type":40,"tag":107,"props":108,"children":109},"span",{},[110],{"type":46,"value":111},"{use:\"sig\",...pub}",{"type":46,"value":113},"})}))})' > .auth-keys.json\nThen set JWT_PRIVATE_KEY and JWKS (from .auth-keys.json) plus SITE_URL on the deployment. Prefer the Convex MCP ",{"type":40,"tag":72,"props":115,"children":117},{"className":116},[],[118],{"type":46,"value":119},"envSet",{"type":46,"value":121}," tool, one call per var, to avoid shell-quoting the multi-line key. CLI fallback: use the NAME=VALUE form (",{"type":40,"tag":72,"props":123,"children":125},{"className":124},[],[126],{"type":46,"value":127},"npx convex env set \"JWT_PRIVATE_KEY=$JWT\"",{"type":46,"value":129},"), NEVER ",{"type":40,"tag":72,"props":131,"children":133},{"className":132},[],[134],{"type":46,"value":135},"env set JWT_PRIVATE_KEY \"$JWT\"",{"type":46,"value":137}," (the value starts with ",{"type":40,"tag":72,"props":139,"children":141},{"className":140},[],[142],{"type":46,"value":143},"-----BEGIN",{"type":46,"value":145}," and the CLI parses the leading ",{"type":40,"tag":72,"props":147,"children":149},{"className":148},[],[150],{"type":46,"value":151},"-",{"type":46,"value":153}," as an unknown flag). SITE_URL is the dev URL (e.g. ",{"type":40,"tag":155,"props":156,"children":160},"a",{"href":157,"rel":158},"http:\u002F\u002Flocalhost:3000",[159],"nofollow",[161],{"type":46,"value":157},{"type":46,"value":163},"). Delete .auth-keys.json after.",{"type":40,"tag":66,"props":165,"children":166},{},[167],{"type":46,"value":168},"Write convex\u002Fauth.config.ts (the silently-always-signed-out bug lives here if it's wrong).",{"type":40,"tag":66,"props":170,"children":171},{},[172,174,180],{"type":46,"value":173},"Wire the client: ConvexAuthProvider, the sign-in component, and route guards. If you import shadcn\u002Fui primitives (button, input, textarea, label, and so on), add them first with ",{"type":40,"tag":72,"props":175,"children":177},{"className":176},[],[178],{"type":46,"value":179},"npx shadcn@latest add \u003Cname>",{"type":46,"value":181},"; a missing @\u002Fcomponents\u002Fui\u002F* is a hard build error.",{"type":40,"tag":66,"props":183,"children":184},{},[185],{"type":46,"value":186},"Verify a sign-in round-trips before declaring done.",{"type":40,"tag":55,"props":188,"children":190},{"id":189},"rules",[191],{"type":46,"value":192},"Rules",{"type":40,"tag":194,"props":195,"children":196},"ul",{},[197,230,235,240,253],{"type":40,"tag":66,"props":198,"children":199},{},[200,202,207,209,214,216,221,223,228],{"type":46,"value":201},"Generate JWT_PRIVATE_KEY\u002FJWKS with ",{"type":40,"tag":72,"props":203,"children":205},{"className":204},[],[206],{"type":46,"value":103},{"type":46,"value":208}," (extractable RS256; PKCS8 newlines to spaces; JWKS = {keys:",{"type":40,"tag":107,"props":210,"children":211},{},[212],{"type":46,"value":213},"{use:\"sig\", ...publicJwk}",{"type":46,"value":215},"}). Do NOT run the interactive ",{"type":40,"tag":72,"props":217,"children":219},{"className":218},[],[220],{"type":46,"value":95},{"type":46,"value":222}," wizard: it hangs headless\u002Fanonymous. Set the vars via the MCP ",{"type":40,"tag":72,"props":224,"children":226},{"className":225},[],[227],{"type":46,"value":119},{"type":46,"value":229}," tool or the NAME=VALUE CLI form.",{"type":40,"tag":66,"props":231,"children":232},{},[233],{"type":46,"value":234},"Always write auth.config.ts: a missing\u002Fincorrect one makes the app silently always-signed-out with no error.",{"type":40,"tag":66,"props":236,"children":237},{},[238],{"type":46,"value":239},"Passkeys by default; only switch to password\u002FOAuth on explicit request.",{"type":40,"tag":66,"props":241,"children":242},{},[243,245,251],{"type":46,"value":244},"Install any shadcn\u002Fui primitive you import up front (",{"type":40,"tag":72,"props":246,"children":248},{"className":247},[],[249],{"type":46,"value":250},"npx shadcn@latest add ...",{"type":46,"value":252},"); a missing @\u002Fcomponents\u002Fui\u002F* is a hard build failure.",{"type":40,"tag":66,"props":254,"children":255},{},[256],{"type":46,"value":257},"Verify a real sign-in works before finishing.",{"items":259,"total":436},[260,275,290,305,322,339,352,364,383,390,407,421],{"slug":8,"name":8,"fn":261,"description":262,"org":263,"tags":264,"stars":272,"repoUrl":273,"updatedAt":274},"guide Convex project setup and usage","Routes general Convex requests to the right project skill. Use when the user asks which Convex skill to use or gives an underspecified Convex app task.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[265,268,269],{"name":266,"slug":267,"type":15},"Backend","backend",{"name":9,"slug":8,"type":15},{"name":270,"slug":271,"type":15},"Database","database",34,"https:\u002F\u002Fgithub.com\u002Fget-convex\u002Fagent-skills","2026-07-12T08:00:45.091281",{"slug":276,"name":276,"fn":277,"description":278,"org":279,"tags":280,"stars":272,"repoUrl":273,"updatedAt":289},"convex-create-component","build reusable Convex components","Builds reusable Convex components with isolated tables and app-facing APIs. Use for new components, reusable backend modules, integrations, or component boundary work.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[281,284,287,288],{"name":282,"slug":283,"type":15},"API Development","api-development",{"name":285,"slug":286,"type":15},"Architecture","architecture",{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},"2026-07-12T08:00:39.428577",{"slug":291,"name":291,"fn":292,"description":293,"org":294,"tags":295,"stars":272,"repoUrl":273,"updatedAt":304},"convex-migration-helper","plan Convex schema and data migrations","Plans Convex schema and data migrations with widen-migrate-narrow and @convex-dev\u002Fmigrations. Use for breaking schema changes, backfills, table reshaping, or zero-downtime rollouts.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[296,297,298,301],{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},{"name":299,"slug":300,"type":15},"Data Engineering","data-engineering",{"name":302,"slug":303,"type":15},"Migration","migration","2026-07-12T08:00:51.27967",{"slug":306,"name":306,"fn":307,"description":308,"org":309,"tags":310,"stars":272,"repoUrl":273,"updatedAt":321},"convex-performance-audit","audit Convex application performance","Audits Convex performance for reads, subscriptions, write contention, and function limits. Use for slow features, insights findings, OCC conflicts, or read amplification.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[311,312,315,318],{"name":9,"slug":8,"type":15},{"name":313,"slug":314,"type":15},"Debugging","debugging",{"name":316,"slug":317,"type":15},"Monitoring","monitoring",{"name":319,"slug":320,"type":15},"Performance","performance","2026-07-12T08:00:50.02928",{"slug":323,"name":323,"fn":324,"description":325,"org":326,"tags":327,"stars":272,"repoUrl":273,"updatedAt":338},"convex-quickstart","initialize Convex in applications","Creates or adds Convex to an app. Use for new Convex projects, npm create convex@latest, frontend setup, env vars, or the first npx convex dev run.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[328,331,332,335],{"name":329,"slug":330,"type":15},"CLI","cli",{"name":9,"slug":8,"type":15},{"name":333,"slug":334,"type":15},"Frontend","frontend",{"name":336,"slug":337,"type":15},"Onboarding","onboarding","2026-07-12T08:00:43.436152",{"slug":340,"name":340,"fn":341,"description":342,"org":343,"tags":344,"stars":272,"repoUrl":273,"updatedAt":351},"convex-setup-auth","set up authentication and access control","Sets up Convex auth, identity mapping, and access control. Use for login, auth providers, users tables, protected functions, or roles in a Convex app.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[345,348,349,350],{"name":346,"slug":347,"type":15},"Access Control","access-control",{"name":14,"slug":4,"type":15},{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},"2026-07-12T08:00:48.652641",{"slug":353,"name":353,"fn":354,"description":355,"org":356,"tags":357,"stars":23,"repoUrl":24,"updatedAt":363},"add","add capabilities to Convex applications","Add a capability to the CURRENT Convex + Next.js project — consults the served Convex capability catalog for always-current procedures (billing, crons, auth, agent, search, …); falls back to built-in hosting or @convex-dev component search. TRIGGER when the user runs $add, or asks to add hosting\u002Fpublishing or any backend capability to an existing Convex app.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[358,359,360],{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},{"name":361,"slug":362,"type":15},"Next.js","next-js","2026-07-12T07:59:59.358004",{"slug":365,"name":365,"fn":366,"description":367,"org":368,"tags":369,"stars":23,"repoUrl":24,"updatedAt":382},"agent","build AI agents with Convex","Build an AI agent \u002F RAG feature on Convex (@convex-dev\u002Fagent: threads, tools, vector search). TRIGGER on an AI-agent\u002Fchatbot\u002FRAG request.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[370,373,376,379],{"name":371,"slug":372,"type":15},"Agents","agents",{"name":374,"slug":375,"type":15},"Engineering","engineering",{"name":377,"slug":378,"type":15},"RAG","rag",{"name":380,"slug":381,"type":15},"Search","search","2026-07-12T08:00:01.921824",{"slug":4,"name":4,"fn":5,"description":6,"org":384,"tags":385,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[386,387,388,389],{"name":14,"slug":4,"type":15},{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},{"slug":391,"name":391,"fn":392,"description":393,"org":394,"tags":395,"stars":23,"repoUrl":24,"updatedAt":406},"billing","integrate Stripe billing in Convex apps","Add Stripe billing to a Convex app via @convex-dev\u002Fstripe (checkout + auto-verified webhook + subscription gating). TRIGGER on a payments\u002Fbilling\u002Fsubscription request.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[396,397,400,403],{"name":9,"slug":8,"type":15},{"name":398,"slug":399,"type":15},"Payments","payments",{"name":401,"slug":402,"type":15},"Stripe","stripe",{"name":404,"slug":405,"type":15},"Webhooks","webhooks","2026-07-12T08:00:08.123246",{"slug":408,"name":408,"fn":409,"description":410,"org":411,"tags":412,"stars":23,"repoUrl":24,"updatedAt":420},"check-updates","upgrade Convex component versions","Check the CURRENT Convex app's pinned components against the latest recommended versions and offer to upgrade them — e.g. the passkey auth component's new email-first sign-in. TRIGGER when the user runs \u002Fcheck-updates or $check-updates, asks 'are my components up to date', 'any updates', 'upgrade auth', 'upgrade my components', or wants the newest features after a quickstart. Applies each upgrade behind a build gate (verify-or-revert) with the user's consent.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[413,416,417],{"name":414,"slug":415,"type":15},"Configuration","configuration",{"name":9,"slug":8,"type":15},{"name":418,"slug":419,"type":15},"Maintenance","maintenance","2026-07-12T08:00:03.236862",{"slug":422,"name":422,"fn":423,"description":424,"org":425,"tags":426,"stars":23,"repoUrl":24,"updatedAt":435},"convex-authz","audit and harden Convex authorization","Audit and harden a Convex app's authorization: identity-from-arg impersonation, missing per-document ownership checks, and public queries leaking PII\u002Ffinancial data by a client-supplied id — the single largest real-defect cluster measured against generated Convex backends (44 of 214). Runs a deterministic scan for the 3 shapes, then applies the canonical requireIdentity\u002FrequireOwner pattern, then verifies with tsc. TRIGGER on 'secure my app', 'audit auth', 'add login', 'who can access this data', or an explicit 'audit my authz'. NOT always-on. SKIP when there is no convex\u002F directory.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[427,428,431,432],{"name":14,"slug":4,"type":15},{"name":429,"slug":430,"type":15},"Code Analysis","code-analysis",{"name":9,"slug":8,"type":15},{"name":433,"slug":434,"type":15},"Security","security","2026-07-12T08:00:04.516752",26,{"items":438,"total":492},[439,445,452,459,466,472,479],{"slug":353,"name":353,"fn":354,"description":355,"org":440,"tags":441,"stars":23,"repoUrl":24,"updatedAt":363},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[442,443,444],{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},{"name":361,"slug":362,"type":15},{"slug":365,"name":365,"fn":366,"description":367,"org":446,"tags":447,"stars":23,"repoUrl":24,"updatedAt":382},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[448,449,450,451],{"name":371,"slug":372,"type":15},{"name":374,"slug":375,"type":15},{"name":377,"slug":378,"type":15},{"name":380,"slug":381,"type":15},{"slug":4,"name":4,"fn":5,"description":6,"org":453,"tags":454,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[455,456,457,458],{"name":14,"slug":4,"type":15},{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},{"slug":391,"name":391,"fn":392,"description":393,"org":460,"tags":461,"stars":23,"repoUrl":24,"updatedAt":406},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[462,463,464,465],{"name":9,"slug":8,"type":15},{"name":398,"slug":399,"type":15},{"name":401,"slug":402,"type":15},{"name":404,"slug":405,"type":15},{"slug":408,"name":408,"fn":409,"description":410,"org":467,"tags":468,"stars":23,"repoUrl":24,"updatedAt":420},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[469,470,471],{"name":414,"slug":415,"type":15},{"name":9,"slug":8,"type":15},{"name":418,"slug":419,"type":15},{"slug":422,"name":422,"fn":423,"description":424,"org":473,"tags":474,"stars":23,"repoUrl":24,"updatedAt":435},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[475,476,477,478],{"name":14,"slug":4,"type":15},{"name":429,"slug":430,"type":15},{"name":9,"slug":8,"type":15},{"name":433,"slug":434,"type":15},{"slug":480,"name":480,"fn":481,"description":482,"org":483,"tags":484,"stars":23,"repoUrl":24,"updatedAt":491},"convex-expert","develop Convex backend applications","Convex backend rules — consult this whenever writing or editing any code inside a convex\u002F directory (schemas, queries, mutations, actions, HTTP endpoints, crons, file storage, auth, component installation). TRIGGER before touching convex\u002F functions, so the code uses the object-form syntax, validators, indexes, and component patterns that generic models get wrong.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[485,486,487,488],{"name":266,"slug":267,"type":15},{"name":9,"slug":8,"type":15},{"name":270,"slug":271,"type":15},{"name":489,"slug":490,"type":15},"TypeScript","typescript","2026-07-18T05:12:50.448833",19]