QuicUI is a powerful Server-Driven UI (SDUI) framework for Flutter that enables you to build, update, and deliver dynamic user interfaces without redeploying your app. Define your UI as JSON and render it natively at runtime. Backend is fully optional - works standalone with local data, or integrates with any cloud backend via plugins.
- Instant Updates: Ship UI changes without App Store/Play Store approval
- JSON-Driven: Define widgets in JSON, render natively in Flutter
- Standalone Usage: Works with local JSON data - no backend required
- Backend Optional: Integrate with Supabase, Firebase, REST API, or custom backends
- Real-Time Sync: Live UI updates with minimal latency (when backend is available)
- Dynamic Navigation: Control routes from the backend or locally
- Form Management: Server-side or local forms with built-in validation
- Dynamic Theming: Update branding and styles in real-time
- Offline-First: Lightning-fast local database (ObjectBox) for offline apps
- Extensible: Custom widgets, actions, and native integrations
- Cross-Platform: iOS, Android, Web, Windows, macOS, Linux
v1.0.5+ (October 31, 2025) - Comprehensive Error Handling System β¨ NEW
- β Multi-Layer Error Handling: Runtime recovery with graceful fallbacks
- β Build-Time Validation: JSON schema checking before deployment
- β CLI Validation Tool: Project-wide validation with watch mode
- β Dependency Analysis: Detect missing assets and broken references
- β Performance Analysis: Identify deep nesting and excessive children
- β Accessibility Checking: Ensure compliance with accessibility standards
- β Security Scanning: Detect potential security vulnerabilities
- β Comprehensive Logging: Detailed error context for debugging
- β Zero Production Impact: Error handling compiled out in release builds
- β IDE Ready: Real-time validation support for future IDE integrations
v1.0.5 (October 31, 2025) - Enhanced Padding/Margin & Task Manager β¨
- β
Enhanced Padding/Margin Support:
{"all": 16},{"horizontal": 20, "vertical": 10}syntax - β Improved Container Rendering: Better support for complex decoration patterns
- β Task Manager Example: Complete production-ready task management app
- β Layout Overflow Fixes: Proper Expanded widget usage for responsive layouts
- β Icon Spacing Improvements: Better touch targets and visual spacing
- β Deprecated API Fixes: Updated to latest Flutter APIs (Color, Radio widgets)
- β JSON Structure Enhancements: Support for nested container hierarchies
- β Mobile-Optimized UI: Perfect spacing and alignment for mobile devices
v1.0.4 (October 30, 2025) - Callback Action System β¨
- β Generic callback action system (navigate, setState, apiCall, custom)
- β JSON-driven interactive flows without Dart code
- β Action chaining with success/error handling
- β
Variable binding with
${variable_name}syntax - β 29 comprehensive unit tests (100% passing)
- β 4,500+ lines of complete documentation
- β 15 working JSON examples (login, registration, CRUD)
- β Custom handler registry for app-specific logic
- β Built-in state management for interactive UIs
v1.0.1 (October 30, 2025) - Production Release β¨
- β Backend-agnostic plugin architecture
- β 70+ pre-built widgets fully functional
- β BLoC state management complete
- β Offline-first architecture with sync
- β Real-time UI sync support
- β ObjectBox local persistence
- β Comprehensive backend integration guides
- β 5 complete example applications
- β 11,000+ lines of documentation
- β 267/267 tests passing (100%)
- β Published to pub.dev
flutter pub add quicuiimport 'package:quicui/quicui.dart';
void main() {
runApp(QuicUIApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Render local JSON without any backend
final jsonData = {
'type': 'column',
'properties': {'mainAxisAlignment': 'center'},
'children': [
{
'type': 'text',
'properties': {'text': 'Hello from Local JSON!', 'fontSize': 24}
}
]
};
final screen = Screen.fromJson(jsonData);
return UIRenderer.render(screen);
}
}- Quick Start Guide - 5-minute setup guide with plugin examples
- Plugin Architecture - Understanding the plugin system
- Backend Integration Guide - How to build custom DataSource implementations
- API Reference - Complete DataSource interface documentation
- Supabase Backend Package - Supabase integration with examples
- Firebase Integration - Firebase backend setup
- Custom Backend - Build your own DataSource
- Example Applications - REST API and custom backend examples
- Scaffold Counter App - Complete counter app with Scaffold widget
- Supabase Examples - See the Supabase package for Supabase-specific examples
- Testing Guide - Mock backends and unit testing
- Performance Guide - Caching, optimization, and best practices
- Architecture Guide - System design and component structure
- Database Strategy - ObjectBox integration and local storage
- Development Roadmap - Phase-by-phase breakdown with milestones
See /example folder for:
- Task Manager Runner β¨ NEW - Production-ready task management app with advanced UI patterns
- Counter App - Simple state management
- Form App - Input handling and validation
- Todo App - CRUD operations
- Offline Sync App - Offline-first synchronization
- Dashboard App - Complex layouts and theming
- Advanced Layout Patterns: Nested containers with proper spacing
- Mobile-Optimized Design: Perfect touch targets and visual hierarchy
- Complex JSON Structure: Real-world example of sophisticated UI composition
- Responsive Layout: Proper Expanded widget usage to prevent overflow
- Enhanced Styling: Modern Material Design with shadows, borders, and gradients
QuicUI supports backend integration through official plugins. Mix and match plugins based on your needs:
Complete Supabase backend integration with real-time synchronization and offline-first architecture.
Features:
- Real-time UI updates via WebSocket
- Offline-first with automatic sync
- Screen management and search
- Conflict resolution
- PostgreSQL database integration
Installation:
dependencies:
quicui: ^1.0.2
quicui_supabase: ^2.0.1Usage:
import 'package:quicui_supabase/quicui_supabase.dart';
final dataSource = SupabaseDataSource(
'https://your-project.supabase.co',
'your-anon-key',
);
await QuicUIService().initializeWithDataSource(dataSource);π View Supabase Plugin Documentation
βββββββββββββββββββββββββββββββ
β Presentation Layer (UI) β
β Widgets, Factory, Renderingβ
βββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β Business Logic Layer β
β State, Forms, Actions β
βββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββ
β Data Layer β
β API, Database, Cache β
βββββββββββββββββββββββββββββββ
| Component | Purpose |
|---|---|
| Widget Factory | Convert JSON to Flutter widgets |
| JSON Parser | Parse and validate JSON schemas |
| State Manager | Centralized reactive state |
| Action Executor | Handle navigation, API, events |
| Form System | Build & validate forms server-side |
| Local DB (ObjectBox) | Fast, persistent local storage |
| Theme Manager | Dynamic runtime theming |
| Sync Manager | Offline-first sync strategy |
- Container, Column, Row, Stack, Center
- Scaffold, AppBar, BottomNav, Drawer
- ListView, GridView, SingleChildScrollView
- TextField, Checkbox, Radio, DropDown
- Switch, DatePicker, FilePicker
- Text, Image, Icon, Badge, Chip
- Card, Dialog, SnackBar
- Conditional (if/else)
- Loop (dynamic lists)
- Form (with validation)
- Custom (extensible)
Build dynamic, responsive UIs without writing Dart code! Define interactive workflows as JSON - the callback system handles everything from button taps to API calls to state management.
Transform any static UI into an interactive app with these 4 reusable actions:
| Action | Purpose | Example |
|---|---|---|
| navigate | Move between screens | Navigate to login, home, profile |
| setState | Update UI state dynamically | Toggle loading, show/hide elements |
| apiCall | Make HTTP requests | Fetch data, submit forms, authenticate |
| custom | Execute app-specific logic | Email validation, calculations, business logic |
{
"id": "button_login",
"type": "ElevatedButton",
"properties": {"label": "Login"},
"actions": [
{
"action": "setState",
"updates": {"isLoading": true}
},
{
"action": "apiCall",
"method": "POST",
"endpoint": "/api/auth/login",
"body": {
"email": "${email_input}",
"password": "${password_input}"
},
"onSuccess": {
"action": "navigate",
"screen": "home",
"replace": true
},
"onError": {
"action": "setState",
"updates": {"error": "Login failed"}
}
},
{
"action": "setState",
"updates": {"isLoading": false}
}
]
}β
Action Chaining - Execute actions sequentially with success/error handling
β
Variable Binding - Reference form inputs with ${variable_name}
β
Event Triggers - onPressed, onTap, onLongTap, onChanged, onSubmitted
β
State Management - Update UI state on-the-fly
β
Custom Handlers - Register custom validation and business logic functions
β
Error Handling - Built-in error callbacks with automatic retry
β
Loading States - Show/hide loading indicators automatically
- Login Screen - Email/password authentication with loading states
- Registration Form - Multi-field validation and submission
- Data List with CRUD - Create, read, update, delete operations
Step 1: Configure Base URL
void main() {
ApiConfig.baseUrl = 'https://your-api.com';
runApp(QuicUI());
}Step 2: Use in JSON
{
"action": "apiCall",
"method": "POST",
"endpoint": "/api/auth/login",
"body": {"email": "${email}", "password": "${password}"}
}Step 3: Optional - Add Custom Handlers
CallbackRegistry.register('validateEmail', (context, params) async {
final email = params['email'] as String;
if (!email.contains('@')) throw Exception('Invalid email');
return {'valid': true};
});π Complete Callback Guide - 4,500+ lines with:
- All 4 actions with real code examples
- 15 complete JSON examples
- Step-by-step tutorials
- Configuration guide
- Advanced patterns
- Testing examples
QuicUI includes a robust error handling and JSON validation system that ensures your apps are resilient and debuggable:
Runtime Error Recovery
- Graceful error handling with automatic fallback widgets
- Detailed error context and debugging information
- Production-friendly error displays for users
- Debug mode with full error details for developers
Build-Time Validation
- JSON schema validation before deployment
- Dependency checking (missing assets, broken references)
- Performance analysis (deep nesting, excessive children)
- Accessibility compliance checking
- Security vulnerability scanning
CLI Validation Tool
# Validate entire project
dart run quicui:validate
# Validate specific file
dart run quicui:validate --file assets/screens/login.json
# Watch mode for real-time feedback
dart run quicui:validate --watch
# Generate JSON report
dart run quicui:validate --output report.json --strictβ Automatic Error Handling - No crashes from JSON errors β Detailed Logging - Rich context for debugging issues β Graceful Fallbacks - Users see appropriate error messages β Performance Optimized - Minimal runtime overhead β Comprehensive Validation - Catch errors early in development β IDE Integration - Real-time validation support
// Error handling is automatic - no try/catch needed
final widget = UIRenderer.render(jsonData);
// Errors are logged, fallback widgets shown, app stays stable// Validate JSON programmatically
final validator = BuildTimeValidator();
final result = await validator.validateJson(jsonString);
if (!result.isValid) {
for (final issue in result.issues) {
print('${issue.severity}: ${issue.message}');
}
}π Complete Error Handling Guide - 1,000+ lines with:
- Runtime error handling patterns
- Build-time validation setup
- CLI tool usage
- Best practices
- Troubleshooting guide
- Performance tips
QuicUI now supports multiple padding and margin formats for easier styling:
{
"type": "Container",
"properties": {
"padding": {"all": 16}, // Uniform padding
"margin": {"horizontal": 20, "vertical": 10}, // Symmetric spacing
"decoration": {
"color": "#F5F5F5",
"borderRadius": {"all": 12}
}
},
"children": [...]
}Supported Formats:
{"all": 16}- Apply to all sides{"horizontal": 20, "vertical": 10}- Symmetric spacing{"left": 10, "right": 20, "top": 5, "bottom": 15}- Individual sides16- Simple number (applies to all sides)
The id field in widgets is completely optional:
- When to use: When you need to reference the widget from code (testing, state binding, or programmatic updates)
- When to skip: For most widgets - just define
typeandproperties
{
"type": "text",
"properties": {"text": "Hello"}
}This minimal example works perfectly! Add id only if needed:
{
"id": "greeting_text",
"type": "text",
"properties": {"text": "Hello"}
}{
"type": "scaffold",
"appBar": {
"type": "appbar",
"title": "Welcome"
},
"body": {
"type": "column",
"properties": {"padding": "16"},
"children": [
{
"type": "text",
"properties": {
"text": "Hello QuicUI",
"fontSize": 24,
"fontWeight": "bold"
}
},
{
"type": "button",
"properties": {"label": "Click Me"},
"events": {
"onPressed": {
"action": "navigate",
"screen": "detail_screen"
}
}
}
]
}
}Note: All fields except type and properties are optional. The id field is optional and only needed if you want to reference the widget programmatically.
{
"type": "scaffold",
"appBar": {
"type": "appBar",
"title": "Counter App",
"backgroundColor": "#1976D2"
},
"body": {
"type": "center",
"child": {
"type": "column",
"mainAxisAlignment": "center",
"crossAxisAlignment": "center",
"children": [
{
"type": "text",
"properties": {
"text": "You have pushed the button this many times:",
"fontSize": 16
}
},
{
"type": "sizedBox",
"properties": {"height": 16}
},
{
"type": "container",
"properties": {
"padding": "24",
"decoration": {
"color": "#E3F2FD",
"borderRadius": "12"
}
},
"child": {
"type": "text",
"properties": {
"text": "42",
"fontSize": 72,
"fontWeight": "bold",
"color": "#1976D2"
}
}
},
{
"type": "sizedBox",
"properties": {"height": 32}
},
{
"type": "row",
"mainAxisAlignment": "center",
"children": [
{
"type": "elevatedButton",
"properties": {
"label": "β",
"backgroundColor": "#F44336"
}
},
{
"type": "sizedBox",
"properties": {"width": 16}
},
{
"type": "elevatedButton",
"properties": {
"label": "+",
"backgroundColor": "#4CAF50"
}
}
]
}
]
}
},
"floatingActionButton": {
"type": "floatingActionButton",
"icon": "Icons.add",
"tooltip": "Increment"
}
}See Scaffold Counter App Example for complete implementation with state management.
{
"type": "form",
"formId": "contact_form",
"fields": [
{
"type": "textfield",
"fieldName": "name",
"label": "Full Name",
"validators": [
{"type": "required", "message": "Name is required"},
{"type": "minLength", "value": 2}
]
},
{
"type": "textfield",
"fieldName": "email",
"label": "Email",
"validators": [
{"type": "required"},
{"type": "email"}
]
}
],
"submitAction": {
"type": "api",
"method": "POST",
"url": "/api/contact",
"body": {"name": "${name}", "email": "${email}"}
}
}QuicUI uses ObjectBox for blazingly fast local storage:
- β‘ Sub-millisecond queries (0.2ms avg)
- π ACID transactions for data integrity
- π¦ 50x faster than SQLite for typical operations
- π Built for sync scenarios
- π Optional encryption support
// Cache UI responses
await QuicUIManager.cache('home', jsonData);
// Retrieve from cache
final cached = await QuicUIManager.getCache('home');
// Offline support with automatic sync
await QuicUIManager.syncOfflineChanges();// Access global state
Consumer<QuicState>(
builder: (context, state, _) {
return Text(state.get('userName') ?? 'Guest');
},
)
// Update state
Provider.of<QuicState>(context, listen: false)
.set('userName', 'John Doe');
// Listen to events
state.on('userLoggedIn', (data) {
print('User logged in: $data');
});// Define theme as JSON
final theme = {
"colors": {
"primary": "#6366F1",
"secondary": "#EC4899"
},
"typography": {
"heading": {"fontSize": 24, "fontWeight": "bold"}
}
};
// Apply dynamically at runtime
Provider.of<ThemeManager>(context, listen: false)
.setTheme(jsonEncode(theme));QuicUI includes comprehensive testing utilities:
// Unit tests for JSON parsing
test('Parse simple widget', () {
final json = '{"type":"text","properties":{"text":"Hello"}}';
final widget = QuicWidget.fromJson(jsonDecode(json));
expect(widget.type, equals('text'));
});
// Widget tests
testWidgets('Render QuicText', (tester) async {
await tester.pumpWidget(
MaterialApp(home: Scaffold(body: QuicText(text: 'Hello')))
);
expect(find.text('Hello'), findsOneWidget);
});| Metric | Target | Status |
|---|---|---|
| Widget render | < 100ms | β Target |
| DB query | < 10ms | β Target (ObjectBox) |
| Cache hit | < 1ms | β Target |
| Form validation | < 50ms | β Target |
| Network request | < 500ms | β Target |
- Core models and JSON parser
- Widget factory and all core widgets
- Basic rendering engine
- State management system
- Action execution engine
- Complete form system
- ObjectBox integration
- Sync mechanism
- Dynamic theming system
- Testing & documentation
Target Release: End of Week 7 (v1.0 production-ready)
See ROADMAP.md for detailed timeline.
class CustomWidgetRegistry {
static void register(String type, WidgetBuilder builder) {
// Register custom widget
}
}class CustomActionHandler {
static void register(String type, ActionHandler handler) {
// Handle custom actions
}
}class ValidatorRegistry {
static void register(String type, ValidatorFn validator) {
// Custom validation logic
}
}- β JSON schema validation prevents injection
- β Encrypted local storage (optional)
- β HTTPS-only API communication
- β Request signing and verification
- β Sandbox for custom code execution
| Platform | Status | Min Version |
|---|---|---|
| iOS | β Full | 11.0 |
| Android | β Full | 5.0 (API 21) |
| Web | β Full | Modern browsers |
| Windows | β Full | 10+ |
| macOS | β Full | 10.13+ |
| Linux | β Full | Ubuntu 18.04+ |
flutter_bloc: ^9.0.0- State management (BLoC pattern)equatable: ^2.0.5- Value equalitydio: ^5.7.0- HTTP clientobjectbox: ^4.1.1- Local databasejson_annotation: ^4.8.1- JSON serialization
See pubspec.yaml for complete list.
Complete example applications are available in the /example folder:
- Basic text and button rendering
- Form with validation
- API integration
- List rendering
- Theme switching
- Offline support
- A/B testing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
Found a bug? Please report it on GitHub with:
- Minimal reproducible example
- Flutter/Dart version
- Platform details
- Relevant logs
- π Full Documentation - Complete guides and examples
- ποΈ Architecture Guide - System design
- π± Supabase Integration - Cloud data sync
If you find QuicUI helpful and want to support its development, consider buying me a coffee! Every cup fuels more features, faster updates, and better documentation.
β Buy Me a Coffee - Help keep QuicUI growing!
Your support helps us:
- π Build new features faster
- π Create better documentation
- π Fix bugs quickly
- π‘ Implement community requests
- π― Maintain long-term support
Every contribution is deeply appreciated! β€οΈ
This project is licensed under the MIT License - see the LICENSE file for details.
Inspired by:
- Stac - Server-Driven UI inspiration
- Flutter community and best practices
- Open-source SDUI pioneers
- Review the Implementation Plan
- Read the Architecture Guide
- Follow the Quick Start
- Check the Development Roadmap
Made with β€οΈ by the QuicUI team
β If you find QuicUI useful, please give it a star on GitHub!