Skip to main content
Glama
index.tsx5.77 kB
import { Link, createFileRoute } from '@tanstack/react-router'; import { Authenticated, Unauthenticated, useMutation } from 'convex/react'; import { useAuth } from '@workos/authkit-tanstack-react-start/client'; import { getAuth, getSignInUrl, getSignUpUrl } from '@workos/authkit-tanstack-react-start'; import { convexQuery } from '@convex-dev/react-query'; import { useSuspenseQuery } from '@tanstack/react-query'; import { api } from '../../convex/_generated/api'; import type { User } from '@workos/authkit-tanstack-react-start'; export const Route = createFileRoute('/')({ component: Home, loader: async () => { const { user } = await getAuth(); const signInUrl = await getSignInUrl(); const signUpUrl = await getSignUpUrl(); return { user, signInUrl, signUpUrl }; }, }); function Home() { const { user, signInUrl, signUpUrl } = Route.useLoaderData(); return <HomeContent user={user} signInUrl={signInUrl} signUpUrl={signUpUrl} />; } function HomeContent({ user, signInUrl, signUpUrl }: { user: User | null; signInUrl: string; signUpUrl: string }) { return ( <> <header className="sticky top-0 z-10 bg-background p-4 border-b-2 border-slate-200 dark:border-slate-800 flex flex-row justify-between items-center"> Convex + TanStack Start + WorkOS {user && <UserMenu user={user} />} </header> <main className="p-8 flex flex-col gap-8"> <h1 className="text-4xl font-bold text-center">Convex + TanStack Start + WorkOS</h1> <Authenticated> <Content /> </Authenticated> <Unauthenticated> <SignInForm signInUrl={signInUrl} signUpUrl={signUpUrl} /> </Unauthenticated> </main> </> ); } function SignInForm({ signInUrl, signUpUrl }: { signInUrl: string; signUpUrl: string }) { return ( <div className="flex flex-col gap-8 w-96 mx-auto"> <p>Log in to see the numbers</p> <a href={signInUrl}> <button className="bg-foreground text-background px-4 py-2 rounded-md">Sign in</button> </a> <a href={signUpUrl}> <button className="bg-foreground text-background px-4 py-2 rounded-md">Sign up</button> </a> </div> ); } function Content() { const { data: { viewer, numbers }, } = useSuspenseQuery( convexQuery(api.myFunctions.listNumbers, { count: 10, }), ); const addNumber = useMutation(api.myFunctions.addNumber); return ( <div className="flex flex-col gap-8 max-w-lg mx-auto"> <p>Welcome {viewer}!</p> <p> Click the button below and open this page in another window - this data is persisted in the Convex cloud database! </p> <p> <button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => { void addNumber({ value: Math.floor(Math.random() * 10) }); }} > Add a random number </button> </p> <p>Numbers: {numbers.length === 0 ? 'Click the button!' : numbers.join(', ')}</p> <p> Edit{' '} <code className="text-sm font-bold font-mono bg-slate-200 dark:bg-slate-800 px-1 py-0.5 rounded-md"> convex/myFunctions.ts </code>{' '} to change your backend </p> <p> Edit{' '} <code className="text-sm font-bold font-mono bg-slate-200 dark:bg-slate-800 px-1 py-0.5 rounded-md"> src/routes/index.tsx </code>{' '} to change your frontend </p> <p> See{' '} <Link to="/authenticated" className="underline hover:no-underline"> /authenticated </Link>{' '} for an example of a page only available to authenticated users. </p> <div className="flex flex-col"> <p className="text-lg font-bold">Useful resources:</p> <div className="flex gap-2"> <div className="flex flex-col gap-2 w-1/2"> <ResourceCard title="Convex docs" description="Read comprehensive documentation for all Convex features." href="https://docs.convex.dev/home" /> <ResourceCard title="Stack articles" description="Learn about best practices, use cases, and more from a growing collection of articles, videos, and walkthroughs." href="https://stack.convex.dev" /> </div> <div className="flex flex-col gap-2 w-1/2"> <ResourceCard title="Templates" description="Browse our collection of templates to get started quickly." href="https://www.convex.dev/templates" /> <ResourceCard title="Discord" description="Join our developer community to ask questions, trade tips & tricks, and show off your projects." href="https://www.convex.dev/community" /> </div> </div> </div> </div> ); } function ResourceCard({ title, description, href }: { title: string; description: string; href: string }) { return ( <div className="flex flex-col gap-2 bg-slate-200 dark:bg-slate-800 p-4 rounded-md h-28 overflow-auto"> <a href={href} className="text-sm underline hover:no-underline"> {title} </a> <p className="text-xs">{description}</p> </div> ); } function UserMenu({ user }: { user: User }) { const { signOut } = useAuth(); return ( <div className="flex items-center gap-2"> <span className="text-sm">{user.email}</span> <button onClick={() => signOut()} className="bg-red-500 text-white px-3 py-1 rounded-md text-sm hover:bg-red-600"> Sign out </button> </div> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server