← ConvexCONTENT HISTORY

Update to Convex

Snapshot Sep 30, 2026 · 22:46 UTC · version 2.0.1

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "labs-quickstart",
  "description": "LABS — the FULL Convex quickstart experience: scaffold a running Next.js + shadcn app from one sentence with passkey (WebAuthn) sign-in and a live in-app Chef feedback panel pre-baked, build the idea live, then PUBLISH it to a public https://<app>.convex.app URL (with the user's confirmation before publishing). TRIGGER when the user runs $labs-quickstart, or asks for the full/labs quickstart, a published/public app, sign-in/passkeys, or the in-app feedback panel from scratch. For a plain local-only scaffold use $quickstart instead. SKIP when there's already a Convex project in the cwd.",
  "included_files": [],
  "skill_md_contents": "---\nname: \"labs-quickstart\"\ndescription: \"LABS — the FULL Convex quickstart experience: scaffold a running Next.js + shadcn app from one sentence with passkey (WebAuthn) sign-in and a live in-app Chef feedback panel pre-baked, build the idea live, then PUBLISH it to a public https://<app>.convex.app URL (with the user's confirmation before publishing). TRIGGER when the user runs $labs-quickstart, or asks for the full/labs quickstart, a published/public app, sign-in/passkeys, or the in-app feedback panel from scratch. For a plain local-only scaffold use $quickstart instead. SKIP when there's already a Convex project in the cwd.\"\nlicense: \"Apache-2.0\"\n---\n\n# Convex Labs Quickstart ($labs-quickstart)\n\nThe **full** quickstart experience (labs): a running Next.js + shadcn \"wow-shell\"\nConvex app from one sentence, with **passkey sign-in** and the **Chef feedback\npanel** pre-baked, built live — and, once v1 works and **the user confirms**,\n**published to a public `https://<app>.convex.app` URL**. The heavy scaffold runs\nas a served shell script from the Convex quickstart backend (\"anteater\"); your job\nis to launch it, then build.\n\n> Want just a plain, local-only scaffold (no login, no panel, no publishing)?\n> That's the **`$quickstart`** skill — use it instead.\n\nThe user's request after `$labs-quickstart` is the **app idea** (e.g.\n`$labs-quickstart a movie-night voting app` → idea = \"a movie-night voting app\").\nIf no idea was given, ask for a one-sentence idea, then continue.\n\n## Degradation rule — when the scaffold can't run, write code, not ceremony\n\nIf the bootstrap can't run — a non-interactive/one-shot session, no network access, a\nsandboxed temp dir, or the user just wants code rather than a running app — **don't\nwait on the scaffold or the panel/passkey/publish machinery**. Write a standard Convex\nproject directly:\n\n- **ALL backend code goes under `convex/`** (`schema.ts`, queries, mutations, actions)\n  — **NEVER at the project root.** Convex functions only run from the `convex/`\n  directory.\n- **Write ZERO scaffold/documentation files** unless explicitly asked — no\n  `START_HERE.md`, `ARCHITECTURE.md`, `MANIFEST.txt`, or README walls. \"Build me a\n  backend\" is a request for code, not a design-doc package.\n\n## Data access + imports — read before writing any convex/*.ts\n\n- Never an unbounded `.collect()` on a table that can grow — use `.withIndex(...)` +\n  `.paginate(paginationOpts)`/`.take(n)`.\n- Index, don't filter — `.index(...)` in `schema.ts` for every read path, queried via\n  `.withIndex(...)`; `.filter()` is a full table scan.\n- Imports: `query`/`mutation`/`action`/`internalQuery`/`internalMutation`/`internalAction`\n  from `\"./_generated/server\"`; `api`/`internal` from `\"./_generated/api\"`; never from\n  `\"convex/server\"` in application code.\n- `v.literal(\"exact value\")` for fixed string/enum members, not a bare `v.string()`.\n- `\"use node\";` is action-only — never in a file that also exports a `query` or\n  `mutation`.\n\n## Self-verify — before declaring backend work done\n\nBefore you call any backend work finished: run `npx tsc --noEmit` and, when a\ndeployment is available (or via a local anonymous one:\n`CONVEX_AGENT_MODE=anonymous npx convex dev --once`), push it. Fix every error\neither one reports before finishing — one verify round catches the\nwrong-relative-import / duplicate-symbol / unbalanced-paren class that otherwise\nbreaks the deploy.\n\n## STEP 0 — launch the scaffold NOW (before anything else)\n\nRun this **first**, before any reasoning or other tool calls — it kicks off the\n~45–120s scaffold (npm install, convex dev, next dev) in the background so it's\ninstalling while you read the rest. Substitute the user's idea for `<IDEA>`:\n\n```bash\nBASE=\"https://basic-anteater-667.convex.site\"\nIDEA=\"<IDEA>\"\nSLUG=$(curl -fsS --max-time 15 -X POST \"$BASE/generate\" -H 'content-type: application/json' \\\n  --data \"$(node -e 'process.stdout.write(JSON.stringify({idea:process.argv[1],template:\"nextjs-shadcn\"}))' \"$IDEA\")\" \\\n  | node -e 'let s=\"\";process.stdin.on(\"data\",d=>s+=d).on(\"end\",()=>{try{process.stdout.write(JSON.parse(s).id||\"\")}catch{}})') || true\necho \"SLUG=$SLUG\"\nQB=$(mktemp -t convex-qb-XXXX.sh)\ncurl -fsS --max-time 20 \"$BASE/quickstart-bootstrap\" -o \"$QB\" || { echo \"BOOTSTRAP_FETCH_FAILED\"; exit 3; }\n# The bootstrap is feature-flagged via a profile. LABS ships the FULL profile:\n# passkey auth pre-baked, the Chef feedback panel wired, and public *.convex.app\n# publishing enabled — EXCEPT custom domains, which stay off (QB_DOMAIN=0).\n# Only fall back from pre-baked passkeys if the idea asked for a different auth\n# method (else the agent rips it out mid-build). Emit AUTH_MODE for STEP 2.\nif printf '%s' \"$IDEA\" | grep -qiE 'oauth|google (sign|login|auth)|github (login|auth)|sso|saml|magic[ -]?link|password[- ]?only|email.?(\\+|and|/).?password|clerk|workos|auth0|\\.tgz'; then echo \"AUTH_MODE=custom\"; else echo \"AUTH_MODE=passkeys\"; fi\n# QB_HARNESS=codex tags telemetry; QB_ARGS_BASE/QB_FEEDBACK_URL keep the args +\n# panel feedback on the same host the slug was generated on.\nnohup env QB_PROFILE=full QB_DOMAIN=0 QB_HARNESS=codex QB_ARGS_BASE=\"$BASE\" QB_FEEDBACK_URL=\"$BASE/feedback\" \\\n  bash \"$QB\" $SLUG > .quickstart-bootstrap.log 2>&1 &\necho \"SCAFFOLD_LAUNCHED log=.quickstart-bootstrap.log SLUG=$SLUG\"\n```\n\n- If it prints `SCAFFOLD_LAUNCHED`, the scaffold is running in the background.\n  **Do NOT run it again.** Note the `SLUG=`.\n- If `curl` is blocked or you see `BOOTSTRAP_FETCH_FAILED`, the network/sandbox\n  blocked it — tell the user they likely need to run Codex with network access /\n  auto-approve (`codex --sandbox danger-full-access`), then retry.\n\n## STEP 1 — wait for the scaffold, open the browser\n\nPoll `.quickstart-bootstrap.log` until it contains `BOOTSTRAP_COMPLETE`.\n\n**Codex's sandbox often reaps backgrounded (`nohup … &`) processes when the launch\ncall returns** — so the bootstrap may write its first line, then die before scaffolding.\nIf within ~20s the log has stalled (no new lines), **no app subdirectory has appeared**,\nand there's no `BOOTSTRAP_COMPLETE`, the background launch was reaped. Recover by running\nthe bootstrap in the **FOREGROUND** — re-run the STEP 0 block but replace the\n`nohup env … &` line with a plain foreground run, same env:\n\n```bash\nQB_PROFILE=full QB_DOMAIN=0 QB_HARNESS=codex QB_ARGS_BASE=\"$BASE\" QB_FEEDBACK_URL=\"$BASE/feedback\" bash \"$QB\" $SLUG\n```\n\nIt backgrounds `convex dev` / `next dev` itself and returns at `BOOTSTRAP_COMPLETE` in\n~1–2 min (set a generous command timeout, 300s+). `BOOTSTRAP_FETCH_FAILED` → server\nunreachable; tell the user. When it completes the log prints:\n- `OPEN_BROWSER_URL: http://localhost:<port>` — open this for the user immediately.\n- The app is scaffolded in a new subdirectory with `convex dev` + `next dev` running\n  and error watchers armed (`convex-errors.log` / `next-errors.log` paths are in the log).\n\n## STEP 2 — read the runbook + build the idea live\n\nRead the personalized runbook for the full build flow (it's served — fetch it):\n\n```bash\ncurl -fsS \"https://basic-anteater-667.convex.site/q/$SLUG.md\"\n```\n\nThen build the user's idea following it. What's already done by the scaffold:\n- **Auth:** check `AUTH_MODE` in the launch log. If `AUTH_MODE=custom` (the idea\n  asked for OAuth/password/magic-link/a specific auth component), passkeys were NOT\n  pre-baked — wire the **requested** provider per its README (delegate `convex/` code\n  to the `convex-expert` skill) and skip the passkey button. If `AUTH_MODE=passkeys`\n  (default), **passkeys** are pre-baked (`@convex-dev/auth` pinned build,\n  `convex/auth.ts`, `...authTables`, `ConvexAuthProvider`, JWT keys set) — you add the\n  **email-first sign-in UI**: an email input + one call to\n  `usePasskeyAuth().signInOrRegisterWithPasskey({ email })`, which signs the user in if\n  they already have a passkey for that email or registers a new one (the build enables\n  enumeration-by-email + autofill). Use the returned `registered` flag for the\n  welcome message; give the input `autoComplete=\"username webauthn\"` for autofill.\n  ⚠ The email is self-asserted/unverified — authorize off the Convex user `_id`\n  (`getAuthUserId`), never `user.email`.\n- The **Chef feedback panel** is wired — keep the `FeatureRequestPanel` mount (a\n  floating panel in the layout, e.g. `app/_chef-panel.tsx` / `<ChefPanel />`) — **never\n  delete or unmount it**. **Narrate your build through the panel, not chat** —\n  `npx convex run progress:post '{\"message\":\"…\"}'`,\n  `npx convex run todos:plan '{\"items\":[…]}'` / `todos:advance`, ask the user\n  clarifying questions with `npx convex run refinementQuestions:ask '{\"text\":\"…\"}'`,\n  and resolve incoming feature requests with\n  `npx convex run featureRequests:setState '{\"id\":\"…\",\"state\":\"…\"}'`.\n- **Custom domains are NOT part of this release** — don't brainstorm, offer, or\n  register domains, and don't look for `.quickstart-domains.json`. (If the user\n  already owns a domain and asks to wire it, that's the separate `$domains` skill.)\n\nRules while building:\n- Delegate all code inside `convex/` to the **`convex-expert`** skill's rules\n  (object-form syntax, validators, indexes, internal vs public).\n- Watch for `convex/` + `next` errors and fix them as they appear — the easiest way\n  is the `fix_errors_automatically` tool (see STEP 4), which surfaces them as events.\n\n## STEP 3 — publish to *.convex.app (ASK THE USER FIRST)\n\nWhen the app builds clean and the core feature works (your \"v1\"), **offer to\npublish** — do not publish silently:\n\n> \"v1 is working locally. Want me to publish it to a public\n>  `https://<app>.convex.app` URL anyone can open?\"\n\nPublish **only on a clear yes**. On a no, the app keeps running locally — done.\n\nOn yes, three parts (the served runbook has the full detail — it wins on conflict):\n\n**1. Rebind passkeys to the public page origin** (WebAuthn is origin-bound; the\npage moves to `<app>.convex.app` while the auth HTTP routes stay on the\ndeployment's `*.convex.site`). `<app>` = the deployment name (the subdomain of\n`NEXT_PUBLIC_CONVEX_URL`). Use the `NAME=VALUE` form (never `env set NAME \"$VALUE\"`\n— values starting with `-` parse as flags):\n\n```bash\nnpx convex env set \"SITE_URL=https://<app>.convex.app\"\nnpx convex env set \"AUTH_PASSKEY_RP_ID=<app>.convex.app\"\nnpx convex env set \"AUTH_PASSKEY_ORIGIN=https://<app>.convex.app\"\n```\n\n**2. Static export** — `next.config.ts` must be exactly\n`{ output: \"export\", images: { unoptimized: true } }` (never silence the linter or\ntype-checker to force a build — fix the real cause). Export emits to `out/`.\n\n**3. Publish through the moderated gateway** (no static-hosting component needed):\n\n```bash\ncurl -fsSL https://basic-anteater-667.convex.site/publish-convex-app -o publish-convex-app.mjs\nnpm install -D fflate\nnode publish-convex-app.mjs            # build → zip out/ → moderated gateway upload\n```\n\nIt prints `https://<app>.convex.app` — pass that URL to the user, and verify the\npasskey ceremony works on the published page (register a test passkey; an\nRP-ID/origin error means the three env vars above don't match the `.convex.app`\nhost). If the gateway returns 403 (content moderation), it prints the reasons — a\nlegitimate app should pass; report a false positive to the user, don't evade it.\nPublishing needs a cloud Convex deployment; if anonymous/local, `npx convex dev`\ninto a cloud project first.\n\n## STEP 4 — stay on watch with `fix_errors_automatically` (start EARLY, don't yield)\n\nThis harness has no push: a user request typed into the Chef panel or a runtime\nerror sits **unseen** until you actively look. This plugin bundles a `convex-plugin`\nMCP server with one **blocking** tool that surfaces it as an event and fixes it.\n\n**Start watching as soon as the app is open (right after STEP 1) — not just after\nv1.** The user is most engaged at the very start and will often submit a request or\nquestion while you're still building. Call `fix_errors_automatically` between build\nmilestones and whenever you'd otherwise pause; on the FIRST call it returns\n**immediately** if anything is already pending (it surfaces existing unhandled\nrequests/questions as `existing: true`), so feedback submitted before you started\nwatching is never lost. Then make it your standing idle action for the rest of the\nsession.\n\n> **Avoid the repeated approval prompt:** each call is a separate tool invocation,\n> so a one-time \"Allow\" re-asks every loop. Choose **\"Always allow\"** when prompted,\n> or add to `~/.codex/config.toml`: `[mcp_servers.convex-plugin]` then\n> `trust_level = \"trusted\"`. Also pass a long `timeoutMs` (e.g. 280000) so each\n> block is long and you re-call less often.\n\nCall the **`fix_errors_automatically`** tool with `projectDir` set to your app's\n**absolute path** (the `convex-app/` subdir, where `.env.local` lives). It BLOCKS\nuntil the next event, then returns one of:\n- `feature_request` / `refinement_answer` → the user wants something — handle it\n  (loop back through STEP 2/3), then call the tool again.\n- `convex_error` / `next_error` → stop, read the line, fix the file, wait for\n  `convex dev` / Next to recover, then call again.\n- `quiet` → heartbeat timeout, nothing happened — just call it again.\n\n**Loop on this tool instead of ending your turn.** Each call blocks, so you stay on\nwatch and react within seconds — no polling, no walking away. Keep looping until the\nuser clearly says they're done.\n\n## After the run\n\nOffer `$quickstart-improve` so the user can send this session for an AI review that\nimproves the quickstart.\n\n## On failure / friction — offer to self-report (WITH the user's permission)\n\nIf the run doesn't go smoothly — you give up, hit a blocker, it takes way too long, or\nthe user is frustrated — don't yield silently. **Ask first, send only on a yes**:\n\n> \"That didn't go as smoothly as it should have. May I send this session — the transcript,\n>  with secrets redacted — to the Convex team so they can fix what went wrong? [yes / no]\"\n\n- **On yes** → run the `quickstart-improve` flow (ships the redacted transcript):\n  `curl -fsSL \"https://basic-anteater-667.convex.site/send-transcript\" | QB_HARNESS=codex bash -s -- --base https://basic-anteater-667.convex.site --idea \"<what broke>\"`\n- **On no** → respect it; send nothing.\n- Either way, give the user an honest summary of where it got stuck.\n\nNever send the transcript without an explicit yes.\n"
}

SHA-256: f780b2543159860cf7c8761948dbfa458bc952b0d269b09ee8a4191329cf07a6