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:
2026-01-21 02:25:05 +00:00
parent 8c1a8486c7
commit 53c8a72c0f
19 changed files with 2406 additions and 430 deletions

View 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 |

View 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.