10 KiB
features.json - Complete Configuration System
Build half your app (or more!) with declarative JSON configuration.
Overview
The enhanced features.json is a comprehensive, declarative configuration system that enables you to build complete applications without writing most of the boilerplate code. It provides:
- 🌐 Translations (i18n) for all UI elements
- 📐 Layout definitions for tables, columns, and components
- 🎯 Action namespaces mapping UI actions to functions
- 📝 Form schemas with validation rules
- 🔌 API endpoint configurations
- 🔐 Permission system for role-based access
- 🔗 Relationship definitions between resources
- 🌳 Component trees for declarative UI hierarchies
- ⚙️ Component props with runtime validation
Quick Example
Instead of writing this JSX:
function UserListPage() {
const [users, setUsers] = useState([]);
return (
<Box>
<Typography variant="h4">Users</Typography>
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={handleCreate}
>
Create New
</Button>
<DataGrid
columns={[
{ name: 'id', label: 'ID', width: 80 },
{ name: 'name', label: 'Name', width: 200 },
{ name: 'email', label: 'Email', width: 250 }
]}
rows={users}
/>
</Box>
);
}
You define this in JSON:
{
"componentTrees": {
"UserListPage": {
"component": "Box",
"children": [
{
"component": "Typography",
"props": { "variant": "h4", "text": "{{resourceName}}" }
},
{
"component": "Button",
"condition": "hasPermission('create')",
"props": {
"variant": "contained",
"startIcon": "Add",
"text": "Create New",
"onClick": "handleCreate"
}
},
{
"component": "DataGrid",
"dataSource": "tableData",
"props": {
"columns": "{{columns}}",
"rows": "{{rows}}"
}
}
]
}
}
}
Then render it:
import { getComponentTree } from '@/utils/featureConfig';
const tree = getComponentTree('UserListPage');
renderComponentTree(tree, data, handlers);
What Can You Build?
✅ Complete CRUD Interfaces
Define tables, columns, forms, and actions in JSON:
{
"tableLayouts": {
"users": {
"columns": ["id", "name", "email"],
"columnWidths": { "id": 80, "name": 200, "email": 250 }
}
},
"formSchemas": {
"users": {
"fields": [
{ "name": "name", "type": "text", "required": true },
{ "name": "email", "type": "email", "required": true }
]
}
}
}
✅ Multilingual UIs
Support multiple languages:
{
"translations": {
"en": {
"actions": { "create": "Create", "delete": "Delete" }
},
"fr": {
"actions": { "create": "Créer", "delete": "Supprimer" }
}
}
}
✅ Permission-Based Access
Control who can do what:
{
"permissions": {
"users": {
"create": ["admin"],
"read": ["admin", "user"],
"update": ["admin"],
"delete": ["admin"]
}
}
}
if (hasPermission('users', 'delete', userRole)) {
// Show delete button
}
✅ Complete Page Layouts
Define entire pages declaratively:
{
"componentTrees": {
"AdminDashboard": {
"component": "Box",
"children": [
{ "component": "Sidebar" },
{ "component": "AppBar" },
{ "component": "MainContent" }
]
}
}
}
✅ Validated Components
Ensure components are used correctly:
{
"componentProps": {
"Button": {
"props": {
"variant": {
"type": "enum",
"values": ["text", "outlined", "contained"],
"default": "text"
}
}
}
}
}
// Automatic validation
validateComponentProps('Button', {
variant: 'invalid' // ❌ Error caught!
});
Configuration Sections
1. Translations
Define UI text in multiple languages.
Functions:
getFeatureTranslation(id, locale)getActionTranslation(action, locale)getTableTranslation(table, locale)getColumnTranslation(column, locale)
2. Actions
Map UI actions to function names.
Functions:
getActionFunctionName(feature, action)
3. Table & Column Layouts
Define how data is displayed.
Functions:
getTableLayout(table)getColumnLayout(column)
4. Table & Column Features
Enable/disable features per table/column.
Functions:
getTableFeatures(table)getColumnFeatures(column)
5. Form Schemas
Define forms declaratively.
Functions:
getFormSchema(table)
6. Validation Rules
Define reusable validation patterns.
Functions:
getValidationRule(ruleName)
7. API Endpoints
Configure REST API routes.
Functions:
getApiEndpoints(resource)getApiEndpoint(resource, action)
8. Permissions
Role-based access control.
Functions:
getPermissions(resource)hasPermission(resource, action, role)
9. Relationships
Define data relationships.
Functions:
getRelationships(table)
10. UI Views
Configure view types for resources.
Functions:
getUiViews(resource)getUiView(resource, view)
11. Component Trees
Define UI hierarchies in JSON.
Functions:
getComponentTree(treeName)getAllComponentTrees()
12. Component Props
Define and validate component props.
Functions:
getComponentPropSchema(component)validateComponentProps(component, props)getComponentsByCategory(category)
13. Component Layouts
Configure component display settings.
Functions:
getComponentLayout(component)
Complete Example
Generate a full CRUD interface from configuration:
import {
getTableLayout,
getFormSchema,
getApiEndpoints,
getPermissions,
getComponentTree,
hasPermission,
} from '@/utils/featureConfig';
function generateCRUDPage(resourceName: string, userRole: string) {
const layout = getTableLayout(resourceName);
const form = getFormSchema(resourceName);
const api = getApiEndpoints(resourceName);
const permissions = getPermissions(resourceName);
const tree = getComponentTree('ResourceListPage');
return {
// Table configuration
columns: layout?.columns.map(col => ({
name: col,
width: layout.columnWidths[col],
})),
// Actions based on permissions
actions: ['create', 'update', 'delete'].filter(action =>
hasPermission(resourceName, action, userRole)
),
// Form fields
formFields: form?.fields,
// API endpoints
endpoints: api,
// UI tree
componentTree: tree,
};
}
// Generate complete page for users
const userPage = generateCRUDPage('users', 'admin');
Documentation
Comprehensive guides are available:
- FEATURES_CONFIG_GUIDE.md - Quick start and API reference
- BUILDING_WITH_CONFIG.md - Building apps from configuration
- COMPONENT_TREES.md - Declarative UI hierarchies
- COMPONENT_PROPS.md - Prop validation and type checking
Statistics
- ~2000 lines of configuration
- 40+ helper functions
- 25+ TypeScript types
- 250+ test cases
- 21 component schemas
- 5 pre-built component trees
- 60+ pages of documentation
Benefits
🚀 Rapid Development
Add features by updating JSON, not writing code.
🎯 Consistency
All features follow the same patterns.
📚 Self-Documenting
Configuration serves as documentation.
✅ Type Safety
Runtime validation without TypeScript overhead.
🔧 Maintainable
Central source of truth for all configuration.
🌐 Internationalized
Built-in translation support.
🔐 Secure
Centralized permission management.
🧪 Testable
Easy to test configuration vs. hardcoded logic.
🎨 Flexible
Override defaults when needed.
📈 Scalable
Add resources without boilerplate.
Real-World Use Cases
1. Admin Panels
Generate complete admin interfaces from database schema.
2. CRUD Applications
Build data management apps declaratively.
3. Dashboards
Create dashboards with widgets defined in JSON.
4. Forms
Generate complex forms with validation.
5. Permissions
Implement role-based access control.
6. Multi-Tenant Apps
Configure different UIs per tenant.
7. API Clients
Auto-generate API calls from endpoints.
8. Documentation
Generate component docs from schemas.
9. Prototyping
Quickly build prototypes without code.
10. A/B Testing
Swap UI configurations for testing.
Best Practices
- Start with core resources - Define tables, columns, forms
- Add translations early - Easier than retrofitting
- Use validation - Validate props before rendering
- Document everything - Add descriptions to schemas
- Test configurations - Unit test helper functions
- Version control - Track config changes
- Keep trees shallow - Avoid deep nesting
- Reuse patterns - Extract common structures
- Validate on save - Check JSON validity
- Generate types - Create TypeScript types from config
Getting Started
- Explore the config:
import { getFeatures, getNavItems } from '@/utils/featureConfig';
const features = getFeatures();
const navItems = getNavItems();
- Add a new resource:
{
"tableLayouts": {
"products": {
"columns": ["id", "name", "price"]
}
}
}
- Generate a form:
const schema = getFormSchema('products');
// Use schema to render form
- Check permissions:
if (hasPermission('products', 'create', userRole)) {
// Show create button
}
- Render a component tree:
const tree = getComponentTree('ResourceListPage');
renderComponentTree(tree, data, handlers);
Conclusion
With a comprehensive features.json, you can:
✅ Build half your app (or more!) from configuration ✅ Generate UIs declaratively ✅ Validate components at runtime ✅ Support multiple languages ✅ Implement permissions ✅ Create forms without code ✅ Define entire page layouts ✅ Maintain consistency ✅ Improve developer experience ✅ Scale rapidly
The future is declarative. The future is features.json.
For detailed documentation, see the guides in the /docs folder.