7.7 KiB
Props Configuration Guide
Overview
The CodeForge application now supports dynamic component props configuration through the pages.json file. This declarative approach eliminates the need to modify App.tsx when adding or updating component props, making the system more maintainable and scalable.
Architecture
Key Files
src/config/pages.json- Declarative page and props configurationsrc/config/page-loader.ts- Props resolution logic and interfacessrc/App.tsx- Consumes the configuration and renders pages
Props Configuration Schema
Basic Props Structure
{
"id": "example-page",
"component": "ExampleComponent",
"props": {
"state": ["stateKey1", "stateKey2"],
"actions": ["actionPropName:actionFunctionName"]
}
}
Props Configuration Options
state Array
Maps application state to component props. Supports two formats:
-
Direct mapping (prop name = state key):
"state": ["files", "models", "theme"]Results in:
{ files, models, theme } -
Renamed mapping (prop name : state key):
"state": ["trees:componentTrees", "config:flaskConfig"]Results in:
{ trees: componentTrees, config: flaskConfig }
actions Array
Maps action functions (handlers/setters) to component props. Uses format:
"actions": ["propName:functionName"]
Example:
"actions": [
"onModelsChange:setModels",
"onFileSelect:setActiveFileId"
]
Resizable Page Configuration
For pages with split-panel layouts (e.g., File Explorer + Code Editor):
{
"id": "code",
"component": "CodeEditor",
"requiresResizable": true,
"props": {
"state": ["files", "activeFileId"],
"actions": ["onFileChange:handleFileChange"]
},
"resizableConfig": {
"leftComponent": "FileExplorer",
"leftProps": {
"state": ["files", "activeFileId"],
"actions": ["onFileSelect:setActiveFileId"]
},
"leftPanel": {
"defaultSize": 20,
"minSize": 15,
"maxSize": 30
},
"rightPanel": {
"defaultSize": 80
}
}
}
Available State Keys
The following state variables are available in the state context:
files- Project filesmodels- Data modelscomponents- Component definitionscomponentTrees- Component tree structuresworkflows- Workflow definitionslambdas- Lambda function definitionstheme- Theme configurationplaywrightTests- Playwright test definitionsstorybookStories- Storybook story definitionsunitTests- Unit test definitionsflaskConfig- Flask API configurationnextjsConfig- Next.js project configurationnpmSettings- NPM package settingsfeatureToggles- Feature toggle statesactiveFileId- Currently selected file ID
Available Actions
The following action functions are available in the action context:
handleFileChange- Update file contentsetActiveFileId- Set active filehandleFileClose- Close a filehandleFileAdd- Add new filesetModels- Update modelssetComponents- Update componentssetComponentTrees- Update component treessetWorkflows- Update workflowssetLambdas- Update lambdassetTheme- Update themesetPlaywrightTests- Update Playwright testssetStorybookStories- Update Storybook storiessetUnitTests- Update unit testssetFlaskConfig- Update Flask configsetNextjsConfig- Update Next.js configsetNpmSettings- Update NPM settingssetFeatureToggles- Update feature toggles
Examples
Simple Component (No Props)
{
"id": "docs",
"title": "Documentation",
"component": "DocumentationView",
"props": {}
}
Component with State Only
{
"id": "models",
"title": "Models",
"component": "ModelDesigner",
"props": {
"state": ["models"]
}
}
Component with State and Actions
{
"id": "models",
"title": "Models",
"component": "ModelDesigner",
"props": {
"state": ["models"],
"actions": ["onModelsChange:setModels"]
}
}
Component with Renamed Props
{
"id": "flask",
"title": "Flask API",
"component": "FlaskDesigner",
"props": {
"state": ["config:flaskConfig"],
"actions": ["onConfigChange:setFlaskConfig"]
}
}
Dashboard with Multiple State Props
{
"id": "dashboard",
"title": "Dashboard",
"component": "ProjectDashboard",
"props": {
"state": [
"files",
"models",
"components",
"theme",
"playwrightTests",
"storybookStories",
"unitTests",
"flaskConfig"
]
}
}
Adding a New Page
To add a new page with props configuration:
-
Add the page to
pages.json:{ "id": "new-page", "title": "New Feature", "icon": "Star", "component": "NewFeatureComponent", "enabled": true, "order": 21, "props": { "state": ["relevantState"], "actions": ["onAction:setRelevantState"] } } -
Add the component to the lazy import map in
App.tsx:const componentMap: Record<string, React.LazyExoticComponent<any>> = { // ... existing components NewFeatureComponent: lazy(() => import('@/components/NewFeatureComponent').then(m => ({ default: m.NewFeatureComponent }))), } -
Optionally add to feature toggles (if applicable):
{ "toggleKey": "newFeature" }
That's it! No need to modify the getPropsForComponent function or other logic in App.tsx.
Benefits
- Declarative Configuration - All page configs in one place
- No Code Changes - Add/modify pages without touching
App.tsxlogic - Type Safety - TypeScript interfaces ensure configuration validity
- Maintainability - Easy to understand and modify page props
- Scalability - Simple to add new pages and props
- Consistency - Standardized prop resolution across all pages
Migration from Old System
The old hardcoded propsMap in getPropsForComponent has been replaced with dynamic resolution using resolveProps(). The configuration in pages.json now drives all prop mapping.
Before (Hardcoded in App.tsx)
const propsMap: Record<string, any> = {
'ModelDesigner': {
models,
onModelsChange: setModels,
},
// ... 20+ more entries
}
After (Declarative in pages.json)
{
"id": "models",
"component": "ModelDesigner",
"props": {
"state": ["models"],
"actions": ["onModelsChange:setModels"]
}
}
Future Enhancements
Potential extensions to the props configuration system:
- Computed Props - Props derived from multiple state values
- Prop Transformations - Map/filter/reduce operations on state
- Conditional Props - Props based on feature toggles or user state
- Default Values - Fallback values for missing state
- Validation Rules - Runtime prop validation from schema
- Hook Configuration - Custom hooks to inject into components
- Event Handlers - Declarative event handler composition
Troubleshooting
Props not being passed to component
- Check that the state/action key exists in the context objects
- Verify the prop name mapping is correct (before:after colon)
- Ensure the page is enabled and not filtered by feature toggles
- Check browser console for resolution errors
Component not rendering
- Verify the component is added to the
componentMapinApp.tsx - Check that the component name matches exactly (case-sensitive)
- Ensure the component export matches the import pattern
State updates not working
- Verify the action function name is correct
- Check that the setter is using functional updates for array/object state
- Ensure the action is properly mapped in the action context