as enabled/disabled based on this value
```
```typescript
// --- Client usage (native) ---
const openaiKeySet = useQuery(api.openai.openaiKeySet) ?? false;
// Disables the summarization checkbox when false
{isAdvancedSummarizationEnabled && }
```
--------------------------------
### Use a Convex Mutation Function in React
Source: https://github.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/blob/main/packages/backend/convex/README.md
Shows how to call a Convex mutation function from a React component using the `useMutation` hook. Mutations can be fired and forgotten or their results can be awaited.
```typescript
const mutation = useMutation(api.functions.myMutationFunction);
function handleButtonPress() {
// fire and forget, the most common way to use mutations
mutation({ first: "Hello!", second: "me" });
// OR
// use the result once the mutation has completed
mutation({ first: "Hello!", second: "me" }).then((result) =>
console.log(result),
);
}
```
--------------------------------
### api.notes.getNote
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Fetches a single note by its ID. Returns the note document if it belongs to the authenticated user, or null if the note does not exist, the ID is invalid, or the user does not own it.
```APIDOC
## Query: api.notes.getNote
### Description
Fetches a single note by its ID. Returns the note document if it belongs to the authenticated user, or null if the note does not exist, the ID is invalid, or the user does not own it.
### Parameters
#### Arguments
- **id** (string) - Optional - The ID of the note to fetch.
### Handler
```typescript
// packages/backend/convex/notes.ts
import { query } from "./_generated/server";
import { v } from "convex/values";
export const getNote = query({
args: {
id: v.optional(v.string()),
},
handler: async (ctx, args) => {
const { id } = args;
if (!id) return null;
const normalizedId = ctx.db.normalizeId("notes", id); // validates Id format
if (!normalizedId) return null;
const userId = await getUserId(ctx);
if (!userId) return null;
const note = await ctx.db.get(normalizedId);
if (!note || note.userId !== userId) return null; // ownership check
return note; // Doc<"notes"> | null
},
});
```
### Client Usage (Web)
```typescript
// packages/backend/convex/_generated/api
import { useQuery } from "convex/react";
import { api } from "@packages/backend/convex/_generated/api";
import { Id } from "@packages/backend/convex/_generated/dataModel";
const NoteDetails = ({ noteId }: { noteId: Id<"notes"> }) => {
const note = useQuery(api.notes.getNote, { id: noteId });
// note is undefined (loading) | null (not found/unauthed) | Doc<"notes">
return {note?.content ?? "Loading…"}
;
};
```
### Client Usage (Native)
```typescript
// packages/backend/convex/_generated/api
const { noteId } = useLocalSearchParams<{ noteId: string }>();
const note = useQuery(api.notes.getNote, { id: noteId ?? undefined });
const displayText =
activeTab === "original"
? note?.content
: note?.summary ?? "No summary available";
```
```
--------------------------------
### Convex Query: Fetch Single Note by ID
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Fetches a single note by its ID from the Convex backend. It validates the ID format, checks user ownership, and returns the note document or null if not found, invalid, or unauthorized.
```typescript
import { query } from "./_generated/server";
import { v } from "convex/values";
export const getNote = query({
args: {
id: v.optional(v.string()),
},
handler: async (ctx, args) => {
const { id } = args;
if (!id) return null;
const normalizedId = ctx.db.normalizeId("notes", id); // validates Id format
if (!normalizedId) return null;
const userId = await getUserId(ctx);
if (!userId) return null;
const note = await ctx.db.get(normalizedId);
if (!note || note.userId !== userId) return null; // ownership check
return note; // Doc<"notes"> | null
},
});
```
```typescript
import { useQuery } from "convex/react";
import { api } from "@packages/backend/convex/_generated/api";
import { Id } from "@packages/backend/convex/_generated/dataModel";
const NoteDetails = ({ noteId }: { noteId: Id<"notes"> }) => {
const note = useQuery(api.notes.getNote, { id: noteId });
// note is undefined (loading) | null (not found/unauthed) | Doc<"notes">
return {note?.content ?? "Loading…"}
;
};
```
```typescript
const { noteId } = useLocalSearchParams<{ noteId: string }>();
const note = useQuery(api.notes.getNote, { id: noteId ?? undefined });
const displayText =
activeTab === "original"
? note?.content
: note?.summary ?? "No summary available";
```
--------------------------------
### Configure Clerk JWT Provider for Convex
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Configuration for Clerk as a JWT provider in Convex. Requires CLERK_JWT_ISSUER_DOMAIN environment variable.
```typescript
// packages/backend/convex/auth.config.ts — configure Clerk as JWT provider
import { type AuthConfig } from "convex/server";
export default {
providers: [
{
domain: process.env.CLERK_JWT_ISSUER_DOMAIN, // e.g. https://xxx.clerk.accounts.dev
applicationID: "convex",
},
],
} satisfies AuthConfig;
```
--------------------------------
### Convex Database Schema Definition
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Defines the 'notes' table schema for the Convex backend, including fields for userId, title, content, and an optional summary. It includes an index for efficient per-user queries.
```typescript
import {
defineSchema,
defineTable,
} from "convex/server";
import { v } from "convex/values";
export default defineSchema({
notes: defineTable({
userId: v.string(), // Clerk subject identifier
title: v.string(),
content: v.string(),
summary: v.optional(v.string()), // Populated by OpenAI action
}).index("by_userId", ["userId"]),
});
```
--------------------------------
### Native OAuth Sign-In with Clerk Expo
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Initiates OAuth flows for Google and Apple using Clerk's useSSO hook in an Expo app. Redirects to the main app route upon successful session activation.
```typescript
import { useSSO } from "@clerk/clerk-expo";
import { useRouter } from "expo-router";
type OAuthStrategy = "oauth_google" | "oauth_apple";
const LoginScreen = () => {
const { startSSOFlow } = useSSO();
const router = useRouter();
const onPress = async ({ strategy }: { strategy: OAuthStrategy }) => {
try {
const { createdSessionId, setActive } = await startSSOFlow({ strategy });
if (!createdSessionId || !setActive) return;
await setActive({ session: createdSessionId });
router.replace("/"); // navigate to authenticated dashboard
} catch (err) {
const message = String(err);
if (message.includes("already signed in")) return;
console.error("OAuth error", err);
}
};
return (
<>
onPress({ strategy: "oauth_google" })}>
Continue with Google
onPress({ strategy: "oauth_apple" })}>
Continue with Apple
>
);
};
```
--------------------------------
### Set Convex JWT Issuer Domain
Source: https://github.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/blob/main/README.md
Configure the Clerk JWT issuer domain in your Convex environment variables. This is crucial for authentication between Clerk and Convex.
```sh
CLERK_JWT_ISSUER_DOMAIN=https://your-frontend-api.clerk.accounts.dev
```
--------------------------------
### api.notes.deleteNote
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Permanently deletes a note after verifying ownership. Throws errors if the note is not found or not owned by the user.
```APIDOC
## api.notes.deleteNote — Mutation: delete a note
### Description
Permanently deletes a note after verifying it exists and is owned by the calling user. Throws descriptive errors if the note is not found or if the user does not own it.
### Arguments
- **noteId** (Id<"notes">) - Required - The ID of the note to delete.
### Client Usage Example
```typescript
const deleteNote = useMutation(api.notes.deleteNote);
await deleteNote({ noteId: "someNoteId" });
```
```
--------------------------------
### Delete Note Mutation
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Permanently deletes a note after verifying ownership. Throws errors if the note is not found or not owned by the user.
```typescript
// packages/backend/convex/notes.ts
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const deleteNote = mutation({
args: {
noteId: v.id("notes"), // strongly-typed Convex ID
},
handler: async (ctx, { noteId }) => {
const userId = await requireUserId(ctx);
const note = await ctx.db.get(noteId);
if (!note) throw new Error(`Note '${noteId}' could not be found`);
if (note.userId !== userId)
throw new Error(`User '${userId}' cannot delete note '${noteId}'`);
await ctx.db.delete(noteId);
},
});
```
```typescript
// --- Client usage (web, in Notes component) ---
const deleteNote = useMutation(api.notes.deleteNote);
// Passed down to NoteItem → DeleteNote dialog
deleteNote({ noteId: note._id })} />
```
```typescript
// --- Client usage (native) ---
// Triggered from a swipe-to-delete or button press
await deleteNote({ noteId: someNoteId });
```
--------------------------------
### Define a Convex Mutation Function
Source: https://github.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/blob/main/packages/backend/convex/README.md
Use this to define a mutation function that writes data to the database. It requires argument validators and an async handler.
```typescript
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const myMutationFunction = mutation({
// Validators for arguments.
args: {
first: v.string(),
second: v.string(),
},
// Function implementation.
handler: async (ctx, args) => {
// Insert or modify documents in the database here.
// Mutations can also read from the database like queries.
// See https://docs.convex.dev/database/writing-data.
const message = { body: args.first, author: args.second };
const id = await ctx.db.insert("messages", message);
// Optionally, return a value from your mutation.
return await ctx.db.get(id);
},
});
```
--------------------------------
### Define a Convex Query Function
Source: https://github.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/blob/main/packages/backend/convex/README.md
Use this to define a query function that reads data from the database. It requires argument validators and an async handler.
```typescript
import { query } from "./_generated/server";
import { v } from "convex/values";
export const myQueryFunction = query({
// Validators for arguments.
args: {
first: v.number(),
second: v.string(),
},
// Function implementation.
handler: async (ctx, args) => {
// Read the database as many times as you need here.
// See https://docs.convex.dev/database/reading-data.
const documents = await ctx.db.query("tablename").collect();
// Arguments passed from the client are properties of the args object.
console.log(args.first, args.second);
// Write arbitrary JavaScript here: filter, aggregate, build derived data,
// remove non-public properties, or create new objects.
return documents;
},
});
```
--------------------------------
### Native Route Guard with Expo Router
Source: https://context7.com/get-convex/turbo-expo-nextjs-clerk-convex-monorepo/llms.txt
Protects the '(app)' route group in Expo Router by redirecting unauthenticated users to the '/sign-in' route. Ensures Clerk is loaded before checking authentication status.
```typescript
import { useAuth } from "@clerk/clerk-expo";
import { Redirect, Stack } from "expo-router";
export default function AppLayout() {
const { isLoaded, isSignedIn } = useAuth();
if (!isLoaded) return null; // wait for Clerk to initialize
if (!isSignedIn) return ;
return ;
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.