From 33ec7b787ffd19d774c226f259074bde73f1dcfa Mon Sep 17 00:00:00 2001 From: Mark Henderson Date: Mon, 2 Mar 2026 19:22:13 -0800 Subject: [PATCH] Major cleanup: remove all dead pages and components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Components deleted (~27 files): - components/ai/ (9 files — collector, extraction, vision, phase sidebar) - components/assistant-ui/ (thread.tsx, markdown-text.tsx) - components/mission/, sidebar/, extension/, icons/ - layout/app-shell, left-rail, right-panel, connect-sources-modal, mcp-connect-modal, page-header, page-template, project-sidebar, workspace-left-rail, PAGE_TEMPLATE_GUIDE - chatgpt-import-card, mcp-connection-card, mcp-playground Project pages deleted (~20 dirs): - analytics, api-map, architecture, associate-sessions, audit, audit-test, automation, code, context, design-old, docs, features, getting-started, journey, market, mission, money, plan, product, progress, sandbox, sessions, tech, timeline-plan Workspace routes deleted (~12 dirs): - connections, costs, debug-projects, debug-sessions, keys, mcp, new-project, projects/new, test-api-key, test-auth, test-sessions, users Remaining: 5 components, 2 layout files, 8 project tabs, 3 workspace routes Made-with: Cursor --- app/[workspace]/connections/layout.tsx | 33 - app/[workspace]/connections/page.tsx | 360 ------- app/[workspace]/costs/layout.tsx | 34 - app/[workspace]/costs/page.tsx | 181 ---- app/[workspace]/debug-projects/page.tsx | 239 ----- app/[workspace]/debug-sessions/page.tsx | 279 ----- app/[workspace]/keys/layout.tsx | 34 - app/[workspace]/keys/page.tsx | 412 -------- app/[workspace]/mcp/page.tsx | 21 - app/[workspace]/new-project/new/layout.tsx | 8 - app/[workspace]/new-project/new/page.tsx | 506 --------- .../project/[projectId]/analytics/page.tsx | 179 ---- .../project/[projectId]/api-map/page.tsx | 74 -- .../project/[projectId]/architecture/page.tsx | 131 --- .../[projectId]/associate-sessions/page.tsx | 223 ---- .../project/[projectId]/audit-test/page.tsx | 17 - .../project/[projectId]/audit/page.tsx | 956 ------------------ .../project/[projectId]/automation/page.tsx | 69 -- .../project/[projectId]/code/page.tsx | 447 -------- .../project/[projectId]/context/page.tsx | 590 ----------- .../design-old/[pageSlug]/page.tsx | 633 ------------ .../project/[projectId]/design-old/page.tsx | 558 ---------- .../project/[projectId]/docs/page.tsx | 408 -------- .../project/[projectId]/features/page.tsx | 66 -- .../getting-started/analyze/page.tsx | 72 -- .../getting-started/connect/page.tsx | 138 --- .../[projectId]/getting-started/layout.tsx | 37 - .../getting-started/setup/page.tsx | 102 -- .../getting-started/summarize/page.tsx | 120 --- .../project/[projectId]/journey/page.tsx | 546 ---------- .../project/[projectId]/market/page.tsx | 321 ------ .../project/[projectId]/mission/page.tsx | 354 ------- .../project/[projectId]/money/page.tsx | 302 ------ .../[projectId]/plan/build-plan/page.tsx | 298 ------ .../project/[projectId]/plan/page.tsx | 768 -------------- .../project/[projectId]/product/page.tsx | 179 ---- .../project/[projectId]/progress/page.tsx | 227 ----- .../project/[projectId]/sandbox/page.tsx | 58 -- .../project/[projectId]/sessions/page.tsx | 209 ---- .../[projectId]/sessions/sessions/page.tsx | 208 ---- .../project/[projectId]/tech/page.tsx | 401 -------- .../[projectId]/timeline-plan/page.tsx | 736 -------------- app/[workspace]/projects/new/layout.tsx | 8 - app/[workspace]/projects/new/page.tsx | 462 --------- app/[workspace]/test-api-key/layout.tsx | 24 - app/[workspace]/test-api-key/page.tsx | 103 -- app/[workspace]/test-auth/layout.tsx | 29 - app/[workspace]/test-auth/page.tsx | 99 -- app/[workspace]/test-sessions/layout.tsx | 9 - app/[workspace]/test-sessions/page.tsx | 119 --- app/[workspace]/users/layout.tsx | 34 - app/[workspace]/users/page.tsx | 190 ---- components/ai/collector-actions.tsx | 385 ------- components/ai/collector-checklist.tsx | 225 ----- components/ai/extraction-results-editable.tsx | 318 ------ components/ai/extraction-results.tsx | 305 ------ components/ai/extraction-review-checklist.tsx | 129 --- components/ai/github-repo-picker.tsx | 269 ----- components/ai/phase-sidebar.tsx | 90 -- components/ai/project-config-generator.tsx | 171 ---- components/ai/vision-form.tsx | 245 ----- components/assistant-ui/markdown-text.tsx | 50 - components/assistant-ui/thread.tsx | 312 ------ components/chatgpt-import-card.tsx | 643 ------------ components/extension/project-linker.tsx | 147 --- components/icons/custom-icons.tsx | 230 ----- components/layout/PAGE_TEMPLATE_GUIDE.md | 355 ------- components/layout/app-shell.tsx | 50 - components/layout/connect-sources-modal.tsx | 161 --- components/layout/left-rail.tsx | 126 --- components/layout/mcp-connect-modal.tsx | 189 ---- components/layout/page-header.tsx | 38 - components/layout/page-template.tsx | 306 ------ components/layout/project-sidebar.tsx | 655 ------------ components/layout/right-panel.tsx | 119 --- components/layout/workspace-left-rail.tsx | 141 --- components/mcp-connection-card.tsx | 299 ------ components/mcp-playground.tsx | 207 ---- components/mission/mission-context-tree.tsx | 333 ------ components/mission/mission-idea-section.tsx | 201 ---- components/sidebar/project-sidebar.tsx | 130 --- components/sidebar/resizable-sidebar.tsx | 143 --- 82 files changed, 19583 deletions(-) delete mode 100644 app/[workspace]/connections/layout.tsx delete mode 100644 app/[workspace]/connections/page.tsx delete mode 100644 app/[workspace]/costs/layout.tsx delete mode 100644 app/[workspace]/costs/page.tsx delete mode 100644 app/[workspace]/debug-projects/page.tsx delete mode 100644 app/[workspace]/debug-sessions/page.tsx delete mode 100644 app/[workspace]/keys/layout.tsx delete mode 100644 app/[workspace]/keys/page.tsx delete mode 100644 app/[workspace]/mcp/page.tsx delete mode 100644 app/[workspace]/new-project/new/layout.tsx delete mode 100644 app/[workspace]/new-project/new/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/analytics/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/api-map/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/architecture/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/associate-sessions/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/audit-test/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/audit/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/automation/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/code/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/context/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/design-old/[pageSlug]/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/design-old/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/docs/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/features/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/getting-started/analyze/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/getting-started/connect/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/getting-started/layout.tsx delete mode 100644 app/[workspace]/project/[projectId]/getting-started/setup/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/getting-started/summarize/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/journey/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/market/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/mission/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/money/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/plan/build-plan/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/plan/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/product/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/progress/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/sandbox/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/sessions/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/sessions/sessions/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/tech/page.tsx delete mode 100644 app/[workspace]/project/[projectId]/timeline-plan/page.tsx delete mode 100644 app/[workspace]/projects/new/layout.tsx delete mode 100644 app/[workspace]/projects/new/page.tsx delete mode 100644 app/[workspace]/test-api-key/layout.tsx delete mode 100644 app/[workspace]/test-api-key/page.tsx delete mode 100644 app/[workspace]/test-auth/layout.tsx delete mode 100644 app/[workspace]/test-auth/page.tsx delete mode 100644 app/[workspace]/test-sessions/layout.tsx delete mode 100644 app/[workspace]/test-sessions/page.tsx delete mode 100644 app/[workspace]/users/layout.tsx delete mode 100644 app/[workspace]/users/page.tsx delete mode 100644 components/ai/collector-actions.tsx delete mode 100644 components/ai/collector-checklist.tsx delete mode 100644 components/ai/extraction-results-editable.tsx delete mode 100644 components/ai/extraction-results.tsx delete mode 100644 components/ai/extraction-review-checklist.tsx delete mode 100644 components/ai/github-repo-picker.tsx delete mode 100644 components/ai/phase-sidebar.tsx delete mode 100644 components/ai/project-config-generator.tsx delete mode 100644 components/ai/vision-form.tsx delete mode 100644 components/assistant-ui/markdown-text.tsx delete mode 100644 components/assistant-ui/thread.tsx delete mode 100644 components/chatgpt-import-card.tsx delete mode 100644 components/extension/project-linker.tsx delete mode 100644 components/icons/custom-icons.tsx delete mode 100644 components/layout/PAGE_TEMPLATE_GUIDE.md delete mode 100644 components/layout/app-shell.tsx delete mode 100644 components/layout/connect-sources-modal.tsx delete mode 100644 components/layout/left-rail.tsx delete mode 100644 components/layout/mcp-connect-modal.tsx delete mode 100644 components/layout/page-header.tsx delete mode 100644 components/layout/page-template.tsx delete mode 100644 components/layout/project-sidebar.tsx delete mode 100644 components/layout/right-panel.tsx delete mode 100644 components/layout/workspace-left-rail.tsx delete mode 100644 components/mcp-connection-card.tsx delete mode 100644 components/mcp-playground.tsx delete mode 100644 components/mission/mission-context-tree.tsx delete mode 100644 components/mission/mission-idea-section.tsx delete mode 100644 components/sidebar/project-sidebar.tsx delete mode 100644 components/sidebar/resizable-sidebar.tsx diff --git a/app/[workspace]/connections/layout.tsx b/app/[workspace]/connections/layout.tsx deleted file mode 100644 index 3b2d6a3..0000000 --- a/app/[workspace]/connections/layout.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client"; - -import { WorkspaceLeftRail } from "@/components/layout/workspace-left-rail"; -import { RightPanel } from "@/components/layout/right-panel"; -import { ReactNode, useState } from "react"; -import { Toaster } from "sonner"; - -export default function ConnectionsLayout({ - children, -}: { - children: ReactNode; -}) { - const [activeSection, setActiveSection] = useState("connections"); - - return ( - <> -
- {/* Left Rail - Workspace Navigation */} - - - {/* Main Content Area */} -
- {children} -
- - {/* Right Panel - AI Chat */} - -
- - - ); -} - diff --git a/app/[workspace]/connections/page.tsx b/app/[workspace]/connections/page.tsx deleted file mode 100644 index fa8c7c8..0000000 --- a/app/[workspace]/connections/page.tsx +++ /dev/null @@ -1,360 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Github, CheckCircle2, Download, Copy, Check, Eye, EyeOff } from "lucide-react"; -import { CursorIcon } from "@/components/icons/custom-icons"; -import { toast } from "sonner"; -import { auth } from "@/lib/firebase/config"; -import type { User } from "firebase/auth"; -import { MCPConnectionCard } from "@/components/mcp-connection-card"; -import { ChatGPTImportCard } from "@/components/chatgpt-import-card"; - -export default function ConnectionsPage() { - const [githubConnected, setGithubConnected] = useState(false); - const [extensionInstalled] = useState(false); // Future use: track extension installation - const [copiedApiKey, setCopiedApiKey] = useState(false); - const [showApiKey, setShowApiKey] = useState(false); - const [apiKey, setApiKey] = useState(null); - const [loadingApiKey, setLoadingApiKey] = useState(true); - const [apiUrl, setApiUrl] = useState('https://vibnai.com'); - - // Set API URL on client side to avoid hydration mismatch - useEffect(() => { - if (typeof window !== 'undefined') { - setApiUrl(window.location.origin); - } - }, []); - - // Fetch API key on mount - useEffect(() => { - async function fetchApiKey(user: User) { - try { - console.log('[Client] Getting ID token for user:', user.uid); - const token = await user.getIdToken(); - console.log('[Client] Token received, length:', token.length); - - const response = await fetch('/api/user/api-key', { - headers: { - 'Authorization': `Bearer ${token}`, - }, - }); - - console.log('[Client] Response status:', response.status); - - if (response.ok) { - const data = await response.json(); - console.log('[Client] API key received'); - setApiKey(data.apiKey); - } else { - const errorData = await response.json(); - console.error('[Client] Failed to fetch API key:', response.status, errorData); - } - } catch (error) { - console.error('[Client] Error fetching API key:', error); - } finally { - setLoadingApiKey(false); - } - } - - // Listen for auth state changes - const unsubscribe = auth.onAuthStateChanged((user) => { - if (user) { - fetchApiKey(user); - } else { - setLoadingApiKey(false); - } - }); - - return () => unsubscribe(); - }, []); - - const handleConnectGitHub = async () => { - // TODO: Implement GitHub OAuth flow - toast.success("GitHub connected successfully!"); - setGithubConnected(true); - }; - - const handleInstallExtension = () => { - // Link to Cursor Monitor extension (update with actual marketplace URL when published) - window.open("https://marketplace.visualstudio.com/items?itemName=cursor-monitor", "_blank"); - }; - - const handleCopyApiKey = () => { - if (apiKey) { - navigator.clipboard.writeText(apiKey); - setCopiedApiKey(true); - toast.success("API key copied to clipboard!"); - setTimeout(() => setCopiedApiKey(false), 2000); - } - }; - - return ( -
-
- {/* Header */} -
-

Connect Your Tools

-

- Set up your development tools to unlock the full power of Vib'n -

-
- - {/* Connection Cards */} -
- {/* Cursor Extension */} - - -
-
-
- -
-
-
- Cursor Monitor Extension - {extensionInstalled && ( - - )} -
- - Automatically track your coding sessions, AI usage, and costs - -
-
- {!extensionInstalled ? ( - - ) : ( - - )} -
-
- -
-
-

What it does:

-
    -
  • Tracks your coding sessions in real-time
  • -
  • Monitors AI model usage and token consumption
  • -
  • Logs file changes and conversation history
  • -
  • Calculates costs automatically
  • -
-
- - {!extensionInstalled && ( - <> -
-

Installation Steps:

-
    -
  1. Install the Cursor Monitor extension from the marketplace
  2. -
  3. Restart Cursor to activate the extension
  4. -
  5. Configure your API key (see instructions below)
  6. -
  7. Start coding - sessions will be tracked automatically!
  8. -
-
- -
-
-

Your API Key

- {!loadingApiKey && apiKey && ( -
- - -
- )} -
- - {loadingApiKey ? ( -
Loading...
- ) : apiKey ? ( - <> - -

- Add this key to your extension settings to connect it to your Vibn account. -

- - ) : ( -

- Sign in to generate your API key -

- )} -
- -
-

Configure Cursor Monitor Extension:

-
    -
  1. Open Cursor Settings (Cmd/Ctrl + ,)
  2. -
  3. Search for "Cursor Monitor"
  4. -
  5. Find "Cursor Monitor: Vibn Api Key"
  6. -
  7. Paste your API key (from above)
  8. -
  9. Verify "Cursor Monitor: Vibn Api Url" is set to: {apiUrl}/api
  10. -
  11. Make sure "Cursor Monitor: Vibn Enabled" is checked
  12. -
  13. Reload Cursor to start tracking
  14. -
-
- - )} - - {extensionInstalled && ( -
-

- ✓ Extension is installed and tracking your sessions -

-
- )} -
-
-
- - {/* GitHub Connection */} - - -
-
-
- -
-
-
- GitHub - {githubConnected && ( - - )} -
- - Connect your repositories for automatic analysis - -
-
- {!githubConnected ? ( - - ) : ( - - )} -
-
- -
-
-

What we'll access:

-
    -
  • Read your repository code and structure
  • -
  • Access repository metadata and commit history
  • -
  • Analyze tech stack and dependencies
  • -
  • Identify project architecture patterns
  • -
-
- - {!githubConnected && ( -
-

Why connect GitHub?

-

- Our AI will analyze your codebase to understand your tech stack, - architecture, and features. This helps generate better documentation - and provides smarter insights. -

-
- )} - - {githubConnected && ( -
-

- ✓ GitHub connected - Your repositories are ready for analysis -

-
- )} -
-
-
- - {/* ChatGPT (MCP) Connection */} - - - {/* ChatGPT Import */} - -
- - {/* Status Summary */} - {(githubConnected || extensionInstalled) && ( - - - Connection Status - - -
-
- - - Cursor Extension - - {extensionInstalled ? ( - - - Installed - - ) : ( - Not installed - )} -
-
- - - GitHub - - {githubConnected ? ( - - - Connected - - ) : ( - Not connected - )} -
-
-
-
- )} -
-
- ); -} - diff --git a/app/[workspace]/costs/layout.tsx b/app/[workspace]/costs/layout.tsx deleted file mode 100644 index 01a5c04..0000000 --- a/app/[workspace]/costs/layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; - -import { WorkspaceLeftRail } from "@/components/layout/workspace-left-rail"; -import { RightPanel } from "@/components/layout/right-panel"; -import { ReactNode, useState } from "react"; -import { Toaster } from "sonner"; - -export default function CostsLayout({ - children, -}: { - children: ReactNode; -}) { - const [activeSection, setActiveSection] = useState("costs"); - - return ( - <> -
- {/* Left Rail - Workspace Navigation */} - - - {/* Main Content Area */} -
- {children} -
- - {/* Right Panel - AI Chat */} - -
- - - - ); -} - diff --git a/app/[workspace]/costs/page.tsx b/app/[workspace]/costs/page.tsx deleted file mode 100644 index 2f27293..0000000 --- a/app/[workspace]/costs/page.tsx +++ /dev/null @@ -1,181 +0,0 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { auth } from '@/lib/firebase/config'; -import { toast } from 'sonner'; -import { DollarSign, TrendingUp, TrendingDown, Calendar } from 'lucide-react'; -import { useParams } from 'next/navigation'; - -interface CostData { - total: number; - thisMonth: number; - lastMonth: number; - byProject: Array<{ - projectId: string; - projectName: string; - cost: number; - }>; - byDate: Array<{ - date: string; - cost: number; - }>; -} - -export default function CostsPage() { - const params = useParams(); - const workspace = params.workspace as string; - const [costs, setCosts] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - loadCosts(); - }, []); - - const loadCosts = async () => { - try { - const user = auth.currentUser; - if (!user) return; - - const token = await user.getIdToken(); - const response = await fetch('/api/costs', { - headers: { - 'Authorization': `Bearer ${token}`, - }, - }); - - if (response.ok) { - const data = await response.json(); - setCosts(data); - } - } catch (error) { - console.error('Error loading costs:', error); - toast.error('Failed to load cost data'); - } finally { - setLoading(false); - } - }; - - const percentageChange = costs && costs.lastMonth > 0 - ? ((costs.thisMonth - costs.lastMonth) / costs.lastMonth) * 100 - : 0; - - return ( -
-
- {/* Header */} -
-

Costs

-

- Track your AI usage costs across all projects -

-
- - {/* Summary Cards */} - {loading ? ( - - -

Loading cost data...

-
-
- ) : ( - <> -
- - - Total Costs - - - -
${costs?.total.toFixed(2) || '0.00'}
-

All time

-
-
- - - - This Month - - - -
${costs?.thisMonth.toFixed(2) || '0.00'}
-

- {new Date().toLocaleDateString('en-US', { month: 'long', year: 'numeric' })} -

-
-
- - - - vs Last Month - {percentageChange >= 0 ? ( - - ) : ( - - )} - - -
- {percentageChange >= 0 ? '+' : ''}{percentageChange.toFixed(1)}% -
-

- Last month: ${costs?.lastMonth.toFixed(2) || '0.00'} -

-
-
-
- - {/* Costs by Project */} - - - Costs by Project - Your spending broken down by project - - - {costs?.byProject && costs.byProject.length > 0 ? ( -
- {costs.byProject.map((project) => ( -
-
-

{project.projectName}

-

Project ID: {project.projectId}

-
-
-

${project.cost.toFixed(2)}

-

- {((project.cost / (costs.total || 1)) * 100).toFixed(1)}% of total -

-
-
- ))} -
- ) : ( -

No project costs yet

- )} -
-
- - {/* Info Card */} - - - About Cost Tracking - - -

- 📊 Automatic Tracking: All AI API costs are automatically tracked when you use Vibn features. -

-

- 💰 Your Keys, Your Costs: Costs reflect usage of your own API keys - Vibn doesn't add any markup. -

-

- 📈 Project Attribution: Costs are attributed to projects based on session metadata. -

-
-
- - )} -
-
- ); -} - diff --git a/app/[workspace]/debug-projects/page.tsx b/app/[workspace]/debug-projects/page.tsx deleted file mode 100644 index ef626b6..0000000 --- a/app/[workspace]/debug-projects/page.tsx +++ /dev/null @@ -1,239 +0,0 @@ -"use client"; - -import { useEffect, useState } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { auth, db } from '@/lib/firebase/config'; -import { collection, query, where, getDocs } from 'firebase/firestore'; -import { Button } from '@/components/ui/button'; -import { RefreshCw } from 'lucide-react'; - -interface ProjectDebugInfo { - id: string; - productName: string; - name: string; - slug: string; - userId: string; - workspacePath?: string; - createdAt: any; - updatedAt: any; -} - -export default function DebugProjectsPage() { - const [projects, setProjects] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [userId, setUserId] = useState(''); - - const loadProjects = async () => { - setLoading(true); - setError(null); - try { - const user = auth.currentUser; - if (!user) { - setError('Not authenticated'); - return; - } - - setUserId(user.uid); - - const projectsRef = collection(db, 'projects'); - const projectsQuery = query( - projectsRef, - where('userId', '==', user.uid) - ); - const snapshot = await getDocs(projectsQuery); - - const projectsData = snapshot.docs.map(doc => { - const data = doc.data(); - return { - id: doc.id, - productName: data.productName || 'N/A', - name: data.name || 'N/A', - slug: data.slug || 'N/A', - userId: data.userId || 'N/A', - workspacePath: data.workspacePath, - createdAt: data.createdAt, - updatedAt: data.updatedAt, - }; - }); - - console.log('DEBUG: All projects from Firebase:', projectsData); - setProjects(projectsData); - } catch (err: any) { - console.error('Error loading projects:', err); - setError(err.message); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - const unsubscribe = auth.onAuthStateChanged((user) => { - if (user) { - loadProjects(); - } else { - setError('Please sign in'); - setLoading(false); - } - }); - - return () => unsubscribe(); - }, []); - - return ( -
-
-
-
-

🔍 Projects Debug Page

-

- View all your projects and their unique IDs from Firebase -

- {userId && ( -

- User ID: {userId} -

- )} -
- -
- - {error && ( - - -

Error: {error}

-
-
- )} - - {loading && !error && ( - - -

Loading projects from Firebase...

-
-
- )} - - {!loading && !error && ( - <> - - - Summary - - -
-
-

Total Projects

-

{projects.length}

-
-
-

Unique IDs

-

- {new Set(projects.map(p => p.id)).size} -

-
-
-

Duplicate IDs?

-

p.id)).size ? 'text-red-500' : 'text-green-500'}`}> - {projects.length !== new Set(projects.map(p => p.id)).size ? 'YES ⚠️' : 'NO ✓'} -

-
-
-
-
- -
-

All Projects

- {projects.map((project, index) => ( - - - - #{index + 1}: {project.productName} - - Open Overview → - - - - -
-
-

Project ID

- - {project.id} - -
-
-

Slug

- - {project.slug} - -
-
-

Product Name

-

{project.productName}

-
-
-

Internal Name

-

{project.name}

-
- {project.workspacePath && ( -
-

Workspace Path

- - {project.workspacePath} - -
- )} -
- -
- - - -
-
-
- ))} -
- - )} -
-
- ); -} - diff --git a/app/[workspace]/debug-sessions/page.tsx b/app/[workspace]/debug-sessions/page.tsx deleted file mode 100644 index c6fc8c3..0000000 --- a/app/[workspace]/debug-sessions/page.tsx +++ /dev/null @@ -1,279 +0,0 @@ -"use client"; - -import { useEffect, useState, useCallback } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; -import { auth, db } from '@/lib/firebase/config'; -import { collection, query, where, getDocs, orderBy, limit } from 'firebase/firestore'; -import { RefreshCw, CheckCircle2, AlertCircle, Link as LinkIcon } from 'lucide-react'; - -interface SessionDebugInfo { - id: string; - projectId?: string; - workspacePath?: string; - workspaceName?: string; - needsProjectAssociation: boolean; - model?: string; - tokensUsed?: number; - cost?: number; - createdAt: any; -} - -export default function DebugSessionsPage() { - const [sessions, setSessions] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [userId, setUserId] = useState(''); - - const loadSessions = useCallback(async () => { - setLoading(true); - setError(null); - try { - const user = auth.currentUser; - if (!user) { - setError('Not authenticated'); - setLoading(false); - return; - } - - setUserId(user.uid); - - const sessionsRef = collection(db, 'sessions'); - // Remove orderBy to avoid index issues - just get recent sessions - const sessionsQuery = query( - sessionsRef, - where('userId', '==', user.uid), - limit(50) - ); - const snapshot = await getDocs(sessionsQuery); - - const sessionsData = snapshot.docs.map(doc => { - const data = doc.data(); - return { - id: doc.id, - projectId: data.projectId || null, - workspacePath: data.workspacePath || null, - workspaceName: data.workspaceName || null, - needsProjectAssociation: data.needsProjectAssociation || false, - model: data.model, - tokensUsed: data.tokensUsed, - cost: data.cost, - createdAt: data.createdAt, - }; - }); - - console.log('DEBUG: All sessions from Firebase:', sessionsData); - setSessions(sessionsData); - } catch (err: any) { - console.error('Error loading sessions:', err); - setError(err.message); - } finally { - setLoading(false); - } - }, []); - - useEffect(() => { - let mounted = true; - - const unsubscribe = auth.onAuthStateChanged((user) => { - if (!mounted) return; - - if (user) { - loadSessions(); - } else { - setError('Please sign in'); - setLoading(false); - } - }); - - return () => { - mounted = false; - unsubscribe(); - }; - }, [loadSessions]); - - const unassociatedSessions = sessions.filter(s => s.needsProjectAssociation); - const associatedSessions = sessions.filter(s => !s.needsProjectAssociation); - - // Group unassociated sessions by workspace path - const sessionsByWorkspace = unassociatedSessions.reduce((acc, session) => { - const path = session.workspacePath || 'No workspace path'; - if (!acc[path]) acc[path] = []; - acc[path].push(session); - return acc; - }, {} as Record); - - return ( -
-
-
-
-

🔍 Sessions Debug Page

-

- View all your chat sessions and their workspace paths -

- {userId && ( -

- User ID: {userId} -

- )} -
- -
- - {error && ( - - -

Error: {error}

-
-
- )} - - {loading && !error && ( - - -

Loading sessions...

-
-
- )} - - {!loading && !error && ( - <> - {/* Summary */} - - - Summary - - -
-
-

Total Sessions

-

{sessions.length}

-
-
-

Linked to Projects

-

{associatedSessions.length}

-
-
-

Unassociated (Available)

-

{unassociatedSessions.length}

-
-
-
-
- - {/* Unassociated Sessions by Workspace */} - {unassociatedSessions.length > 0 && ( - - - - - Unassociated Sessions (Available to Link) - - - - {Object.entries(sessionsByWorkspace).map(([path, workspaceSessions]) => { - const folderName = path !== 'No workspace path' ? path.split('/').pop() : null; - return ( -
-
-
-
-

📁 {folderName || 'Unknown folder'}

- {path} -
-
-

{workspaceSessions.length}

-

sessions

-
-
-
-
- {workspaceSessions.slice(0, 3).map((session) => ( -
-
- {session.id.substring(0, 12)}... - {session.model || 'unknown'} -
-
- {session.tokensUsed?.toLocaleString()} tokens • ${session.cost?.toFixed(4)} -
-
- ))} - {workspaceSessions.length > 3 && ( -

- + {workspaceSessions.length - 3} more sessions... -

- )} -
-
-

- 💡 To link these sessions: -

-
    -
  1. Create a project with workspace path: {path}
  2. -
  3. OR connect GitHub to a project that already has this workspace path set
  4. -
-

- Folder name: {folderName} -

-
-
- ); - })} -
-
- )} - - {/* Associated Sessions */} - {associatedSessions.length > 0 && ( - - - - - Linked Sessions - - - -

- These sessions are already linked to projects -

-
- {associatedSessions.slice(0, 5).map((session) => ( -
-
- {session.id.substring(0, 12)}... -

- {session.workspaceName || 'No workspace'} -

-
-
- -

- Project: {session.projectId?.substring(0, 8)}... -

-
-
- ))} -
-
-
- )} - - {sessions.length === 0 && ( - - -

No sessions found. Start coding with Cursor to track sessions!

-
-
- )} - - )} -
-
- ); -} - diff --git a/app/[workspace]/keys/layout.tsx b/app/[workspace]/keys/layout.tsx deleted file mode 100644 index 61a4127..0000000 --- a/app/[workspace]/keys/layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; - -import { WorkspaceLeftRail } from "@/components/layout/workspace-left-rail"; -import { RightPanel } from "@/components/layout/right-panel"; -import { ReactNode, useState } from "react"; -import { Toaster } from "sonner"; - -export default function KeysLayout({ - children, -}: { - children: ReactNode; -}) { - const [activeSection, setActiveSection] = useState("keys"); - - return ( - <> -
- {/* Left Rail - Workspace Navigation */} - - - {/* Main Content Area */} -
- {children} -
- - {/* Right Panel - AI Chat */} - -
- - - - ); -} - diff --git a/app/[workspace]/keys/page.tsx b/app/[workspace]/keys/page.tsx deleted file mode 100644 index c8ee5e3..0000000 --- a/app/[workspace]/keys/page.tsx +++ /dev/null @@ -1,412 +0,0 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { auth } from '@/lib/firebase/config'; -import { toast } from 'sonner'; -import { Key, Plus, Trash2, Eye, EyeOff, ExternalLink, Save } from 'lucide-react'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from "@/components/ui/alert-dialog"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; - -interface ApiKey { - id: string; - service: string; - name: string; - createdAt: any; - lastUsed: any; -} - -const SUPPORTED_SERVICES = [ - { - id: 'openai', - name: 'OpenAI', - description: 'For ChatGPT imports and AI features', - placeholder: 'sk-...', - helpUrl: 'https://platform.openai.com/api-keys', - }, - { - id: 'github', - name: 'GitHub', - description: 'Personal access token for repository access', - placeholder: 'ghp_...', - helpUrl: 'https://github.com/settings/tokens', - }, - { - id: 'anthropic', - name: 'Anthropic (Claude)', - description: 'For Claude AI integrations', - placeholder: 'sk-ant-...', - helpUrl: 'https://console.anthropic.com/settings/keys', - }, -]; - -export default function KeysPage() { - const [keys, setKeys] = useState([]); - const [loading, setLoading] = useState(true); - const [showAddDialog, setShowAddDialog] = useState(false); - const [selectedService, setSelectedService] = useState(''); - const [keyValue, setKeyValue] = useState(''); - const [showKey, setShowKey] = useState(false); - const [saving, setSaving] = useState(false); - - useEffect(() => { - loadKeys(); - }, []); - - const loadKeys = async () => { - try { - const user = auth.currentUser; - if (!user) return; - - const token = await user.getIdToken(); - const response = await fetch('/api/keys', { - headers: { - 'Authorization': `Bearer ${token}`, - }, - }); - - if (response.ok) { - const data = await response.json(); - setKeys(data.keys); - } - } catch (error) { - console.error('Error loading keys:', error); - toast.error('Failed to load API keys'); - } finally { - setLoading(false); - } - }; - - const handleAddKey = async () => { - if (!selectedService || !keyValue) { - toast.error('Please select a service and enter a key'); - return; - } - - setSaving(true); - try { - const user = auth.currentUser; - if (!user) { - toast.error('Please sign in'); - return; - } - - const token = await user.getIdToken(); - const service = SUPPORTED_SERVICES.find(s => s.id === selectedService); - - const response = await fetch('/api/keys', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - service: selectedService, - name: service?.name, - keyValue, - }), - }); - - if (response.ok) { - toast.success(`${service?.name} key saved successfully`); - setShowAddDialog(false); - setSelectedService(''); - setKeyValue(''); - loadKeys(); - } else { - const error = await response.json(); - toast.error(error.error || 'Failed to save key'); - } - } catch (error) { - console.error('Error saving key:', error); - toast.error('Failed to save key'); - } finally { - setSaving(false); - } - }; - - const handleDeleteKey = async (service: string, name: string) => { - try { - const user = auth.currentUser; - if (!user) return; - - const token = await user.getIdToken(); - const response = await fetch('/api/keys', { - method: 'DELETE', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ service }), - }); - - if (response.ok) { - toast.success(`${name} key deleted`); - loadKeys(); - } else { - toast.error('Failed to delete key'); - } - } catch (error) { - console.error('Error deleting key:', error); - toast.error('Failed to delete key'); - } - }; - - const getServiceConfig = (serviceId: string) => { - return SUPPORTED_SERVICES.find(s => s.id === serviceId); - }; - - return ( -
-
- {/* Header */} -
-
-

API Keys

-

- Manage your third-party API keys for Vibn integrations -

-
- - - - - - - Add API Key - - Add a third-party API key for Vibn to use on your behalf - - - -
-
- - - {selectedService && ( -

- {getServiceConfig(selectedService)?.description} -

- )} -
- -
- -
-
- setKeyValue(e.target.value)} - className="pr-10" - /> - -
-
- {selectedService && ( - - Get your API key - - )} -
- -
-

- 🔐 Secure Storage: Your API key will be encrypted and stored securely. - Vibn will only use it when you explicitly request actions that require it. -

-
-
- - - - - -
-
-
- - {/* Keys List */} - {loading ? ( - - -

Loading your API keys...

-
-
- ) : keys.length === 0 ? ( - - -
-
- -
-
-
-

No API keys yet

-

- Add your third-party API keys to enable Vibn features like ChatGPT imports and AI analysis -

- -
-
-
- ) : ( -
- {keys.map((key) => { - const serviceConfig = getServiceConfig(key.service); - return ( - - -
-
-
- -
-
- {key.name} - - {serviceConfig?.description || key.service} - -
-
- - - - - - - Delete API Key? - - This will remove your {key.name} API key. Features using this key will stop working until you add a new one. - - - - Cancel - handleDeleteKey(key.service, key.name)}> - Delete Key - - - - -
-
- -
-
-

- Added: {key.createdAt ? new Date(key.createdAt._seconds * 1000).toLocaleDateString() : 'Unknown'} -

- {key.lastUsed && ( -

- Last used: {new Date(key.lastUsed._seconds * 1000).toLocaleDateString()} -

- )} -
- {serviceConfig && ( - - Manage on {serviceConfig.name} - - )} -
-
-
- ); - })} -
- )} - - {/* Info Card */} - - - How API Keys Work - - -

- 🔐 Encrypted Storage: All API keys are encrypted before being stored in the database. -

-

- 🎯 Automatic Usage: When you use Vibn features (like ChatGPT import), we'll automatically use your stored keys instead of asking each time. -

-

- 🔄 Easy Updates: Add a new key with the same service name to replace an existing one. -

-

- 🗑️ Full Control: Delete keys anytime - you can always add them back later. -

-
-
-
-
- ); -} - diff --git a/app/[workspace]/mcp/page.tsx b/app/[workspace]/mcp/page.tsx deleted file mode 100644 index e97b22f..0000000 --- a/app/[workspace]/mcp/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -/** - * MCP Integration Page - * - * Test and demonstrate Vibn's Model Context Protocol capabilities - */ - -import { MCPPlayground } from '@/components/mcp-playground'; - -export const metadata = { - title: 'MCP Integration | Vibn', - description: 'Connect AI assistants to your Vibn projects using the Model Context Protocol', -}; - -export default function MCPPage() { - return ( -
- -
- ); -} - diff --git a/app/[workspace]/new-project/new/layout.tsx b/app/[workspace]/new-project/new/layout.tsx deleted file mode 100644 index e651bbe..0000000 --- a/app/[workspace]/new-project/new/layout.tsx +++ /dev/null @@ -1,8 +0,0 @@ -export default function NewProjectLayout({ - children, -}: { - children: React.ReactNode; -}) { - return children; -} - diff --git a/app/[workspace]/new-project/new/page.tsx b/app/[workspace]/new-project/new/page.tsx deleted file mode 100644 index b7088eb..0000000 --- a/app/[workspace]/new-project/new/page.tsx +++ /dev/null @@ -1,506 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { ArrowLeft, ArrowRight, Check, Sparkles, Code2 } from "lucide-react"; -import { useRouter, useSearchParams } from "next/navigation"; -import { auth } from "@/lib/firebase/config"; -import { toast } from "sonner"; - -type ProjectType = "scratch" | "existing" | null; - -export default function NewProjectPage() { - const router = useRouter(); - const searchParams = useSearchParams(); - const [step, setStep] = useState(1); - const [projectName, setProjectName] = useState(""); - const [projectType, setProjectType] = useState(null); - const [workspacePath, setWorkspacePath] = useState(null); - - // Product vision (can skip) - const [productVision, setProductVision] = useState(""); - - // Product details - const [productName, setProductName] = useState(""); - const [isForClient, setIsForClient] = useState(null); - const [hasLogo, setHasLogo] = useState(null); - const [hasDomain, setHasDomain] = useState(null); - const [hasWebsite, setHasWebsite] = useState(null); - const [hasGithub, setHasGithub] = useState(null); - const [hasChatGPT, setHasChatGPT] = useState(null); - - const [isCheckingSlug, setIsCheckingSlug] = useState(false); - const [slugAvailable, setSlugAvailable] = useState(null); - - // Check for workspacePath query parameter - useEffect(() => { - const path = searchParams.get('workspacePath'); - if (path) { - setWorkspacePath(path); - // Auto-fill project name from workspace path - const folderName = path.split('/').pop(); - if (folderName && !projectName) { - setProjectName(folderName.replace(/-/g, ' ').replace(/_/g, ' ')); - } - } - }, [searchParams, projectName]); - - const generateSlug = (name: string) => { - return name - .toLowerCase() - .replace(/[^a-z0-9]+/g, "-") - .replace(/^-+|-+$/g, ""); - }; - - const checkSlugAvailability = async (name: string) => { - const slug = generateSlug(name); - if (!slug) return; - - setIsCheckingSlug(true); - // TODO: Replace with actual API call - await new Promise(resolve => setTimeout(resolve, 500)); - - // Mock check - in reality, check against database - const isAvailable = !["test", "demo", "admin"].includes(slug); - setSlugAvailable(isAvailable); - setIsCheckingSlug(false); - }; - - const handleProductNameChange = (value: string) => { - setProductName(value); - setSlugAvailable(null); - if (value.length > 2) { - checkSlugAvailability(value); - } - }; - - const handleNext = () => { - if (step === 1 && projectName && projectType) { - setStep(2); - } else if (step === 2) { - // Can skip questions - setStep(3); - } else if (step === 3 && productName && slugAvailable) { - handleCreateProject(); - } - }; - - const handleBack = () => { - if (step > 1) setStep(step - 1); - }; - - const handleSkipQuestions = () => { - setStep(3); - }; - - const handleCreateProject = async () => { - const slug = generateSlug(productName); - - const projectData = { - projectName, - projectType, - slug, - vision: productVision, - product: { - name: productName, - isForClient, - hasLogo, - hasDomain, - hasWebsite, - hasGithub, - hasChatGPT, - }, - workspacePath, - }; - - try { - const user = auth.currentUser; - if (!user) { - toast.error('You must be signed in to create a project'); - return; - } - - const token = await user.getIdToken(); - - const response = await fetch('/api/projects/create', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(projectData), - }); - - if (response.ok) { - const data = await response.json(); - toast.success('Project created successfully!'); - // Redirect to AI chat to start with vision questions - router.push(`/${data.workspace}/project/${data.projectId}/v_ai_chat`); - } else { - const error = await response.json(); - toast.error(error.error || 'Failed to create project'); - } - } catch (error) { - console.error('Error creating project:', error); - toast.error('An error occurred while creating project'); - } - }; - - const canProceedStep1 = projectName.trim() && projectType; - const canProceedStep3 = productName.trim() && slugAvailable; - - return ( -
-
- {/* Header */} -
- -

Create New Project

-

- Step {step} of 3 -

-
- - {/* Progress */} -
- {[1, 2, 3].map((s) => ( -
- ))} -
- - {/* Step 1: Project Setup */} - {step === 1 && ( - - - Project Setup - - Give your project a name and choose how you want to start - - - -
- - setProjectName(e.target.value)} - /> -
- -
- -
- - - -
-
-
-
- )} - - {/* Step 2: Product Vision */} - {step === 2 && ( - - - Describe your product vision - - Help us understand your project (you can skip this) - - - -
-