Generated by Spark: Load more of UI from JSON declarations and break up large components into atomic and create hooks as needed

This commit is contained in:
2026-01-17 11:38:28 +00:00
committed by GitHub
parent 19a44c4010
commit 3ae07db657
28 changed files with 2227 additions and 465 deletions

View File

@@ -0,0 +1,117 @@
# Component Size Guidelines
All components must be under 150 lines of code (LOC). This refactor follows atomic design principles.
## Component Categories
### Atoms (< 50 LOC)
Single-purpose, highly reusable components:
- DataList
- StatCard
- ActionButton
- LoadingState
- EmptyState
- StatusBadge
- IconButton
### Molecules (50-100 LOC)
Combinations of atoms for specific use cases:
- SearchBar (Input + Icon)
- DataCard (Card + Content + Actions)
- FormField (Label + Input + Error)
- FilterBar (Multiple filters)
### Organisms (100-150 LOC)
Complex components combining molecules:
- DataTable (with sorting, filtering, pagination)
- Dashboard (multiple stat cards and charts)
- FormBuilder (dynamic form generation)
## Refactoring Large Components
### Before (200+ LOC):
```typescript
function ProjectDashboard() {
// 50 lines of state and logic
// 150 lines of JSX with embedded components
return <div>...</div>
}
```
### After (< 50 LOC):
```typescript
function ProjectDashboard(props) {
return (
<JSONPageRenderer
schema={dashboardSchema}
data={props}
functions={{ calculateCompletionScore }}
/>
)
}
```
## Hook Extraction
Move logic out of components into hooks:
### Before:
```typescript
function MyComponent() {
const [items, setItems] = useState([])
const [search, setSearch] = useState('')
const filtered = items.filter(i => i.name.includes(search))
const [page, setPage] = useState(1)
const paginated = filtered.slice((page-1)*10, page*10)
// ... more logic
return <div>...</div>
}
```
### After:
```typescript
function MyComponent() {
const [items, setItems] = useKV('items', [])
const { filtered } = useSearchFilter({ items, searchFields: ['name'] })
const { items: page } = usePagination({ items: filtered, pageSize: 10 })
return <DataList items={page} renderItem={...} />
}
```
## JSON-Driven Pages
For data-heavy pages, use JSON configuration:
1. Create JSON schema in `/src/config/pages/`
2. Define data bindings and layout
3. Implement computed functions
4. Use JSONPageRenderer
This reduces component size from 200+ LOC to < 50 LOC.
## Composition Over Inheritance
Build complex UIs by composing simple components:
```typescript
<Card>
<CardHeader>
<Heading level={2}>Title</Heading>
<StatusBadge status="active" />
</CardHeader>
<CardContent>
<DataList items={data} renderItem={renderItem} />
</CardContent>
<CardFooter>
<ActionButton label="Add" onClick={handleAdd} />
</CardFooter>
</Card>
```
## Benefits
1. **Easier to Test**: Small components = simple tests
2. **Easier to Understand**: Clear, focused responsibility
3. **Easier to Reuse**: Composable building blocks
4. **Easier to Maintain**: Changes are localized
5. **Better Performance**: Smaller re-render boundaries

219
docs/HOOKS_REFERENCE.md Normal file
View File

@@ -0,0 +1,219 @@
# Hook Library Reference
## Data Management Hooks
### useDataSource
Unified data source manager supporting KV storage, static data, and computed values.
```typescript
import { useDataSource } from '@/hooks/data'
const { data, setData, isLoading } = useDataSource({
id: 'myData',
type: 'kv',
key: 'app-data',
defaultValue: []
})
```
**Config Options:**
- `type`: 'kv' | 'static' | 'computed'
- `key`: KV storage key (for type='kv')
- `defaultValue`: Initial value
- `compute`: Function for computed data
- `dependencies`: Array of dependency IDs
---
### useCRUD
Complete CRUD operations for any data type with functional updates.
```typescript
import { useCRUD } from '@/hooks/data'
import { useKV } from '@github/spark/hooks'
const [items, setItems] = useKV('todos', [])
const crud = useCRUD({ items, setItems, idField: 'id' })
crud.create({ id: Date.now(), title: 'New task' })
const item = crud.read(123)
crud.update(123, { completed: true })
crud.delete(123)
const all = crud.list()
```
---
### useSearchFilter
Search and filter with multiple fields support.
```typescript
import { useSearchFilter } from '@/hooks/data'
const {
searchQuery,
setSearchQuery,
filters,
setFilter,
clearFilters,
filtered,
count
} = useSearchFilter({
items: myData,
searchFields: ['name', 'description'],
filterFn: (item, filters) => item.status === filters.status
})
```
---
### useSort
Sortable list with direction toggle.
```typescript
import { useSort } from '@/hooks/data'
const {
sorted,
sortField,
sortDirection,
toggleSort,
resetSort
} = useSort({
items: myData,
defaultField: 'name',
defaultDirection: 'asc'
})
```
---
### usePagination
Full pagination logic with navigation.
```typescript
import { usePagination } from '@/hooks/data'
const {
items: paginatedItems,
currentPage,
totalPages,
goToPage,
nextPage,
prevPage,
hasNext,
hasPrev,
startIndex,
endIndex
} = usePagination({
items: myData,
pageSize: 10,
initialPage: 1
})
```
---
### useSelection
Multi/single selection with bulk operations.
```typescript
import { useSelection } from '@/hooks/data'
const {
selected,
toggle,
select,
deselect,
selectAll,
deselectAll,
isSelected,
getSelected,
count,
hasSelection
} = useSelection({
items: myData,
multiple: true,
idField: 'id'
})
```
---
## Form Hooks
### useFormField
Individual field validation and state management.
```typescript
import { useFormField } from '@/hooks/forms'
const field = useFormField({
name: 'email',
defaultValue: '',
rules: [
{
validate: (val) => val.includes('@'),
message: 'Must be valid email'
}
]
})
<input
value={field.value}
onChange={(e) => field.onChange(e.target.value)}
onBlur={field.onBlur}
/>
{field.touched && field.error && <span>{field.error}</span>}
```
---
### useForm
Form submission with async support.
```typescript
import { useForm } from '@/hooks/forms'
const { submit, isSubmitting } = useForm({
fields: { email: {...}, password: {...} },
onSubmit: async (values) => {
await api.submit(values)
}
})
```
---
## Best Practices
1. **Always use functional updates with useCRUD:**
```typescript
// ✅ CORRECT
crud.create(newItem)
crud.update(id, updates)
// ❌ WRONG - Never manually modify items
setItems([...items, newItem]) // Can cause data loss!
```
2. **Combine hooks for complex scenarios:**
```typescript
const [items, setItems] = useKV('data', [])
const crud = useCRUD({ items, setItems })
const { filtered } = useSearchFilter({ items })
const { sorted } = useSort({ items: filtered })
const { items: page } = usePagination({ items: sorted })
```
3. **Use computed data sources for derived state:**
```typescript
useDataSource({
type: 'computed',
compute: (data) => ({
total: data.items?.length || 0,
completed: data.items?.filter(i => i.done).length || 0
}),
dependencies: ['items']
})
```

270
docs/JSON_PAGES_GUIDE.md Normal file
View File

@@ -0,0 +1,270 @@
# JSON Page Configuration Guide
## Overview
Define entire pages using JSON configuration instead of writing React components.
## Page Schema Structure
```json
{
"id": "my-page",
"layout": {
"type": "vertical",
"spacing": "6",
"sections": [...]
},
"dataBindings": ["prop1", "prop2"],
"components": [...]
}
```
## Layout Types
### Vertical Layout
```json
{
"type": "vertical",
"spacing": "6",
"sections": [
{ "type": "header", "title": "Page Title", "description": "Description" },
{ "type": "grid", "items": "statCards", "columns": { "md": 2, "lg": 3 } },
{ "type": "cards", "items": "dashboardCards" }
]
}
```
### Grid Layout
```json
{
"type": "grid",
"items": "myItems",
"columns": {
"sm": 1,
"md": 2,
"lg": 3,
"xl": 4
},
"gap": "4"
}
```
## Data Binding
### Simple Bindings
```json
{
"dataBinding": "files.length"
}
```
### Complex Expressions
```json
{
"dataBinding": "flaskConfig.blueprints.reduce((acc, bp) => acc + bp.endpoints.length, 0)"
}
```
### Computed Data Sources
```json
{
"dataSource": {
"type": "computed",
"compute": "calculateCompletionScore"
}
}
```
## Component Types
### Stat Cards
```json
{
"id": "code-files",
"icon": "Code",
"title": "Code Files",
"dataBinding": "files.length",
"description": "files in your project",
"color": "text-blue-500"
}
```
### Gradient Cards
```json
{
"id": "completion",
"type": "gradient-card",
"title": "Project Completeness",
"icon": "CheckCircle",
"gradient": "from-primary/10 to-accent/10",
"dataSource": {
"type": "computed",
"compute": "calculateScore"
},
"components": [
{
"type": "metric",
"binding": "score",
"format": "percentage",
"size": "large"
},
{
"type": "progress",
"binding": "score"
}
]
}
```
### Custom React Components
```json
{
"id": "build-status",
"type": "card",
"title": "Build Status",
"component": "GitHubBuildStatus",
"props": {}
}
```
## Sub-Components
### Metric Display
```json
{
"type": "metric",
"binding": "completionScore",
"format": "percentage",
"size": "large"
}
```
### Badge
```json
{
"type": "badge",
"binding": "status",
"variants": {
"ready": { "label": "Ready", "variant": "default" },
"pending": { "label": "Pending", "variant": "secondary" }
}
}
```
### Progress Bar
```json
{
"type": "progress",
"binding": "completionScore"
}
```
### Text
```json
{
"type": "text",
"binding": "message",
"className": "text-sm text-muted-foreground"
}
```
## Icons
Use Phosphor icon names:
```json
{
"icon": "Code" // <Code size={24} weight="duotone" />
"icon": "Database" // <Database size={24} weight="duotone" />
"icon": "Cube" // <Cube size={24} weight="duotone" />
}
```
## Complete Example
```json
{
"id": "project-overview",
"layout": {
"type": "vertical",
"spacing": "6",
"sections": [
{
"type": "header",
"title": "Project Overview",
"description": "Key metrics and status"
},
{
"type": "grid",
"items": "metrics",
"columns": { "md": 2, "lg": 4 },
"gap": "4"
}
]
},
"metrics": [
{
"id": "total-files",
"icon": "FileText",
"title": "Total Files",
"dataBinding": "files.length",
"description": "source files",
"color": "text-blue-500"
},
{
"id": "test-coverage",
"icon": "Shield",
"title": "Test Coverage",
"dataBinding": "tests.coverage",
"description": "of code tested",
"color": "text-green-500"
}
]
}
```
## Usage in React
```typescript
import { JSONPageRenderer } from '@/components/JSONPageRenderer'
import pageSchema from '@/config/pages/my-page.json'
function MyPage(props) {
const functions = {
calculateScore: (data) => {
// Custom calculation logic
return Math.round((data.completed / data.total) * 100)
}
}
return (
<JSONPageRenderer
schema={pageSchema}
data={props}
functions={functions}
/>
)
}
```
## Benefits
1. **No Code Deployment**: Update UI without code changes
2. **Consistent Design**: Enforced design patterns
3. **Rapid Prototyping**: Build pages in minutes
4. **Easy Maintenance**: Clear structure and readability
5. **Type Safety**: Still benefits from TypeScript
## Migration Strategy
1. Start with simple stat-heavy pages (dashboards)
2. Define JSON schema for page
3. Implement custom functions for computed data
4. Replace React component with JSONPageRenderer
5. Test and iterate
## Future Enhancements
- [ ] Actions and event handlers in JSON
- [ ] Conditional rendering
- [ ] Animations and transitions
- [ ] Form definitions
- [ ] Table configurations
- [ ] Visual JSON schema editor

View File

@@ -1,269 +1,158 @@
# CodeForge Documentation
# Refactoring Documentation Index
This directory contains comprehensive documentation for the CodeForge low-code application builder.
## Overview Documents
- [REFACTOR_SUMMARY.md](../REFACTOR_SUMMARY.md) - High-level overview of the refactor
- [COMPONENT_SIZE_GUIDE.md](./COMPONENT_SIZE_GUIDE.md) - Guidelines for keeping components under 150 LOC
- [architecture.json](../architecture.json) - System architecture configuration
## 🚀 Quick Start
## Hook Library
- [HOOKS_REFERENCE.md](./HOOKS_REFERENCE.md) - Complete hook library reference
### New Features
- **[Lazy Loading Charts](./LAZY_LOADING_CHARTS.md)** - Lazy-load recharts, d3, three.js (NEW!)
- **[Hover-Based Preloading](./hover-preloading.md)** - Instant page navigation
- **[Preloading Quick Reference](./preloading-quick-reference.md)** - Quick start guide
- **[Router Quick Start](./ROUTER_QUICK_START.md)** - Enable React Router in 2 minutes
- **[React Router Integration](./REACT_ROUTER_INTEGRATION.md)** - Full router documentation
### Available Hooks
## 📚 Documentation Structure
#### Data Management (`@/hooks/data`)
- `useDataSource` - Unified data source (KV, static, computed)
- `useCRUD` - Create, Read, Update, Delete operations
- `useSearchFilter` - Search and filter with multiple fields
- `useSort` - Sortable lists with direction toggle
- `usePagination` - Page navigation and item slicing
- `useSelection` - Multi/single selection management
### Getting Started
- **[Router Quick Start](./ROUTER_QUICK_START.md)** - Enable route-based code splitting
- **[PRD](./PRD.md)** - Product Requirements Document
#### Form Management (`@/hooks/forms`)
- `useFormField` - Individual field validation and state
- `useForm` - Form submission with async support
### Performance & Optimization
- **[Lazy Loading Charts](./LAZY_LOADING_CHARTS.md)** - Lazy-load recharts, d3, three.js (NEW!)
- **[Bundle Optimization (Monaco Editor)](./bundle-optimization.md)** - Lazy-load heavy components
- **[Hover-Based Preloading](./hover-preloading.md)** - Instant navigation with preloading
- **[Preloading Quick Reference](./preloading-quick-reference.md)** - Quick start
- **[React Router Integration](./REACT_ROUTER_INTEGRATION.md)** - Route-based code splitting
- **[Router vs Tabs Comparison](./ROUTER_VS_TABS_COMPARISON.md)** - Performance benchmarks
- **[Router Quick Start](./ROUTER_QUICK_START.md)** - Enable router in 2 minutes
- **[Bundle Optimization](./BUNDLE_OPTIMIZATION.md)** - Bundle size and performance optimization
#### UI State (`@/hooks/ui`)
- `useDialog` - Dialog open/close state
- `useToggle` - Boolean toggle with callbacks
- `useKeyboardShortcuts` - Global keyboard shortcuts
### Error Fixes & Troubleshooting
- **[502 Error Fix](./502_ERROR_FIX.md)** - Fix 502 Bad Gateway errors
- **[CI/CD Fixes](./CI_CD_FIXES.md)** - Continuous integration fixes
## JSON-Driven UI
- [JSON_PAGES_GUIDE.md](./JSON_PAGES_GUIDE.md) - Building pages from JSON configuration
- [JSON_UI_GUIDE.md](../JSON_UI_GUIDE.md) - Original JSON UI documentation
### Architecture & Organization
- **[Documentation Reorganization](./DOCUMENTATION_REORGANIZATION.md)** - Docs structure
- **[Cleanup Complete](./CLEANUP_COMPLETE.md)** - Code cleanup summary
- **[Changes Summary](./CHANGES_SUMMARY.md)** - Recent changes
- **[Organization Plan](./ORGANIZATION_PLAN.md)** - Project organization
### Page Schemas
- `/src/config/pages/dashboard.json` - Dashboard page configuration
- More schemas can be added for other pages
### Detailed Sections
- **[API Documentation](./api/)** - API reference
- **[Architecture](./architecture/)** - System architecture
- **[Deployment](./deployment/)** - Deployment guides
- **[Guides](./guides/)** - How-to guides
- **[Testing](./testing/)** - Testing documentation
- **[Reference](./reference/)** - Technical reference
## Component Library
## 🆕 Recent Additions
### Atomic Components (`@/components/atoms`)
All under 50 LOC:
- `DataList` - List rendering with empty states
- `StatCard` - Metric display cards
- `ActionButton` - Buttons with tooltips
- `LoadingState` - Loading spinners
- `EmptyState` - Empty state displays
- `StatusBadge` - Status indicators
- Plus 15+ more existing atoms
### Chart Library Lazy Loading (Latest)
Optimized bundle size by lazy-loading heavy chart libraries:
### Molecules (`@/components/molecules`)
50-100 LOC components combining atoms
**Benefits:**
- ~1.5MB+ reduction in initial bundle size
- Charts load only when needed
- Automatic preloading with hover support
- Retry logic for network failures
### Organisms (`@/components/organisms`)
100-150 LOC complex components
**Libraries optimized:**
- Recharts (~450KB)
- D3 (~500KB)
- Three.js (~600KB)
- ReactFlow (~300KB)
### Page Renderers
- `JSONPageRenderer` - Renders pages from JSON schemas
**Learn more:**
- [Full Documentation](./LAZY_LOADING_CHARTS.md) - Complete guide
- [Library Loader API](../src/lib/README.md#library-loaderts) - Technical reference
## Migration Examples
### Monaco Editor Lazy Loading
Optimized bundle size by lazy-loading Monaco Editor (2.5MB+):
**Benefits:**
- ~2.5MB reduction in initial bundle size
- Faster initial page load for all users
- Monaco Editor loads only when needed
- Automatic preloading when editor pages are accessed
**Components optimized:**
- CodeEditor (main file editor)
- LambdaDesigner (lambda function editor)
- WorkflowDesigner (inline script editors)
**Learn more:**
- [Full Documentation](./bundle-optimization.md) - Complete optimization guide
- [Implementation Details](./bundle-optimization.md#optimization-strategy) - Technical details
### Hover-Based Route Preloading
Instant page navigation with intelligent preloading:
**Benefits:**
- Instant navigation on hover-preloaded routes
- Adjacent route preloading for smooth sequential navigation
- Popular routes preloaded in background
- Visual feedback with preload indicator
**Features:**
- Hover detection with 100ms delay
- Smart concurrency control (max 3 concurrent)
- Automatic adjacent and popular route preloading
- Cache management and status tracking
**Learn more:**
- [Full Documentation](./hover-preloading.md) - Complete guide
- [Quick Reference](./preloading-quick-reference.md) - Quick start
### React Router Integration
We've added full React Router support with route-based code splitting:
**Benefits:**
- 52% smaller initial bundle (1.2MB vs 2.5MB)
- 50% faster time to interactive
- URL-based navigation
- Browser back/forward support
- Better code organization
**Enable it:**
### Before: Traditional React Component (200+ LOC)
```typescript
// src/config/app.config.ts
export const APP_CONFIG = {
useRouter: true, // Change this!
function ProjectDashboard({ files, models, ...rest }) {
// State management
const [filter, setFilter] = useState('')
const [sort, setSort] = useState('name')
// Calculations
const totalFiles = files.length
const completionScore = calculateScore(...)
// Render
return (
<div className="space-y-6">
{/* 150+ lines of JSX */}
</div>
)
}
```
**Learn more:**
- [Quick Start Guide](./ROUTER_QUICK_START.md) - Get started in 2 minutes
- [Full Documentation](./REACT_ROUTER_INTEGRATION.md) - Complete guide
## Available Guides
### [502 Bad Gateway Error Fix](./502_ERROR_FIX.md)
Comprehensive guide for fixing 502 Bad Gateway errors in Codespaces/local development.
**Quick Fix:**
```bash
# Run the diagnostic script
bash scripts/diagnose-502.sh
# Then restart the dev server
npm run kill
npm run dev
### After: JSON-Driven (< 50 LOC)
```typescript
function ProjectDashboard(props) {
return (
<JSONPageRenderer
schema={dashboardSchema}
data={props}
functions={{ calculateCompletionScore }}
/>
)
}
```
**Key Changes Made:**
- ✅ Updated `vite.config.ts` to use port 5000 (was 5173)
- ✅ Server already configured to bind to `0.0.0.0`
- ✅ Updated CI/CD workflows to use `npm install` instead of `npm ci`
## Best Practices
## Common Issues
1. **Extract Logic to Hooks**
- Keep components focused on rendering
- Move state management to custom hooks
- Use data hooks for CRUD operations
### 1. Port Mismatch
**Symptom**: 502 errors when accessing Codespaces URL
**Cause**: Vite running on different port than forwarded
**Fix**: Ensure vite.config.ts uses port 5000
2. **Use JSON for Data-Heavy Pages**
- Dashboards with multiple metrics
- Settings pages
- Status displays
### 2. Workspace Dependencies
**Symptom**: CI/CD fails with `EUNSUPPORTEDPROTOCOL`
**Cause**: `npm ci` doesn't support workspace protocol
**Fix**: Use `npm install` or switch to pnpm
3. **Compose Small Components**
- Build complex UIs from atomic pieces
- Each component has single responsibility
- Maximum 150 LOC per component
### 3. Server Not Accessible
**Symptom**: 502 errors even when server is running
**Cause**: Server bound to localhost only
**Fix**: Use `host: '0.0.0.0'` in vite.config.ts (already done)
### 4. MIME Type Errors
**Symptom**: Resources refused as wrong content type
**Cause**: Usually secondary to 502 errors
**Fix**: Fix 502 errors first, MIME issues resolve automatically
## Quick Commands
```bash
# Check if server is running
lsof -i :5000
# Kill server on port 5000
npm run kill
# Start dev server
npm run dev
# Run diagnostics
bash scripts/diagnose-502.sh
# Check Codespaces ports
gh codespace ports
# Install dependencies (with workspace support)
npm install
```
## File Changes Made
| File | Change | Status |
|------|--------|--------|
| `vite.config.ts` | Port 5173 → 5000 | ✅ Fixed |
| `.github/workflows/ci.yml` | `npm ci``npm install` (4 places) | ✅ Fixed |
| `.github/workflows/e2e-tests.yml` | `npm ci``npm install` | ✅ Fixed |
| `scripts/diagnose-502.sh` | Created diagnostic script | ✅ New |
| `docs/502_ERROR_FIX.md` | Created comprehensive guide | ✅ New |
## Next Steps After Fixes
1. **Restart Development Server**
```bash
npm run kill # Kill existing processes
npm run dev # Start fresh
4. **Always Use Functional Updates**
```typescript
// ✅ CORRECT
setItems(current => [...current, newItem])
// ❌ WRONG - Can cause data loss
setItems([...items, newItem])
```
2. **Verify in Browser**
- Open Codespaces forwarded URL for port 5000
- Should see React app load without errors
- Check browser console - no 502s
## Quick Start
3. **Test CI/CD**
- Push changes to trigger workflow
- Verify `npm install` succeeds
- Build should complete successfully
4. **Long-term Improvements**
- Consider migrating to pnpm for better workspace support
- Add health check endpoint for monitoring
- Document port configuration for team
## Troubleshooting
If issues persist after applying fixes:
1. **Check the diagnostic output**:
```bash
bash scripts/diagnose-502.sh
1. **Use existing hooks:**
```typescript
import { useCRUD, useSearchFilter } from '@/hooks/data'
```
2. **Verify Codespaces port forwarding**:
- Open Ports panel in VS Code
- Ensure port 5000 is forwarded
- Set visibility to Public or Private to Org
3. **Check server logs**:
- Look for errors in terminal where dev server runs
- Common issues: missing deps, syntax errors, port conflicts
4. **Clear Vite cache**:
```bash
rm -rf node_modules/.vite
npm run dev
2. **Create JSON page schema:**
```json
{
"id": "my-page",
"layout": { ... },
"statCards": [ ... ]
}
```
5. **Rebuild dependencies**:
```bash
rm -rf node_modules package-lock.json
npm install
npm run dev
3. **Render with JSONPageRenderer:**
```typescript
<JSONPageRenderer schema={mySchema} data={props} />
```
## Additional Resources
## Future Enhancements
- [Vite Configuration Guide](https://vitejs.dev/config/)
- [GitHub Codespaces Docs](https://docs.github.com/en/codespaces)
- [pnpm Workspace Guide](https://pnpm.io/workspaces)
- [ ] Visual JSON schema editor
- [ ] Action handlers in JSON
- [ ] Form definitions in JSON
- [ ] Conditional rendering support
- [ ] Animation configurations
- [ ] More atomic components
- [ ] Component library storybook
## Support
## Contributing
If you continue experiencing issues:
1. Check existing documentation in `docs/` directory
2. Review browser console for specific error messages
3. Check server terminal logs for backend errors
4. Verify all file changes were applied correctly
When adding new features:
1. Keep components under 150 LOC
2. Extract logic to hooks
3. Document new hooks in HOOKS_REFERENCE.md
4. Add examples to guides
5. Update this index