DEV Community

Convex fitness app

Claude Code 100 messages April 07, 2026
by alexdavies74
Convex fitness app claude-sonnet-4-6
You

We are going to use Convex. Here is an empty one:
Project ID: trustworthy-ram-942

Start by installing the packages, then start from the core README and enter planning mode.

I'd like you to plan, and then build, a complete, usable, fitness studio booking web app.

The first user will create and manage a Studio, which has a class schedule. Keep it simple, offer inputs for start and end time for each class, participant limit, with a button to make a new class. No weekly repetition. They should be able to copy a link to provide to their customers.

When others scan and follow the link, after logging in, they enter the booking experience. This is a very simple text-based experience, listing the available classes. Each class has a book button, which immediately reserves a slot in that class for the logged-in user. Other customers should (within a few seconds) see the slots are taken. This should work even if the original owner's client is not online.

Security model: Only the original owner should be able to see everything. Each customer should be able to create/cancel their own bookings, and see the presence of other customers' bookings, but NOT see the identity of the booker, or any other private details of the booking. This security should be robust to customers who can modify their own client code. You are responsible for this security, and if you need my help, you must ask for it.

Interaction model: All create/write actions in the UI should feel instant, using optimistic updates. If the owner is looking at a class when someone books, they should be able to see that the class got a new signup, within several seconds.

You may ask me about problems with your tooling. Avoid other questions, we are practicing to one-shot this task.

Do not explore my file system outside the current directory.

Don't write a custom backend!

Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
You

[Request interrupted by user for tool use]

You

I've now run convex dev for you.

I switched you to plan mode to begin the main build phase

Agent
Agent
Agent

Let me read the Convex guidelines and existing files before designing the plan.

Agent
Agent
Agent

Now let me design the plan with a Plan agent.

Agent
Agent

Now I'll write the final plan file.

Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent

Now writing the frontend files:

Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent

The other errors will resolve as I create the page files. Continuing:

Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent
Agent

Now run the auth setup script:

Agent
Agent

The shell is choking on the key PEM starting with -----. Need to use spawnSync with an args array to avoid shell parsing:

Agent
Agent
You

[Request interrupted by user]

You

Would it help for me to run something manually?

Agent

Yes — the convex env set CLI is treating -----BEGIN as a flag name. The cleanest fix is to generate the key values and have you paste them into the Convex dashboard directly.

Please run this to generate the keys and print them:

Agent
Agent

Run node print-auth-keys.mjs in your terminal, then go to the Convex dashboard environment variables page (the URL is printed at the end) and add three variables:

  • JWT_PRIVATE_KEY — the long [REDACTED]\n... single-line string
  • JWKS — the JSON {"keys":[...]} string
  • SITE_URLhttps://trustworthy-ram-942.convex.site

Let me know once those are set and I'll verify the TypeScript is clean before you start npx convex dev and npm run dev.

You

Done!

Agent

Let me check for any TypeScript issues before you start the dev servers:

Agent
Agent
Agent

Clean. Let me also verify the generated Convex API has picked up all our new functions:

Agent
Agent
Agent

The generated types are stale — npx convex dev needs to run with our new files to deploy the backend and regenerate them. TypeScript was happy because the generated api object is currently typed as {} (permissive), but the actual functions need to be deployed.

Agent
Agent

Please run these two commands (each in its own terminal):

Terminal 1 (deploys backend + watches for changes):

npx convex dev

Terminal 2 (starts the frontend):

npm run dev

Wait for convex dev to print something like ✔ Deployed in X seconds before checking the app. Once both are running, visit http://localhost:5173 — you should see the sign-in page. After that, let me know if anything goes wrong and I'll fix it.

You

<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>

You

<command-name>/context</command-name>
<command-message>context</command-message>
<command-args></command-args>

You

<ide_opened_file>The user opened the file [REDACTED]/code/experiment convex 1/.gitignore in the IDE. This may or may not be related to the current task.</ide_opened_file>

% npx convex dev
⠹ Bundling component schemas and implementations...
✘ [ERROR] No matching export in "node_modules/@convex-dev/auth/dist/providers/Password.js" for import "default"

convex/auth.ts:2:7:
  2 │ import Password from "@convex-dev/auth/provide...
    ╵        ~~~~~~~~
Agent
Agent
Agent
Agent
Agent
Agent
You

[Request interrupted by user]

You

<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>

You

<command-name>/context</command-name>
<command-message>context</command-message>
<command-args></command-args>

You

[CONVEX A(auth:signIn)] [Request ID: f0adc8793670cb17] Server Error Uncaught Error: Uncaught InvalidCharacterError: Failed to execute 'atob': Invalid byte 92, offset 0. at genericImport (../../node_modules/jose/dist/browser/runtime/asn1.js:64:17) at fromPKCS8 (../../node_modules/jose/dist/browser/runtime/asn1.js:121:25) at importPKCS8 (../../node_modules/jose/dist/browser/key/import.js:22:0) at generateToken (../../node_modules/@convex-dev/auth/src/server/implementation/tokens.ts:25:18) at generateTokensForSession (../../node_modules/@convex-dev/auth/src/server/implementation/sessions.ts:77:18) at async maybeGenerateTokensForSession (../../node_modules/@convex-dev/auth/src/server/implementation/sessions.ts:32:10) at async signInImpl (../../node_modules/@convex-dev/auth/src/server/implementation/mutations/signIn.ts:34:0) at async handleCredentials (../../node_modules/@convex-dev/auth/src/server/implementation/signIn.ts:195:12) at async handler (../../node_modules/@convex-dev/auth/src/server/implementation/index.ts:416:26) Called by client

Agent

The error is Invalid byte 92 — byte 92 is a backslash. The library passes JWT_PRIVATE_KEY directly to jose without replacing \n → newlines, so the stored escaped version breaks it.

The fix: the key needs to be stored with actual newlines in the dashboard, not \n. Update the print script:

Agent
Agent

Please run node print-auth-keys.mjs again. This time the JWT_PRIVATE_KEY output will have real newlines in it. In the Convex dashboard, delete the old JWT_PRIVATE_KEY value and paste the new one — the textarea in the dashboard accepts multiline content. The JWKS and SITE_URL values haven't changed so you can leave those alone.

You

<ide_opened_file>The user opened the file [REDACTED]/code/experiment convex 1/setup-auth.mjs in the IDE. This may or may not be related to the current task.</ide_opened_file>

Now the "Create account" button just flickers to "Please wait" for a bit.

I also saw in the log:
react-BCRm9iGP.js?v=f4f7ab16:187 Failed to authenticate: "Could not verify OIDC token claim. Check that the token signature is valid and the token hasn't expired.", check your server auth config

Please confirm the actual cause before fixing it. If you add logs, I can paste them to you

Agent

The error "Could not verify OIDC token claim" means Convex is verifying the JWT signature against the JWKS public key, but the signature doesn't match.

The most likely cause: JWT_PRIVATE_KEY and JWKS are from different key generation runs. Here's the sequence:

  1. First print-auth-keys.mjs run → you pasted all 3 values (but JWT_PRIVATE_KEY had \n escape issue)
  2. I updated the script to print real newlines → you ran it again and updated only JWT_PRIVATE_KEY
  3. Now JWT_PRIVATE_KEY is from run #2 and JWKS is still from run #1 — they don't match, so signatures fail

Please run node print-auth-keys.mjs one more time and update both JWT_PRIVATE_KEY and JWKS from this single fresh run. SITE_URL can stay as-is.

You

<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>

You

<command-name>/context</command-name>
<command-message>context</command-message>
<command-args></command-args>

You

<ide_opened_file>The user opened the file [REDACTED]/code/experiment convex 1/print-auth-keys.mjs in the IDE. This may or may not be related to the current task.</ide_opened_file>

Now you've had experience working with Convex, I'd like to get your evaluation of the platform in comparison to other options you know. Where did it cause friction?

Focus on the things that slowed you down or wasted tokens, as well as things that contributed to bugs. You may also share what was a positive surprise about the experience.

Keep it brief and don't describe solutions.

Agent

Convex evaluation from this build

Friction / token waste

  • Auth setup is genuinely hard to one-shot. @convex-dev/auth requires external env vars (JWT key pair + SITE_URL) that must be set before the app works at all. The CLI can't accept PEM values as shell args (the -----BEGIN flag-parsing bug), so there's no clean scriptable path — it forced a detour through the dashboard and two debugging cycles around key mismatches. This is the single biggest source of wasted effort.

  • npx convex dev must run before TypeScript is useful. The generated api.d.ts starts empty, so IDE errors are suppressed until after first deploy. You can write broken code and not know it.

  • The Password import ambiguity. Default vs. named export wasn't clear from the package without grepping the dist files. Docs and type declarations didn't surface this well.

  • No -- option terminator in convex env set. A minor CLI gap that cascaded into a significant detour.

Positive surprises

  • The real-time model is genuinely zero-effort. I wrote no WebSocket, polling, or pub/sub code. useQuery subscriptions just work across clients, which is the core hard problem of this app.

  • The security model maps naturally to server functions. Enforcing that customers never see booking identities was straightforward — put the logic in a query, never return the field. No middleware, no API layer to reason about.

  • Optimistic updates are well-designed. The .withOptimisticUpdate() API is clean and the rollback-on-failure is automatic.

  • Validators as the schema source of truth (using v.* in both schema and function args) eliminated a whole class of drift bugs.

You

Give a two-sentence summary evaluation: would you want to use Convex again?

Agent

Yes — the real-time data model and server-function security make it genuinely better than REST+WebSocket for this class of app. The auth setup friction is real but a one-time cost, and everything after that moved fast.