@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.
Files changed (194) hide show
  1. package/README.md +39 -0
  2. package/bin/cli.js +133 -0
  3. package/package.json +40 -0
  4. package/src/template/App.tsx +68 -0
  5. package/src/template/agent-os/commands/create-tasks/1-get-spec-requirements.md +19 -0
  6. package/src/template/agent-os/commands/create-tasks/2-create-tasks-list.md +234 -0
  7. package/src/template/agent-os/commands/create-tasks/create-tasks.md +254 -0
  8. package/src/template/agent-os/commands/design-screen/design-screen.md +32 -0
  9. package/src/template/agent-os/commands/design-shell/design-shell.md +34 -0
  10. package/src/template/agent-os/commands/design-tokens/design-tokens.md +36 -0
  11. package/src/template/agent-os/commands/export-product/export-product.md +44 -0
  12. package/src/template/agent-os/commands/implement-tasks/1-determine-tasks.md +13 -0
  13. package/src/template/agent-os/commands/implement-tasks/2-implement-tasks.md +63 -0
  14. package/src/template/agent-os/commands/implement-tasks/3-verify-implementation.md +113 -0
  15. package/src/template/agent-os/commands/implement-tasks/implement-tasks.md +207 -0
  16. package/src/template/agent-os/commands/initialize-design/initialize-design.md +54 -0
  17. package/src/template/agent-os/commands/orchestrate-tasks/orchestrate-tasks.md +180 -0
  18. package/src/template/agent-os/commands/plan-product/1-product-concept.md +53 -0
  19. package/src/template/agent-os/commands/plan-product/2-create-mission.md +78 -0
  20. package/src/template/agent-os/commands/plan-product/3-create-roadmap.md +73 -0
  21. package/src/template/agent-os/commands/plan-product/4-create-tech-stack.md +46 -0
  22. package/src/template/agent-os/commands/plan-product/plan-product.md +241 -0
  23. package/src/template/agent-os/commands/sample-data/sample-data.md +51 -0
  24. package/src/template/agent-os/commands/scaffold-implementation/scaffold-implementation.md +36 -0
  25. package/src/template/agent-os/commands/screenshot-design/screenshot-design.md +21 -0
  26. package/src/template/agent-os/commands/shape-spec/1-initialize-spec.md +95 -0
  27. package/src/template/agent-os/commands/shape-spec/2-shape-spec.md +300 -0
  28. package/src/template/agent-os/commands/shape-spec/shape-spec.md +40 -0
  29. package/src/template/agent-os/commands/write-spec/write-spec.md +134 -0
  30. package/src/template/agent-os/config.yml +13 -0
  31. package/src/template/agent-os/product/mission.md +29 -0
  32. package/src/template/agent-os/product/roadmap.md +9 -0
  33. package/src/template/agent-os/product/tech-stack.md +14 -0
  34. package/src/template/agent-os/specs/README.md +1 -0
  35. package/src/template/agent-os/standards/backend/api.md +10 -0
  36. package/src/template/agent-os/standards/backend/migrations.md +9 -0
  37. package/src/template/agent-os/standards/backend/models.md +10 -0
  38. package/src/template/agent-os/standards/backend/queries.md +9 -0
  39. package/src/template/agent-os/standards/frontend/accessibility.md +10 -0
  40. package/src/template/agent-os/standards/frontend/components.md +11 -0
  41. package/src/template/agent-os/standards/frontend/css.md +7 -0
  42. package/src/template/agent-os/standards/frontend/responsive.md +11 -0
  43. package/src/template/agent-os/standards/global/coding-style.md +10 -0
  44. package/src/template/agent-os/standards/global/commenting.md +5 -0
  45. package/src/template/agent-os/standards/global/conventions.md +11 -0
  46. package/src/template/agent-os/standards/global/error-handling.md +9 -0
  47. package/src/template/agent-os/standards/global/tech-stack.md +31 -0
  48. package/src/template/agent-os/standards/global/validation.md +11 -0
  49. package/src/template/agent-os/standards/testing/test-writing.md +9 -0
  50. package/src/template/agent-os-ui/README.md +73 -0
  51. package/src/template/agent-os-ui/package-lock.json +5028 -0
  52. package/src/template/agent-os-ui/package.json +52 -0
  53. package/src/template/agent-os-ui/postcss.config.js +6 -0
  54. package/src/template/agent-os-ui/src/components/AgentShell.tsx +31 -0
  55. package/src/template/agent-os-ui/src/components/AgentSidebar.tsx +65 -0
  56. package/src/template/agent-os-ui/src/components/GuidanceCard.tsx +75 -0
  57. package/src/template/agent-os-ui/src/components/MarkdownViewer.tsx +25 -0
  58. package/src/template/agent-os-ui/src/components/PromptButton.tsx +28 -0
  59. package/src/template/agent-os-ui/src/components/StatusItem.tsx +45 -0
  60. package/src/template/agent-os-ui/src/components/ThemeToggle.tsx +72 -0
  61. package/src/template/agent-os-ui/src/index.ts +11 -0
  62. package/src/template/agent-os-ui/src/style.css +3 -0
  63. package/src/template/agent-os-ui/tailwind.config.js +50 -0
  64. package/src/template/agent-os-ui/tsconfig.json +33 -0
  65. package/src/template/agent-os-ui/vite.config.ts +32 -0
  66. package/src/template/control-center/backend/backend.log +2 -0
  67. package/src/template/control-center/backend/index.js +228 -0
  68. package/src/template/control-center/backend/package-lock.json +951 -0
  69. package/src/template/control-center/backend/package.json +19 -0
  70. package/src/template/control-center/frontend/README.md +73 -0
  71. package/src/template/control-center/frontend/eslint.config.js +23 -0
  72. package/src/template/control-center/frontend/index.html +21 -0
  73. package/src/template/control-center/frontend/package-lock.json +5752 -0
  74. package/src/template/control-center/frontend/package.json +42 -0
  75. package/src/template/control-center/frontend/public/runtime-config.json +11 -0
  76. package/src/template/control-center/frontend/public/vite.svg +1 -0
  77. package/src/template/control-center/frontend/src/App.css +42 -0
  78. package/src/template/control-center/frontend/src/App.tsx +738 -0
  79. package/src/template/control-center/frontend/src/assets/react.svg +1 -0
  80. package/src/template/control-center/frontend/src/components/ThemeToggle.tsx +64 -0
  81. package/src/template/control-center/frontend/src/components/ui/ToastContext.tsx +81 -0
  82. package/src/template/control-center/frontend/src/index.css +194 -0
  83. package/src/template/control-center/frontend/src/main.tsx +14 -0
  84. package/src/template/control-center/frontend/src/vite-env.d.ts +1 -0
  85. package/src/template/control-center/frontend/tsconfig.app.json +28 -0
  86. package/src/template/control-center/frontend/tsconfig.json +7 -0
  87. package/src/template/control-center/frontend/tsconfig.node.json +26 -0
  88. package/src/template/control-center/frontend/vite.config.ts +22 -0
  89. package/src/template/design/.claude/commands/design-os/data-model.md +122 -0
  90. package/src/template/design/.claude/commands/design-os/design-screen.md +309 -0
  91. package/src/template/design/.claude/commands/design-os/design-shell.md +238 -0
  92. package/src/template/design/.claude/commands/design-os/design-tokens.md +166 -0
  93. package/src/template/design/.claude/commands/design-os/export-product.md +1105 -0
  94. package/src/template/design/.claude/commands/design-os/product-roadmap.md +121 -0
  95. package/src/template/design/.claude/commands/design-os/product-vision.md +99 -0
  96. package/src/template/design/.claude/commands/design-os/sample-data.md +263 -0
  97. package/src/template/design/.claude/commands/design-os/screenshot-design.md +112 -0
  98. package/src/template/design/.claude/commands/design-os/shape-section.md +138 -0
  99. package/src/template/design/.claude/skills/frontend-design/SKILL.md +42 -0
  100. package/src/template/design/.github/CODE_OF_CONDUCT.md +5 -0
  101. package/src/template/design/.github/CONTRIBUTING.md +51 -0
  102. package/src/template/design/.github/ISSUE_TEMPLATE/config.yml +22 -0
  103. package/src/template/design/.github/PULL_REQUEST_TEMPLATE.md +20 -0
  104. package/src/template/design/.github/SECURITY.yml +5 -0
  105. package/src/template/design/.github/SUPPORT.md +19 -0
  106. package/src/template/design/.github/workflows/pr-decline.yml +135 -0
  107. package/src/template/design/.github/workflows/stale.yml +25 -0
  108. package/src/template/design/CHANGELOG.md +13 -0
  109. package/src/template/design/LICENSE +21 -0
  110. package/src/template/design/README.md +54 -0
  111. package/src/template/design/agents.md +218 -0
  112. package/src/template/design/claude.md +1 -0
  113. package/src/template/design/components.json +22 -0
  114. package/src/template/design/docs/codebase-implementation.md +153 -0
  115. package/src/template/design/docs/design-section.md +135 -0
  116. package/src/template/design/docs/export.md +149 -0
  117. package/src/template/design/docs/getting-started.md +59 -0
  118. package/src/template/design/docs/index.md +56 -0
  119. package/src/template/design/docs/product-planning.md +113 -0
  120. package/src/template/design/docs/requirements.md +22 -0
  121. package/src/template/design/docs/usage.md +62 -0
  122. package/src/template/design/eslint.config.js +23 -0
  123. package/src/template/design/index.html +21 -0
  124. package/src/template/design/package-lock.json +5473 -0
  125. package/src/template/design/package.json +47 -0
  126. package/src/template/design/product-plan.zip +0 -0
  127. package/src/template/design/public/vite.svg +1 -0
  128. package/src/template/design/src/assets/react.svg +1 -0
  129. package/src/template/design/src/components/AppLayout.tsx +95 -0
  130. package/src/template/design/src/components/DataCard.tsx +139 -0
  131. package/src/template/design/src/components/DataModelPage.tsx +120 -0
  132. package/src/template/design/src/components/DesignPage.tsx +284 -0
  133. package/src/template/design/src/components/EmptyState.tsx +155 -0
  134. package/src/template/design/src/components/ExportPage.tsx +344 -0
  135. package/src/template/design/src/components/NextPhaseButton.tsx +33 -0
  136. package/src/template/design/src/components/PhaseNav.tsx +152 -0
  137. package/src/template/design/src/components/PhaseWarningBanner.tsx +81 -0
  138. package/src/template/design/src/components/ProductOverviewCard.tsx +102 -0
  139. package/src/template/design/src/components/ProductPage.tsx +97 -0
  140. package/src/template/design/src/components/ScreenDesignPage.tsx +370 -0
  141. package/src/template/design/src/components/ScreenDesignsCard.tsx +49 -0
  142. package/src/template/design/src/components/SectionPage.tsx +256 -0
  143. package/src/template/design/src/components/SectionsCard.tsx +47 -0
  144. package/src/template/design/src/components/SectionsPage.tsx +181 -0
  145. package/src/template/design/src/components/ShellCard.tsx +85 -0
  146. package/src/template/design/src/components/ShellDesignPage.tsx +242 -0
  147. package/src/template/design/src/components/SpecCard.tsx +121 -0
  148. package/src/template/design/src/components/StepIndicator.tsx +75 -0
  149. package/src/template/design/src/components/ThemeToggle.tsx +86 -0
  150. package/src/template/design/src/components/ui/ToastContext.tsx +81 -0
  151. package/src/template/design/src/components/ui/avatar.tsx +53 -0
  152. package/src/template/design/src/components/ui/badge.tsx +46 -0
  153. package/src/template/design/src/components/ui/button.tsx +60 -0
  154. package/src/template/design/src/components/ui/card.tsx +92 -0
  155. package/src/template/design/src/components/ui/collapsible.tsx +48 -0
  156. package/src/template/design/src/components/ui/dialog.tsx +143 -0
  157. package/src/template/design/src/components/ui/dropdown-menu.tsx +255 -0
  158. package/src/template/design/src/components/ui/input.tsx +21 -0
  159. package/src/template/design/src/components/ui/label.tsx +22 -0
  160. package/src/template/design/src/components/ui/progress.tsx +24 -0
  161. package/src/template/design/src/components/ui/scroll-area.tsx +18 -0
  162. package/src/template/design/src/components/ui/select.tsx +67 -0
  163. package/src/template/design/src/components/ui/separator.tsx +28 -0
  164. package/src/template/design/src/components/ui/sheet.tsx +137 -0
  165. package/src/template/design/src/components/ui/skeleton.tsx +13 -0
  166. package/src/template/design/src/components/ui/switch.tsx +46 -0
  167. package/src/template/design/src/components/ui/table.tsx +116 -0
  168. package/src/template/design/src/components/ui/tabs.tsx +64 -0
  169. package/src/template/design/src/index.css +284 -0
  170. package/src/template/design/src/lib/data-model-loader.ts +91 -0
  171. package/src/template/design/src/lib/design-system-loader.ts +101 -0
  172. package/src/template/design/src/lib/product-loader.ts +221 -0
  173. package/src/template/design/src/lib/router.tsx +52 -0
  174. package/src/template/design/src/lib/section-loader.ts +272 -0
  175. package/src/template/design/src/lib/shell-loader.ts +175 -0
  176. package/src/template/design/src/lib/utils.ts +6 -0
  177. package/src/template/design/src/main.tsx +15 -0
  178. package/src/template/design/src/sections/.gitkeep +0 -0
  179. package/src/template/design/src/sections/ai-orchestration-engine-oai/OrchestrationEngine.tsx +348 -0
  180. package/src/template/design/src/sections/core-platform-shell/AppShell.tsx +403 -0
  181. package/src/template/design/src/sections/gemini-live-integration/GeminiIntegration.tsx +332 -0
  182. package/src/template/design/src/sections/interactive-2d-canvas/WhiteboardCanvas.tsx +334 -0
  183. package/src/template/design/src/sections/participation-equity-tracker/EquityTracker.tsx +383 -0
  184. package/src/template/design/src/sections/persistent-memory-system/PersistentMemory.tsx +308 -0
  185. package/src/template/design/src/sections/real-time-communication-layer/VideoSession.tsx +342 -0
  186. package/src/template/design/src/sections/visual-intelligence-agents/VisualAgents.tsx +311 -0
  187. package/src/template/design/src/types/product.ts +97 -0
  188. package/src/template/design/src/types/section.ts +33 -0
  189. package/src/template/design/tsconfig.app.json +34 -0
  190. package/src/template/design/tsconfig.json +13 -0
  191. package/src/template/design/tsconfig.node.json +26 -0
  192. package/src/template/design/vite.config.ts +18 -0
  193. package/src/template/package.json +27 -0
  194. package/src/template/vite.config.ts +16 -0
@@ -0,0 +1,256 @@
1
+ import { useMemo } from 'react'
2
+ import { useParams, Link, useNavigate } from 'react-router-dom'
3
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
4
+ import { AppLayout } from '@/components/AppLayout'
5
+ import { EmptyState } from '@/components/EmptyState'
6
+ import { PhaseWarningBanner } from '@/components/PhaseWarningBanner'
7
+ import { SpecCard } from '@/components/SpecCard'
8
+ import { DataCard } from '@/components/DataCard'
9
+ import { StepIndicator, type StepStatus } from '@/components/StepIndicator'
10
+ import { loadProductData } from '@/lib/product-loader'
11
+ import { loadSectionData } from '@/lib/section-loader'
12
+ import { ChevronRight, Layout, Image, Download, ArrowRight, LayoutList } from 'lucide-react'
13
+
14
+ /**
15
+ * Determine the status of each step based on what data exists
16
+ * Steps: 1. Section Overview (Spec), 2. Sample Data, 3. Screen Designs, 4. Screenshots
17
+ */
18
+ function getStepStatuses(sectionData: ReturnType<typeof loadSectionData> | null): StepStatus[] {
19
+ const hasSpec = !!sectionData?.specParsed
20
+ const hasData = !!sectionData?.data
21
+ const hasScreenDesigns = !!(sectionData?.screenDesigns && sectionData.screenDesigns.length > 0)
22
+ const hasScreenshots = !!(sectionData?.screenshots && sectionData.screenshots.length > 0)
23
+
24
+ const steps: boolean[] = [hasSpec, hasData, hasScreenDesigns, hasScreenshots]
25
+ const firstIncomplete = steps.findIndex((done) => !done)
26
+
27
+ return steps.map((done, index) => {
28
+ if (done) return 'completed'
29
+ if (index === firstIncomplete) return 'current'
30
+ return 'upcoming'
31
+ })
32
+ }
33
+
34
+ /**
35
+ * Check if the required steps for a section are complete (Spec, Data, Screen Designs)
36
+ * Screenshots are optional and don't count toward completion
37
+ */
38
+ function areRequiredStepsComplete(sectionData: ReturnType<typeof loadSectionData> | null): boolean {
39
+ const hasSpec = !!sectionData?.specParsed
40
+ const hasData = !!sectionData?.data
41
+ const hasScreenDesigns = !!(sectionData?.screenDesigns && sectionData.screenDesigns.length > 0)
42
+ return hasSpec && hasData && hasScreenDesigns
43
+ }
44
+
45
+ export function SectionPage() {
46
+ const { sectionId } = useParams<{ sectionId: string }>()
47
+ const navigate = useNavigate()
48
+
49
+ // Load product data to get section info
50
+ const productData = useMemo(() => loadProductData(), [])
51
+ const sections = productData.roadmap?.sections || []
52
+ const section = sections.find((s) => s.id === sectionId)
53
+ const currentIndex = sections.findIndex((s) => s.id === sectionId)
54
+
55
+ // Load section-specific data (spec, data.json, screen designs, screenshots)
56
+ const sectionData = useMemo(
57
+ () => (sectionId ? loadSectionData(sectionId) : null),
58
+ [sectionId]
59
+ )
60
+
61
+ // Handle missing section
62
+ if (!section) {
63
+ return (
64
+ <AppLayout backTo="/sections" backLabel="Sections">
65
+ <div className="text-center py-12">
66
+ <p className="text-stone-600 dark:text-stone-400">
67
+ Section not found: {sectionId}
68
+ </p>
69
+ </div>
70
+ </AppLayout>
71
+ )
72
+ }
73
+
74
+ const stepStatuses = getStepStatuses(sectionData)
75
+ const requiredStepsComplete = areRequiredStepsComplete(sectionData)
76
+
77
+ // Next section navigation logic
78
+ const isLastSection = currentIndex === sections.length - 1 || currentIndex === -1
79
+ const nextSection = !isLastSection ? sections[currentIndex + 1] : null
80
+
81
+ return (
82
+ <AppLayout backTo="/sections" backLabel="Sections" title={section.title}>
83
+ <div className="space-y-6">
84
+ {/* Page intro */}
85
+ <div className="mb-8">
86
+ <h1 className="text-2xl font-semibold text-stone-900 dark:text-stone-100 mb-2">
87
+ {section.title}
88
+ </h1>
89
+ <p className="text-stone-600 dark:text-stone-400">
90
+ {section.description}
91
+ </p>
92
+ </div>
93
+
94
+ {/* Warning banner for incomplete prerequisite phases */}
95
+ <PhaseWarningBanner />
96
+
97
+ {/* Step 1: Section Overview (Spec) */}
98
+ <StepIndicator step={1} status={stepStatuses[0]}>
99
+ <SpecCard
100
+ spec={sectionData?.specParsed || null}
101
+ sectionTitle={section?.title || "Section Overview"}
102
+ sectionId={sectionId}
103
+ />
104
+ </StepIndicator>
105
+
106
+ {/* Step 2: Sample Data */}
107
+ <StepIndicator step={2} status={stepStatuses[1]}>
108
+ <DataCard
109
+ data={sectionData?.data || null}
110
+ sectionTitle={section?.title}
111
+ sectionId={sectionId}
112
+ />
113
+ </StepIndicator>
114
+
115
+ {/* Step 3: Screen Designs */}
116
+ <StepIndicator step={3} status={stepStatuses[2]}>
117
+ {!sectionData?.screenDesigns || sectionData.screenDesigns.length === 0 ? (
118
+ <EmptyState
119
+ type="screen-designs"
120
+ context={section?.title}
121
+ contextId={sectionId}
122
+ />
123
+ ) : (
124
+ <Card className="border-stone-200 dark:border-stone-700 shadow-sm">
125
+ <CardHeader className="pb-4">
126
+ <CardTitle className="text-lg font-semibold text-stone-900 dark:text-stone-100">
127
+ Screen Designs
128
+ <span className="ml-2 text-sm font-normal text-stone-500 dark:text-stone-400">
129
+ ({sectionData.screenDesigns.length})
130
+ </span>
131
+ </CardTitle>
132
+ </CardHeader>
133
+ <CardContent className="p-0">
134
+ <ul className="divide-y divide-stone-200 dark:divide-stone-700">
135
+ {sectionData.screenDesigns.map((screenDesign) => (
136
+ <li key={screenDesign.name}>
137
+ <Link
138
+ to={`/sections/${sectionId}/screen-designs/${screenDesign.name}`}
139
+ className="flex items-center justify-between gap-4 px-6 py-4 hover:bg-stone-50 dark:hover:bg-stone-800/50 transition-colors"
140
+ >
141
+ <div className="flex items-center gap-3 min-w-0">
142
+ <div className="w-8 h-8 rounded-md bg-stone-200 dark:bg-stone-700 flex items-center justify-center shrink-0">
143
+ <Layout className="w-4 h-4 text-stone-600 dark:text-stone-300" strokeWidth={1.5} />
144
+ </div>
145
+ <span className="font-medium text-stone-900 dark:text-stone-100 truncate">
146
+ {screenDesign.name}
147
+ </span>
148
+ </div>
149
+ <ChevronRight className="w-4 h-4 text-stone-400 dark:text-stone-500 shrink-0" strokeWidth={1.5} />
150
+ </Link>
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ </CardContent>
155
+ </Card>
156
+ )}
157
+ </StepIndicator>
158
+
159
+ {/* Step 4: Screenshots */}
160
+ <StepIndicator step={4} status={stepStatuses[3]} isLast={!requiredStepsComplete}>
161
+ {!sectionData?.screenshots || sectionData.screenshots.length === 0 ? (
162
+ <EmptyState
163
+ type="screenshots"
164
+ context={section?.title}
165
+ contextId={sectionId}
166
+ />
167
+ ) : (
168
+ <Card className="border-stone-200 dark:border-stone-700 shadow-sm">
169
+ <CardHeader className="pb-4">
170
+ <CardTitle className="text-lg font-semibold text-stone-900 dark:text-stone-100">
171
+ Screenshots
172
+ <span className="ml-2 text-sm font-normal text-stone-500 dark:text-stone-400">
173
+ ({sectionData.screenshots.length})
174
+ </span>
175
+ </CardTitle>
176
+ </CardHeader>
177
+ <CardContent>
178
+ <div className="grid grid-cols-2 gap-4">
179
+ {sectionData.screenshots.map((screenshot) => (
180
+ <div key={screenshot.name} className="group">
181
+ <div className="aspect-video rounded-lg overflow-hidden bg-stone-100 dark:bg-stone-800 border border-stone-200 dark:border-stone-700">
182
+ <img
183
+ src={screenshot.url}
184
+ alt={screenshot.name}
185
+ className="w-full h-full object-cover"
186
+ />
187
+ </div>
188
+ <div className="mt-2 flex items-center justify-between gap-2">
189
+ <p className="text-sm text-stone-600 dark:text-stone-400 truncate">
190
+ {screenshot.name}
191
+ </p>
192
+ <a
193
+ href={screenshot.url}
194
+ download={`${screenshot.name}.png`}
195
+ className="shrink-0 p-1.5 rounded-md text-stone-400 hover:text-stone-600 dark:text-stone-500 dark:hover:text-stone-300 hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors"
196
+ title="Download screenshot"
197
+ >
198
+ <Download className="w-4 h-4" strokeWidth={1.5} />
199
+ </a>
200
+ </div>
201
+ </div>
202
+ ))}
203
+ </div>
204
+ </CardContent>
205
+ </Card>
206
+ )}
207
+ </StepIndicator>
208
+
209
+ {/* Next Step - shown when required steps (Spec, Data, Screen Designs) are complete */}
210
+ {requiredStepsComplete && (
211
+ <StepIndicator step={5} status="current" isLast>
212
+ <div className="space-y-3">
213
+ {/* If there's a next section, show two options */}
214
+ {nextSection ? (
215
+ <>
216
+ <button
217
+ onClick={() => navigate(`/sections/${nextSection.id}`)}
218
+ className="w-full flex items-center justify-between gap-4 px-6 py-4 bg-stone-900 dark:bg-stone-100 text-stone-100 dark:text-stone-900 rounded-lg hover:bg-stone-800 dark:hover:bg-stone-200 transition-colors group"
219
+ >
220
+ <div className="flex items-center gap-3">
221
+ <ArrowRight className="w-5 h-5" strokeWidth={1.5} />
222
+ <span className="font-medium">Continue to {nextSection.title}</span>
223
+ </div>
224
+ <ArrowRight className="w-5 h-5 transition-transform group-hover:translate-x-1" strokeWidth={1.5} />
225
+ </button>
226
+ <button
227
+ onClick={() => navigate('/sections')}
228
+ className="w-full flex items-center justify-between gap-4 px-6 py-4 bg-stone-100 dark:bg-stone-800 text-stone-700 dark:text-stone-300 rounded-lg hover:bg-stone-200 dark:hover:bg-stone-700 transition-colors group"
229
+ >
230
+ <div className="flex items-center gap-3">
231
+ <LayoutList className="w-5 h-5" strokeWidth={1.5} />
232
+ <span className="font-medium">View All Sections</span>
233
+ </div>
234
+ <ChevronRight className="w-5 h-5 transition-transform group-hover:translate-x-1" strokeWidth={1.5} />
235
+ </button>
236
+ </>
237
+ ) : (
238
+ /* If this is the last or only section, show single link back to sections */
239
+ <button
240
+ onClick={() => navigate('/sections')}
241
+ className="w-full flex items-center justify-between gap-4 px-6 py-4 bg-stone-900 dark:bg-stone-100 text-stone-100 dark:text-stone-900 rounded-lg hover:bg-stone-800 dark:hover:bg-stone-200 transition-colors group"
242
+ >
243
+ <div className="flex items-center gap-3">
244
+ <LayoutList className="w-5 h-5" strokeWidth={1.5} />
245
+ <span className="font-medium">Back to All Sections</span>
246
+ </div>
247
+ <ArrowRight className="w-5 h-5 transition-transform group-hover:translate-x-1" strokeWidth={1.5} />
248
+ </button>
249
+ )}
250
+ </div>
251
+ </StepIndicator>
252
+ )}
253
+ </div>
254
+ </AppLayout>
255
+ )
256
+ }
@@ -0,0 +1,47 @@
1
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
2
+ import { ChevronRight } from 'lucide-react'
3
+ import type { ProductRoadmap } from '@/types/product'
4
+
5
+ interface SectionsCardProps {
6
+ roadmap: ProductRoadmap
7
+ onSectionClick: (sectionId: string) => void
8
+ }
9
+
10
+ export function SectionsCard({ roadmap, onSectionClick }: SectionsCardProps) {
11
+ return (
12
+ <Card className="border-stone-200 dark:border-stone-700 shadow-sm">
13
+ <CardHeader className="pb-4">
14
+ <CardTitle className="text-lg font-semibold text-stone-900 dark:text-stone-100">
15
+ Sections
16
+ </CardTitle>
17
+ </CardHeader>
18
+ <CardContent className="p-0">
19
+ <ul className="divide-y divide-stone-200 dark:divide-stone-700">
20
+ {roadmap.sections.map((section) => (
21
+ <li key={section.id}>
22
+ <button
23
+ onClick={() => onSectionClick(section.id)}
24
+ className="w-full px-6 py-4 flex items-center justify-between gap-4 text-left hover:bg-stone-50 dark:hover:bg-stone-800/50 transition-colors"
25
+ >
26
+ <div className="flex items-start gap-4 min-w-0">
27
+ <span className="shrink-0 w-6 h-6 rounded-full bg-stone-200 dark:bg-stone-700 text-stone-600 dark:text-stone-300 text-xs font-medium flex items-center justify-center">
28
+ {section.order}
29
+ </span>
30
+ <div className="min-w-0">
31
+ <h3 className="font-medium text-stone-900 dark:text-stone-100 truncate">
32
+ {section.title}
33
+ </h3>
34
+ <p className="text-sm text-stone-500 dark:text-stone-400 mt-0.5 line-clamp-1">
35
+ {section.description}
36
+ </p>
37
+ </div>
38
+ </div>
39
+ <ChevronRight className="w-4 h-4 text-stone-400 dark:text-stone-500 flex-shrink-0" strokeWidth={1.5} />
40
+ </button>
41
+ </li>
42
+ ))}
43
+ </ul>
44
+ </CardContent>
45
+ </Card>
46
+ )
47
+ }
@@ -0,0 +1,181 @@
1
+ import { useMemo } from 'react'
2
+ import { useNavigate } from 'react-router-dom'
3
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
4
+ import { AppLayout } from '@/components/AppLayout'
5
+ import { EmptyState } from '@/components/EmptyState'
6
+ import { PhaseWarningBanner } from '@/components/PhaseWarningBanner'
7
+ import { NextPhaseButton } from '@/components/NextPhaseButton'
8
+ import { loadProductData } from '@/lib/product-loader'
9
+ import { getSectionScreenDesigns, getSectionScreenshots, hasSectionSpec, hasSectionData } from '@/lib/section-loader'
10
+ import { ChevronRight, Check, Circle } from 'lucide-react'
11
+
12
+ interface SectionProgress {
13
+ hasSpec: boolean
14
+ hasData: boolean
15
+ hasScreenDesigns: boolean
16
+ screenDesignCount: number
17
+ hasScreenshots: boolean
18
+ screenshotCount: number
19
+ }
20
+
21
+ function getSectionProgress(sectionId: string): SectionProgress {
22
+ const screenDesigns = getSectionScreenDesigns(sectionId)
23
+ const screenshots = getSectionScreenshots(sectionId)
24
+ return {
25
+ hasSpec: hasSectionSpec(sectionId),
26
+ hasData: hasSectionData(sectionId),
27
+ hasScreenDesigns: screenDesigns.length > 0,
28
+ screenDesignCount: screenDesigns.length,
29
+ hasScreenshots: screenshots.length > 0,
30
+ screenshotCount: screenshots.length,
31
+ }
32
+ }
33
+
34
+ export function SectionsPage() {
35
+ const navigate = useNavigate()
36
+ const productData = useMemo(() => loadProductData(), [])
37
+
38
+ const sections = productData.roadmap?.sections || []
39
+
40
+ // Calculate progress for each section
41
+ const sectionProgressMap = useMemo(() => {
42
+ const map: Record<string, SectionProgress> = {}
43
+ for (const section of sections) {
44
+ map[section.id] = getSectionProgress(section.id)
45
+ }
46
+ return map
47
+ }, [sections])
48
+
49
+ // Count completed sections (those with spec, data, AND screen designs)
50
+ const completedSections = sections.filter(s => {
51
+ const p = sectionProgressMap[s.id]
52
+ return p?.hasSpec && p?.hasData && p?.hasScreenDesigns
53
+ }).length
54
+
55
+ return (
56
+ <AppLayout>
57
+ <div className="space-y-6">
58
+ {/* Page intro */}
59
+ <div className="mb-8">
60
+ <h1 className="text-2xl font-semibold text-stone-900 dark:text-stone-100 mb-2">
61
+ Sections
62
+ </h1>
63
+ <p className="text-stone-600 dark:text-stone-400">
64
+ Design each section of your product with specifications, sample data, and screen designs.
65
+ </p>
66
+ {sections.length > 0 && (
67
+ <p className="text-sm text-stone-500 dark:text-stone-400 mt-2">
68
+ {completedSections} of {sections.length} sections completed
69
+ </p>
70
+ )}
71
+ </div>
72
+
73
+ {/* Warning banner for incomplete prerequisite phases */}
74
+ <PhaseWarningBanner />
75
+
76
+ {/* Sections list */}
77
+ {sections.length === 0 ? (
78
+ <EmptyState type="roadmap" />
79
+ ) : (
80
+ <Card className="border-stone-200 dark:border-stone-700 shadow-sm">
81
+ <CardHeader className="pb-2">
82
+ <CardTitle className="text-lg font-semibold text-stone-900 dark:text-stone-100">
83
+ All Sections
84
+ </CardTitle>
85
+ </CardHeader>
86
+ <CardContent className="p-0">
87
+ <ul className="divide-y divide-stone-200 dark:divide-stone-700">
88
+ {sections.map((section) => {
89
+ const progress = sectionProgressMap[section.id]
90
+ const isComplete = progress?.hasSpec && progress?.hasData && progress?.hasScreenDesigns
91
+
92
+ return (
93
+ <li key={section.id}>
94
+ <button
95
+ onClick={() => navigate(`/sections/${section.id}`)}
96
+ className="w-full px-6 py-4 flex items-center justify-between gap-4 text-left hover:bg-stone-50 dark:hover:bg-stone-800/50 transition-colors"
97
+ >
98
+ <div className="flex items-start gap-4 min-w-0">
99
+ {/* Status indicator */}
100
+ <div className="shrink-0 mt-0.5">
101
+ {isComplete ? (
102
+ <div className="w-6 h-6 rounded-full bg-lime-100 dark:bg-lime-900/30 flex items-center justify-center">
103
+ <Check className="w-3.5 h-3.5 text-lime-600 dark:text-lime-400" strokeWidth={2.5} />
104
+ </div>
105
+ ) : (
106
+ <div className="w-6 h-6 rounded-full bg-stone-200 dark:bg-stone-700 flex items-center justify-center">
107
+ <span className="text-xs font-medium text-stone-600 dark:text-stone-400">
108
+ {section.order}
109
+ </span>
110
+ </div>
111
+ )}
112
+ </div>
113
+
114
+ <div className="min-w-0 flex-1">
115
+ <h3 className="font-medium text-stone-900 dark:text-stone-100 truncate">
116
+ {section.title}
117
+ </h3>
118
+ <p className="text-sm text-stone-500 dark:text-stone-400 mt-0.5 line-clamp-1">
119
+ {section.description}
120
+ </p>
121
+
122
+ {/* Progress indicators */}
123
+ <div className="flex items-center gap-3 mt-2">
124
+ <ProgressDot label="Spec" done={progress?.hasSpec} />
125
+ <ProgressDot label="Data" done={progress?.hasData} />
126
+ <ProgressDot
127
+ label={progress?.screenDesignCount ? `${progress.screenDesignCount} screen design${progress.screenDesignCount !== 1 ? 's' : ''}` : 'Screen Designs'}
128
+ done={progress?.hasScreenDesigns}
129
+ />
130
+ <ProgressDot
131
+ label={progress?.screenshotCount ? `${progress.screenshotCount} screenshot${progress.screenshotCount !== 1 ? 's' : ''}` : 'Screenshots'}
132
+ done={progress?.hasScreenshots}
133
+ optional
134
+ />
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <ChevronRight className="w-4 h-4 text-stone-400 dark:text-stone-500 flex-shrink-0" strokeWidth={1.5} />
140
+ </button>
141
+ </li>
142
+ )
143
+ })}
144
+ </ul>
145
+ </CardContent>
146
+ </Card>
147
+ )}
148
+
149
+ {/* Next Phase Button - shown when all sections are complete */}
150
+ {sections.length > 0 && completedSections === sections.length && (
151
+ <NextPhaseButton nextPhase="export" />
152
+ )}
153
+ </div>
154
+ </AppLayout>
155
+ )
156
+ }
157
+
158
+ interface ProgressDotProps {
159
+ label: string
160
+ done?: boolean
161
+ optional?: boolean
162
+ }
163
+
164
+ function ProgressDot({ label, done, optional }: ProgressDotProps) {
165
+ return (
166
+ <span className={`flex items-center gap-1 text-xs ${
167
+ done
168
+ ? 'text-stone-700 dark:text-stone-300'
169
+ : optional
170
+ ? 'text-stone-300 dark:text-stone-600'
171
+ : 'text-stone-400 dark:text-stone-500'
172
+ }`}>
173
+ {done ? (
174
+ <Check className="w-3 h-3 text-lime-600 dark:text-lime-400" strokeWidth={2.5} />
175
+ ) : (
176
+ <Circle className={`w-3 h-3 ${optional ? 'opacity-50' : ''}`} strokeWidth={1.5} />
177
+ )}
178
+ {label}
179
+ </span>
180
+ )
181
+ }
@@ -0,0 +1,85 @@
1
+ import { useState } from 'react'
2
+ import { Link } from 'react-router-dom'
3
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
4
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
5
+ import { ChevronDown, ChevronRight, PanelLeft, Layout } from 'lucide-react'
6
+ import type { ShellInfo } from '@/types/product'
7
+
8
+ interface ShellCardProps {
9
+ shell: ShellInfo
10
+ }
11
+
12
+ export function ShellCard({ shell }: ShellCardProps) {
13
+ const [navigationOpen, setNavigationOpen] = useState(false)
14
+
15
+ return (
16
+ <Card className="border-stone-200 dark:border-stone-700 shadow-sm">
17
+ <CardHeader className="pb-4">
18
+ <CardTitle className="text-lg font-semibold text-stone-900 dark:text-stone-100 flex items-center gap-2">
19
+ <PanelLeft className="w-5 h-5 text-stone-500 dark:text-stone-400" strokeWidth={1.5} />
20
+ Application Shell
21
+ </CardTitle>
22
+ </CardHeader>
23
+ <CardContent className="space-y-4">
24
+ {/* Overview */}
25
+ {shell.spec && shell.spec.overview && (
26
+ <p className="text-stone-600 dark:text-stone-400 leading-relaxed">
27
+ {shell.spec.overview}
28
+ </p>
29
+ )}
30
+
31
+ {/* Navigation - Collapsible */}
32
+ {shell.spec && shell.spec.navigationItems.length > 0 && (
33
+ <Collapsible open={navigationOpen} onOpenChange={setNavigationOpen}>
34
+ <CollapsibleTrigger className="flex items-center justify-between w-full py-2 text-left group">
35
+ <span className="text-sm font-medium text-stone-500 dark:text-stone-400 uppercase tracking-wide">
36
+ Navigation
37
+ <span className="ml-2 text-stone-400 dark:text-stone-500 normal-case tracking-normal">
38
+ ({shell.spec.navigationItems.length})
39
+ </span>
40
+ </span>
41
+ <ChevronDown
42
+ className={`w-4 h-4 text-stone-400 dark:text-stone-500 transition-transform ${
43
+ navigationOpen ? 'rotate-180' : ''
44
+ }`}
45
+ strokeWidth={1.5}
46
+ />
47
+ </CollapsibleTrigger>
48
+ <CollapsibleContent>
49
+ <ul className="space-y-2 pt-2 ml-1">
50
+ {shell.spec.navigationItems.map((item, index) => (
51
+ <li key={index} className="flex items-start gap-3">
52
+ <span className="w-1.5 h-1.5 rounded-full bg-stone-400 dark:bg-stone-500 mt-2 shrink-0" />
53
+ <span className="text-stone-600 dark:text-stone-400">
54
+ {item}
55
+ </span>
56
+ </li>
57
+ ))}
58
+ </ul>
59
+ </CollapsibleContent>
60
+ </Collapsible>
61
+ )}
62
+
63
+ {/* View Shell Design Link */}
64
+ {shell.hasComponents && (
65
+ <div className="pt-2 border-t border-stone-100 dark:border-stone-800">
66
+ <Link
67
+ to="/shell/design"
68
+ className="flex items-center justify-between gap-4 py-2 hover:text-stone-900 dark:hover:text-stone-100 transition-colors group"
69
+ >
70
+ <div className="flex items-center gap-3">
71
+ <div className="w-8 h-8 rounded-md bg-stone-200 dark:bg-stone-700 flex items-center justify-center">
72
+ <Layout className="w-4 h-4 text-stone-600 dark:text-stone-300" strokeWidth={1.5} />
73
+ </div>
74
+ <span className="font-medium text-stone-700 dark:text-stone-300 group-hover:text-stone-900 dark:group-hover:text-stone-100">
75
+ View Shell Design
76
+ </span>
77
+ </div>
78
+ <ChevronRight className="w-4 h-4 text-stone-400 dark:text-stone-500" strokeWidth={1.5} />
79
+ </Link>
80
+ </div>
81
+ )}
82
+ </CardContent>
83
+ </Card>
84
+ )
85
+ }