mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
feat: Migrate 5 key molecules to JSON architecture
Converted AppBranding, DataSourceCard, CodeExplanationDialog, ComponentPalette, and CanvasRenderer from TSX to JSON-based architecture. Changes: - Created JSON definitions in src/components/json-definitions/ - Created TypeScript interfaces in src/lib/json-ui/interfaces/ - Added exports to src/lib/json-ui/json-components.ts - Updated json-components-registry.json with 5 new components - Updated registry statistics (total: 347, molecules: 50, jsonCompatible: 124) All components use createJsonComponent for pure JSON rendering without hooks. Build passes with no errors. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
730
docs/plans/2026-01-21-tier-1-bootstrap-json-migration.md
Normal file
730
docs/plans/2026-01-21-tier-1-bootstrap-json-migration.md
Normal file
@@ -0,0 +1,730 @@
|
||||
# Tier 1 Bootstrap Components JSON Migration
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Migrate 7 critical app bootstrap components (AppBootstrap, AppRouterBootstrap, AppLayout, AppRouterLayout, AppMainPanel, AppDialogs, LoadingScreen) from TSX to JSON-driven architecture to prove the JSON migration pattern works at the critical entry point.
|
||||
|
||||
**Architecture:** Each component will be converted using the established pattern: JSON definition + optional custom hook + TypeScript interface. The architecture leverages `createJsonComponent` (pure/stateless) and `createJsonComponentWithHooks` (stateful). Components are exported from `src/lib/json-ui/json-components.ts` rather than kept as TSX files in `src/components/`.
|
||||
|
||||
**Tech Stack:** React 18, TypeScript, custom hooks system (no wrapper files), JSON component factory functions, sonner for toasts, react-router-dom for routing.
|
||||
|
||||
---
|
||||
|
||||
## Tier 1 Components Overview
|
||||
|
||||
| Component | Type | Complexity | Hook Required | Status | Strategy |
|
||||
|-----------|------|-----------|---|--------|-----------|
|
||||
| LoadingScreen | Atom | Pure/Stateless | No | ✅ Already JSON | N/A |
|
||||
| AppBootstrap | Organism | Minimal | Yes - useAppBootstrap | ✅ Keep TSX | BrowserRouter wrapper (10 lines) |
|
||||
| AppRouterBootstrap | Organism | Minimal | Yes - useAppBootstrap | ✅ Keep TSX | BrowserRouter wrapper (10 lines) |
|
||||
| AppLayout | Organism | Stateful | Yes - Multiple hooks | TSX → JSON | Migrate to JSON with useAppLayout hook |
|
||||
| AppRouterLayout | Organism | Stateful | Yes - Multiple hooks | TSX → JSON | Migrate to JSON with useAppRouterLayout hook |
|
||||
| AppMainPanel | Organism | Stateful | Yes - Multiple hooks | TSX → JSON | Migrate to JSON (pure, receives all props) |
|
||||
| AppDialogs | Organism | Stateless* | No* | TSX → JSON | Migrate to JSON (pure, receives all props) |
|
||||
|
||||
**Rationale for hybrid approach:** BrowserRouter is a React Router provider not JSON-renderable. Keeping AppBootstrap/AppRouterBootstrap as minimal TSX wrappers is simpler and aligns with framework architecture. Focus JSON migration on layout and dialog composition components (5 components migrated).
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Create Git Worktree for Tier 1
|
||||
|
||||
**Files:**
|
||||
- Create: Git worktree `tier-1-bootstrap`
|
||||
- Reference: Current branch `festive-mestorf`
|
||||
|
||||
**Step 1: Create isolated git worktree**
|
||||
|
||||
```bash
|
||||
cd /Users/rmac/Documents/GitHub/low-code-react-app-b
|
||||
git worktree add tier-1-bootstrap festive-mestorf
|
||||
cd tier-1-bootstrap
|
||||
```
|
||||
|
||||
Expected: New directory created with fresh checkout of `festive-mestorf` branch
|
||||
|
||||
**Step 2: Verify worktree state**
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
Expected: Clean working tree on `festive-mestorf`, no uncommitted changes
|
||||
|
||||
**Step 3: Commit (worktree creation)**
|
||||
|
||||
No commit needed - this is infrastructure setup.
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Keep AppBootstrap and AppRouterBootstrap as TSX Wrappers
|
||||
|
||||
**Files:**
|
||||
- Keep: `src/components/app/AppBootstrap.tsx` (no changes)
|
||||
- Keep: `src/components/app/AppRouterBootstrap.tsx` (no changes)
|
||||
- Rationale: These are minimal BrowserRouter wrappers; JSON cannot render framework providers
|
||||
|
||||
**Step 1: Verify TSX files are already correct**
|
||||
|
||||
```bash
|
||||
cat src/components/app/AppBootstrap.tsx
|
||||
cat src/components/app/AppRouterBootstrap.tsx
|
||||
```
|
||||
|
||||
Expected: Both files contain BrowserRouter wrapper pattern
|
||||
|
||||
**Step 2: Confirm these stay TSX**
|
||||
|
||||
No commits needed - these remain as TSX entry points.
|
||||
|
||||
**Step 3: Note for later**
|
||||
|
||||
These wrappers will be cleaned up during final refactoring if we consolidate to a single entry point.
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Migrate AppLayout
|
||||
|
||||
**Files:**
|
||||
- Current: `src/components/app/AppLayout.tsx`
|
||||
- Create: `src/components/json-definitions/app-layout.json`
|
||||
- Modify: `src/lib/json-ui/json-components.ts`
|
||||
|
||||
**Complexity Note:** AppLayout is the most complex Tier 1 component - it uses SidebarProvider, multiple hooks (useAppNavigation, useAppProject, useAppShortcuts), and prop drilling.
|
||||
|
||||
**Step 1: Create AppLayoutProps interface**
|
||||
|
||||
Create `src/lib/json-ui/interfaces/app-layout.ts`:
|
||||
|
||||
```typescript
|
||||
export interface AppLayoutProps {
|
||||
// Props passed from parent
|
||||
// Most state comes from hooks, not props
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Create custom hook for AppLayout state**
|
||||
|
||||
Create `src/hooks/use-app-layout.ts`:
|
||||
|
||||
```typescript
|
||||
import { useState } from 'react'
|
||||
import useAppNavigation from './use-app-navigation'
|
||||
import useAppProject from './use-app-project'
|
||||
import useAppShortcuts from './use-app-shortcuts'
|
||||
|
||||
export function useAppLayout() {
|
||||
const { currentPage, navigateToPage } = useAppNavigation()
|
||||
const {
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
featureToggles,
|
||||
fileOps,
|
||||
currentProject,
|
||||
handleProjectLoad,
|
||||
stateContext,
|
||||
actionContext,
|
||||
} = useAppProject()
|
||||
const { searchOpen, setSearchOpen, shortcutsOpen, setShortcutsOpen, previewOpen, setPreviewOpen } =
|
||||
useAppShortcuts({ featureToggles, navigateToPage })
|
||||
const [lastSaved] = useState<number | null>(() => Date.now())
|
||||
const [errorCount] = useState(0)
|
||||
|
||||
return {
|
||||
currentPage,
|
||||
navigateToPage,
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
featureToggles,
|
||||
fileOps,
|
||||
currentProject,
|
||||
handleProjectLoad,
|
||||
stateContext,
|
||||
actionContext,
|
||||
searchOpen,
|
||||
setSearchOpen,
|
||||
shortcutsOpen,
|
||||
setShortcutsOpen,
|
||||
previewOpen,
|
||||
setPreviewOpen,
|
||||
lastSaved,
|
||||
errorCount,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Update `src/hooks/index.ts` to export useAppLayout.
|
||||
|
||||
**Step 3: Register hook in hooks-registry**
|
||||
|
||||
Update `src/lib/json-ui/hooks-registry.ts`:
|
||||
|
||||
```typescript
|
||||
import { useAppLayout } from '@/hooks/use-app-layout'
|
||||
|
||||
export const hooksRegistry = {
|
||||
useAppLayout,
|
||||
// ... rest
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: Create JSON definition**
|
||||
|
||||
This is complex - AppLayout uses SidebarProvider and renders:
|
||||
- NavigationMenu (organism)
|
||||
- AppMainPanel (organism)
|
||||
- AppDialogs (organism)
|
||||
|
||||
**Important:** Use `"conditional"` pattern (NOT ConditionalRender component). Use `{ "source": "hookData.propertyName" }` for hook data binding.
|
||||
|
||||
Create `src/components/json-definitions/app-layout.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "app-layout",
|
||||
"type": "SidebarProvider",
|
||||
"props": {
|
||||
"defaultOpen": true
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "nav-menu",
|
||||
"type": "NavigationMenu",
|
||||
"bindings": {
|
||||
"activeTab": { "source": "hookData.currentPage" },
|
||||
"onTabChange": { "source": "hookData.navigateToPage" },
|
||||
"featureToggles": { "source": "hookData.featureToggles" },
|
||||
"errorCount": { "source": "hookData.errorCount" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sidebar-inset-wrapper",
|
||||
"type": "SidebarInset",
|
||||
"children": [
|
||||
{
|
||||
"id": "app-layout-main",
|
||||
"type": "div",
|
||||
"className": "h-screen flex flex-col bg-background",
|
||||
"children": [
|
||||
{
|
||||
"id": "main-panel",
|
||||
"type": "AppMainPanel",
|
||||
"bindings": {
|
||||
"currentPage": { "source": "hookData.currentPage" },
|
||||
"navigateToPage": { "source": "hookData.navigateToPage" },
|
||||
"featureToggles": { "source": "hookData.featureToggles" },
|
||||
"errorCount": { "source": "hookData.errorCount" },
|
||||
"lastSaved": { "source": "hookData.lastSaved" },
|
||||
"currentProject": { "source": "hookData.currentProject" },
|
||||
"onProjectLoad": { "source": "hookData.handleProjectLoad" },
|
||||
"onSearch": { "source": "hookData.setSearchOpen", "transform": "() => setSearchOpen(true)" },
|
||||
"onShowShortcuts": { "source": "hookData.setShortcutsOpen", "transform": "() => setShortcutsOpen(true)" },
|
||||
"onGenerateAI": { "source": "hookData.onGenerateAI" },
|
||||
"onExport": { "source": "hookData.onExport" },
|
||||
"onPreview": { "source": "hookData.setPreviewOpen", "transform": "() => setPreviewOpen(true)" },
|
||||
"onShowErrors": { "source": "hookData.navigateToPage", "transform": "() => navigateToPage('errors')" },
|
||||
"stateContext": { "source": "hookData.stateContext" },
|
||||
"actionContext": { "source": "hookData.actionContext" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dialogs-container",
|
||||
"type": "AppDialogs",
|
||||
"bindings": {
|
||||
"searchOpen": { "source": "hookData.searchOpen" },
|
||||
"onSearchOpenChange": { "source": "hookData.setSearchOpen" },
|
||||
"shortcutsOpen": { "source": "hookData.shortcutsOpen" },
|
||||
"onShortcutsOpenChange": { "source": "hookData.setShortcutsOpen" },
|
||||
"previewOpen": { "source": "hookData.previewOpen" },
|
||||
"onPreviewOpenChange": { "source": "hookData.setPreviewOpen" },
|
||||
"files": { "source": "hookData.files" },
|
||||
"models": { "source": "hookData.models" },
|
||||
"components": { "source": "hookData.components" },
|
||||
"componentTrees": { "source": "hookData.componentTrees" },
|
||||
"workflows": { "source": "hookData.workflows" },
|
||||
"lambdas": { "source": "hookData.lambdas" },
|
||||
"playwrightTests": { "source": "hookData.playwrightTests" },
|
||||
"storybookStories": { "source": "hookData.storybookStories" },
|
||||
"unitTests": { "source": "hookData.unitTests" },
|
||||
"onNavigate": { "source": "hookData.navigateToPage" },
|
||||
"onFileSelect": { "source": "hookData.onFileSelect" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Step 5: Export AppLayout from json-components.ts**
|
||||
|
||||
```typescript
|
||||
export const AppLayout = createJsonComponentWithHooks<AppLayoutProps>(
|
||||
appLayoutDef,
|
||||
{
|
||||
hooks: {
|
||||
hookData: {
|
||||
hookName: 'useAppLayout',
|
||||
args: (props) => [props]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Step 6: Update registry and delete TSX**
|
||||
|
||||
Add to registry:
|
||||
```json
|
||||
{
|
||||
"type": "AppLayout",
|
||||
"source": "app",
|
||||
"jsonCompatible": true
|
||||
}
|
||||
```
|
||||
|
||||
Update imports, verify build, delete TSX file.
|
||||
|
||||
**Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add src/lib/json-ui/interfaces/app-layout.ts \
|
||||
src/lib/json-ui/interfaces/index.ts \
|
||||
src/hooks/use-app-layout.ts \
|
||||
src/hooks/index.ts \
|
||||
src/lib/json-ui/hooks-registry.ts \
|
||||
src/components/json-definitions/app-layout.json \
|
||||
src/lib/json-ui/json-components.ts \
|
||||
json-components-registry.json
|
||||
|
||||
git commit -m "feat: migrate AppLayout to JSON with useAppLayout hook"
|
||||
```
|
||||
|
||||
Then delete TSX:
|
||||
|
||||
```bash
|
||||
rm src/components/app/AppLayout.tsx
|
||||
git add -A
|
||||
git commit -m "feat: delete legacy AppLayout TSX file"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Migrate AppRouterLayout
|
||||
|
||||
**Files:**
|
||||
- Current: `src/components/app/AppRouterLayout.tsx`
|
||||
- Create: `src/components/json-definitions/app-router-layout.json`
|
||||
- Create: `src/hooks/use-app-router-layout.ts`
|
||||
|
||||
**Step 1-7: Follow same pattern as AppLayout**
|
||||
|
||||
AppRouterLayout is nearly identical to AppLayout but:
|
||||
- Does NOT use SidebarProvider
|
||||
- Does NOT include NavigationMenu
|
||||
- Renders div.h-screen with AppMainPanel and AppDialogs directly
|
||||
|
||||
Create `src/hooks/use-app-router-layout.ts` (identical to useAppLayout).
|
||||
|
||||
Create `src/components/json-definitions/app-router-layout.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "app-router-layout",
|
||||
"type": "div",
|
||||
"className": "h-screen flex flex-col bg-background",
|
||||
"children": [
|
||||
{
|
||||
"type": "AppMainPanel",
|
||||
"props": {
|
||||
// Same props mapping as AppLayout
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "AppDialogs",
|
||||
"props": {
|
||||
// Same props mapping as AppLayout
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Export and register following same pattern.
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Migrate AppMainPanel
|
||||
|
||||
**Files:**
|
||||
- Current: `src/components/app/AppMainPanel.tsx`
|
||||
- Create: `src/components/json-definitions/app-main-panel.json`
|
||||
- Create: `src/lib/json-ui/interfaces/app-main-panel.ts`
|
||||
|
||||
**Note:** AppMainPanel primarily composes three things:
|
||||
1. PWAStatusBar (from PWARegistry)
|
||||
2. PWAUpdatePrompt (from PWARegistry)
|
||||
3. AppHeader (organism - will be migrated later)
|
||||
4. RouterProvider (global provider - may stay TSX)
|
||||
|
||||
**Step 1: Create interface**
|
||||
|
||||
```typescript
|
||||
export interface AppMainPanelProps {
|
||||
currentPage: string
|
||||
navigateToPage: (page: string) => void
|
||||
featureToggles: FeatureToggles
|
||||
errorCount: number
|
||||
lastSaved: number | null
|
||||
currentProject: Project
|
||||
onProjectLoad: (project: Project) => void
|
||||
onSearch: () => void
|
||||
onShowShortcuts: () => void
|
||||
onGenerateAI: () => void
|
||||
onExport: () => void
|
||||
onPreview: () => void
|
||||
onShowErrors: () => void
|
||||
stateContext: any
|
||||
actionContext: any
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Create JSON definition**
|
||||
|
||||
Since AppMainPanel primarily uses registry components (PWAStatusBar, AppHeader) and provider (RouterProvider), this is relatively straightforward:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "app-main-panel",
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": {
|
||||
"type": "div",
|
||||
"className": "h-1 bg-primary animate-pulse"
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "PWAStatusBar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "PWAUpdatePrompt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "AppHeader",
|
||||
"props": {
|
||||
"activeTab": { "source": "props.currentPage" },
|
||||
"onTabChange": { "source": "props.navigateToPage" },
|
||||
"featureToggles": { "source": "props.featureToggles" },
|
||||
"errorCount": { "source": "props.errorCount" },
|
||||
"lastSaved": { "source": "props.lastSaved" },
|
||||
"currentProject": { "source": "props.currentProject" },
|
||||
"onProjectLoad": { "source": "props.onProjectLoad" },
|
||||
"onSearch": { "source": "props.onSearch" },
|
||||
"onShowShortcuts": { "source": "props.onShowShortcuts" },
|
||||
"onGenerateAI": { "source": "props.onGenerateAI" },
|
||||
"onExport": { "source": "props.onExport" },
|
||||
"onPreview": { "source": "props.onPreview" },
|
||||
"onShowErrors": { "source": "props.onShowErrors" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "main-content",
|
||||
"type": "div",
|
||||
"className": "flex-1 overflow-hidden",
|
||||
"children": [
|
||||
{
|
||||
"type": "RouterProvider",
|
||||
"props": {
|
||||
"featureToggles": { "source": "props.featureToggles" },
|
||||
"stateContext": { "source": "props.stateContext" },
|
||||
"actionContext": { "source": "props.actionContext" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Export as pure JSON component**
|
||||
|
||||
```typescript
|
||||
export const AppMainPanel = createJsonComponent<AppMainPanelProps>(appMainPanelDef)
|
||||
```
|
||||
|
||||
**Step 4: Update registry and migrate**
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Migrate AppDialogs
|
||||
|
||||
**Files:**
|
||||
- Current: `src/components/app/AppDialogs.tsx`
|
||||
- Create: `src/components/json-definitions/app-dialogs.json`
|
||||
- Create: `src/lib/json-ui/interfaces/app-dialogs.ts`
|
||||
|
||||
**Note:** AppDialogs is primarily a container for registry-sourced dialogs with conditional rendering based on props.
|
||||
|
||||
**Step 1: Create interface**
|
||||
|
||||
```typescript
|
||||
export interface AppDialogsProps {
|
||||
searchOpen: boolean
|
||||
onSearchOpenChange: (open: boolean) => void
|
||||
shortcutsOpen: boolean
|
||||
onShortcutsOpenChange: (open: boolean) => void
|
||||
previewOpen: boolean
|
||||
onPreviewOpenChange: (open: boolean) => void
|
||||
files: ProjectFile[]
|
||||
models: PrismaModel[]
|
||||
components: ComponentNode[]
|
||||
componentTrees: ComponentTree[]
|
||||
workflows: Workflow[]
|
||||
lambdas: Lambda[]
|
||||
playwrightTests: PlaywrightTest[]
|
||||
storybookStories: StorybookStory[]
|
||||
unitTests: UnitTest[]
|
||||
onNavigate: (page: string) => void
|
||||
onFileSelect: (fileId: string) => void
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Create JSON definition**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "app-dialogs",
|
||||
"type": "div",
|
||||
"children": [
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "GlobalSearch",
|
||||
"props": {
|
||||
"open": { "source": "props.searchOpen" },
|
||||
"onOpenChange": { "source": "props.onSearchOpenChange" },
|
||||
"files": { "source": "props.files" },
|
||||
"models": { "source": "props.models" },
|
||||
"components": { "source": "props.components" },
|
||||
"componentTrees": { "source": "props.componentTrees" },
|
||||
"workflows": { "source": "props.workflows" },
|
||||
"lambdas": { "source": "props.lambdas" },
|
||||
"playwrightTests": { "source": "props.playwrightTests" },
|
||||
"storybookStories": { "source": "props.storybookStories" },
|
||||
"unitTests": { "source": "props.unitTests" },
|
||||
"onNavigate": { "source": "props.onNavigate" },
|
||||
"onFileSelect": { "source": "props.onFileSelect" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "KeyboardShortcutsDialog",
|
||||
"props": {
|
||||
"open": { "source": "props.shortcutsOpen" },
|
||||
"onOpenChange": { "source": "props.onShortcutsOpenChange" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "PreviewDialog",
|
||||
"props": {
|
||||
"open": { "source": "props.previewOpen" },
|
||||
"onOpenChange": { "source": "props.onPreviewOpenChange" }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Suspense",
|
||||
"props": {
|
||||
"fallback": null
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "PWAInstallPrompt"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Export as pure JSON component**
|
||||
|
||||
```typescript
|
||||
export const AppDialogs = createJsonComponent<AppDialogsProps>(appDialogsDef)
|
||||
```
|
||||
|
||||
**Step 4: Follow standard migration pattern**
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Verify Build and Run Tests
|
||||
|
||||
**Files:**
|
||||
- Run: `npm run build`
|
||||
- Run: `npm test`
|
||||
|
||||
**Step 1: Build**
|
||||
|
||||
```bash
|
||||
npm run build 2>&1 | tee build-output.log
|
||||
echo "Build exit code: $?"
|
||||
```
|
||||
|
||||
Expected: Exit code 0, no errors
|
||||
|
||||
**Step 2: Run type checker**
|
||||
|
||||
```bash
|
||||
npx tsc --noEmit 2>&1 | head -50
|
||||
```
|
||||
|
||||
Expected: No TypeScript errors
|
||||
|
||||
**Step 3: Run tests (if applicable)**
|
||||
|
||||
```bash
|
||||
npm test 2>&1 | tail -30
|
||||
```
|
||||
|
||||
Expected: All tests pass or show expected failures
|
||||
|
||||
**Step 4: Commit if successful**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "feat: complete Tier 1 bootstrap components JSON migration - build verified"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 8: Create Pull Request
|
||||
|
||||
**Files:**
|
||||
- Reference: Recent commit hashes
|
||||
- Target: `main` branch
|
||||
|
||||
**Step 1: View recent commits**
|
||||
|
||||
```bash
|
||||
git log --oneline -10
|
||||
```
|
||||
|
||||
Expected: See series of commits for Tier 1 components
|
||||
|
||||
**Step 2: Create PR**
|
||||
|
||||
```bash
|
||||
gh pr create \
|
||||
--title "feat: migrate Tier 1 bootstrap components to JSON" \
|
||||
--body "Completes JSON migration for critical bootstrap path:
|
||||
|
||||
- AppBootstrap (with useAppBootstrap hook)
|
||||
- AppRouterBootstrap (with useAppBootstrap hook)
|
||||
- AppLayout (with useAppLayout hook)
|
||||
- AppRouterLayout (with useAppRouterLayout hook)
|
||||
- AppMainPanel (pure component)
|
||||
- AppDialogs (pure component)
|
||||
- LoadingScreen (already JSON)
|
||||
|
||||
All components now use JSON-driven architecture. Build verified." \
|
||||
--base main \
|
||||
--head tier-1-bootstrap
|
||||
```
|
||||
|
||||
Expected: PR created with link
|
||||
|
||||
**Step 3: Commit**
|
||||
|
||||
No commit - PR creation complete.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Validation Checklist
|
||||
|
||||
After all 7 components are migrated, verify:
|
||||
|
||||
- [ ] No imports of `@/components/app/` components exist in codebase (except app.tsx entry)
|
||||
- [ ] All components exported from `@/lib/json-ui/json-components`
|
||||
- [ ] Build succeeds with `npm run build`
|
||||
- [ ] Type checking passes with `npx tsc --noEmit`
|
||||
- [ ] All custom hooks registered in `hooks-registry.ts`
|
||||
- [ ] Component registry updated with all new entries
|
||||
- [ ] All JSON definitions are valid JSON (jq verification)
|
||||
- [ ] PR merged to `main`
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (After Tier 1)
|
||||
|
||||
Once Tier 1 is complete:
|
||||
|
||||
1. **Tier 2 - Organisms** (3 components):
|
||||
- DataSourceManager
|
||||
- NavigationMenu
|
||||
- TreeListPanel
|
||||
|
||||
2. **Tier 3 - Core Atoms/Molecules** (150+ in batches):
|
||||
- Batch by size/complexity
|
||||
- Reuse established patterns
|
||||
|
||||
---
|
||||
|
||||
## Key Decision Points
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|----------|--------|-----------|
|
||||
| Hook pattern | `createJsonComponentWithHooks` | Centralizes stateful logic, no wrapper files needed |
|
||||
| Hook location | `src/hooks/` | Organized, follows existing pattern |
|
||||
| JSON definitions | `src/components/json-definitions/` | Clear separation from legacy TSX |
|
||||
| Interface files | One per component in `src/lib/json-ui/interfaces/` | Matches established convention |
|
||||
| Registry location | `json-components-registry.json` | Single source of truth |
|
||||
|
||||
713
docs/plans/2026-01-21-tier-2-cleanup-remaining-migrations.md
Normal file
713
docs/plans/2026-01-21-tier-2-cleanup-remaining-migrations.md
Normal file
@@ -0,0 +1,713 @@
|
||||
# Tier 2-3 Cleanup & Remaining Migrations Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Complete remaining component migrations, eliminate duplicate TSX/JSON implementations, fix orphaned registry entries, and achieve 95%+ JSON coverage.
|
||||
|
||||
**Architecture:** Three parallel work streams: (1) Fix registry inconsistencies, (2) Migrate remaining molecules/organisms with duplicates, (3) Delete legacy TSX files and consolidate to pure JSON.
|
||||
|
||||
**Tech Stack:** TypeScript, React, JSON Schema, Git, npm
|
||||
|
||||
---
|
||||
|
||||
## Work Stream 1: Registry Cleanup (5 tasks)
|
||||
|
||||
### Task 1: Fix Orphaned JSON Registry Entries
|
||||
|
||||
**Files:**
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Add missing registry entries for orphaned JSON types**
|
||||
|
||||
The audit found 6 orphaned JSON files referencing types not in the registry. Add entries for:
|
||||
- `single` (layout component)
|
||||
- `kv` (data source component)
|
||||
- `create` (action type)
|
||||
- `delete` (action type)
|
||||
- `navigate` (action type)
|
||||
- `update` (action type)
|
||||
|
||||
Add to `json-components-registry.json`:
|
||||
```json
|
||||
{
|
||||
"type": "single",
|
||||
"source": "layouts",
|
||||
"jsonCompatible": true
|
||||
},
|
||||
{
|
||||
"type": "kv",
|
||||
"source": "dataSources",
|
||||
"jsonCompatible": true
|
||||
},
|
||||
{
|
||||
"type": "create",
|
||||
"source": "actions",
|
||||
"jsonCompatible": true
|
||||
},
|
||||
{
|
||||
"type": "delete",
|
||||
"source": "actions",
|
||||
"jsonCompatible": true
|
||||
},
|
||||
{
|
||||
"type": "navigate",
|
||||
"source": "actions",
|
||||
"jsonCompatible": true
|
||||
},
|
||||
{
|
||||
"type": "update",
|
||||
"source": "actions",
|
||||
"jsonCompatible": true
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Verify registry is valid JSON**
|
||||
|
||||
Run: `jq empty json-components-registry.json && echo "✓ Registry is valid JSON"`
|
||||
Expected: ✓ Registry is valid JSON
|
||||
|
||||
**Step 3: Run audit to verify orphaned entries are resolved**
|
||||
|
||||
Run: `npm run audit:json 2>&1 | grep "ORPHANED JSON" | wc -l`
|
||||
Expected: 0 (no orphaned JSON errors)
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add json-components-registry.json
|
||||
git commit -m "fix: add missing registry entries for orphaned JSON types (single, kv, create, delete, navigate, update)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Fix Broken Load Paths in Registry
|
||||
|
||||
**Files:**
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Identify and fix broken load paths**
|
||||
|
||||
The audit found 5 components with broken load paths:
|
||||
- Chart: "@/components/ui/chart/chart-container.tsx"
|
||||
- ComponentTreeManager: "@/components/ComponentTreeManager"
|
||||
- JSONUIShowcase: "@/components/JSONUIShowcase.tsx"
|
||||
- Resizable: "@/components/ui/resizable.tsx"
|
||||
- StyleDesigner: "@/components/StyleDesigner"
|
||||
|
||||
For each:
|
||||
1. Check if the component exists elsewhere with a correct path
|
||||
2. If exists: Update load.path to correct location
|
||||
3. If doesn't exist: Remove load.path (let it resolve through JSON)
|
||||
4. If it's a third-party component (Resizable): Mark `jsonCompatible: false`
|
||||
|
||||
```bash
|
||||
# Check for these files
|
||||
find src -name "chart*.tsx" -o -name "*ComponentTreeManager*" -o -name "*JSONUIShowcase*" -o -name "*resizable*" -o -name "*StyleDesigner*"
|
||||
```
|
||||
|
||||
**Step 2: Remove load.path for components that should use JSON**
|
||||
|
||||
For each broken entry, if no TSX file exists, remove the `load` property entirely:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "Chart",
|
||||
"source": "ui",
|
||||
"jsonCompatible": true
|
||||
// Remove: "load": { "path": "...", "export": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Run audit to verify broken paths are resolved**
|
||||
|
||||
Run: `npm run audit:json 2>&1 | grep "BROKEN LOAD PATH" | wc -l`
|
||||
Expected: 0 (no broken path errors)
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add json-components-registry.json
|
||||
git commit -m "fix: resolve broken load paths in registry (remove paths for JSON-only components)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Mark Third-Party Components in Registry
|
||||
|
||||
**Files:**
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Identify components that are third-party (Shadcn, Recharts, etc.)**
|
||||
|
||||
Run: `grep -r "from '@/components/ui'" src --include="*.tsx" | head -20`
|
||||
|
||||
Add `jsonCompatible: false` for:
|
||||
- Resizable (from Shadcn)
|
||||
- Chart (from Recharts or custom wrapper)
|
||||
- Any other third-party components
|
||||
|
||||
**Step 2: Update registry entries**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "Resizable",
|
||||
"source": "ui",
|
||||
"jsonCompatible": false,
|
||||
"load": {
|
||||
"path": "@/components/ui/resizable",
|
||||
"export": "Resizable"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Verify no build errors**
|
||||
|
||||
Run: `npm run build 2>&1 | grep -E "error|Error"`
|
||||
Expected: No errors
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add json-components-registry.json
|
||||
git commit -m "fix: mark third-party components as not JSON-compatible in registry"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Consolidate Duplicate Implementation Warnings
|
||||
|
||||
**Files:**
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Mark all 125 duplicate components for deletion**
|
||||
|
||||
For each duplicate TSX file with JSON equivalent, set `deleteOldTSX: true` flag:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "AppHeader",
|
||||
"source": "organisms",
|
||||
"jsonCompatible": true,
|
||||
"deleteOldTSX": true
|
||||
}
|
||||
```
|
||||
|
||||
This documents which TSX files should be removed after JSON verification.
|
||||
|
||||
Run script to add flags:
|
||||
```bash
|
||||
# Find all duplicates and add deleteOldTSX flag
|
||||
node -e "
|
||||
const registry = require('./json-components-registry.json');
|
||||
const fs = require('fs');
|
||||
|
||||
// Add to all organisms/molecules/atoms with JSON equivalents
|
||||
const duplicates = [
|
||||
'AppHeader', 'EmptyCanvasState', 'NavigationMenu', 'PageHeader', 'SchemaCodeViewer',
|
||||
// ... (load full list from audit output)
|
||||
];
|
||||
|
||||
duplicates.forEach(type => {
|
||||
const entry = registry.find(e => e.type === type);
|
||||
if (entry) entry.deleteOldTSX = true;
|
||||
});
|
||||
|
||||
fs.writeFileSync('./json-components-registry.json', JSON.stringify(registry, null, 2));
|
||||
"
|
||||
```
|
||||
|
||||
**Step 2: Verify registry is still valid**
|
||||
|
||||
Run: `jq empty json-components-registry.json && echo "✓ Registry valid"`
|
||||
Expected: ✓ Registry valid
|
||||
|
||||
**Step 3: Run audit to document status**
|
||||
|
||||
Run: `npm run audit:json 2>&1 | grep "DUPLICATE IMPLEMENTATION" | wc -l`
|
||||
Expected: 125 (these will be deleted in next phase)
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add json-components-registry.json
|
||||
git commit -m "docs: mark 125 duplicate TSX files for deletion (JSON equivalents exist)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Generate Updated Audit Report
|
||||
|
||||
**Files:**
|
||||
- Create: `MIGRATION_STATUS_REPORT.md`
|
||||
|
||||
**Step 1: Run full audit and capture output**
|
||||
|
||||
Run: `npm run audit:json > audit-current.txt 2>&1`
|
||||
|
||||
**Step 2: Create summary report**
|
||||
|
||||
```bash
|
||||
cat > MIGRATION_STATUS_REPORT.md << 'EOF'
|
||||
# Migration Status Report - 2026-01-21
|
||||
|
||||
## Registry Cleanup Complete ✓
|
||||
|
||||
### Fixed Issues
|
||||
- ✓ 6 orphaned JSON entries added to registry
|
||||
- ✓ 5 broken load paths resolved
|
||||
- ✓ 125 duplicates documented for deletion
|
||||
|
||||
### Current Status
|
||||
- Total JSON components: 119
|
||||
- Total TSX files: 538
|
||||
- Registry entries: 347
|
||||
- Duplicates marked for deletion: 125
|
||||
|
||||
### Next Phase
|
||||
Delete 125 duplicate TSX files now that JSON equivalents are verified and properly registered.
|
||||
EOF
|
||||
```
|
||||
|
||||
**Step 3: Commit report**
|
||||
|
||||
```bash
|
||||
git add MIGRATION_STATUS_REPORT.md audit-current.txt
|
||||
git commit -m "docs: add migration status report after registry cleanup"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Work Stream 2: Migrate Remaining Molecules & Organisms (3 tasks in parallel)
|
||||
|
||||
### Task 6: Migrate Remaining Molecules (AppBranding, CanvasRenderer, etc.)
|
||||
|
||||
**Files:**
|
||||
- Create: `src/components/json-definitions/app-branding.json`
|
||||
- Create: `src/lib/json-ui/interfaces/app-branding.ts`
|
||||
- Modify: `src/lib/json-ui/json-components.ts`
|
||||
- Modify: `src/lib/json-ui/hooks-registry.ts` (if stateful)
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Research remaining molecules in src/components/molecules/**
|
||||
|
||||
Run: `ls -1 src/components/molecules/*.tsx | wc -l`
|
||||
|
||||
Identify 5-10 key molecules that are NOT yet migrated.
|
||||
|
||||
**Step 2: For each molecule: Create JSON definition**
|
||||
|
||||
Example for AppBranding:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "app-branding-container",
|
||||
"type": "div",
|
||||
"props": {
|
||||
"className": "flex items-center gap-3"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"id": "branding-logo",
|
||||
"type": "img",
|
||||
"bindings": {
|
||||
"src": { "source": "props.logoSrc" },
|
||||
"alt": { "source": "props.logoAlt" },
|
||||
"className": "h-8 w-8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "branding-text",
|
||||
"type": "span",
|
||||
"bindings": {
|
||||
"children": { "source": "props.appName" },
|
||||
"className": "font-semibold text-lg"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: Create interface file**
|
||||
|
||||
```typescript
|
||||
// src/lib/json-ui/interfaces/app-branding.ts
|
||||
export interface AppBrandingProps {
|
||||
logoSrc: string
|
||||
logoAlt?: string
|
||||
appName: string
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: Export from json-components.ts**
|
||||
|
||||
```typescript
|
||||
import appBrandingDef from '@/components/json-definitions/app-branding.json'
|
||||
export const AppBranding = createJsonComponent<AppBrandingProps>(appBrandingDef)
|
||||
```
|
||||
|
||||
**Step 5: Update registry**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "AppBranding",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true,
|
||||
"deleteOldTSX": true
|
||||
}
|
||||
```
|
||||
|
||||
**Step 6: Build and verify**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 7: Commit**
|
||||
|
||||
```bash
|
||||
git add src/components/json-definitions/app-branding.json src/lib/json-ui/interfaces/app-branding.ts src/lib/json-ui/json-components.ts json-components-registry.json
|
||||
git commit -m "feat: migrate AppBranding molecule to JSON"
|
||||
```
|
||||
|
||||
Repeat for 5-10 remaining molecules in parallel batches.
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Migrate Remaining Organisms (Schema Viewers, Canvas Components, etc.)
|
||||
|
||||
**Files:**
|
||||
- Create: `src/components/json-definitions/schema-code-viewer.json`
|
||||
- Create: `src/lib/json-ui/interfaces/schema-code-viewer.ts`
|
||||
- Modify: `src/lib/json-ui/json-components.ts`
|
||||
- Modify: `src/lib/json-ui/hooks-registry.ts` (for stateful organisms)
|
||||
- Modify: `json-components-registry.json`
|
||||
|
||||
**Step 1: Identify 3-5 key organisms to migrate**
|
||||
|
||||
From audit: SchemaCodeViewer, SchemaEditorLayout, CanvasRenderer, etc.
|
||||
|
||||
**Step 2: Create JSON definitions with hook integration**
|
||||
|
||||
For organisms with complex state (SchemaEditorLayout):
|
||||
|
||||
```typescript
|
||||
// Create hook
|
||||
export const useSchemaEditorLayout = () => {
|
||||
const [activePanel, setActivePanel] = useState('code')
|
||||
const [schema, setSchema] = useState({})
|
||||
|
||||
return {
|
||||
activePanel,
|
||||
setActivePanel,
|
||||
schema,
|
||||
setSchema
|
||||
}
|
||||
}
|
||||
|
||||
// Register in hooks-registry.ts
|
||||
hooksRegistry['useSchemaEditorLayout'] = useSchemaEditorLayout
|
||||
|
||||
// Use in JSON
|
||||
export const SchemaEditorLayout = createJsonComponentWithHooks<Props>(
|
||||
schemaEditorLayoutDef,
|
||||
{
|
||||
hooks: {
|
||||
editor: { hookName: 'useSchemaEditorLayout', args: () => [] }
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Step 3: Create interface files**
|
||||
|
||||
```typescript
|
||||
export interface SchemaCodeViewerProps {
|
||||
code: string
|
||||
language?: string
|
||||
readonly?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: Update registry and build**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 5: Commit each organism**
|
||||
|
||||
```bash
|
||||
git commit -m "feat: migrate SchemaCodeViewer to JSON with hook support"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Consolidate and Verify All Exports
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/lib/json-ui/json-components.ts`
|
||||
- Modify: `src/lib/json-ui/interfaces/index.ts`
|
||||
- Verify: All exports match registry
|
||||
|
||||
**Step 1: Run type check**
|
||||
|
||||
Run: `npm run components:generate-types 2>&1`
|
||||
Expected: Successful type generation
|
||||
|
||||
**Step 2: Verify all registry entries are exported**
|
||||
|
||||
Run: `node -e "const reg = require('./json-components-registry.json'); console.log('Total entries:', reg.length); console.log('JSON-compatible:', reg.filter(e => e.jsonCompatible).length)"`
|
||||
|
||||
**Step 3: Check for missing exports**
|
||||
|
||||
```bash
|
||||
# Compare registry entries against actual exports in json-components.ts
|
||||
node scripts/verify-exports.ts
|
||||
```
|
||||
|
||||
**Step 4: Build and verify**
|
||||
|
||||
Run: `npm run build 2>&1 | grep -E "error|✓"`
|
||||
Expected: ✓ built in X.XXs (no errors)
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git commit -m "fix: verify all JSON-compatible components are exported and registered"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Work Stream 3: Delete Legacy TSX Files (4 tasks)
|
||||
|
||||
### Task 9: Delete 125 Duplicate TSX Files - Batch 1
|
||||
|
||||
**Files:**
|
||||
- Delete: 30-40 TSX files from src/components/atoms/ and src/components/molecules/
|
||||
|
||||
**Step 1: Generate deletion script**
|
||||
|
||||
```bash
|
||||
cat > scripts/delete-duplicates-batch-1.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Delete atoms batch 1 (marked as deleted in latest commit)
|
||||
rm -f src/components/atoms/ActionCard.tsx
|
||||
rm -f src/components/atoms/AppLogo.tsx
|
||||
rm -f src/components/atoms/BindingIndicator.tsx
|
||||
rm -f src/components/atoms/Breadcrumb.tsx
|
||||
rm -f src/components/atoms/Calendar.tsx
|
||||
# ... etc for 30-40 files
|
||||
|
||||
echo "✓ Deleted 30 TSX files (atoms batch 1)"
|
||||
EOF
|
||||
chmod +x scripts/delete-duplicates-batch-1.sh
|
||||
```
|
||||
|
||||
**Step 2: Run deletion script**
|
||||
|
||||
Run: `bash scripts/delete-duplicates-batch-1.sh`
|
||||
|
||||
**Step 3: Verify deletions with git**
|
||||
|
||||
Run: `git status | grep "deleted:" | wc -l`
|
||||
Expected: ~30
|
||||
|
||||
**Step 4: Build to verify no import errors**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "refactor: delete 30 duplicate TSX atoms (JSON equivalents exist)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 10: Delete 125 Duplicate TSX Files - Batch 2
|
||||
|
||||
**Files:**
|
||||
- Delete: 30-40 TSX files from src/components/molecules/ and src/components/organisms/
|
||||
|
||||
**Step 1: Generate and run deletion script**
|
||||
|
||||
```bash
|
||||
bash scripts/delete-duplicates-batch-2.sh
|
||||
```
|
||||
|
||||
**Step 2: Verify and build**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git commit -m "refactor: delete 30 duplicate TSX molecules and organisms (JSON equivalents exist)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 11: Delete Remaining TSX Files - Batch 3
|
||||
|
||||
**Files:**
|
||||
- Delete: ~40-50 remaining duplicate TSX files
|
||||
|
||||
**Step 1: Run final deletion batch**
|
||||
|
||||
```bash
|
||||
bash scripts/delete-duplicates-batch-3.sh
|
||||
```
|
||||
|
||||
**Step 2: Verify build**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 3: Final audit**
|
||||
|
||||
Run: `npm run audit:json 2>&1 | grep "DUPLICATE IMPLEMENTATION" | wc -l`
|
||||
Expected: 0 (all duplicates removed)
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git commit -m "refactor: delete final batch of duplicate TSX files - 95% JSON migration complete"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 12: Update Index Files for Remaining Components
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/components/atoms/index.ts`
|
||||
- Modify: `src/components/molecules/index.ts`
|
||||
- Modify: `src/components/organisms/index.ts`
|
||||
|
||||
**Step 1: Verify remaining TSX exports**
|
||||
|
||||
Run: `ls -1 src/components/atoms/*.tsx | grep -v json-ui`
|
||||
|
||||
Only remaining TSX files should be those NOT marked for JSON conversion (framework providers, complex integrations, etc.)
|
||||
|
||||
**Step 2: Update index files to only export non-JSON components**
|
||||
|
||||
```typescript
|
||||
// src/components/atoms/index.ts - only export non-JSON atoms
|
||||
export { SomeFrameworkComponent } from './SomeFrameworkComponent'
|
||||
// ... remove all that have JSON equivalents
|
||||
```
|
||||
|
||||
**Step 3: Build and verify**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -5`
|
||||
Expected: ✓ built in X.XXs
|
||||
|
||||
**Step 4: Run audit**
|
||||
|
||||
Run: `npm run audit:json`
|
||||
Expected: 0 errors, 0 duplicate warnings, only framework providers remain
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git commit -m "fix: update component index files after TSX cleanup"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Final Verification (1 task)
|
||||
|
||||
### Task 13: Run Full Test Suite and Final Audit
|
||||
|
||||
**Files:**
|
||||
- Create: `FINAL_MIGRATION_REPORT.md`
|
||||
|
||||
**Step 1: Run build**
|
||||
|
||||
Run: `npm run build 2>&1 | tail -10`
|
||||
Expected: ✓ built in X.XXs (no errors)
|
||||
|
||||
**Step 2: Run full audit**
|
||||
|
||||
Run: `npm run audit:json > final-audit.txt 2>&1`
|
||||
|
||||
**Step 3: Verify migration targets met**
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const registry = require('./json-components-registry.json');
|
||||
|
||||
const stats = {
|
||||
total: registry.length,
|
||||
jsonCompatible: registry.filter(e => e.jsonCompatible).length,
|
||||
coverage: (registry.filter(e => e.jsonCompatible).length / registry.length * 100).toFixed(1)
|
||||
};
|
||||
|
||||
console.log('Migration Coverage:', stats.coverage + '%');
|
||||
console.log('Total Components:', stats.total);
|
||||
console.log('JSON Components:', stats.jsonCompatible);
|
||||
"
|
||||
```
|
||||
|
||||
Expected: Coverage ≥ 95%
|
||||
|
||||
**Step 4: Create final report**
|
||||
|
||||
```markdown
|
||||
# Final Migration Report - 2026-01-21
|
||||
|
||||
## Migration Complete ✓
|
||||
|
||||
### Statistics
|
||||
- Total components migrated: 150+
|
||||
- JSON compatibility: 95%+
|
||||
- Registry cleaned: 11 errors fixed
|
||||
- Duplicate TSX files deleted: 125
|
||||
- Build status: PASSING
|
||||
|
||||
### Components by Type
|
||||
- Atoms: ~85% migrated
|
||||
- Molecules: ~80% migrated
|
||||
- Organisms: ~85% migrated
|
||||
- Framework providers: Kept as TSX (not JSON-renderable)
|
||||
|
||||
### Key Achievements
|
||||
1. Eliminated 125 duplicate implementations
|
||||
2. Fixed all registry inconsistencies
|
||||
3. Established scalable JSON migration patterns
|
||||
4. Achieved 95%+ JSON component coverage
|
||||
5. Zero build failures or regressions
|
||||
|
||||
### Remaining Work
|
||||
- Future phases can focus on remaining 5% framework-specific components
|
||||
- Additional optimizations possible (code splitting, chunking improvements)
|
||||
```
|
||||
|
||||
**Step 5: Commit final report**
|
||||
|
||||
```bash
|
||||
git add FINAL_MIGRATION_REPORT.md final-audit.txt
|
||||
git commit -m "docs: add final migration report - 95%+ JSON coverage achieved"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
This plan represents three parallel work streams over 13 focused tasks:
|
||||
1. **Registry Cleanup** (5 tasks): Fix inconsistencies, mark duplicates, generate reports
|
||||
2. **Component Migrations** (3 tasks): Migrate remaining molecules/organisms in parallel
|
||||
3. **Cleanup & Verification** (4 tasks): Delete duplicate TSX, update indexes, final audit
|
||||
|
||||
**Expected Outcomes:**
|
||||
- ✓ 0 registry errors
|
||||
- ✓ 95%+ JSON component coverage
|
||||
- ✓ 125 duplicate TSX files deleted
|
||||
- ✓ All imports consolidated through JSON architecture
|
||||
- ✓ Build passing with no errors
|
||||
- ✓ Clear foundation for future migrations
|
||||
|
||||
**Execution Model:** Parallel subagents on independent work streams + periodic consolidation commits.
|
||||
Reference in New Issue
Block a user