Auto-Generated, Data-Driven Frontend Framework
AFrame is a complete full-stack framework that generates production-ready React/MUI components and C# backend controllers directly from OpenAPI specifications. Build complete CRUD applications in minutes without writing UI code.
AFrame bridges the gap between your API specification and your application by:
- Parsing your OpenAPI 3.x spec
- Inferring component types and behaviors
- Generating React components, hooks, and configuration
- Enforcing backend API structure with C# controller interfaces
The result: A fully functional, themed, validated UI that stays in sync with your API.
- π Zero-Config Generation - Point at OpenAPI spec, get complete UI
- π¨ Zero CSS Required - Everything via MUI theme tokens
- π Full CRUD Components - Cards, DataGrids, Forms, Search, Infinite Scroll
- π Smart Relations - Auto-detected from $ref, with modals and grids
- βοΈ Highly Configurable - Override at global, entity, or component level
- πͺ React Query Hooks - Built-in caching and state management
- π‘οΈ Type Safe - Full TypeScript support throughout
- π Backend Enforcement - C# controller interfaces ensure API consistency
- π Complete Documentation - Astro-based docs site with examples
- OpenAPI parser
- Code generator
- Runtime components (Card, DataGrid, Search, etc.)
- React Query hooks
- Theming system
- Configuration system
- Controller interface (
IAFrameController) - Base controller implementation
- Entity interface (
IEntity) - Service interface (
IEntityService) - Standard response formats
- Example User and Role controllers
- Complete working example
- User and Role management
- Mock API with sample data
- Multiple view types (Grid, Cards, Search)
- Full CRUD operations
- Getting started guide
- Architecture overview
- API inference rules
- Configuration guide
- Code examples
- Deployment instructions
npm installnpm run devVisit http://localhost:5173 to see the demo with User and Role management.
npm run generate -- -i your-api.yaml -o ./generated/aframeimport { AFrameProvider } from 'aframe';
import { A } from './generated/aframe';
const config = {
api: { baseUrl: 'https://api.example.com' },
theme: { palette: { primary: { main: '#6366f1' } } },
};
function App() {
return (
<AFrameProvider config={config}>
<A.User.DataGrid />
<A.User.CreationCard />
</AFrameProvider>
);
}aframe/
βββ src/ # Frontend framework
β βββ cli/ # Code generator CLI
β βββ parser/ # OpenAPI parser
β βββ generator/ # Code generator
β βββ runtime/
β β βββ components/ # React components
β β βββ hooks/ # React Query hooks
β β βββ context/ # Theme & config
β βββ types/ # TypeScript types
β βββ index.ts # Main exports
β
βββ backend/ # C# backend library
β βββ Core/
β β βββ IEntity.cs # Base entity interface
β β βββ IEntityService.cs # Service contract
β β βββ ListResponse.cs # Standard response
β βββ Controllers/
β β βββ IAFrameController.cs # Controller interface
β β βββ AFrameControllerBase.cs # Base implementation
β βββ Models/
β β βββ User.cs # User entity & DTOs
β β βββ Role.cs # Role entity & DTOs
β βββ Examples/
β β βββ UserController.cs # Example controller
β β βββ RoleController.cs # Example controller
β βββ AFrame.Backend.csproj
β
βββ demo/ # React demo app
β βββ src/
β β βββ generated/ # Generated components
β β βββ App.tsx # Demo application
β β βββ main.tsx # Entry point
β β βββ mockApi.ts # Mock API
β βββ index.html
β βββ tsconfig.json
β βββ README.md
β
βββ docs/ # Documentation site (Astro)
β βββ src/
β β βββ layouts/Layout.astro # Main layout
β β βββ pages/
β β βββ index.astro # Homepage
β β βββ examples.astro # Code examples
β β βββ docs/
β β βββ getting-started.astro
β β βββ how-it-works.astro
β β βββ frontend.astro
β β βββ backend.astro
β β βββ api-inference.astro
β β βββ configuration.astro
β βββ astro.config.mjs
β βββ package.json
β
βββ package.json # Root dependencies
βββ tsconfig.json # TypeScript config
βββ vite.config.ts # Vite config
βββ .gitignore
βββ README.md # This file
OpenAPI Spec
β
[Parser] β Extracts entities, fields, relations, operations
β
[Generator] β Emits React components and hooks
β
React Components + Configuration
AFrame intelligently infers how to render your data:
| OpenAPI | Component | Example |
|---|---|---|
string |
TextField | firstName |
string, format: email |
EmailField | user@example.com |
string, format: date |
DateField | 2024-01-25 |
integer |
NumberField | 42 |
boolean |
Switch | true/false |
string, enum |
Select | active, pending |
array of $ref |
RelationGrid | List of roles |
GET /resourceβ DataGrid, InfiniteScroll, SearchGET /resource/{id}β Card (view mode)POST /resourceβ CreationCardPATCH /resource/{id}β Card (edit mode)DELETE /resource/{id}β Delete button
Each entity gets these components:
<A.User.Card id="123" /> // View/edit single
<A.User.CreationCard /> // Create new
<A.User.DataGrid /> // Paginated table
<A.User.Search /> // Search & filter
<A.User.ListItem data={user} /> // List item
<A.User.InfiniteScroll /> // Infinite scroll
<A.User.Fields.Email /> // Individual field
<A.User.Relations.Roles.DataGrid /> // Relation gridconst { data, isLoading } = useEntity('User', '123');
const { data, isLoading } = useEntityList('User', { page: 1 });
const mutation = useCreateEntity('User');
const mutation = useUpdateEntity('User');
const mutation = useDeleteEntity('User');const config = {
api: {
baseUrl: 'https://api.example.com',
headers: { 'Authorization': 'Bearer token' },
},
theme: {
palette: {
primary: { main: '#6366f1' },
secondary: { main: '#ec4899' },
},
},
Card: {
// optional component-level settings
},
// optional entity specific settings
entities: {
User: {
// optional settings to override globals
props: {
title: (e) => `${e.firstName} ${e.lastName}`,
subtitle: 'email',
},
styles: {
Card: { elevation: 2 },
TextField: { size: 'small' },
},
theme: {
palette: { primary: { main: '#4A6CF7' } },
},
fields: {
email: {
validation: (v) => v?.includes('@') ? undefined : 'Invalid',
},
},
},
},
};// All entities must implement IEntity
public interface IEntity
{
string Id { get; set; }
DateTime CreatedAt { get; set; }
DateTime UpdatedAt { get; set; }
}
// All services must implement IEntityService
public interface IEntityService<TEntity, TCreateDto, TUpdateDto>
{
Task<ListResponse<TEntity>> GetAllAsync(int page, int pageSize, string? search);
Task<TEntity?> GetByIdAsync(string id);
Task<TEntity> CreateAsync(TCreateDto dto);
Task<TEntity> UpdateAsync(string id, TUpdateDto dto);
Task DeleteAsync(string id);
Task<bool> ExistsAsync(string id);
}
// All controllers must implement IAFrameController
public interface IAFrameController<TEntity, TCreateDto, TUpdateDto>
{
Task<ActionResult> GetAll(int page, int pageSize, string? search);
Task<ActionResult> GetById(string id);
Task<ActionResult> Create(TCreateDto dto);
Task<ActionResult> Update(string id, TUpdateDto dto);
Task<ActionResult> Delete(string id);
}[ApiController]
[Route("api/[controller]")]
public class UserController : AFrameControllerBase<User, CreateUserDto, UpdateUserDto>
{
public UserController(IEntityService<User, CreateUserDto, UpdateUserDto> service)
: base(service) { }
// All CRUD endpoints automatically provided
}GET /api/users # List with pagination
GET /api/users/{id} # Get single
POST /api/users # Create
PATCH /api/users/{id} # Update
DELETE /api/users/{id} # Delete
Full documentation available in /docs:
cd docs
npm install
npm run devVisit http://localhost:3000 for:
- Getting started guide
- Architecture overview
- API inference rules
- Configuration options
- Code examples
- Deployment guides
The demo showcases a complete user management application:
npm run devFeatures:
- User and Role management
- Multiple view types (Grid, Cards, Search)
- Full CRUD operations
- Relation handling (Users β Roles)
- Mock API with sample data
- Responsive Material Design UI
# Install dependencies
npm install
# Run demo app
npm run dev
# Generate components from OpenAPI
npm run generate -- -i api.yaml -o ./generated
# Build frontend
npm run build
# Build documentation
cd docs && npm run build
# Deploy documentation
cd docs && npm run build && netlify deploy --prod --dir=dist- Vite-based React app
- Deploy to Netlify, Vercel, AWS S3, etc.
- ASP.NET Core 8.0+
- Deploy to Azure, AWS, Docker, etc.
- Static Astro site
- Deploy to Netlify, Vercel, GitHub Pages, etc.
See /docs/DEPLOYMENT.md for detailed instructions.
import React, { useState } from 'react';
import { AFrameProvider } from 'aframe';
import { A } from './generated/aframe';
function App() {
const [selectedId, setSelectedId] = useState(null);
return (
<AFrameProvider config={config}>
<A.User.Search />
<A.User.DataGrid onRowClick={(row) => setSelectedId(row.id)} />
{selectedId && <A.User.Card id={selectedId} />}
</AFrameProvider>
);
}[ApiController]
[Route("api/[controller]")]
public class UserController : AFrameControllerBase<User, CreateUserDto, UpdateUserDto>
{
public UserController(IEntityService<User, CreateUserDto, UpdateUserDto> service)
: base(service) { }
}Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
MIT
Q: Do I need to write CSS? A: No! Everything is controlled through MUI theme tokens.
Q: Can I customize components? A: Yes! Override at global, entity, or component level.
Q: Does it support TypeScript? A: Yes! Full TypeScript support throughout.
Q: Can I use it with my existing API? A: Yes! Just create an OpenAPI spec for your API.
Q: What about relations between entities? A: Automatically detected from $ref in your OpenAPI spec.