Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@BilalG1
Copy link
Contributor

@BilalG1 BilalG1 commented Oct 10, 2025

High-level PR Summary

This PR fixes dependency management issues by adding the missing wait-on package to the Convex example's dependencies, reorganizing the dependency order in package.json for consistency, and regenerating the pnpm-lock.yaml file to ensure proper dependency resolution across the monorepo.

⏱️ Estimated Review Time: 5-15 minutes

💡 Review Order Suggestion
Order File Path
1 examples/convex/package.json
2 pnpm-lock.yaml

Need help? Join our Discord

Analyze latest changes

Summary by CodeRabbit

  • New Features

    • Added UI buttons to view user info via different clients, a server-side user info section, and an Action page to view/submit updates to user metadata.
    • Added a server-side action to update a user's client-read-only metadata.
  • Documentation

    • In-app link and guidance to the Action route for updating user data.
  • Chores

    • Updated project dependencies/devDependencies and added .env.local to .gitignore.
  • Bug Fixes

    • Token-missing scenario now handled gracefully instead of throwing.

@vercel
Copy link

vercel bot commented Oct 10, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
stack-backend Ready Ready Preview Comment Oct 15, 2025 10:30pm
stack-dashboard Ready Ready Preview Comment Oct 15, 2025 10:30pm
stack-demo Ready Ready Preview Comment Oct 15, 2025 10:30pm
stack-docs Ready Ready Preview Comment Oct 15, 2025 10:30pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Walkthrough

Adds client and server Convex helpers and UI to fetch and display user info, a client action page and a new server action to update user metadata, moves a prior action between backend modules, changes an auth helper to return an empty string when no token is present, and updates deps and .gitignore.

Changes

Cohort / File(s) Summary
Example UI & helpers
examples/convex/app/page.tsx, examples/convex/app/server/page.tsx, examples/convex/app/action/page.tsx, examples/convex/app/user-info.ts
Adds client buttons and flows to fetch user info via Convex JS client and ConvexHttpClient; server-side page uses ConvexHttpClient with cookie auth to fetch user info; adds a client action page that calls a Convex action; exports two helper functions to fetch user info.
Convex backend modules
examples/convex/convex/myActions.ts, examples/convex/convex/myFunctions.ts
Adds myAction in myActions.ts to update client-read-only metadata; removes previous myAction from myFunctions.ts; other functions (getUserInfo, listNumbers, addNumber) remain.
Auth helper change
packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
getConvexHttpClientAuth now returns an empty string ("") when no access token is available instead of throwing an error.
Tooling and ignores
examples/convex/package.json, examples/convex/.gitignore
Adds workspace dependency @stackframe/stack-shared; adds devDependencies postcss and wait-on (reorders some devDeps); adds .env.local to .gitignore.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant P as Client Page
  participant UI as user-info.ts
  participant C as Convex Client / ConvexHttpClient
  participant S as Convex Backend (myFunctions.getUserInfo)

  U->>P: Click "View user info" (JS / HTTP)
  P->>UI: call getUserInfoConvexClient()/getUserInfoConvexHttpClient()
  UI->>C: init client + setAuth(token from stackClientApp)
  C->>S: query getUserInfo
  S-->>C: userInfo
  C-->>UI: userInfo
  UI-->>P: userInfo
  P-->>U: alert(userInfo)
  note right of UI: If token missing, auth helper may supply ""
Loading
sequenceDiagram
  autonumber
  participant BR as Next.js Server
  participant HC as ConvexHttpClient
  participant SSA as stackServerApp (cookie store)
  participant S as Convex Backend (myFunctions.getUserInfo)

  BR->>SSA: getAccessToken()
  SSA-->>BR: token | ""
  BR->>HC: init + setAuth(token)
  HC->>S: query getUserInfo
  S-->>HC: userInfo
  HC-->>BR: userInfo
  BR-->>BR: render server page with JSON userInfo
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant C as Action Page
  participant A as useAction(myActions.myAction)
  participant S as Convex Backend (myActions.myAction)
  participant SS as stackServerApp

  U->>C: Enter text + Click "Run action"
  C->>A: call({ testMetadata })
  A->>S: invoke myAction
  S->>SS: getPartialUser / getUser
  alt User found
    S->>SS: update client-read-only metadata { test }
  end
  S-->>A: resolve
  A-->>C: promise resolved
  C-->>U: alert("Action executed")
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Convex implementation #913 — Convex example app and Convex client/server helpers; overlaps Convex integration and the auth helper change.
  • Init stack more args #892 — Refactor splitting stack into server/client modules and updating server import paths used by server-side Convex code.

Suggested reviewers

  • N2D4

Poem

I hopped through code with eager paws,
Buttons clicked and server claws,
Two clients fetched, one action ran,
Metadata sprouted—what a plan!
🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title "convex example testing" is too vague and generic to meaningfully describe the changeset. The raw summary reveals extensive modifications across multiple files including new authentication examples, server-side and client-side Convex integration, new action handlers, new exported functions, and configuration changes—far beyond what "testing" suggests. The title does not convey the primary changes from either the developer's stated objectives (dependency management) or the actual code modifications (substantial new functionality and integration examples).
Description Check ❓ Inconclusive The description includes the CONTRIBUTING.md reminder as specified in the template and provides a high-level summary with review suggestions. However, there is a significant mismatch between the stated scope and the actual changes: the description claims the PR fixes dependency management by adding wait-on and reorganizing package.json, yet the raw summary shows extensive new functionality including server-side authentication, client-side Convex functions, new action handlers, and new page components. This incompleteness creates ambiguity about whether the PR scope has been fully understood or documented.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch convex-full-example

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d93fad8 and 07bfe17.

📒 Files selected for processing (3)
  • examples/convex/convex/myFunctions.ts (1 hunks)
  • examples/convex/package.json (2 hunks)
  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • examples/convex/convex/myFunctions.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: restart-dev-and-test
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: docker
  • GitHub Check: build (22.x)
  • GitHub Check: Security Check
🔇 Additional comments (1)
examples/convex/convex/myFunctions.ts (1)

1-1: Minimal formatting change.

The addition of an empty line at the beginning of the file appears to be a formatting adjustment. This change is minor and doesn't affect functionality.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 77777a5..7741c72

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (2)

examples/convex/package.json
pnpm-lock.yaml

@BilalG1 BilalG1 changed the title fix pnpm-lock, and convex example dep convex example testing Oct 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
examples/convex/app/server/page.tsx (1)

25-25: Simplify JSON processing.

The code performs JSON.stringify(JSON.parse(userInfo), null, 2) which suggests userInfo is already a JSON string. If getUserInfo returns a JSON string, this double processing is redundant and could be simplified.

Consider one of these approaches:

  1. If the query returns an object, remove JSON.parse:
-          <pre>{JSON.stringify(JSON.parse(userInfo), null, 2)}</pre>
+          <pre>{JSON.stringify(userInfo, null, 2)}</pre>
  1. If the query returns a JSON string, remove JSON.stringify:
-          <pre>{JSON.stringify(JSON.parse(userInfo), null, 2)}</pre>
+          <pre>{JSON.parse(userInfo)}</pre>
examples/convex/app/page.tsx (1)

51-65: Add error handling for async button click handlers.

The async operations in the onClick handlers lack error handling. If the promises reject, users will see unhandled promise rejections in the console without any feedback in the UI.

Apply this diff to add error handling:

         <button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => {
           getUserInfoConvexHttpClient().then(userInfo => {
             alert(userInfo);
-          });
+          }).catch(error => {
+            alert(`Error fetching user info: ${error.message}`);
+          });
         }}>
           View user info (http client)
         </button>
         <button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => {
           getUserInfoConvexClient().then(userInfo => {
             alert(userInfo);
-          });
+          }).catch(error => {
+            alert(`Error fetching user info: ${error.message}`);
+          });
         }}>
           View user info (js client)
         </button>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7741c72 and 9e28cd2.

📒 Files selected for processing (6)
  • examples/convex/.gitignore (1 hunks)
  • examples/convex/app/page.tsx (2 hunks)
  • examples/convex/app/server/page.tsx (2 hunks)
  • examples/convex/app/user-info.ts (1 hunks)
  • examples/convex/stack/server.tsx (1 hunks)
  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/template/**

📄 CodeRabbit inference engine (AGENTS.md)

When modifying the SDK copies, make changes in packages/template (source of truth)

Files:

  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
  • examples/convex/stack/server.tsx
  • examples/convex/app/user-info.ts
  • examples/convex/app/page.tsx
  • examples/convex/app/server/page.tsx
🧬 Code graph analysis (3)
examples/convex/stack/server.tsx (1)
packages/template/src/lib/stack-app/apps/interfaces/server-app.ts (2)
  • StackServerApp (18-88)
  • StackServerApp (97-97)
examples/convex/app/page.tsx (2)
examples/convex/convex/myFunctions.ts (1)
  • getUserInfo (11-16)
examples/convex/app/user-info.ts (2)
  • getUserInfoConvexHttpClient (7-12)
  • getUserInfoConvexClient (18-21)
examples/convex/app/server/page.tsx (1)
examples/convex/stack/server.tsx (1)
  • stackServerApp (4-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: restart-dev-and-test
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: Security Check
🔇 Additional comments (1)
examples/convex/.gitignore (1)

42-43: LGTM!

Adding .env.local to .gitignore is a standard best practice for Next.js projects to prevent committing environment-specific configuration and secrets.

Comment on lines +14 to +17
const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
const token = await stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
convex.setAuth(token);
const userInfo = await convex.query(api.myFunctions.getUserInfo, {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add error handling for authentication and query operations.

The token retrieval, authentication setup, and query execution lack error handling. If the token is empty (due to the change in getConvexHttpClientAuth) or if the query fails, the page will crash without a user-friendly error message.

Apply this diff to add error handling:

-  const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
-  const token = await stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
-  convex.setAuth(token);
-  const userInfo = await convex.query(api.myFunctions.getUserInfo, {});
+  const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
+  const token = await stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
+  
+  if (!token) {
+    throw new Error("Failed to obtain authentication token");
+  }
+  
+  convex.setAuth(token);
+  const userInfo = await convex.query(api.myFunctions.getUserInfo, {});
📝 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.

Suggested change
const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
const token = await stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
convex.setAuth(token);
const userInfo = await convex.query(api.myFunctions.getUserInfo, {});
const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
const token = await stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
if (!token) {
throw new Error("Failed to obtain authentication token");
}
convex.setAuth(token);
const userInfo = await convex.query(api.myFunctions.getUserInfo, {});
🤖 Prompt for AI Agents
In examples/convex/app/server/page.tsx around lines 14 to 17, add proper error
handling for token retrieval, auth setup, and the query: wrap the call to
stackServerApp.getConvexHttpClientAuth and convex.query in try/catch blocks,
verify the returned token is non-empty before calling convex.setAuth (and handle
the empty-token case by logging the situation and returning a safe fallback or
rendering an error state), and catch/query errors to log them and return a
fallback userInfo or an error response so the page doesn't crash.

import { stackClientApp } from "@/stack/client";
import { ConvexHttpClient, ConvexClient } from "convex/browser";

const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential issue: Module-level environment variable access.

Creating ConvexHttpClient at module level using process.env.NEXT_PUBLIC_CONVEX_URL! may cause issues in Next.js. Environment variables might not be available during module initialization in certain contexts (e.g., static generation), and the non-null assertion bypasses validation.

Consider moving client creation into the function or adding validation:

-const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
-
 export async function getUserInfoConvexHttpClient() {
+  const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
   const token = await stackClientApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
   convexHttpClient.setAuth(token);
   const userInfo = await convexHttpClient.query(api.myFunctions.getUserInfo, {});
   return userInfo;
 }

Or add validation if keeping module-level creation:

+if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
+  throw new Error("NEXT_PUBLIC_CONVEX_URL environment variable is required");
+}
+
 const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL);
📝 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.

Suggested change
const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export async function getUserInfoConvexHttpClient() {
const convexHttpClient = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
const token = await stackClientApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" });
convexHttpClient.setAuth(token);
const userInfo = await convexHttpClient.query(api.myFunctions.getUserInfo, {});
return userInfo;
}
🤖 Prompt for AI Agents
In examples/convex/app/user-info.ts around line 5, creating ConvexHttpClient at
module initialization with process.env.NEXT_PUBLIC_CONVEX_URL! is unsafe; move
the client creation into the function that uses it (so the env var is read at
request/runtime) or, if you must keep module-level creation, validate the
environment variable first (check for undefined and throw a clear error or
fallback) and remove the non-null assertion to avoid runtime surprises.

Comment on lines 1686 to 1690
async getConvexHttpClientAuth(options: { tokenStore: TokenStoreInit }): Promise<string> {
const session = await this._getSession(options.tokenStore);
const tokens = await session.getOrFetchLikelyValidTokens(20_000);
return tokens?.accessToken.token ?? throwErr("No access token available");
return tokens?.accessToken.token ?? "";
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that all callers handle empty auth strings correctly.

This change modifies error signaling from throwing an exception to returning an empty string when no access token is available. Callers that previously relied on catching exceptions for missing tokens will now receive an empty string, which could lead to silent authentication failures if not properly handled downstream.

Run the following script to find all usages of getConvexHttpClientAuth and verify they handle empty string returns:

Additionally, check if Convex clients properly handle empty auth strings or if they require non-empty tokens:


🏁 Script executed:

#!/bin/bash
# Search for all call sites of getConvexHttpClientAuth
rg -n -C5 'getConvexHttpClientAuth\s*\(' --type=ts --type=tsx

Length of output: 27


🌐 Web query:

Does ConvexHttpClient.setAuth() handle empty strings gracefully, or does it require a valid token?

💡 Result:

Short answer: setAuth accepts a string but an empty string is not treated as "no token" — it will result in an Authorization: Bearer header (and the backend will reject it). Use clearAuth() (or pass null/undefined where supported by that API) to remove auth. [1][2]

Sources:

  • ConvexHttpClient API (setAuth(value: string) signature). [1]
  • Convex auth debugging docs (notes that null/undefined → auth skipped; implies empty string is different). [2]

#!/bin/bash
# Search for all call sites of getConvexHttpClientAuth across the repo
rg -n -C5 'getConvexHttpClientAuth\s*\(' .

#!/bin/bash
# Search for all call sites of getConvexHttpClientAuth across the repo
rg -n -C5 'getConvexHttpClientAuth\s*\(' .

🏁 Script executed:

#!/bin/bash
# Search for all call sites of getConvexHttpClientAuth across the repo
rg -n -C5 'getConvexHttpClientAuth\s*\(' .

Length of output: 6283


Handle empty auth strings in all callers
Returning "" on missing tokens no longer throws, so examples (user-info.ts, server/page.tsx) and tests must check for "" and either throw a descriptive error or call clearAuth() instead of setAuth(""). Otherwise the backend will reject the request silently and E2E tests will fail.

🤖 Prompt for AI Agents
In packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
around lines 1686–1690, getConvexHttpClientAuth currently returns an empty
string when tokens are missing; update all callers (at minimum examples
user-info.ts and server/page.tsx and any E2E tests) to treat "" as a
missing-auth condition: after calling getConvexHttpClientAuth, check if the
returned string is empty and either throw a descriptive error (e.g., "No auth
token available; please sign in") or call clearAuth() instead of calling
setAuth("") so the backend won’t silently reject requests; make the same
explicit handling in tests (assert that callers throw or call clearAuth) and
update any example flows to show the correct behavior.

const session = await this._getSession(options.tokenStore);
const tokens = await session.getOrFetchLikelyValidTokens(20_000);
return tokens?.accessToken.token ?? throwErr("No access token available");
return tokens?.accessToken.token ?? "";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return tokens?.accessToken.token ?? "";
return tokens?.accessToken.token ?? throwErr("No access token available");

Changed error handling behavior from throwing an error to returning empty string when no access token is available, which can cause silent failures in server-side authentication.

View Details

Analysis

Silent authentication failure in getConvexHttpClientAuth() method

What fails: getConvexHttpClientAuth() in packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts returns empty string instead of throwing error when no access token is available, causing silent authentication failures

How to reproduce:

  1. Call stackServerApp.getConvexHttpClientAuth({ tokenStore: "nextjs-cookie" }) when user is not authenticated
  2. Method returns "" instead of throwing error
  3. Empty string is passed to convex.setAuth(token) in server-side code like examples/convex/app/server/page.tsx
  4. Subsequent convex.query() calls operate without authentication instead of failing explicitly

Result: Authentication failures become silent - instead of clear error indicating missing token, Convex receives empty string and treats user as unauthenticated without obvious indication

Expected: Method should throw clear error "No access token available" as originally implemented, making authentication issues immediately apparent for debugging

Evidence: Git commit 6d0bab553ff198ec97e6ad70e2322bda4fa2dc15 changed behavior from throwErr("No access token available") to return "" on 2025-10-10

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
examples/convex/convex/myActions.ts (2)

18-18: Remove redundant optional chaining.

Line 18 uses optional chaining (partialUser?.id) after already checking !partialUser on Line 15. The optional chaining is redundant since partialUser is guaranteed to be non-null at this point.

Apply this diff:

-    const user = await stackServerApp.getUser(partialUser?.id);
+    const user = await stackServerApp.getUser(partialUser.id);

22-25: Add explicit return value and error handling.

The action currently:

  1. Returns undefined implicitly after a successful metadata update, which may confuse callers
  2. Lacks error handling for the setClientReadOnlyMetadata call, which could throw

Consider returning a success indicator and wrapping the update in try-catch.

Apply this diff:

-    await user.setClientReadOnlyMetadata({
-      test: args.testMetadata,
-    })
+    try {
+      await user.setClientReadOnlyMetadata({
+        test: args.testMetadata,
+      });
+      return { success: true };
+    } catch (error) {
+      console.error("Failed to update metadata:", error);
+      return { success: false, error: String(error) };
+    }
   },
 });
examples/convex/app/action/page.tsx (2)

22-22: Add label for accessibility.

The input field lacks an associated label, which impacts keyboard navigation and screen reader users.

Apply this diff to add a label:

+      <label htmlFor="metadata-input" className="text-sm font-medium">Test Metadata</label>
-      <input type="text" placeholder="test 123" className="border border-slate-300 rounded-md p-2" onChange={(e) => setData(e.target.value)} />
+      <input id="metadata-input" type="text" placeholder="test 123" className="border border-slate-300 rounded-md p-2" onChange={(e) => setData(e.target.value)} />

23-31: Add error handling and improve UX.

The button click handler has several issues:

  1. No error handling for the action call—failures will silently break the flow
  2. Using alert() interrupts the user experience
  3. Requiring a manual refresh to see changes is suboptimal
  4. Button text "My Action" is not descriptive of what it does

Apply this diff:

+      const [isUpdating, setIsUpdating] = useState(false);
+      const [message, setMessage] = useState<string | null>(null);
+
       <button
         className="bg-foreground text-background text-sm px-4 py-2 rounded-md"
+        disabled={isUpdating}
         onClick={async () => {
-          await myAction({ testMetadata: data ?? "" })
-          alert("User's client read-only metadata updated, refresh to see changes")
+          setIsUpdating(true);
+          setMessage(null);
+          try {
+            await myAction({ testMetadata: data ?? "" });
+            setMessage("Metadata updated successfully!");
+            // Optionally trigger a user refetch here instead of requiring manual refresh
+          } catch (error) {
+            setMessage(`Failed to update metadata: ${error}`);
+          } finally {
+            setIsUpdating(false);
+          }
         }}
       >
-        My Action
+        {isUpdating ? "Updating..." : "Update Metadata"}
       </button>
+      {message && <div className="text-sm">{message}</div>}

Note: You'll need to add the state declarations near the top of the component (after line 11).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e28cd2 and 18fd2ea.

⛔ Files ignored due to path filters (1)
  • examples/convex/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (4)
  • examples/convex/app/action/page.tsx (1 hunks)
  • examples/convex/app/page.tsx (3 hunks)
  • examples/convex/convex/myActions.ts (1 hunks)
  • examples/convex/convex/myFunctions.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/convex/app/page.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • examples/convex/convex/myActions.ts
  • examples/convex/app/action/page.tsx
  • examples/convex/convex/myFunctions.ts
🧬 Code graph analysis (1)
examples/convex/app/action/page.tsx (1)
examples/convex/convex/myActions.ts (1)
  • myAction (8-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: all-good
  • GitHub Check: docker
  • GitHub Check: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test
  • GitHub Check: Security Check
🔇 Additional comments (4)
examples/convex/convex/myFunctions.ts (1)

1-1: LGTM! Clean refactoring.

The action has been successfully moved to examples/convex/convex/myActions.ts, and the remaining code in this file is unaffected.

examples/convex/convex/myActions.ts (1)

1-1: LGTM! Correct Convex directive.

The "use node" directive properly configures this action to run in a Node.js environment, which is required for server-side operations.

examples/convex/app/action/page.tsx (2)

1-11: LGTM! Proper setup.

The imports and hook setup are correct. The useUser({ or: "redirect" }) properly handles unauthenticated users by redirecting them.


16-21: LGTM! Clear metadata display.

The JSON display of user metadata is appropriate for an example/demo page.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e28cd2 and 18fd2ea.

⛔ Files ignored due to path filters (1)
  • examples/convex/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (4)
  • examples/convex/app/action/page.tsx (1 hunks)
  • examples/convex/app/page.tsx (3 hunks)
  • examples/convex/convex/myActions.ts (1 hunks)
  • examples/convex/convex/myFunctions.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • examples/convex/app/page.tsx
  • examples/convex/convex/myFunctions.ts
  • examples/convex/app/action/page.tsx
  • examples/convex/convex/myActions.ts
🧬 Code graph analysis (2)
examples/convex/app/page.tsx (2)
examples/convex/convex/myFunctions.ts (1)
  • getUserInfo (11-16)
examples/convex/app/user-info.ts (2)
  • getUserInfoConvexHttpClient (7-12)
  • getUserInfoConvexClient (18-21)
examples/convex/app/action/page.tsx (1)
examples/convex/convex/myActions.ts (1)
  • myAction (8-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: all-good
  • GitHub Check: docker
  • GitHub Check: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test
  • GitHub Check: Security Check

@BilalG1 BilalG1 requested a review from N2D4 October 10, 2025 21:28
@BilalG1 BilalG1 assigned N2D4 and unassigned BilalG1 Oct 10, 2025
@zeropath-ai
Copy link

zeropath-ai bot commented Oct 13, 2025

Some new issue(s) might be present. Please use the following link(s) to view them:

https://zeropath.com/app/issues/1a7b42f8-5231-4c05-8d3d-5fd1a5b5a776

Reply to this PR with @zeropath-ai followed by a description of what change you want and we'll auto-submit a change to this PR to implement it.

@zeropath-ai
Copy link

zeropath-ai bot commented Oct 14, 2025

Some new issue(s) might be present. Please use the following link(s) to view them:

https://zeropath.com/app/issues/2aa8dc50-d495-4b5e-af04-00de81c9f444

Reply to this PR with @zeropath-ai followed by a description of what change you want and we'll auto-submit a change to this PR to implement it.

@zeropath-ai
Copy link

zeropath-ai bot commented Oct 14, 2025

Some new issue(s) might be present. Please use the following link(s) to view them:

https://zeropath.com/app/issues/62135586-dd4d-4e9a-9ba4-7aa774bffe33

Reply to this PR with @zeropath-ai followed by a description of what change you want and we'll auto-submit a change to this PR to implement it.

@github-actions github-actions bot assigned BilalG1 and unassigned N2D4 Oct 15, 2025
@BilalG1 BilalG1 merged commit 91d8c16 into dev Oct 15, 2025
17 of 19 checks passed
@BilalG1 BilalG1 deleted the convex-full-example branch October 15, 2025 22:50
N2D4 added a commit that referenced this pull request Oct 16, 2025
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

<!-- RECURSEML_SUMMARY:START -->
## High-level PR Summary
This PR fixes dependency management issues by adding the missing
`wait-on` package to the Convex example's dependencies, reorganizing the
dependency order in `package.json` for consistency, and regenerating the
`pnpm-lock.yaml` file to ensure proper dependency resolution across the
monorepo.

⏱️ Estimated Review Time: 5-15 minutes

<details>
<summary>💡 Review Order Suggestion</summary>

| Order | File Path |
|-------|-----------|
| 1 | `examples/convex/package.json` |
| 2 | `pnpm-lock.yaml` |
</details>



[![Need help? Join our
Discord](https://img.shields.io/badge/Need%20help%3F%20Join%20our%20Discord-5865F2?style=plastic&logo=discord&logoColor=white)](https://discord.gg/n3SsVDAW6U)


[![Analyze latest
changes](https://img.shields.io/badge/Analyze%20latest%20changes-238636?style=plastic)](https://squash-322339097191.europe-west3.run.app/interactive/c932fc0941a3f377a683c72390f091ad3b2c120001b7b49eaf2bab337e1efadc/?repo_owner=stack-auth&repo_name=stack-auth&pr_number=943)
<!-- RECURSEML_SUMMARY:END -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added UI buttons to view user info via different clients, a
server-side user info section, and an Action page to view/submit updates
to user metadata.
- Added a server-side action to update a user's client-read-only
metadata.

- **Documentation**
  - In-app link and guidance to the Action route for updating user data.

- **Chores**
- Updated project dependencies/devDependencies and added .env.local to
.gitignore.

- **Bug Fixes**
  - Token-missing scenario now handled gracefully instead of throwing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konsti Wohlwend <[email protected]>
@coderabbitai coderabbitai bot mentioned this pull request Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants