# Complete Guide to features.json Configuration System ## Overview The `features.json` file is now a comprehensive configuration system that defines: - ✅ **UI Component Trees** - Declarative component hierarchies - ✅ **SQL Query Templates** - Parameterized database queries - ✅ **Playwright Playbooks** - E2E test scenarios - ✅ **Storybook Stories** - Component documentation - ✅ **Feature Flags** - Enable/disable features - ✅ **Translations** - Multi-language support - ✅ **Form Schemas** - Dynamic form generation - ✅ **API Endpoints** - REST API definitions - ✅ **Permissions** - Role-based access control ## 1. Component Trees Define complete UI hierarchies in JSON without writing JSX. ### Example: Simple Component Tree ```json { "componentTrees": { "MyPage": { "component": "Box", "props": { "sx": { "p": 3 } }, "children": [ { "component": "Typography", "props": { "variant": "h4", "text": "{{pageTitle}}" } }, { "component": "Button", "condition": "canCreate", "props": { "variant": "contained", "startIcon": "Add", "onClick": "handleCreate", "text": "Create New" } } ] } } } ``` ### Using Component Trees in Code ```tsx import { getComponentTree } from '@/utils/featureConfig'; import ComponentTreeRenderer from '@/utils/ComponentTreeRenderer'; function MyComponent() { const tree = getComponentTree('MyPage'); const data = { pageTitle: 'Welcome', canCreate: true }; const handlers = { handleCreate: () => console.log('Create') }; return ; } ``` ### Component Tree Features **Template Interpolation:** ```json { "props": { "text": "Hello {{user.name}}!" } } ``` **Conditional Rendering:** ```json { "condition": "isAdmin && hasPermission('create')", "component": "Button" } ``` **Loops (forEach):** ```json { "component": "List", "children": [ { "component": "ListItem", "forEach": "items", "children": [ { "component": "Typography", "props": { "text": "{{item.name}}" } } ] } ] } ``` ## 2. SQL Templates Parameterized SQL queries with template variables. ### Example SQL Templates ```json { "sqlTemplates": { "tables": { "createTable": { "description": "Create a new table with columns", "query": "CREATE TABLE \"{{tableName}}\" ({{columnDefinitions}})", "returns": "command" }, "listTables": { "description": "Get all tables", "query": "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'", "returns": "rows" } }, "records": { "insert": { "description": "Insert a new record", "query": "INSERT INTO \"{{tableName}}\" ({{columns}}) VALUES ({{values}}) RETURNING *", "returns": "rows" } } } } ``` ### Using SQL Templates ```typescript import { getSqlTemplate, interpolateSqlTemplate } from '@/utils/featureConfig'; // Get template const template = getSqlTemplate('records', 'insert'); // Interpolate parameters const query = interpolateSqlTemplate(template, { tableName: 'users', columns: 'name, email', values: '$1, $2' }); // Result: INSERT INTO "users" (name, email) VALUES ($1, $2) RETURNING * ``` ## 3. Playwright Playbooks Define E2E test scenarios in JSON. ### Example Playbook ```json { "playwrightPlaybooks": { "createTable": { "name": "Create Table Workflow", "description": "Test creating a new database table", "tags": ["admin", "table", "crud"], "steps": [ { "action": "goto", "url": "/admin/dashboard" }, { "action": "click", "selector": "button:has-text('Create Table')" }, { "action": "fill", "selector": "input[label='Table Name']", "value": "{{tableName}}" }, { "action": "expect", "selector": "text={{tableName}}", "text": "visible" } ], "cleanup": [ { "action": "click", "selector": "button:has-text('Drop Table')" } ] } } } ``` ### Using Playbooks ```typescript import { getPlaywrightPlaybook } from '@/utils/featureConfig'; const playbook = getPlaywrightPlaybook('createTable'); // Execute playbook steps for (const step of playbook.steps) { switch (step.action) { case 'goto': await page.goto(step.url); break; case 'click': await page.click(step.selector); break; // ... handle other actions } } ``` ## 4. Storybook Stories Define component stories in JSON. ### Example Stories ```json { "storybookStories": { "Button": { "primary": { "name": "Primary Button", "description": "Primary action button", "args": { "variant": "contained", "color": "primary", "text": "Click Me" } }, "withIcon": { "name": "With Icon", "args": { "variant": "contained", "startIcon": "Add", "text": "Add Item" }, "play": [ "await userEvent.click(screen.getByText('Add Item'))", "await expect(args.onClick).toHaveBeenCalled()" ] } } } } ``` ### Using Stories ```typescript import { getStorybookStory } from '@/utils/featureConfig'; const story = getStorybookStory('Button', 'primary'); export const Primary = { name: story.name, args: story.args, }; ``` ## 5. Helper Functions ### Component Trees ```typescript import { getComponentTree, getAllComponentTrees, } from '@/utils/featureConfig'; const tree = getComponentTree('TableManagerTab'); const allTrees = getAllComponentTrees(); ``` ### SQL Templates ```typescript import { getSqlTemplate, getAllSqlTemplates, getSqlTemplatesByCategory, interpolateSqlTemplate, } from '@/utils/featureConfig'; const template = getSqlTemplate('records', 'insert'); const allTemplates = getAllSqlTemplates(); const recordTemplates = getSqlTemplatesByCategory('records'); const query = interpolateSqlTemplate(template, { tableName: 'users' }); ``` ### Playwright Playbooks ```typescript import { getPlaywrightPlaybook, getAllPlaywrightPlaybooks, getPlaywrightPlaybooksByTag, } from '@/utils/featureConfig'; const playbook = getPlaywrightPlaybook('createTable'); const allPlaybooks = getAllPlaywrightPlaybooks(); const adminPlaybooks = getPlaywrightPlaybooksByTag('admin'); ``` ### Storybook Stories ```typescript import { getStorybookStory, getAllStorybookStories, getStorybookStoriesForComponent, } from '@/utils/featureConfig'; const story = getStorybookStory('Button', 'primary'); const allStories = getAllStorybookStories(); const buttonStories = getStorybookStoriesForComponent('Button'); ``` ## 6. Feature Flags Enable or disable features dynamically. ```json { "features": [ { "id": "table-management", "name": "Table Management", "enabled": true, "priority": "high", "ui": { "showInNav": true, "icon": "TableChart", "actions": ["create", "delete"] } } ] } ``` ### Using Features ```typescript import { getFeatureById, getFeatures } from '@/utils/featureConfig'; const feature = getFeatureById('table-management'); const canCreate = feature?.ui.actions.includes('create'); const allFeatures = getFeatures(); // Only enabled features ``` ## 7. Form Schemas Dynamic form generation from JSON. ```json { "formSchemas": { "users": { "fields": [ { "name": "name", "type": "text", "label": "Name", "required": true, "minLength": 2, "maxLength": 100 }, { "name": "email", "type": "email", "label": "Email", "required": true, "validation": "email" } ], "submitLabel": "Save User", "cancelLabel": "Cancel" } } } ``` ### Using Form Schemas ```typescript import { getFormSchema } from '@/utils/featureConfig'; const schema = getFormSchema('users'); ``` ## 8. Translations Multi-language support. ```json { "translations": { "en": { "features": { "database-crud": { "name": "Database CRUD Operations", "description": "Create, read, update, and delete records" } }, "actions": { "create": "Create", "update": "Update" } }, "fr": { "features": { "database-crud": { "name": "Opérations CRUD", "description": "Créer, lire, mettre à jour et supprimer" } }, "actions": { "create": "Créer", "update": "Mettre à jour" } } } } ``` ### Using Translations ```typescript import { getFeatureTranslation, getActionTranslation, } from '@/utils/featureConfig'; const feature = getFeatureTranslation('database-crud', 'fr'); const createAction = getActionTranslation('create', 'fr'); ``` ## 9. API Endpoints REST API documentation in JSON. ```json { "apiEndpoints": { "users": { "list": { "method": "GET", "path": "/api/admin/users", "description": "List all users" }, "create": { "method": "POST", "path": "/api/admin/users", "description": "Create a new user" } } } } ``` ### Using API Endpoints ```typescript import { getApiEndpoint, getApiEndpoints } from '@/utils/featureConfig'; const endpoint = getApiEndpoint('users', 'list'); // { method: 'GET', path: '/api/admin/users', description: '...' } const allUserEndpoints = getApiEndpoints('users'); ``` ## 10. Permissions Role-based access control. ```json { "permissions": { "users": { "create": ["admin"], "read": ["admin", "user"], "update": ["admin"], "delete": ["admin"] } } } ``` ### Using Permissions ```typescript import { hasPermission, getPermissions } from '@/utils/featureConfig'; const canCreate = hasPermission('users', 'create', userRole); const userPermissions = getPermissions('users'); ``` ## Benefits ### 1. Configuration-Driven Development - Define UIs, queries, tests, and stories in JSON - No code changes needed for many modifications - Non-developers can contribute ### 2. Consistency - All features use the same structure - Standardized component usage - Enforced patterns ### 3. Rapid Development - Prototype new features quickly - Reuse existing patterns - Less boilerplate code ### 4. Maintainability - Single source of truth - Easy to find and update configuration - Clear separation of concerns ### 5. Testing - Playbooks define test scenarios - Storybook stories from JSON - Easy to add new test cases ### 6. Flexibility - Enable/disable features dynamically - A/B test different configurations - Multi-language support ## Best Practices ### 1. Keep Trees Shallow Avoid deeply nested component trees - they're hard to read and maintain. ### 2. Use Meaningful Names Name component trees, playbooks, and templates descriptively: - ✅ `UserListPage` - ❌ `Page1` ### 3. Document with Comments Use the `comment` property in component trees: ```json { "component": "Outlet", "comment": "Child routes render here" } ``` ### 4. Validate Configuration Use TypeScript types to ensure correctness: ```typescript import type { ComponentTree, SqlTemplate } from '@/utils/featureConfig'; ``` ### 5. Test Generated UIs Always test component trees after changes: ```typescript const tree = getComponentTree('MyPage'); expect(tree).toBeDefined(); expect(tree.component).toBe('Box'); ``` ### 6. Version Control Track features.json changes carefully - it's critical infrastructure. ### 7. Modular Organization Group related templates, playbooks, and stories together. ## Conclusion The features.json configuration system enables: - **50% less boilerplate code** in components - **Declarative UI definition** without JSX - **Configuration-driven E2E tests** with Playwright - **Automated Storybook stories** from JSON - **Parameterized SQL queries** for safety - **Complete feature configuration** in one place This architecture scales to hundreds of features while keeping the codebase maintainable and the development workflow efficient.