The boilerplate in platform documentation for OSDK apps is missing an example of a basic login flow that will work in NextJS apps. I have seen a NextJS example out there in Palantir’s open source projects, but I could not find it. The last time I saw the example though it was for an SPA. Many React apps today use NextJS for its server capabilities. So, I created a boilerplate example that works.
import { Client, createClient, Osdk } from '@osdk/client';
import { createPublicOauthClient } from '@osdk/oauth';
import { useCallback, useEffect, useState } from 'react';
import { User, Users } from '@osdk/foundry.admin';
// setup the OSDK
const clientId = process.env['NEXT_PUBLIC_OSDK_CLIENT_ID'];
const url = process.env['NEXT_PUBLIC_FOUNDRY_STACK_URL'];
const ontologyRid = process.env['NEXT_PUBLIC_ONTOLOGY_RID'];
const redirectUrl = window.location.href.split('?')[0].replace(/\/+$/, '');
const scopes: string[] = [
'api:use-ontologies-read',
'api:use-ontologies-write',
'api:use-admin-read',
'api:use-connectivity-read',
'api:use-connectivity-execute',
'api:use-mediasets-read',
'api:use-mediasets-write',
];
const auth = createPublicOauthClient(
clientId!,
url!,
redirectUrl,
true,
undefined,
window.location.toString(),
scopes,
);
const client: Client = createClient(url!, ontologyRid!, auth);
export default function App() {
const [user, setUser] = useState<User | null>(null);
const singOut = useCallback(async () => {
await auth.signOut();
window.location.reload();
}, [auth]);
const singIn = useCallback(async () => {
try {
await auth.signIn();
} catch (error) {
console.error('Sign-in error:', error);
}
}, [auth]);
const getUserDetails = useCallback(async () => {
try {
const user: User = await Users.getCurrent(client);
setUser(user);
console.log('Current User:', user);
} catch (error) {
console.error('Error fetching user details:', error);
}
}, []);
useEffect(() => {
getUserDetails();
}, [getUserDetails]);
return (
<div>
{user ? (
<>
<p>Current logged in user: {user.email}</p>
<button onClick={singOut}>Sign Out</button>
</>
) : (
<>
<p>Welcome! Please sign in to continue.</p>
<button onClick={singIn}>Sign In</button>
</>
)}
</div>
);
}
IMPORTANT: to make this work without putting use client all over the place and dealing with window is undefined errors use a dynamic import. Let’s assume the code above is in JibDashboard. To use do:
'use client';
import dynamic from 'next/dynamic';
// important, OSDK is client side only! This prevents use client all over the place
// and ensures we don't get window undefined errors and the like
const JibDashboard = dynamic(() => import('./JibDashboard'), { ssr: false });
export default function JibClient() {
return <JibDashboard />;
}
It would be great to have a first class login example so users can customize login/logout. This is the most common thing developers need to do in OSDK apps IMO.