Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,3 @@ WORKOS_CLIENT_ID=client_your_client_id_here
WORKOS_API_KEY=sk_test_your_api_key_here
WORKOS_COOKIE_PASSWORD=your_secure_password_here_must_be_at_least_32_characters_long
NEXT_PUBLIC_WORKOS_REDIRECT_URI=http://localhost:3000/callback

# Convex Configuration
NEXT_PUBLIC_CONVEX_URL=https://your-convex-url.convex.cloud
CONVEX_DEPLOY_KEY=your_convex_deploy_key_here
6 changes: 1 addition & 5 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ function Content() {
const addNumber = useMutation(api.myFunctions.addNumber);

if (viewer === undefined || numbers === undefined) {
return (
<div className="mx-auto">
<p>loading... (consider a loading skeleton)</p>
</div>
);
return <div className="mx-auto"></div>;
}

return (
Expand Down
2 changes: 1 addition & 1 deletion app/server/inner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function Home({ preloaded }: { preloaded: Preloaded<typeof api.my
return (
<>
<div className="flex flex-col gap-4 bg-slate-200 dark:bg-slate-800 p-4 rounded-md">
<h2 className="text-xl font-bold">Reactive client-loaded data</h2>
<h2 className="text-xl font-bold">Reactive client-loaded data (using server data during hydration)</h2>
<code>
<pre>{JSON.stringify(data, null, 2)}</pre>
</code>
Expand Down
12 changes: 9 additions & 3 deletions app/server/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import Home from './inner';
import { preloadQuery, preloadedQueryResult } from 'convex/nextjs';
import { api } from '@/convex/_generated/api';
import { withAuth } from '@workos-inc/authkit-nextjs';

export default async function ServerPage() {
const preloaded = await preloadQuery(api.myFunctions.listNumbers, {
count: 3,
});
const { accessToken } = await withAuth();
Copy link

Choose a reason for hiding this comment

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

Is this call to withAuth essentially instant since we already authenticated in the middleware.ts? Or does this make a server round trip, meaning we have a round trip in middleware followed by a second round trip here (on an already authenticated route)?

If it is the latter, would it make sense for us to switch the middleware.ts to page based auth instead of the current middleware auth? Middleware documentation.

Copy link
Member

Choose a reason for hiding this comment

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

Great question! the withAuth() call is essentially instant. It reads the session from a header that the middleware already set. There's no additional authentication or API call happening.

Copy link

Choose a reason for hiding this comment

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

Ooh sweet. Thanks for the info!

const preloaded = await preloadQuery(
api.myFunctions.listNumbers,
{
count: 3,
},
{ token: accessToken },
);

const data = preloadedQueryResult(preloaded);

Expand Down
12 changes: 7 additions & 5 deletions components/ConvexClientProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use client';

import { ReactNode, useCallback, useRef } from 'react';
import { ReactNode, useCallback, useRef, useState } from 'react';
import { ConvexReactClient } from 'convex/react';
import { ConvexProviderWithAuth } from 'convex/react';
import { AuthKitProvider, useAuth, useAccessToken } from '@workos-inc/authkit-nextjs/components';

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: ReactNode }) {
const [convex] = useState(() => {
return new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
});
return (
<AuthKitProvider>
<ConvexProviderWithAuth client={convex} useAuth={useAuthFromAuthKit}>
Expand All @@ -20,8 +21,9 @@ export function ConvexClientProvider({ children }: { children: ReactNode }) {
function useAuthFromAuthKit() {
const { user, loading: isLoading } = useAuth();
const { accessToken, loading: tokenLoading, error: tokenError } = useAccessToken();
const loading = (isLoading ?? false) || (tokenLoading ?? false) || !accessToken;
const authenticated = !!user && !!accessToken && !loading;
const hasIncompleteAuth = (!!user && !accessToken) || (!user && !!accessToken);
const loading = (isLoading ?? false) || (tokenLoading ?? false) || hasIncompleteAuth;
const authenticated = !!user && !!accessToken;

// Memoize the token to prevent unnecessary changes
const stableAccessToken = useRef<string | null>(null);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"format": "prettier --write ."
},
"dependencies": {
"@workos-inc/authkit-nextjs": "^2.4.4",
"convex": "^1.25.4",
"@workos-inc/authkit-nextjs": "^2.6.0",
"convex": "^1.26.2",
"next": "15.4.3",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Expand Down