@@ -29,25 +29,80 @@ import {
2929 Inbox ,
3030} from "lucide-react"
3131import { type SidebarData } from "./types"
32- import { useUser } from "@clerk/clerk-react"
3332import { useQuery } from "convex/react"
3433import { api } from "convex/_generated/api"
3534import type { Doc } from "convex/_generated/dataModel"
3635
36+ const clerkPublishableKey = import . meta. env . VITE_CLERK_PUBLISHABLE_KEY
37+
38+ // Conditionally import useUser - only if Clerk is configured
39+ // This avoids bundling Clerk if not needed, but we must handle SSR
40+ let useUserHook : ( ( ) => { user : any } | null ) | null = null
41+ if ( clerkPublishableKey && typeof window !== "undefined" ) {
42+ try {
43+ // eslint-disable-next-line @typescript-eslint/no-var-requires
44+ const clerkReact = require ( "@clerk/clerk-react" )
45+ useUserHook = clerkReact . useUser
46+ } catch {
47+ // Clerk not available
48+ }
49+ }
50+
3751// Helper hook to get user data from Clerk
52+ // Note: This hook should only be called on the client side (after mount)
53+ // to avoid SSR issues with ClerkProvider. AppSidebar ensures this.
3854function useSidebarUser ( ) {
39- const { user } = useUser ( )
55+ // Check if Convex is configured before calling useQuery
56+ const convexUrl = import . meta. env . VITE_CONVEX_URL
57+ if ( ! convexUrl ) {
58+ return {
59+ name : "User" ,
60+ email : "" ,
61+ avatar : "" ,
62+ }
63+ }
64+
65+ // useQuery will throw if ConvexProvider isn't available
66+ // We can't catch this, so the caller must handle it
4067 const convexUser = useQuery ( api . users . getCurrent )
4168
69+ // If Clerk is not configured or not available, only use Convex user
70+ if ( ! useUserHook ) {
71+ return {
72+ name : convexUser ?. name || "User" ,
73+ email : "" ,
74+ avatar : "" ,
75+ }
76+ }
77+
78+ // Always call the hook if it's available (React rules require unconditional calls)
79+ // This will throw if not in ClerkProvider, but AppSidebar only calls this on client
80+ // where ClerkProvider should be available
81+ const { user : clerkUser } = useUserHook ( )
82+
4283 return {
43- name : user ?. firstName || convexUser ?. name || user ?. fullName || user ?. primaryEmailAddress ?. emailAddress ?. split ( "@" ) [ 0 ] || "User" ,
44- email : user ?. primaryEmailAddress ?. emailAddress || "" ,
45- avatar : user ?. imageUrl || "" ,
84+ name : clerkUser ?. firstName || convexUser ?. name || clerkUser ?. fullName || clerkUser ?. primaryEmailAddress ?. emailAddress ?. split ( "@" ) [ 0 ] || "User" ,
85+ email : clerkUser ?. primaryEmailAddress ?. emailAddress || "" ,
86+ avatar : clerkUser ?. imageUrl || "" ,
4687 }
4788}
4889
4990// Helper hook to get organizations from Clerk
5091function useSidebarTeams ( ) {
92+ // Check if Convex is configured before calling useQuery
93+ const convexUrl = import . meta. env . VITE_CONVEX_URL
94+ if ( ! convexUrl ) {
95+ return [
96+ {
97+ name : "StackDock" ,
98+ logo : Building2 ,
99+ plan : "Free" ,
100+ } ,
101+ ]
102+ }
103+
104+ // useQuery will throw if ConvexProvider isn't available
105+ // We can't catch this, so the caller must handle it
51106 const organizations = useQuery ( api . organizations . list )
52107
53108 if ( ! organizations || organizations . length === 0 ) {
@@ -68,6 +123,17 @@ function useSidebarTeams() {
68123}
69124
70125export function useSidebarData ( ) : SidebarData {
126+ // Check if Convex is configured
127+ const convexUrl = import . meta. env . VITE_CONVEX_URL
128+
129+ // If Convex is not configured, return static data
130+ if ( ! convexUrl ) {
131+ return sidebarData
132+ }
133+
134+ // Try to use hooks, but fall back to static data if ConvexProvider isn't available
135+ // Note: We can't wrap hooks in try-catch, so if useQuery throws, it will propagate
136+ // The component using this hook should handle the error or ensure ConvexProvider is available
71137 const user = useSidebarUser ( )
72138 const teams = useSidebarTeams ( )
73139
0 commit comments