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
92 changes: 42 additions & 50 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,56 +26,48 @@ const queryClient = new QueryClient();
const App = () => (
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
<AuthErrorBoundary>
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<div className="min-h-screen bg-background">
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
{/* Public routes - no auth required */}
<Route path="/" element={<Index />} />
<Route path="/auth/callback" element={<AuthCallback />} />
<Route path="/pricing" element={<Pricing />} />
<Route path="/checkout" element={<CheckoutPage />} />
<Route path="/terms" element={<TermsOfService />} />
<Route path="/privacy" element={<PrivacyPolicy />} />

{/* Protected routes - auth required */}
<Route path="/chat" element={
<UserSync>
<AuthWrapper>
<AuthGuard>
<Chat />
</AuthGuard>
</AuthWrapper>
</UserSync>
} />
<Route path="/settings" element={
<UserSync>
<AuthWrapper>
<AuthGuard>
<Settings />
</AuthGuard>
</AuthWrapper>
</UserSync>
} />
<Route path="/success" element={
<UserSync>
<AuthWrapper>
<AuthGuard>
<Success />
</AuthGuard>
</AuthWrapper>
</UserSync>
} />
</Routes>
</BrowserRouter>
</div>
</TooltipProvider>
</QueryClientProvider>
</trpc.Provider>
<UserSync>
<AuthWrapper>
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<div className="min-h-screen bg-background">
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
{/* Public routes - no auth required */}
<Route path="/" element={<Index />} />
<Route path="/auth/callback" element={<AuthCallback />} />
<Route path="/pricing" element={<Pricing />} />
<Route path="/checkout" element={<CheckoutPage />} />
<Route path="/terms" element={<TermsOfService />} />
<Route path="/privacy" element={<PrivacyPolicy />} />

{/* Protected routes - auth required */}
<Route path="/chat" element={
<AuthGuard>
<Chat />
</AuthGuard>
} />
<Route path="/settings" element={
<AuthGuard>
<Settings />
</AuthGuard>
} />
<Route path="/success" element={
<AuthGuard>
<Success />
</AuthGuard>
} />
</Routes>
</BrowserRouter>
</div>
</TooltipProvider>
</QueryClientProvider>
</trpc.Provider>
</AuthWrapper>
</UserSync>
</AuthErrorBoundary>
</ConvexProviderWithClerk>
);
Expand Down
11 changes: 9 additions & 2 deletions src/lib/convex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import { ConvexReactClient } from "convex/react";
const convexUrl = import.meta.env.VITE_CONVEX_URL;

if (!convexUrl) {
throw new Error("VITE_CONVEX_URL environment variable is not set");
console.warn("⚠️ Missing Convex URL - Database will be disabled");
console.log("💡 To enable database:");
console.log(" 1. Get a Convex deployment URL from: https://dashboard.convex.dev");
console.log(" 2. Add VITE_CONVEX_URL=https://your-app.convex.cloud to .env.local");
console.log(" 3. Restart the development server");
}

export const convex = new ConvexReactClient(convexUrl);
// Create a mock client for development when URL is missing
export const convex = convexUrl
? new ConvexReactClient(convexUrl)
: new ConvexReactClient("https://mock-convex-url.convex.cloud"); // Mock URL for development
102 changes: 82 additions & 20 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@

const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
if (!PUBLISHABLE_KEY) {
throw new Error("Missing Clerk Publishable Key - Check your environment configuration");
console.warn("⚠️ Missing Clerk Publishable Key - Authentication will be disabled");
console.log("💡 To enable authentication:");
console.log(" 1. Get a Clerk key from: https://dashboard.clerk.com");
console.log(" 2. Add VITE_CLERK_PUBLISHABLE_KEY=pk_test_... to .env.local");
console.log(" 3. Restart the development server");
}

// Security validation for production - temporarily disabled for development
Expand All @@ -76,27 +80,85 @@
}
};

// Fallback component when authentication is not configured
const UnauthenticatedApp = () => (
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 flex items-center justify-center p-4">
<div className="max-w-md w-full space-y-6 text-center">
<div className="space-y-4">
<div className="w-16 h-16 mx-auto bg-gradient-to-br from-blue-500 to-purple-600 rounded-xl flex items-center justify-center">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
</div>
<h1 className="text-3xl font-bold text-white">ZapDev AI Platform</h1>
<p className="text-slate-300 text-lg">Authentication Setup Required</p>
</div>

<div className="bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-lg p-6 space-y-4 text-left">
<h2 className="text-xl font-semibold text-white">Quick Setup:</h2>
<div className="space-y-3 text-sm text-slate-300">
<div className="flex items-start gap-3">
<span className="flex-shrink-0 w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-bold">1</span>
<div>
<p className="text-white font-medium">Get Clerk API Key</p>
<p>Visit <code className="bg-slate-700 px-1 rounded">dashboard.clerk.com</code></p>
</div>
</div>
<div className="flex items-start gap-3">
<span className="flex-shrink-0 w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-bold">2</span>
<div>
<p className="text-white font-medium">Get Convex URL</p>
<p>Visit <code className="bg-slate-700 px-1 rounded">dashboard.convex.dev</code></p>
</div>
</div>
<div className="flex items-start gap-3">
<span className="flex-shrink-0 w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-bold">3</span>
<div>
<p className="text-white font-medium">Update .env.local</p>
<code className="block bg-slate-700 p-2 rounded mt-1 text-xs">
VITE_CLERK_PUBLISHABLE_KEY=pk_test_...<br/>
VITE_CONVEX_URL=https://your-app.convex.cloud
</code>
</div>
</div>
</div>
</div>

<button
onClick={() => window.location.reload()}
className="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white font-semibold py-3 px-6 rounded-lg hover:from-blue-600 hover:to-purple-700 transition-all duration-200 shadow-lg hover:shadow-xl"
>
Refresh After Setup
</button>
</div>
</div>
);

root.render(
<StrictMode>
<PostHogProvider
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}
options={posthogOptions}
>
<ClerkProvider
publishableKey={PUBLISHABLE_KEY}
afterSignOutUrl="/"
fallbackRedirectUrl="/chat"
appearance={{
elements: {
formButtonPrimary: 'bg-primary hover:bg-primary/90',
card: 'bg-card border border-border',
},
}}
{PUBLISHABLE_KEY ? (
<PostHogProvider
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}
options={posthogOptions}
>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
<App />
</ConvexProviderWithClerk>
</ClerkProvider>
</PostHogProvider>
<ClerkProvider
publishableKey={PUBLISHABLE_KEY}
afterSignOutUrl="/"
fallbackRedirectUrl="/chat"
appearance={{
elements: {
formButtonPrimary: 'bg-primary hover:bg-primary/90',
card: 'bg-card border border-border',
},
}}
>
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
<App />
</ConvexProviderWithClerk>
</ClerkProvider>
</PostHogProvider>
) : (
<UnauthenticatedApp />
)}
</StrictMode>
);