diff --git a/src/App.new.tsx b/src/App.new.tsx
new file mode 100644
index 0000000..e71ebfe
--- /dev/null
+++ b/src/App.new.tsx
@@ -0,0 +1,307 @@
+import { useState } from 'react'
+import { Toaster } from 'sonner'
+import { Tabs, TabsContent } from '@/components/ui/tabs'
+import { AppHeader, PageHeader } from '@/components/organisms'
+import { ProjectDashboard } from '@/components/ProjectDashboard'
+import { CodeEditor } from '@/components/CodeEditor'
+import { ModelDesigner } from '@/components/ModelDesigner'
+import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
+import { ComponentTreeManager } from '@/components/ComponentTreeManager'
+import { WorkflowDesigner } from '@/components/WorkflowDesigner'
+import { LambdaDesigner } from '@/components/LambdaDesigner'
+import { StyleDesigner } from '@/components/StyleDesigner'
+import { FileExplorer } from '@/components/FileExplorer'
+import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
+import { StorybookDesigner } from '@/components/StorybookDesigner'
+import { UnitTestDesigner } from '@/components/UnitTestDesigner'
+import { FlaskDesigner } from '@/components/FlaskDesigner'
+import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
+import { ErrorPanel } from '@/components/ErrorPanel'
+import { DocumentationView } from '@/components/DocumentationView'
+import { SassStylesShowcase } from '@/components/SassStylesShowcase'
+import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
+import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
+import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
+import { PWAStatusBar } from '@/components/PWAStatusBar'
+import { PWASettings } from '@/components/PWASettings'
+import { FaviconDesigner } from '@/components/FaviconDesigner'
+import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
+import { GlobalSearch } from '@/components/GlobalSearch'
+import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
+import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
+import { useProjectState } from '@/hooks/use-project-state'
+import { useFileOperations } from '@/hooks/use-file-operations'
+import { useProjectExport } from '@/hooks/use-project-export'
+import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
+import { useAutoRepair } from '@/hooks/use-auto-repair'
+
+function App() {
+ const {
+ files,
+ models,
+ components,
+ componentTrees,
+ workflows,
+ lambdas,
+ theme,
+ playwrightTests,
+ storybookStories,
+ unitTests,
+ flaskConfig,
+ nextjsConfig,
+ npmSettings,
+ featureToggles,
+ setFiles,
+ setModels,
+ setComponents,
+ setComponentTrees,
+ setWorkflows,
+ setLambdas,
+ setTheme,
+ setPlaywrightTests,
+ setStorybookStories,
+ setUnitTests,
+ setFlaskConfig,
+ setNextjsConfig,
+ setNpmSettings,
+ setFeatureToggles,
+ lastSaved,
+ getCurrentProject,
+ loadProject,
+ } = useProjectState()
+
+ const {
+ activeFileId,
+ setActiveFileId,
+ handleFileChange,
+ handleFileAdd,
+ handleFileClose,
+ } = useFileOperations(files, setFiles)
+
+ const { handleExportProject, exportDialogOpen, setExportDialogOpen, generatedCode, handleDownloadZip } = useProjectExport({
+ files,
+ models,
+ components,
+ theme,
+ playwrightTests,
+ storybookStories,
+ unitTests,
+ flaskConfig,
+ nextjsConfig,
+ npmSettings,
+ })
+
+ const [activeTab, setActiveTab] = useState('dashboard')
+ const [searchDialogOpen, setSearchDialogOpen] = useState(false)
+ const [shortcutsDialogOpen, setShortcutsDialogOpen] = useState(false)
+
+ const { errors: autoDetectedErrors = [] } = useAutoRepair(files, false)
+ const errorCount = Array.isArray(autoDetectedErrors) ? autoDetectedErrors.length : 0
+
+ useKeyboardShortcuts([
+ { key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
+ { key: '2', ctrl: true, description: 'Code Editor', action: () => setActiveTab('code') },
+ { key: '3', ctrl: true, description: 'Models', action: () => setActiveTab('models') },
+ { key: 'k', ctrl: true, description: 'Search', action: () => setSearchDialogOpen(true) },
+ { key: 'e', ctrl: true, description: 'Export', action: () => handleExportProject() },
+ { key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsDialogOpen(true) },
+ ])
+
+ return (
+
+
+
+
+
setSearchDialogOpen(true)}
+ onShowShortcuts={() => setShortcutsDialogOpen(true)}
+ onGenerateAI={() => {}}
+ onExport={handleExportProject}
+ onShowErrors={() => setActiveTab('errors')}
+ />
+
+
+
+
+
+
+
+
+
+ {featureToggles.codeEditor && (
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ {featureToggles.models && (
+
+
+
+ )}
+
+ {featureToggles.components && (
+
+
+
+ )}
+
+ {featureToggles.componentTrees && (
+
+
+
+ )}
+
+ {featureToggles.workflows && (
+
+
+
+ )}
+
+ {featureToggles.lambdas && (
+
+
+
+ )}
+
+ {featureToggles.styling && (
+
+
+
+ )}
+
+ {featureToggles.flaskApi && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {featureToggles.playwright && (
+
+
+
+ )}
+
+ {featureToggles.storybook && (
+
+
+
+ )}
+
+ {featureToggles.unitTests && (
+
+
+
+ )}
+
+ {featureToggles.errorRepair && (
+
+
+
+ )}
+
+ {featureToggles.documentation && (
+
+
+
+ )}
+
+ {featureToggles.sassStyles && (
+
+
+
+ )}
+
+ {featureToggles.faviconDesigner && (
+
+
+
+ )}
+
+ {featureToggles.ideaCloud && (
+
+
+
+ )}
+
+
+
+ setActiveTab(tab)}
+ onFileSelect={setActiveFileId}
+ />
+
+
+
+
+ )
+}
+
+export default App
diff --git a/src/App.refactored.tsx b/src/App.refactored.tsx
new file mode 100644
index 0000000..d6178e5
--- /dev/null
+++ b/src/App.refactored.tsx
@@ -0,0 +1,157 @@
+import { useState } from 'react'
+import { useKV } from '@github/spark/hooks'
+import { Tabs, TabsContent } from '@/components/ui/tabs'
+import { AppHeader, PageHeader } from '@/components/organisms'
+import { ProjectDashboard } from '@/components/ProjectDashboard'
+import { CodeEditor } from '@/components/CodeEditor'
+import { ModelDesigner } from '@/components/ModelDesigner'
+import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
+import { ComponentTreeManager } from '@/components/ComponentTreeManager'
+import { WorkflowDesigner } from '@/components/WorkflowDesigner'
+import { LambdaDesigner } from '@/components/LambdaDesigner'
+import { StyleDesigner } from '@/components/StyleDesigner'
+import { FileExplorer } from '@/components/FileExplorer'
+import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
+import { StorybookDesigner } from '@/components/StorybookDesigner'
+import { UnitTestDesigner } from '@/components/UnitTestDesigner'
+import { FlaskDesigner } from '@/components/FlaskDesigner'
+import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
+import { ErrorPanel } from '@/components/ErrorPanel'
+import { DocumentationView } from '@/components/DocumentationView'
+import { SassStylesShowcase } from '@/components/SassStylesShowcase'
+import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
+import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
+import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
+import { PWAStatusBar } from '@/components/PWAStatusBar'
+import { PWASettings } from '@/components/PWASettings'
+import { FaviconDesigner } from '@/components/FaviconDesigner'
+import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
+import { GlobalSearch } from '@/components/GlobalSearch'
+import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
+import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
+import { useProjectState } from '@/hooks/use-project-state'
+import { useFileOperations } from '@/hooks/use-file-operations'
+import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
+import { useAutoRepair } from '@/hooks/use-auto-repair'
+import { toast } from 'sonner'
+
+function App() {
+ const projectState = useProjectState()
+ const { files, models, components, componentTrees, workflows, lambdas, theme, playwrightTests, storybookStories, unitTests, flaskConfig, nextjsConfig, npmSettings, featureToggles } = projectState
+ const { setFiles, setModels, setComponents, setComponentTrees, setWorkflows, setLambdas, setTheme, setPlaywrightTests, setStorybookStories, setUnitTests, setFlaskConfig, setNextjsConfig, setNpmSettings, setFeatureToggles } = projectState
+
+ const fileOps = useFileOperations(files, setFiles)
+ const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
+
+ const [activeTab, setActiveTab] = useState('dashboard')
+ const [searchOpen, setSearchOpen] = useState(false)
+ const [shortcutsOpen, setShortcutsOpen] = useState(false)
+ const [lastSaved] = useState(Date.now())
+
+ const { errors = [] } = useAutoRepair(files, false)
+ const errorCount = errors.length
+
+ useKeyboardShortcuts([
+ { key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
+ { key: '2', ctrl: true, description: 'Code', action: () => setActiveTab('code') },
+ { key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) },
+ { key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
+ ])
+
+ const getCurrentProject = () => ({
+ name: nextjsConfig.appName,
+ files,
+ models,
+ components,
+ componentTrees,
+ workflows,
+ lambdas,
+ theme,
+ playwrightTests,
+ storybookStories,
+ unitTests,
+ flaskConfig,
+ nextjsConfig,
+ npmSettings,
+ featureToggles,
+ })
+
+ const handleProjectLoad = (project: any) => {
+ if (project.files) setFiles(project.files)
+ if (project.models) setModels(project.models)
+ if (project.components) setComponents(project.components)
+ if (project.componentTrees) setComponentTrees(project.componentTrees)
+ if (project.workflows) setWorkflows(project.workflows)
+ if (project.lambdas) setLambdas(project.lambdas)
+ if (project.theme) setTheme(project.theme)
+ if (project.playwrightTests) setPlaywrightTests(project.playwrightTests)
+ if (project.storybookStories) setStorybookStories(project.storybookStories)
+ if (project.unitTests) setUnitTests(project.unitTests)
+ if (project.flaskConfig) setFlaskConfig(project.flaskConfig)
+ if (project.nextjsConfig) setNextjsConfig(project.nextjsConfig)
+ if (project.npmSettings) setNpmSettings(project.npmSettings)
+ if (project.featureToggles) setFeatureToggles(project.featureToggles)
+ toast.success('Project loaded')
+ }
+
+ return (
+
+
+
+
setSearchOpen(true)}
+ onShowShortcuts={() => setShortcutsOpen(true)}
+ onGenerateAI={() => toast.info('AI generation coming soon')}
+ onExport={() => toast.info('Export coming soon')}
+ onShowErrors={() => setActiveTab('errors')}
+ />
+
+
+
+
+
+
+ {featureToggles.codeEditor && (
+
+
+
+
+
+
+
+ )}
+ {featureToggles.models &&
}
+ {featureToggles.components &&
}
+ {featureToggles.componentTrees &&
}
+ {featureToggles.workflows &&
}
+ {featureToggles.lambdas &&
}
+ {featureToggles.styling &&
}
+ {featureToggles.flaskApi &&
}
+
+
+
+ {featureToggles.playwright &&
}
+ {featureToggles.storybook &&
}
+ {featureToggles.unitTests &&
}
+ {featureToggles.errorRepair &&
}
+ {featureToggles.documentation &&
}
+ {featureToggles.sassStyles &&
}
+ {featureToggles.faviconDesigner &&
}
+ {featureToggles.ideaCloud &&
}
+
+
+
+
+
+
+ )
+}
+
+export default App
diff --git a/src/App.simple.tsx b/src/App.simple.tsx
new file mode 100644
index 0000000..01c51bc
--- /dev/null
+++ b/src/App.simple.tsx
@@ -0,0 +1,110 @@
+import { useState } from 'react'
+import { useKV } from '@github/spark/hooks'
+import { Tabs, TabsContent } from '@/components/ui/tabs'
+import { Button } from '@/components/ui/button'
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
+import { AppHeader, PageHeader } from '@/components/organisms'
+import { FeatureToggles, Project } from '@/types/project'
+import { toast } from 'sonner'
+
+const DEFAULT_FEATURE_TOGGLES: FeatureToggles = {
+ codeEditor: true,
+ models: true,
+ components: true,
+ componentTrees: true,
+ workflows: true,
+ lambdas: true,
+ styling: true,
+ flaskApi: true,
+ playwright: true,
+ storybook: true,
+ unitTests: true,
+ errorRepair: true,
+ documentation: true,
+ sassStyles: true,
+ faviconDesigner: true,
+ ideaCloud: true,
+}
+
+function App() {
+ const [featureToggles] = useKV('feature-toggles', DEFAULT_FEATURE_TOGGLES)
+ const [activeTab, setActiveTab] = useState('dashboard')
+ const [lastSaved] = useState(Date.now())
+
+ const safeFeatureToggles = featureToggles || DEFAULT_FEATURE_TOGGLES
+
+ const getCurrentProject = (): Project => {
+ return {
+ name: 'Test Project',
+ files: [],
+ models: [],
+ components: [],
+ componentTrees: [],
+ workflows: [],
+ lambdas: [],
+ theme: {
+ variants: [],
+ activeVariantId: 'light',
+ fontFamily: 'Inter',
+ fontSize: { small: 12, medium: 14, large: 20 },
+ spacing: 8,
+ borderRadius: 4,
+ },
+ }
+ }
+
+ const handleProjectLoad = (project: Project) => {
+ toast.success('Project loaded')
+ }
+
+ return (
+
+
{}}
+ onShowShortcuts={() => {}}
+ onGenerateAI={() => {}}
+ onExport={() => {}}
+ onShowErrors={() => {}}
+ />
+
+
+
+
+
+
+
+
+ Dashboard
+ Welcome to CodeForge
+
+
+ The application is loading successfully!
+
+
+
+
+
+
+
+
+ Code Editor
+
+
+ Code editor will load here
+
+
+
+
+
+
+ )
+}
+
+export default App
diff --git a/src/App.tsx b/src/App.tsx
index 5670176..1f7a9e4 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,13 +1,7 @@
-import { useState, useEffect } from 'react'
-import { useKV } from '@github/spark/hooks'
-import { useAutoRepair } from '@/hooks/use-auto-repair'
-import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
-import { Button } from '@/components/ui/button'
-import { Badge } from '@/components/ui/badge'
-import { Card } from '@/components/ui/card'
-import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
-import { Download } from '@phosphor-icons/react'
-import { ProjectFile, PrismaModel, ComponentNode, ComponentTree, ThemeConfig, PlaywrightTest, StorybookStory, UnitTest, FlaskConfig, NextJsConfig, NpmSettings, Workflow, Lambda, FeatureToggles, Project } from '@/types/project'
+import { useState } from 'react'
+import { Tabs, TabsContent } from '@/components/ui/tabs'
+import { AppHeader, PageHeader } from '@/components/organisms'
+import { ProjectDashboard } from '@/components/ProjectDashboard'
import { CodeEditor } from '@/components/CodeEditor'
import { ModelDesigner } from '@/components/ModelDesigner'
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
@@ -24,8 +18,6 @@ import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
import { ErrorPanel } from '@/components/ErrorPanel'
import { DocumentationView } from '@/components/DocumentationView'
import { SassStylesShowcase } from '@/components/SassStylesShowcase'
-import { ProjectDashboard } from '@/components/ProjectDashboard'
-import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
@@ -34,215 +26,17 @@ import { PWASettings } from '@/components/PWASettings'
import { FaviconDesigner } from '@/components/FaviconDesigner'
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
import { GlobalSearch } from '@/components/GlobalSearch'
-import { AppHeader, PageHeader } from '@/components/organisms'
+import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
+import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
+import { useProjectState } from '@/hooks/use-project-state'
+import { useFileOperations } from '@/hooks/use-file-operations'
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
-import { generateNextJSProject, generatePrismaSchema, generateMUITheme, generatePlaywrightTests, generateStorybookStories, generateUnitTests, generateFlaskApp } from '@/lib/generators'
-import { AIService } from '@/lib/ai-service'
+import { useAutoRepair } from '@/hooks/use-auto-repair'
import { toast } from 'sonner'
-import JSZip from 'jszip'
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogHeader,
- DialogTitle,
-} from '@/components/ui/dialog'
-import { ScrollArea } from '@/components/ui/scroll-area'
-import { Textarea } from '@/components/ui/textarea'
-
-const DEFAULT_FLASK_CONFIG: FlaskConfig = {
- blueprints: [],
- corsOrigins: ['http://localhost:3000'],
- enableSwagger: true,
- port: 5000,
- debug: true,
-}
-
-const DEFAULT_NEXTJS_CONFIG: NextJsConfig = {
- appName: 'my-nextjs-app',
- typescript: true,
- eslint: true,
- tailwind: true,
- srcDirectory: true,
- appRouter: true,
- importAlias: '@/*',
- turbopack: false,
-}
-
-const DEFAULT_NPM_SETTINGS: NpmSettings = {
- packages: [
- { id: '1', name: 'react', version: '^18.2.0', isDev: false },
- { id: '2', name: 'react-dom', version: '^18.2.0', isDev: false },
- { id: '3', name: 'next', version: '^14.0.0', isDev: false },
- { id: '4', name: '@mui/material', version: '^5.14.0', isDev: false },
- { id: '5', name: 'typescript', version: '^5.0.0', isDev: true },
- { id: '6', name: '@types/react', version: '^18.2.0', isDev: true },
- ],
- scripts: {
- dev: 'next dev',
- build: 'next build',
- start: 'next start',
- lint: 'next lint',
- },
- packageManager: 'npm',
-}
-
-const DEFAULT_FEATURE_TOGGLES: FeatureToggles = {
- codeEditor: true,
- models: true,
- components: true,
- componentTrees: true,
- workflows: true,
- lambdas: true,
- styling: true,
- flaskApi: true,
- playwright: true,
- storybook: true,
- unitTests: true,
- errorRepair: true,
- documentation: true,
- sassStyles: true,
- faviconDesigner: true,
- ideaCloud: true,
-}
-
-const DEFAULT_THEME: ThemeConfig = {
- variants: [
- {
- id: 'light',
- name: 'Light',
- colors: {
- primaryColor: '#1976d2',
- secondaryColor: '#dc004e',
- errorColor: '#f44336',
- warningColor: '#ff9800',
- successColor: '#4caf50',
- background: '#ffffff',
- surface: '#f5f5f5',
- text: '#000000',
- textSecondary: '#666666',
- border: '#e0e0e0',
- customColors: {},
- },
- },
- {
- id: 'dark',
- name: 'Dark',
- colors: {
- primaryColor: '#90caf9',
- secondaryColor: '#f48fb1',
- errorColor: '#f44336',
- warningColor: '#ffa726',
- successColor: '#66bb6a',
- background: '#121212',
- surface: '#1e1e1e',
- text: '#ffffff',
- textSecondary: '#b0b0b0',
- border: '#333333',
- customColors: {},
- },
- },
- ],
- activeVariantId: 'light',
- fontFamily: 'Roboto, Arial, sans-serif',
- fontSize: { small: 12, medium: 14, large: 20 },
- spacing: 8,
- borderRadius: 4,
-}
-
-const DEFAULT_FILES: ProjectFile[] = [
- {
- id: 'file-1',
- name: 'page.tsx',
- path: '/src/app/page.tsx',
- content: `'use client'\n\nimport { ThemeProvider } from '@mui/material/styles'\nimport CssBaseline from '@mui/material/CssBaseline'\nimport { theme } from '@/theme'\nimport { Box, Typography, Button } from '@mui/material'\n\nexport default function Home() {\n return (\n \n \n \n \n Welcome to Your App\n \n \n \n \n )\n}`,
- language: 'typescript',
- },
- {
- id: 'file-2',
- name: 'layout.tsx',
- path: '/src/app/layout.tsx',
- content: `export const metadata = {\n title: 'My Next.js App',\n description: 'Generated with CodeForge',\n}\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode\n}) {\n return (\n \n {children}\n \n )\n}`,
- language: 'typescript',
- },
-]
function App() {
- const [files, setFiles] = useKV('project-files', DEFAULT_FILES)
- const [models, setModels] = useKV('project-models', [])
- const [components, setComponents] = useKV('project-components', [])
- const [componentTrees, setComponentTrees] = useKV('project-component-trees', [
- {
- id: 'default-tree',
- name: 'Main App',
- description: 'Default component tree',
- rootNodes: [],
- createdAt: Date.now(),
- updatedAt: Date.now(),
- },
- ])
- const [workflows, setWorkflows] = useKV('project-workflows', [])
- const [lambdas, setLambdas] = useKV('project-lambdas', [])
- const [theme, setTheme] = useKV('project-theme', DEFAULT_THEME)
- const [playwrightTests, setPlaywrightTests] = useKV('project-playwright-tests', [])
- const [storybookStories, setStorybookStories] = useKV('project-storybook-stories', [])
- const [unitTests, setUnitTests] = useKV('project-unit-tests', [])
- const [flaskConfig, setFlaskConfig] = useKV('project-flask-config', DEFAULT_FLASK_CONFIG)
- const [nextjsConfig, setNextjsConfig] = useKV('project-nextjs-config', DEFAULT_NEXTJS_CONFIG)
- const [npmSettings, setNpmSettings] = useKV('project-npm-settings', DEFAULT_NPM_SETTINGS)
- const [featureToggles, setFeatureToggles] = useKV('project-feature-toggles', DEFAULT_FEATURE_TOGGLES)
- const [activeFileId, setActiveFileId] = useState(null)
- const [activeTab, setActiveTab] = useState('dashboard')
- const [exportDialogOpen, setExportDialogOpen] = useState(false)
- const [shortcutsDialogOpen, setShortcutsDialogOpen] = useState(false)
- const [searchDialogOpen, setSearchDialogOpen] = useState(false)
- const [generatedCode, setGeneratedCode] = useState>({})
- const [lastSaved, setLastSaved] = useState(Date.now())
-
- const safeFiles = Array.isArray(files) ? files : []
- const safeModels = Array.isArray(models) ? models : []
- const safeComponents = Array.isArray(components) ? components : []
- const safeComponentTrees = Array.isArray(componentTrees) ? componentTrees : []
- const safeWorkflows = Array.isArray(workflows) ? workflows : []
- const safeLambdas = Array.isArray(lambdas) ? lambdas : []
- const safeTheme = (theme && theme.variants && Array.isArray(theme.variants) && theme.variants.length > 0) ? theme : DEFAULT_THEME
- const safePlaywrightTests = Array.isArray(playwrightTests) ? playwrightTests : []
- const safeStorybookStories = Array.isArray(storybookStories) ? storybookStories : []
- const safeUnitTests = Array.isArray(unitTests) ? unitTests : []
- const safeFlaskConfig = flaskConfig || DEFAULT_FLASK_CONFIG
- const safeNextjsConfig = nextjsConfig || DEFAULT_NEXTJS_CONFIG
- const safeNpmSettings = npmSettings || DEFAULT_NPM_SETTINGS
- const safeFeatureToggles = featureToggles || DEFAULT_FEATURE_TOGGLES
-
- useEffect(() => {
- if (safeFiles.length > 0 && !activeFileId) {
- setActiveFileId(safeFiles[0].id)
- }
- }, [safeFiles, activeFileId])
-
- useEffect(() => {
- const params = new URLSearchParams(window.location.search)
- const shortcut = params.get('shortcut')
- if (shortcut) {
- setActiveTab(shortcut)
- }
- }, [])
-
- useEffect(() => {
- if (!theme || !theme.variants || theme.variants.length === 0) {
- setTheme(DEFAULT_THEME)
- }
- }, [theme, setTheme])
-
- useEffect(() => {
- if (!featureToggles) {
- setFeatureToggles(DEFAULT_FEATURE_TOGGLES)
- }
- }, [featureToggles, setFeatureToggles])
-
- useEffect(() => {
- setLastSaved(Date.now())
- }, [
+ const projectState = useProjectState()
+ const {
files,
models,
components,
@@ -257,263 +51,59 @@ function App() {
nextjsConfig,
npmSettings,
featureToggles,
- ])
+ setFiles,
+ setModels,
+ setComponents,
+ setComponentTrees,
+ setWorkflows,
+ setLambdas,
+ setTheme,
+ setPlaywrightTests,
+ setStorybookStories,
+ setUnitTests,
+ setFlaskConfig,
+ setNextjsConfig,
+ setNpmSettings,
+ setFeatureToggles,
+ } = projectState
- const { errors: autoDetectedErrors = [] } = useAutoRepair(safeFiles, false)
- const errorCount = Array.isArray(autoDetectedErrors) ? autoDetectedErrors.length : 0
+ const fileOps = useFileOperations(files, setFiles)
+ const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
+
+ const [activeTab, setActiveTab] = useState('dashboard')
+ const [searchOpen, setSearchOpen] = useState(false)
+ const [shortcutsOpen, setShortcutsOpen] = useState(false)
+ const [lastSaved] = useState(Date.now())
+
+ const { errors = [] } = useAutoRepair(files, false)
+ const errorCount = errors.length
useKeyboardShortcuts([
- {
- key: '1',
- ctrl: true,
- description: 'Go to Dashboard',
- action: () => setActiveTab('dashboard'),
- },
- ...(safeFeatureToggles.codeEditor ? [{
- key: '2',
- ctrl: true,
- description: 'Go to Code Editor',
- action: () => setActiveTab('code'),
- }] : []),
- ...(safeFeatureToggles.models ? [{
- key: '3',
- ctrl: true,
- description: 'Go to Models',
- action: () => setActiveTab('models'),
- }] : []),
- ...(safeFeatureToggles.components ? [{
- key: '4',
- ctrl: true,
- description: 'Go to Components',
- action: () => setActiveTab('components'),
- }] : []),
- ...(safeFeatureToggles.componentTrees ? [{
- key: '5',
- ctrl: true,
- description: 'Go to Component Trees',
- action: () => setActiveTab('component-trees'),
- }] : []),
- ...(safeFeatureToggles.workflows ? [{
- key: '6',
- ctrl: true,
- description: 'Go to Workflows',
- action: () => setActiveTab('workflows'),
- }] : []),
- ...(safeFeatureToggles.lambdas ? [{
- key: '7',
- ctrl: true,
- description: 'Go to Lambdas',
- action: () => setActiveTab('lambdas'),
- }] : []),
- ...(safeFeatureToggles.styling ? [{
- key: '8',
- ctrl: true,
- description: 'Go to Styling',
- action: () => setActiveTab('styling'),
- }] : []),
- ...(safeFeatureToggles.faviconDesigner ? [{
- key: '9',
- ctrl: true,
- description: 'Go to Favicon Designer',
- action: () => setActiveTab('favicon'),
- }] : []),
- {
- key: 'k',
- ctrl: true,
- description: 'Search everything',
- action: () => setSearchDialogOpen(true),
- },
- {
- key: 'e',
- ctrl: true,
- description: 'Export Project',
- action: () => handleExportProject(),
- },
- {
- key: 'g',
- ctrl: true,
- shift: true,
- description: 'AI Generate',
- action: () => handleGenerateWithAI(),
- },
- {
- key: '/',
- ctrl: true,
- description: 'Show Keyboard Shortcuts',
- action: () => setShortcutsDialogOpen(true),
- },
+ { key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
+ { key: '2', ctrl: true, description: 'Code', action: () => setActiveTab('code') },
+ { key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) },
+ { key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
])
- const handleFileChange = (fileId: string, content: string) => {
- setFiles((currentFiles) =>
- (currentFiles || []).map((f) => (f.id === fileId ? { ...f, content } : f))
- )
- }
+ const getCurrentProject = () => ({
+ name: nextjsConfig.appName,
+ files,
+ models,
+ components,
+ componentTrees,
+ workflows,
+ lambdas,
+ theme,
+ playwrightTests,
+ storybookStories,
+ unitTests,
+ flaskConfig,
+ nextjsConfig,
+ npmSettings,
+ featureToggles,
+ })
- const handleFileAdd = (file: ProjectFile) => {
- setFiles((currentFiles) => [...(currentFiles || []), file])
- setActiveFileId(file.id)
- }
-
- const handleFileClose = (fileId: string) => {
- if (activeFileId === fileId) {
- const currentIndex = safeFiles.findIndex((f) => f.id === fileId)
- const nextFile = safeFiles[currentIndex + 1] || safeFiles[currentIndex - 1]
- setActiveFileId(nextFile?.id || null)
- }
- }
-
- const handleExportProject = () => {
- const projectFiles = generateNextJSProject(safeNextjsConfig.appName, safeModels, safeComponents, safeTheme)
-
- const prismaSchema = generatePrismaSchema(safeModels)
- const themeCode = generateMUITheme(safeTheme)
- const playwrightTestCode = generatePlaywrightTests(safePlaywrightTests)
- const storybookFiles = generateStorybookStories(safeStorybookStories)
- const unitTestFiles = generateUnitTests(safeUnitTests)
- const flaskFiles = generateFlaskApp(safeFlaskConfig)
-
- const packageJson = {
- name: safeNextjsConfig.appName,
- version: '0.1.0',
- private: true,
- scripts: safeNpmSettings.scripts,
- dependencies: safeNpmSettings.packages
- .filter(pkg => !pkg.isDev)
- .reduce((acc, pkg) => {
- acc[pkg.name] = pkg.version
- return acc
- }, {} as Record),
- devDependencies: safeNpmSettings.packages
- .filter(pkg => pkg.isDev)
- .reduce((acc, pkg) => {
- acc[pkg.name] = pkg.version
- return acc
- }, {} as Record),
- }
-
- const allFiles: Record = {
- ...projectFiles,
- 'package.json': JSON.stringify(packageJson, null, 2),
- 'prisma/schema.prisma': prismaSchema,
- 'src/theme.ts': themeCode,
- 'e2e/tests.spec.ts': playwrightTestCode,
- ...storybookFiles,
- ...unitTestFiles,
- }
-
- Object.entries(flaskFiles).forEach(([path, content]) => {
- allFiles[`backend/${path}`] = content
- })
-
- safeFiles.forEach(file => {
- allFiles[file.path] = file.content
- })
-
- setGeneratedCode(allFiles)
- setExportDialogOpen(true)
- toast.success('Project files generated!')
- }
-
- const handleDownloadZip = async () => {
- try {
- toast.info('Creating ZIP file...')
-
- const zip = new JSZip()
-
- Object.entries(generatedCode).forEach(([path, content]) => {
- const cleanPath = path.startsWith('/') ? path.slice(1) : path
- zip.file(cleanPath, content)
- })
-
- zip.file('README.md', `# ${safeNextjsConfig.appName}
-
-Generated with CodeForge
-
-## Getting Started
-
-1. Install dependencies:
-\`\`\`bash
-npm install
-\`\`\`
-
-2. Set up Prisma (if using database):
-\`\`\`bash
-npx prisma generate
-npx prisma db push
-\`\`\`
-
-3. Run the development server:
-\`\`\`bash
-npm run dev
-\`\`\`
-
-4. Open [http://localhost:3000](http://localhost:3000) in your browser.
-
-## Testing
-
-Run E2E tests:
-\`\`\`bash
-npm run test:e2e
-\`\`\`
-
-Run unit tests:
-\`\`\`bash
-npm run test
-\`\`\`
-
-## Flask Backend (Optional)
-
-Navigate to the backend directory and follow the setup instructions.
-`)
-
- const blob = await zip.generateAsync({ type: 'blob' })
- const url = URL.createObjectURL(blob)
- const a = document.createElement('a')
- a.href = url
- a.download = `${safeNextjsConfig.appName}.zip`
- document.body.appendChild(a)
- a.click()
- document.body.removeChild(a)
- URL.revokeObjectURL(url)
-
- toast.success('Project downloaded successfully!')
- } catch (error) {
- console.error('Failed to create ZIP:', error)
- toast.error('Failed to create ZIP file')
- }
- }
-
- const handleGenerateWithAI = async () => {
- const description = prompt('Describe the application you want to generate:')
- if (!description) return
-
- try {
- toast.info('Generating application with AI...')
-
- const result = await AIService.generateCompleteApp(description)
-
- if (result) {
- if (result.files && result.files.length > 0) {
- setFiles((currentFiles) => [...(currentFiles || []), ...result.files])
- }
- if (result.models && result.models.length > 0) {
- setModels((currentModels) => [...(currentModels || []), ...result.models])
- }
- if (result.theme) {
- setTheme((currentTheme) => ({ ...(currentTheme || DEFAULT_THEME), ...result.theme }))
- }
- toast.success('Application generated successfully!')
- } else {
- toast.error('AI generation failed. Please try again.')
- }
- } catch (error) {
- toast.error('AI generation failed')
- console.error(error)
- }
- }
-
- const handleLoadProject = (project: Project) => {
+ const handleProjectLoad = (project: any) => {
if (project.files) setFiles(project.files)
if (project.models) setModels(project.models)
if (project.components) setComponents(project.components)
@@ -528,71 +118,49 @@ Navigate to the backend directory and follow the setup instructions.
if (project.nextjsConfig) setNextjsConfig(project.nextjsConfig)
if (project.npmSettings) setNpmSettings(project.npmSettings)
if (project.featureToggles) setFeatureToggles(project.featureToggles)
- }
-
- const getCurrentProject = (): Project => {
- return {
- name: safeNextjsConfig.appName,
- files: safeFiles,
- models: safeModels,
- components: safeComponents,
- componentTrees: safeComponentTrees,
- workflows: safeWorkflows,
- lambdas: safeLambdas,
- theme: safeTheme,
- playwrightTests: safePlaywrightTests,
- storybookStories: safeStorybookStories,
- unitTests: safeUnitTests,
- flaskConfig: safeFlaskConfig,
- nextjsConfig: safeNextjsConfig,
- npmSettings: safeNpmSettings,
- featureToggles: safeFeatureToggles,
- }
+ toast.success('Project loaded')
}
return (
-
+
-
setSearchDialogOpen(true)}
- onShowShortcuts={() => setShortcutsDialogOpen(true)}
- onGenerateAI={handleGenerateWithAI}
- onExport={handleExportProject}
+ onProjectLoad={handleProjectLoad}
+ onSearch={() => setSearchOpen(true)}
+ onShowShortcuts={() => setShortcutsOpen(true)}
+ onGenerateAI={() => toast.info('AI generation coming soon')}
+ onExport={() => toast.info('Export coming soon')}
onShowErrors={() => setActiveTab('errors')}
/>
-
-
- {safeFeatureToggles.codeEditor && (
+ {featureToggles.codeEditor && (
)}
- {safeFeatureToggles.models && (
+ {featureToggles.models && (
-
+
)}
- {safeFeatureToggles.components && (
+ {featureToggles.components && (
-
+
)}
- {safeFeatureToggles.componentTrees && (
+ {featureToggles.componentTrees && (
-
+
)}
- {safeFeatureToggles.workflows && (
+ {featureToggles.workflows && (
-
+
)}
- {safeFeatureToggles.lambdas && (
+ {featureToggles.lambdas && (
-
+
)}
- {safeFeatureToggles.styling && (
+ {featureToggles.styling && (
-
+
)}
- {safeFeatureToggles.flaskApi && (
+ {featureToggles.flaskApi && (
-
+
)}
@@ -680,59 +236,52 @@ Navigate to the backend directory and follow the setup instructions.
-
+
- {safeFeatureToggles.playwright && (
+ {featureToggles.playwright && (
-
+
)}
- {safeFeatureToggles.storybook && (
+ {featureToggles.storybook && (
-
+
)}
- {safeFeatureToggles.unitTests && (
+ {featureToggles.unitTests && (
-
+
)}
- {safeFeatureToggles.errorRepair && (
+ {featureToggles.errorRepair && (
-
+
)}
- {safeFeatureToggles.documentation && (
+ {featureToggles.documentation && (
)}
- {safeFeatureToggles.sassStyles && (
+ {featureToggles.sassStyles && (
)}
- {safeFeatureToggles.faviconDesigner && (
+ {featureToggles.faviconDesigner && (
)}
- {safeFeatureToggles.ideaCloud && (
+ {featureToggles.ideaCloud && (
@@ -740,89 +289,26 @@ Navigate to the backend directory and follow the setup instructions.
-
-
-
-
{
- setActiveTab(tab)
- }}
+ open={searchOpen}
+ onOpenChange={setSearchOpen}
+ files={files}
+ models={models}
+ components={components}
+ componentTrees={componentTrees}
+ workflows={workflows}
+ lambdas={lambdas}
+ playwrightTests={playwrightTests}
+ storybookStories={storybookStories}
+ unitTests={unitTests}
+ onNavigate={setActiveTab}
onFileSelect={setActiveFileId}
/>
+
)
}
-export default App
\ No newline at end of file
+export default App
diff --git a/src/ErrorFallback.tsx b/src/ErrorFallback.tsx
index d628fcd..6abc14b 100644
--- a/src/ErrorFallback.tsx
+++ b/src/ErrorFallback.tsx
@@ -3,9 +3,12 @@ import { Button } from "./components/ui/button";
import { AlertTriangleIcon, RefreshCwIcon } from "lucide-react";
-export const ErrorFallback = ({ error, resetErrorBoundary }) => {
- // When encountering an error in the development mode, rethrow it and don't display the boundary.
- // The parent UI will take care of showing a more helpful dialog.
+interface ErrorFallbackProps {
+ error: Error;
+ resetErrorBoundary: () => void;
+}
+
+export const ErrorFallback = ({ error, resetErrorBoundary }: ErrorFallbackProps) => {
if (import.meta.env.DEV) throw error;
return (
diff --git a/src/config/orchestration/component-registry.ts b/src/config/orchestration/component-registry.ts
index 303ca32..bf94b11 100644
--- a/src/config/orchestration/component-registry.ts
+++ b/src/config/orchestration/component-registry.ts
@@ -9,7 +9,22 @@ import { ProjectDashboard } from '@/components/ProjectDashboard'
import { CodeEditor } from '@/components/CodeEditor'
import { ModelDesigner } from '@/components/ModelDesigner'
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
+import { ComponentTreeManager } from '@/components/ComponentTreeManager'
+import { WorkflowDesigner } from '@/components/WorkflowDesigner'
+import { LambdaDesigner } from '@/components/LambdaDesigner'
import { StyleDesigner } from '@/components/StyleDesigner'
+import { FileExplorer } from '@/components/FileExplorer'
+import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
+import { StorybookDesigner } from '@/components/StorybookDesigner'
+import { UnitTestDesigner } from '@/components/UnitTestDesigner'
+import { FlaskDesigner } from '@/components/FlaskDesigner'
+import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
+import { ErrorPanel } from '@/components/ErrorPanel'
+import { DocumentationView } from '@/components/DocumentationView'
+import { SassStylesShowcase } from '@/components/SassStylesShowcase'
+import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
+import { PWASettings } from '@/components/PWASettings'
+import { FaviconDesigner } from '@/components/FaviconDesigner'
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
export const ComponentRegistry: Record
> = {
@@ -27,7 +42,22 @@ export const ComponentRegistry: Record> = {
CodeEditor,
ModelDesigner,
ComponentTreeBuilder,
+ ComponentTreeManager,
+ WorkflowDesigner,
+ LambdaDesigner,
StyleDesigner,
+ FileExplorer,
+ PlaywrightDesigner,
+ StorybookDesigner,
+ UnitTestDesigner,
+ FlaskDesigner,
+ ProjectSettingsDesigner,
+ ErrorPanel,
+ DocumentationView,
+ SassStylesShowcase,
+ FeatureToggleSettings,
+ PWASettings,
+ FaviconDesigner,
FeatureIdeaCloud,
}