@builderos/create-agent-os 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/bin/cli.js +133 -0
- package/package.json +40 -0
- package/src/template/App.tsx +68 -0
- package/src/template/agent-os/commands/create-tasks/1-get-spec-requirements.md +19 -0
- package/src/template/agent-os/commands/create-tasks/2-create-tasks-list.md +234 -0
- package/src/template/agent-os/commands/create-tasks/create-tasks.md +254 -0
- package/src/template/agent-os/commands/design-screen/design-screen.md +32 -0
- package/src/template/agent-os/commands/design-shell/design-shell.md +34 -0
- package/src/template/agent-os/commands/design-tokens/design-tokens.md +36 -0
- package/src/template/agent-os/commands/export-product/export-product.md +44 -0
- package/src/template/agent-os/commands/implement-tasks/1-determine-tasks.md +13 -0
- package/src/template/agent-os/commands/implement-tasks/2-implement-tasks.md +63 -0
- package/src/template/agent-os/commands/implement-tasks/3-verify-implementation.md +113 -0
- package/src/template/agent-os/commands/implement-tasks/implement-tasks.md +207 -0
- package/src/template/agent-os/commands/initialize-design/initialize-design.md +54 -0
- package/src/template/agent-os/commands/orchestrate-tasks/orchestrate-tasks.md +180 -0
- package/src/template/agent-os/commands/plan-product/1-product-concept.md +53 -0
- package/src/template/agent-os/commands/plan-product/2-create-mission.md +78 -0
- package/src/template/agent-os/commands/plan-product/3-create-roadmap.md +73 -0
- package/src/template/agent-os/commands/plan-product/4-create-tech-stack.md +46 -0
- package/src/template/agent-os/commands/plan-product/plan-product.md +241 -0
- package/src/template/agent-os/commands/sample-data/sample-data.md +51 -0
- package/src/template/agent-os/commands/scaffold-implementation/scaffold-implementation.md +36 -0
- package/src/template/agent-os/commands/screenshot-design/screenshot-design.md +21 -0
- package/src/template/agent-os/commands/shape-spec/1-initialize-spec.md +95 -0
- package/src/template/agent-os/commands/shape-spec/2-shape-spec.md +300 -0
- package/src/template/agent-os/commands/shape-spec/shape-spec.md +40 -0
- package/src/template/agent-os/commands/write-spec/write-spec.md +134 -0
- package/src/template/agent-os/config.yml +13 -0
- package/src/template/agent-os/product/mission.md +29 -0
- package/src/template/agent-os/product/roadmap.md +9 -0
- package/src/template/agent-os/product/tech-stack.md +14 -0
- package/src/template/agent-os/specs/README.md +1 -0
- package/src/template/agent-os/standards/backend/api.md +10 -0
- package/src/template/agent-os/standards/backend/migrations.md +9 -0
- package/src/template/agent-os/standards/backend/models.md +10 -0
- package/src/template/agent-os/standards/backend/queries.md +9 -0
- package/src/template/agent-os/standards/frontend/accessibility.md +10 -0
- package/src/template/agent-os/standards/frontend/components.md +11 -0
- package/src/template/agent-os/standards/frontend/css.md +7 -0
- package/src/template/agent-os/standards/frontend/responsive.md +11 -0
- package/src/template/agent-os/standards/global/coding-style.md +10 -0
- package/src/template/agent-os/standards/global/commenting.md +5 -0
- package/src/template/agent-os/standards/global/conventions.md +11 -0
- package/src/template/agent-os/standards/global/error-handling.md +9 -0
- package/src/template/agent-os/standards/global/tech-stack.md +31 -0
- package/src/template/agent-os/standards/global/validation.md +11 -0
- package/src/template/agent-os/standards/testing/test-writing.md +9 -0
- package/src/template/agent-os-ui/README.md +73 -0
- package/src/template/agent-os-ui/package-lock.json +5028 -0
- package/src/template/agent-os-ui/package.json +52 -0
- package/src/template/agent-os-ui/postcss.config.js +6 -0
- package/src/template/agent-os-ui/src/components/AgentShell.tsx +31 -0
- package/src/template/agent-os-ui/src/components/AgentSidebar.tsx +65 -0
- package/src/template/agent-os-ui/src/components/GuidanceCard.tsx +75 -0
- package/src/template/agent-os-ui/src/components/MarkdownViewer.tsx +25 -0
- package/src/template/agent-os-ui/src/components/PromptButton.tsx +28 -0
- package/src/template/agent-os-ui/src/components/StatusItem.tsx +45 -0
- package/src/template/agent-os-ui/src/components/ThemeToggle.tsx +72 -0
- package/src/template/agent-os-ui/src/index.ts +11 -0
- package/src/template/agent-os-ui/src/style.css +3 -0
- package/src/template/agent-os-ui/tailwind.config.js +50 -0
- package/src/template/agent-os-ui/tsconfig.json +33 -0
- package/src/template/agent-os-ui/vite.config.ts +32 -0
- package/src/template/control-center/backend/backend.log +2 -0
- package/src/template/control-center/backend/index.js +228 -0
- package/src/template/control-center/backend/package-lock.json +951 -0
- package/src/template/control-center/backend/package.json +19 -0
- package/src/template/control-center/frontend/README.md +73 -0
- package/src/template/control-center/frontend/eslint.config.js +23 -0
- package/src/template/control-center/frontend/index.html +21 -0
- package/src/template/control-center/frontend/package-lock.json +5752 -0
- package/src/template/control-center/frontend/package.json +42 -0
- package/src/template/control-center/frontend/public/runtime-config.json +11 -0
- package/src/template/control-center/frontend/public/vite.svg +1 -0
- package/src/template/control-center/frontend/src/App.css +42 -0
- package/src/template/control-center/frontend/src/App.tsx +738 -0
- package/src/template/control-center/frontend/src/assets/react.svg +1 -0
- package/src/template/control-center/frontend/src/components/ThemeToggle.tsx +64 -0
- package/src/template/control-center/frontend/src/components/ui/ToastContext.tsx +81 -0
- package/src/template/control-center/frontend/src/index.css +194 -0
- package/src/template/control-center/frontend/src/main.tsx +14 -0
- package/src/template/control-center/frontend/src/vite-env.d.ts +1 -0
- package/src/template/control-center/frontend/tsconfig.app.json +28 -0
- package/src/template/control-center/frontend/tsconfig.json +7 -0
- package/src/template/control-center/frontend/tsconfig.node.json +26 -0
- package/src/template/control-center/frontend/vite.config.ts +22 -0
- package/src/template/design/.claude/commands/design-os/data-model.md +122 -0
- package/src/template/design/.claude/commands/design-os/design-screen.md +309 -0
- package/src/template/design/.claude/commands/design-os/design-shell.md +238 -0
- package/src/template/design/.claude/commands/design-os/design-tokens.md +166 -0
- package/src/template/design/.claude/commands/design-os/export-product.md +1105 -0
- package/src/template/design/.claude/commands/design-os/product-roadmap.md +121 -0
- package/src/template/design/.claude/commands/design-os/product-vision.md +99 -0
- package/src/template/design/.claude/commands/design-os/sample-data.md +263 -0
- package/src/template/design/.claude/commands/design-os/screenshot-design.md +112 -0
- package/src/template/design/.claude/commands/design-os/shape-section.md +138 -0
- package/src/template/design/.claude/skills/frontend-design/SKILL.md +42 -0
- package/src/template/design/.github/CODE_OF_CONDUCT.md +5 -0
- package/src/template/design/.github/CONTRIBUTING.md +51 -0
- package/src/template/design/.github/ISSUE_TEMPLATE/config.yml +22 -0
- package/src/template/design/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- package/src/template/design/.github/SECURITY.yml +5 -0
- package/src/template/design/.github/SUPPORT.md +19 -0
- package/src/template/design/.github/workflows/pr-decline.yml +135 -0
- package/src/template/design/.github/workflows/stale.yml +25 -0
- package/src/template/design/CHANGELOG.md +13 -0
- package/src/template/design/LICENSE +21 -0
- package/src/template/design/README.md +54 -0
- package/src/template/design/agents.md +218 -0
- package/src/template/design/claude.md +1 -0
- package/src/template/design/components.json +22 -0
- package/src/template/design/docs/codebase-implementation.md +153 -0
- package/src/template/design/docs/design-section.md +135 -0
- package/src/template/design/docs/export.md +149 -0
- package/src/template/design/docs/getting-started.md +59 -0
- package/src/template/design/docs/index.md +56 -0
- package/src/template/design/docs/product-planning.md +113 -0
- package/src/template/design/docs/requirements.md +22 -0
- package/src/template/design/docs/usage.md +62 -0
- package/src/template/design/eslint.config.js +23 -0
- package/src/template/design/index.html +21 -0
- package/src/template/design/package-lock.json +5473 -0
- package/src/template/design/package.json +47 -0
- package/src/template/design/product-plan.zip +0 -0
- package/src/template/design/public/vite.svg +1 -0
- package/src/template/design/src/assets/react.svg +1 -0
- package/src/template/design/src/components/AppLayout.tsx +95 -0
- package/src/template/design/src/components/DataCard.tsx +139 -0
- package/src/template/design/src/components/DataModelPage.tsx +120 -0
- package/src/template/design/src/components/DesignPage.tsx +284 -0
- package/src/template/design/src/components/EmptyState.tsx +155 -0
- package/src/template/design/src/components/ExportPage.tsx +344 -0
- package/src/template/design/src/components/NextPhaseButton.tsx +33 -0
- package/src/template/design/src/components/PhaseNav.tsx +152 -0
- package/src/template/design/src/components/PhaseWarningBanner.tsx +81 -0
- package/src/template/design/src/components/ProductOverviewCard.tsx +102 -0
- package/src/template/design/src/components/ProductPage.tsx +97 -0
- package/src/template/design/src/components/ScreenDesignPage.tsx +370 -0
- package/src/template/design/src/components/ScreenDesignsCard.tsx +49 -0
- package/src/template/design/src/components/SectionPage.tsx +256 -0
- package/src/template/design/src/components/SectionsCard.tsx +47 -0
- package/src/template/design/src/components/SectionsPage.tsx +181 -0
- package/src/template/design/src/components/ShellCard.tsx +85 -0
- package/src/template/design/src/components/ShellDesignPage.tsx +242 -0
- package/src/template/design/src/components/SpecCard.tsx +121 -0
- package/src/template/design/src/components/StepIndicator.tsx +75 -0
- package/src/template/design/src/components/ThemeToggle.tsx +86 -0
- package/src/template/design/src/components/ui/ToastContext.tsx +81 -0
- package/src/template/design/src/components/ui/avatar.tsx +53 -0
- package/src/template/design/src/components/ui/badge.tsx +46 -0
- package/src/template/design/src/components/ui/button.tsx +60 -0
- package/src/template/design/src/components/ui/card.tsx +92 -0
- package/src/template/design/src/components/ui/collapsible.tsx +48 -0
- package/src/template/design/src/components/ui/dialog.tsx +143 -0
- package/src/template/design/src/components/ui/dropdown-menu.tsx +255 -0
- package/src/template/design/src/components/ui/input.tsx +21 -0
- package/src/template/design/src/components/ui/label.tsx +22 -0
- package/src/template/design/src/components/ui/progress.tsx +24 -0
- package/src/template/design/src/components/ui/scroll-area.tsx +18 -0
- package/src/template/design/src/components/ui/select.tsx +67 -0
- package/src/template/design/src/components/ui/separator.tsx +28 -0
- package/src/template/design/src/components/ui/sheet.tsx +137 -0
- package/src/template/design/src/components/ui/skeleton.tsx +13 -0
- package/src/template/design/src/components/ui/switch.tsx +46 -0
- package/src/template/design/src/components/ui/table.tsx +116 -0
- package/src/template/design/src/components/ui/tabs.tsx +64 -0
- package/src/template/design/src/index.css +284 -0
- package/src/template/design/src/lib/data-model-loader.ts +91 -0
- package/src/template/design/src/lib/design-system-loader.ts +101 -0
- package/src/template/design/src/lib/product-loader.ts +221 -0
- package/src/template/design/src/lib/router.tsx +52 -0
- package/src/template/design/src/lib/section-loader.ts +272 -0
- package/src/template/design/src/lib/shell-loader.ts +175 -0
- package/src/template/design/src/lib/utils.ts +6 -0
- package/src/template/design/src/main.tsx +15 -0
- package/src/template/design/src/sections/.gitkeep +0 -0
- package/src/template/design/src/sections/ai-orchestration-engine-oai/OrchestrationEngine.tsx +348 -0
- package/src/template/design/src/sections/core-platform-shell/AppShell.tsx +403 -0
- package/src/template/design/src/sections/gemini-live-integration/GeminiIntegration.tsx +332 -0
- package/src/template/design/src/sections/interactive-2d-canvas/WhiteboardCanvas.tsx +334 -0
- package/src/template/design/src/sections/participation-equity-tracker/EquityTracker.tsx +383 -0
- package/src/template/design/src/sections/persistent-memory-system/PersistentMemory.tsx +308 -0
- package/src/template/design/src/sections/real-time-communication-layer/VideoSession.tsx +342 -0
- package/src/template/design/src/sections/visual-intelligence-agents/VisualAgents.tsx +311 -0
- package/src/template/design/src/types/product.ts +97 -0
- package/src/template/design/src/types/section.ts +33 -0
- package/src/template/design/tsconfig.app.json +34 -0
- package/src/template/design/tsconfig.json +13 -0
- package/src/template/design/tsconfig.node.json +26 -0
- package/src/template/design/vite.config.ts +18 -0
- package/src/template/package.json +27 -0
- package/src/template/vite.config.ts +16 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createBrowserRouter } from 'react-router-dom'
|
|
2
|
+
import { ProductPage } from '@/components/ProductPage'
|
|
3
|
+
import { DataModelPage } from '@/components/DataModelPage'
|
|
4
|
+
import { DesignPage } from '@/components/DesignPage'
|
|
5
|
+
import { SectionsPage } from '@/components/SectionsPage'
|
|
6
|
+
import { SectionPage } from '@/components/SectionPage'
|
|
7
|
+
import { ScreenDesignPage, ScreenDesignFullscreen } from '@/components/ScreenDesignPage'
|
|
8
|
+
import { ShellDesignPage, ShellDesignFullscreen } from '@/components/ShellDesignPage'
|
|
9
|
+
import { ExportPage } from '@/components/ExportPage'
|
|
10
|
+
|
|
11
|
+
export const router = createBrowserRouter([
|
|
12
|
+
{
|
|
13
|
+
path: '/',
|
|
14
|
+
element: <ProductPage />,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
path: '/data-model',
|
|
18
|
+
element: <DataModelPage />,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
path: '/design',
|
|
22
|
+
element: <DesignPage />,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
path: '/sections',
|
|
26
|
+
element: <SectionsPage />,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
path: '/sections/:sectionId',
|
|
30
|
+
element: <SectionPage />,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
path: '/sections/:sectionId/screen-designs/:screenDesignName',
|
|
34
|
+
element: <ScreenDesignPage />,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
path: '/sections/:sectionId/screen-designs/:screenDesignName/fullscreen',
|
|
38
|
+
element: <ScreenDesignFullscreen />,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
path: '/shell/design',
|
|
42
|
+
element: <ShellDesignPage />,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
path: '/shell/design/fullscreen',
|
|
46
|
+
element: <ShellDesignFullscreen />,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
path: '/export',
|
|
50
|
+
element: <ExportPage />,
|
|
51
|
+
},
|
|
52
|
+
])
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section data loading utilities for spec.md, data.json, and screen designs
|
|
3
|
+
*
|
|
4
|
+
* File structure:
|
|
5
|
+
* - product/sections/[section-id]/spec.md - Section specification
|
|
6
|
+
* - product/sections/[section-id]/data.json - Sample data
|
|
7
|
+
* - src/sections/[section-id]/[PageName].tsx - Screen design pages
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SectionData, ParsedSpec, ScreenDesignInfo, ScreenshotInfo } from '@/types/section'
|
|
11
|
+
import type { ComponentType } from 'react'
|
|
12
|
+
|
|
13
|
+
// Load spec.md files from product/sections at build time
|
|
14
|
+
const specFiles = import.meta.glob('/product/sections/*/spec.md', {
|
|
15
|
+
query: '?raw',
|
|
16
|
+
import: 'default',
|
|
17
|
+
eager: true,
|
|
18
|
+
}) as Record<string, string>
|
|
19
|
+
|
|
20
|
+
// Load data.json files from product/sections at build time
|
|
21
|
+
const dataFiles = import.meta.glob('/product/sections/*/data.json', {
|
|
22
|
+
eager: true,
|
|
23
|
+
}) as Record<string, { default: Record<string, unknown> }>
|
|
24
|
+
|
|
25
|
+
// Load screen design components from src/sections lazily
|
|
26
|
+
const screenDesignModules = import.meta.glob('/src/sections/*/*.tsx') as Record<
|
|
27
|
+
string,
|
|
28
|
+
() => Promise<{ default: ComponentType }>
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
// Load screenshot files from product/sections at build time
|
|
32
|
+
const screenshotFiles = import.meta.glob('/product/sections/*/*.png', {
|
|
33
|
+
query: '?url',
|
|
34
|
+
import: 'default',
|
|
35
|
+
eager: true,
|
|
36
|
+
}) as Record<string, string>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Extract section ID from a product/sections file path
|
|
40
|
+
* e.g., "/product/sections/invoices/spec.md" -> "invoices"
|
|
41
|
+
*/
|
|
42
|
+
function extractSectionIdFromProduct(path: string): string | null {
|
|
43
|
+
const match = path.match(/\/product\/sections\/([^/]+)\//)
|
|
44
|
+
return match?.[1] || null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract section ID from a src/sections file path
|
|
49
|
+
* e.g., "/src/sections/invoices/InvoiceList.tsx" -> "invoices"
|
|
50
|
+
*/
|
|
51
|
+
function extractSectionIdFromSrc(path: string): string | null {
|
|
52
|
+
const match = path.match(/\/src\/sections\/([^/]+)\//)
|
|
53
|
+
return match?.[1] || null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extract screen design name from a file path
|
|
58
|
+
* e.g., "/src/sections/invoices/InvoiceList.tsx" -> "InvoiceList"
|
|
59
|
+
*/
|
|
60
|
+
function extractScreenDesignName(path: string): string | null {
|
|
61
|
+
const match = path.match(/\/src\/sections\/[^/]+\/([^/]+)\.tsx$/)
|
|
62
|
+
return match?.[1] || null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Extract screenshot name from a file path
|
|
67
|
+
* e.g., "/product/sections/invoices/invoice-list.png" -> "invoice-list"
|
|
68
|
+
*/
|
|
69
|
+
function extractScreenshotName(path: string): string | null {
|
|
70
|
+
const match = path.match(/\/product\/sections\/[^/]+\/([^/]+)\.png$/)
|
|
71
|
+
return match?.[1] || null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Parse spec.md content into ParsedSpec structure
|
|
76
|
+
*
|
|
77
|
+
* Expected format:
|
|
78
|
+
* # Section Specification
|
|
79
|
+
*
|
|
80
|
+
* ## Overview
|
|
81
|
+
* [Brief description of the section]
|
|
82
|
+
*
|
|
83
|
+
* ## User Flows
|
|
84
|
+
* - Flow 1
|
|
85
|
+
* - Flow 2
|
|
86
|
+
*
|
|
87
|
+
* ## UI Requirements
|
|
88
|
+
* - Requirement 1
|
|
89
|
+
* - Requirement 2
|
|
90
|
+
*
|
|
91
|
+
* ## Configuration (optional)
|
|
92
|
+
* - shell: false (to disable app shell wrapping for this section's screen designs)
|
|
93
|
+
*/
|
|
94
|
+
export function parseSpec(md: string): ParsedSpec | null {
|
|
95
|
+
if (!md || !md.trim()) return null
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
// Extract title from first # heading
|
|
99
|
+
const titleMatch = md.match(/^#\s+(.+)$/m)
|
|
100
|
+
const title = titleMatch?.[1]?.trim() || 'Section Specification'
|
|
101
|
+
|
|
102
|
+
// Extract overview - content between ## Overview and next ##
|
|
103
|
+
const overviewMatch = md.match(/## Overview\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
104
|
+
const overview = overviewMatch?.[1]?.trim() || ''
|
|
105
|
+
|
|
106
|
+
// Extract user flows - bullet list after ## User Flows
|
|
107
|
+
const userFlowsSection = md.match(/## User Flows\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
108
|
+
const userFlows: string[] = []
|
|
109
|
+
|
|
110
|
+
if (userFlowsSection?.[1]) {
|
|
111
|
+
const lines = userFlowsSection[1].split('\n')
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
const trimmed = line.trim()
|
|
114
|
+
if (trimmed.startsWith('- ')) {
|
|
115
|
+
userFlows.push(trimmed.slice(2).trim())
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Extract UI requirements - bullet list after ## UI Requirements
|
|
121
|
+
const uiReqSection = md.match(/## UI Requirements\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
122
|
+
const uiRequirements: string[] = []
|
|
123
|
+
|
|
124
|
+
if (uiReqSection?.[1]) {
|
|
125
|
+
const lines = uiReqSection[1].split('\n')
|
|
126
|
+
for (const line of lines) {
|
|
127
|
+
const trimmed = line.trim()
|
|
128
|
+
if (trimmed.startsWith('- ')) {
|
|
129
|
+
uiRequirements.push(trimmed.slice(2).trim())
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Extract configuration - check for shell: false
|
|
135
|
+
// Look for "shell: false" or "- shell: false" anywhere in the document
|
|
136
|
+
const shellDisabled = /(?:^|\n)\s*-?\s*shell\s*:\s*false/i.test(md)
|
|
137
|
+
const useShell = !shellDisabled
|
|
138
|
+
|
|
139
|
+
return { title, overview, userFlows, uiRequirements, useShell }
|
|
140
|
+
} catch {
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get screen designs for a specific section
|
|
147
|
+
*/
|
|
148
|
+
export function getSectionScreenDesigns(sectionId: string): ScreenDesignInfo[] {
|
|
149
|
+
const screenDesigns: ScreenDesignInfo[] = []
|
|
150
|
+
const prefix = `/src/sections/${sectionId}/`
|
|
151
|
+
|
|
152
|
+
for (const path of Object.keys(screenDesignModules)) {
|
|
153
|
+
if (path.startsWith(prefix)) {
|
|
154
|
+
const name = extractScreenDesignName(path)
|
|
155
|
+
if (name) {
|
|
156
|
+
screenDesigns.push({
|
|
157
|
+
name,
|
|
158
|
+
path,
|
|
159
|
+
componentName: name,
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return screenDesigns
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get screenshots for a specific section
|
|
170
|
+
*/
|
|
171
|
+
export function getSectionScreenshots(sectionId: string): ScreenshotInfo[] {
|
|
172
|
+
const screenshots: ScreenshotInfo[] = []
|
|
173
|
+
const prefix = `/product/sections/${sectionId}/`
|
|
174
|
+
|
|
175
|
+
for (const [path, url] of Object.entries(screenshotFiles)) {
|
|
176
|
+
if (path.startsWith(prefix)) {
|
|
177
|
+
const name = extractScreenshotName(path)
|
|
178
|
+
if (name) {
|
|
179
|
+
screenshots.push({
|
|
180
|
+
name,
|
|
181
|
+
path,
|
|
182
|
+
url,
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return screenshots
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Load screen design component dynamically
|
|
193
|
+
*/
|
|
194
|
+
export function loadScreenDesignComponent(
|
|
195
|
+
sectionId: string,
|
|
196
|
+
screenDesignName: string
|
|
197
|
+
): (() => Promise<{ default: ComponentType }>) | null {
|
|
198
|
+
const path = `/src/sections/${sectionId}/${screenDesignName}.tsx`
|
|
199
|
+
return screenDesignModules[path] || null
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Load all data for a specific section
|
|
204
|
+
*/
|
|
205
|
+
export function loadSectionData(sectionId: string): SectionData {
|
|
206
|
+
const specPath = `/product/sections/${sectionId}/spec.md`
|
|
207
|
+
const dataPath = `/product/sections/${sectionId}/data.json`
|
|
208
|
+
|
|
209
|
+
const specContent = specFiles[specPath] || null
|
|
210
|
+
const dataModule = dataFiles[dataPath]
|
|
211
|
+
const data = dataModule?.default || null
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
sectionId,
|
|
215
|
+
spec: specContent,
|
|
216
|
+
specParsed: specContent ? parseSpec(specContent) : null,
|
|
217
|
+
data,
|
|
218
|
+
screenDesigns: getSectionScreenDesigns(sectionId),
|
|
219
|
+
screenshots: getSectionScreenshots(sectionId),
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if a section has a spec.md file
|
|
225
|
+
*/
|
|
226
|
+
export function hasSectionSpec(sectionId: string): boolean {
|
|
227
|
+
return `/product/sections/${sectionId}/spec.md` in specFiles
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Check if a section's screen designs should use the app shell
|
|
232
|
+
* Returns true by default, false if spec contains "shell: false"
|
|
233
|
+
*/
|
|
234
|
+
export function sectionUsesShell(sectionId: string): boolean {
|
|
235
|
+
const specPath = `/product/sections/${sectionId}/spec.md`
|
|
236
|
+
const specContent = specFiles[specPath]
|
|
237
|
+
if (!specContent) return true // Default to using shell if no spec
|
|
238
|
+
|
|
239
|
+
const parsed = parseSpec(specContent)
|
|
240
|
+
return parsed?.useShell ?? true
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Check if a section has a data.json file
|
|
245
|
+
*/
|
|
246
|
+
export function hasSectionData(sectionId: string): boolean {
|
|
247
|
+
return `/product/sections/${sectionId}/data.json` in dataFiles
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get all section IDs that have any artifacts
|
|
252
|
+
*/
|
|
253
|
+
export function getAllSectionIds(): string[] {
|
|
254
|
+
const ids = new Set<string>()
|
|
255
|
+
|
|
256
|
+
for (const path of Object.keys(specFiles)) {
|
|
257
|
+
const id = extractSectionIdFromProduct(path)
|
|
258
|
+
if (id) ids.add(id)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
for (const path of Object.keys(dataFiles)) {
|
|
262
|
+
const id = extractSectionIdFromProduct(path)
|
|
263
|
+
if (id) ids.add(id)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (const path of Object.keys(screenDesignModules)) {
|
|
267
|
+
const id = extractSectionIdFromSrc(path)
|
|
268
|
+
if (id) ids.add(id)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return Array.from(ids)
|
|
272
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell loading and parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ShellSpec, ShellInfo } from '@/types/product'
|
|
6
|
+
import type { ComponentType, ReactNode } from 'react'
|
|
7
|
+
|
|
8
|
+
// Load shell spec markdown file at build time
|
|
9
|
+
const shellSpecFiles = import.meta.glob('/product/shell/*.md', {
|
|
10
|
+
query: '?raw',
|
|
11
|
+
import: 'default',
|
|
12
|
+
eager: true,
|
|
13
|
+
}) as Record<string, string>
|
|
14
|
+
|
|
15
|
+
// Load shell components lazily
|
|
16
|
+
const shellComponentModules = import.meta.glob('/src/shell/components/*.tsx') as Record<
|
|
17
|
+
string,
|
|
18
|
+
() => Promise<{ default: ComponentType }>
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
// Load shell preview component lazily
|
|
22
|
+
const shellPreviewModules = import.meta.glob('/src/shell/*.tsx') as Record<
|
|
23
|
+
string,
|
|
24
|
+
() => Promise<{ default: ComponentType }>
|
|
25
|
+
>
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Parse shell spec.md content into ShellSpec structure
|
|
29
|
+
*
|
|
30
|
+
* Expected format:
|
|
31
|
+
* # Application Shell Specification
|
|
32
|
+
*
|
|
33
|
+
* ## Overview
|
|
34
|
+
* Description of the shell design
|
|
35
|
+
*
|
|
36
|
+
* ## Navigation Structure
|
|
37
|
+
* - Nav Item 1 → Section
|
|
38
|
+
* - Nav Item 2 → Section
|
|
39
|
+
*
|
|
40
|
+
* ## Layout Pattern
|
|
41
|
+
* Description of layout (sidebar, top nav, etc.)
|
|
42
|
+
*/
|
|
43
|
+
export function parseShellSpec(md: string): ShellSpec | null {
|
|
44
|
+
if (!md || !md.trim()) return null
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
// Extract overview
|
|
48
|
+
const overviewMatch = md.match(/## Overview\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
49
|
+
const overview = overviewMatch?.[1]?.trim() || ''
|
|
50
|
+
|
|
51
|
+
// Extract navigation items
|
|
52
|
+
const navSection = md.match(/## Navigation Structure\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
53
|
+
const navigationItems: string[] = []
|
|
54
|
+
|
|
55
|
+
if (navSection?.[1]) {
|
|
56
|
+
const lines = navSection[1].split('\n')
|
|
57
|
+
for (const line of lines) {
|
|
58
|
+
const trimmed = line.trim()
|
|
59
|
+
if (trimmed.startsWith('- ')) {
|
|
60
|
+
navigationItems.push(trimmed.slice(2).trim())
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Extract layout pattern
|
|
66
|
+
const layoutMatch = md.match(/## Layout Pattern\s*\n+([\s\S]*?)(?=\n## |\n#[^#]|$)/)
|
|
67
|
+
const layoutPattern = layoutMatch?.[1]?.trim() || ''
|
|
68
|
+
|
|
69
|
+
// Return null if we couldn't parse anything meaningful
|
|
70
|
+
if (!overview && navigationItems.length === 0 && !layoutPattern) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
raw: md,
|
|
76
|
+
overview,
|
|
77
|
+
navigationItems,
|
|
78
|
+
layoutPattern,
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if shell components exist
|
|
87
|
+
*/
|
|
88
|
+
export function hasShellComponents(): boolean {
|
|
89
|
+
// Check if AppShell.tsx exists
|
|
90
|
+
const exists = '/src/shell/components/AppShell.tsx' in shellComponentModules
|
|
91
|
+
// Debug: log available shell components
|
|
92
|
+
console.log('[Shell] hasShellComponents check:', {
|
|
93
|
+
exists,
|
|
94
|
+
availableComponents: Object.keys(shellComponentModules),
|
|
95
|
+
lookingFor: '/src/shell/components/AppShell.tsx'
|
|
96
|
+
})
|
|
97
|
+
return exists
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Load shell component dynamically
|
|
102
|
+
*/
|
|
103
|
+
export function loadShellComponent(
|
|
104
|
+
componentName: string
|
|
105
|
+
): (() => Promise<{ default: ComponentType }>) | null {
|
|
106
|
+
const path = `/src/shell/components/${componentName}.tsx`
|
|
107
|
+
return shellComponentModules[path] || null
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Load AppShell component that can wrap content
|
|
112
|
+
* First tries to load ShellWrapper (designed for wrapping arbitrary content)
|
|
113
|
+
* Falls back to AppShell if ShellWrapper doesn't exist
|
|
114
|
+
*/
|
|
115
|
+
export function loadAppShell(): (() => Promise<{ default: ComponentType<{ children?: ReactNode }> }>) | null {
|
|
116
|
+
// First try ShellWrapper - a component specifically designed to wrap content
|
|
117
|
+
const wrapperPath = '/src/shell/components/ShellWrapper.tsx'
|
|
118
|
+
if (wrapperPath in shellComponentModules) {
|
|
119
|
+
return shellComponentModules[wrapperPath] as (() => Promise<{ default: ComponentType<{ children?: ReactNode }> }>)
|
|
120
|
+
}
|
|
121
|
+
// Fall back to AppShell
|
|
122
|
+
const path = '/src/shell/components/AppShell.tsx'
|
|
123
|
+
return shellComponentModules[path] as (() => Promise<{ default: ComponentType<{ children?: ReactNode }> }>) || null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Load shell preview wrapper dynamically
|
|
128
|
+
*/
|
|
129
|
+
export function loadShellPreview(): (() => Promise<{ default: ComponentType }>) | null {
|
|
130
|
+
return shellPreviewModules['/src/shell/ShellPreview.tsx'] || null
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Load the complete shell info
|
|
135
|
+
*/
|
|
136
|
+
export function loadShellInfo(): ShellInfo | null {
|
|
137
|
+
const specContent = shellSpecFiles['/product/shell/spec.md']
|
|
138
|
+
const spec = specContent ? parseShellSpec(specContent) : null
|
|
139
|
+
const hasComponents = hasShellComponents()
|
|
140
|
+
|
|
141
|
+
// Return null if neither spec nor components exist
|
|
142
|
+
if (!spec && !hasComponents) {
|
|
143
|
+
return null
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { spec, hasComponents }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Check if shell has been defined (spec or components)
|
|
151
|
+
*/
|
|
152
|
+
export function hasShell(): boolean {
|
|
153
|
+
return hasShellSpec() || hasShellComponents()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check if shell spec has been defined
|
|
158
|
+
*/
|
|
159
|
+
export function hasShellSpec(): boolean {
|
|
160
|
+
return '/product/shell/spec.md' in shellSpecFiles
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get list of shell component names
|
|
165
|
+
*/
|
|
166
|
+
export function getShellComponentNames(): string[] {
|
|
167
|
+
const names: string[] = []
|
|
168
|
+
for (const path of Object.keys(shellComponentModules)) {
|
|
169
|
+
const match = path.match(/\/src\/shell\/components\/([^/]+)\.tsx$/)
|
|
170
|
+
if (match) {
|
|
171
|
+
names.push(match[1])
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return names
|
|
175
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StrictMode } from 'react'
|
|
2
|
+
import { createRoot } from 'react-dom/client'
|
|
3
|
+
import { RouterProvider } from 'react-router-dom'
|
|
4
|
+
import './index.css'
|
|
5
|
+
import { router } from '@/lib/router'
|
|
6
|
+
|
|
7
|
+
import { ToastProvider } from '@/components/ui/ToastContext'
|
|
8
|
+
|
|
9
|
+
createRoot(document.getElementById('root')!).render(
|
|
10
|
+
<StrictMode>
|
|
11
|
+
<ToastProvider>
|
|
12
|
+
<RouterProvider router={router} />
|
|
13
|
+
</ToastProvider>
|
|
14
|
+
</StrictMode>,
|
|
15
|
+
)
|
|
File without changes
|