Skip to content

Jashwanth-Gowda-R/dynamic_ui_renderer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

14 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

dynamic_ui_renderer

pub package style: very good analysis License: MIT Flutter Dart

A powerful Flutter package for rendering UI dynamically from JSON responses. Build forms, screens, and components from server-driven JSON โ€” without requiring app updates.

Perfect for: Server-Driven UI (SDUI), Dynamic Forms, A/B Testing, CMS-driven UIs, and White-Label Apps


โœจ Features (v0.1.0)

๐ŸŽฏ Complete Action System

  • โœ… Print - Debug logging with levels (info/warning/error)
  • โœ… Dialog - Alert dialogs with custom titles and messages
  • โœ… Snackbar - Toast notifications with action buttons
  • โœ… URL Launch - Open web links in browser (uses url_launcher)
  • โœ… Bottom Sheet - Modal bottom sheets
  • โœ… Navigation - Screen navigation with push/pop strategies

๐ŸŽจ Core Widgets

  • โœ… Text - Full styling (size, weight, color, alignment)
  • โœ… Container - Padding, margin, color, dimensions, border radius
  • โœ… Button - Styled buttons with actions
  • โœ… Column - Vertical layouts with alignment
  • โœ… Row - Horizontal layouts with alignment

๐Ÿ› ๏ธ Developer Experience

  • โœ… Type-safe JSON parsing - No runtime surprises
  • โœ… Error handling - Graceful fallbacks with user-friendly messages
  • โœ… Context propagation - Automatic for navigation and dialogs
  • โœ… Extensible architecture - Easy to add custom widgets
  • โœ… Well tested - 90%+ code coverage
  • โœ… Lightweight - Minimal dependencies

๐Ÿ“ฆ Installation

Add the dependency to your pubspec.yaml:

dependencies:
  dynamic_ui_renderer: ^0.1.0

Then run:

flutter pub get

Note: The package automatically includes url_launcher for web URL support. No additional setup needed!


๐Ÿš€ Quick Start

import 'package:flutter/material.dart';
import 'package:dynamic_ui_renderer/dynamic_ui_renderer.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Dynamic UI Demo')),
        body: DynamicUIRenderer.fromJsonString('''
        {
          "type": "column",
          "properties": {
            "mainAxisAlignment": "center",
            "crossAxisAlignment": "center",
            "padding": 16
          },
          "children": [
            {
              "type": "text",
              "properties": {
                "text": "Hello from JSON! ๐Ÿ‘‹",
                "fontSize": 24,
                "fontWeight": "bold",
                "color": "#2196F3",
                "textAlign": "center"
              }
            },
            {
              "type": "container",
              "properties": {
                "margin": [0, 20, 0, 0],
                "padding": 16,
                "color": "#E3F2FD",
                "borderRadius": 8
              },
              "children": [
                {
                  "type": "text",
                  "properties": {
                    "text": "This entire UI is rendered from JSON!",
                    "color": "#1565C0"
                  }
                }
              ]
            },
            {
              "type": "button",
              "properties": {
                "text": "Click Me",
                "backgroundColor": "#4CAF50",
                "foregroundColor": "#FFFFFF",
                "borderRadius": 8,
                "margin": [0, 20, 0, 0]
              },
              "actions": {
                "type": "showDialog",
                "parameters": {
                  "title": "Welcome! ๐ŸŽ‰",
                  "message": "Button clicked successfully!",
                  "buttonText": "OK"
                }
              }
            }
          ]
        }
        ''', context),
      ),
    );
  }
}

๐Ÿ“– Documentation

๐Ÿ“ JSON Schema Reference


๐Ÿงพ Text Widget

{
  "type": "text",
  "properties": {
    "text": "Your text here",        // Required
    "fontSize": 16,                   // Optional
    "fontWeight": "bold",              // Optional: bold, normal, w100-w900
    "color": "#FF0000",                // Optional: hex color (#RGB or #RRGGBB)
    "textAlign": "center"              // Optional: left, center, right
  }
}

๐Ÿ“ฆ Container Widget

{
  "type": "container",
  "properties": {
    "padding": 16,                     // Optional: number or [L,T,R,B]
    "margin": [8, 16, 8, 16],          // Optional: number or [L,T,R,B]
    "color": "#F5F5F5",                 // Optional: hex color
    "width": 200,                       // Optional: number
    "height": 100,                       // Optional: number
    "borderRadius": 8                    // Optional: number
  },
  "children": []                         // Optional: child components
}

Padding/Margin Examples:

  • Single value: "padding": 16 โ†’ applies to all sides
  • List: "padding": [8, 16, 8, 16] โ†’ [left, top, right, bottom]

๐Ÿ”˜ Button Widget with Actions

{
  "type": "button",
  "properties": {
    "text": "Click Me",                  // Optional (use if no children)
    "backgroundColor": "#4CAF50",        // Optional: hex color
    "foregroundColor": "#FFFFFF",        // Optional: text/icon color
    "borderRadius": 8,                   // Optional: number
    "elevation": 4,                       // Optional: number
    "padding": [8, 16, 8, 16]             // Optional: number or list
  },
  "children": [                           // Optional: custom button content
    {
      "type": "text",
      "properties": {
        "text": "Click Me",
        "color": "#FFFFFF"
      }
    }
  ],
  "actions": {                            // Required for interactivity
    "type": "navigate",                    // Action type
    "parameters": {                         // Action-specific parameters
      "route": "/details",
      "type": "push",
      "arguments": {
        "id": 123,
        "name": "Product"
      }
    }
  }
}

๐ŸŽฌ Available Action Types

Type Description Required Parameters Example
print Print to console message, level (info/warning/error) {"message": "Hello", "level": "info"}
showDialog Show alert dialog title, message, buttonText {"title": "Alert", "message": "Hello"}
showSnackbar Show snackbar message, duration, actionLabel {"message": "Saved!", "duration": 3}
launchUrl Open URL in browser url, mode (inApp/external) {"url": "https://flutter.dev"}
showBottomSheet Show modal bottom sheet title, message, buttonText {"title": "Options", "message": "Choose"}
navigate Navigate to route route, type (push/pushReplacement/pop) {"route": "/home", "type": "push"}

๐Ÿ“ Column / Row Widget

{
  "type": "column",  // or "row"
  "properties": {
    "mainAxisAlignment": "center",        // Optional: alignment along main axis
    "crossAxisAlignment": "stretch",      // Optional: alignment along cross axis
    "padding": 16,                        // Optional: padding around the whole column/row
    "margin": [8, 16, 8, 16]              // Optional: margin around the whole column/row
  },
  "children": []                           // Required: list of child components
}

MainAxisAlignment Options:

  • start - Children at the start
  • center - Children centered
  • end - Children at the end
  • spaceBetween - Space evenly between children
  • spaceAround - Space evenly around children
  • spaceEvenly - Space evenly including ends

CrossAxisAlignment Options:

  • start - Children at the start
  • center - Children centered
  • end - Children at the end
  • stretch - Children stretch to fill

๐ŸŽฏ Complete Examples

๐Ÿ” Login Form Example

String loginFormJson = '''
{
  "type": "column",
  "properties": {
    "crossAxisAlignment": "stretch",
    "padding": 20
  },
  "children": [
    {
      "type": "text",
      "properties": {
        "text": "Welcome Back! ๐Ÿ‘‹",
        "fontSize": 28,
        "fontWeight": "bold",
        "color": "#1976D2",
        "textAlign": "center"
      }
    },
    {
      "type": "container",
      "properties": {
        "padding": 20,
        "margin": [0, 20, 0, 0],
        "color": "#FFFFFF",
        "borderRadius": 12
      },
      "children": [
        {
          "type": "column",
          "properties": {
            "crossAxisAlignment": "stretch"
          },
          "children": [
            {
              "type": "text",
              "properties": {
                "text": "Email",
                "fontSize": 14,
                "fontWeight": "bold",
                "color": "#757575"
              }
            },
            {
              "type": "container",
              "properties": {
                "padding": 16,
                "margin": [0, 4, 0, 16],
                "color": "#F5F5F5",
                "borderRadius": 8
              },
              "children": [
                {
                  "type": "text",
                  "properties": {
                    "text": "user@example.com",
                    "color": "#212121"
                  }
                }
              ]
            },
            {
              "type": "text",
              "properties": {
                "text": "Password",
                "fontSize": 14,
                "fontWeight": "bold",
                "color": "#757575"
              }
            },
            {
              "type": "container",
              "properties": {
                "padding": 16,
                "margin": [0, 4, 0, 0],
                "color": "#F5F5F5",
                "borderRadius": 8
              },
              "children": [
                {
                  "type": "text",
                  "properties": {
                    "text": "โ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ข",
                    "color": "#212121"
                  }
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "type": "button",
      "properties": {
        "text": "Login",
        "backgroundColor": "#1976D2",
        "foregroundColor": "#FFFFFF",
        "borderRadius": 8,
        "margin": [0, 20, 0, 0],
        "padding": 16
      },
      "actions": {
        "type": "showDialog",
        "parameters": {
          "title": "Success! ๐ŸŽ‰",
          "message": "Logged in successfully",
          "buttonText": "Continue"
        }
      }
    }
  ]
}
''';

Widget loginForm = DynamicUIRenderer.fromJsonString(loginFormJson, context);

๐ŸŒ Fetch UI from Server

import 'package:http/http.dart' as http;

Future<Widget> fetchUIFromServer(BuildContext context) async {
  try {
    final response = await http.get(
      Uri.parse('https://api.example.com/ui/home')
    );

    if (response.statusCode == 200) {
      return DynamicUIRenderer.fromJsonString(response.body, context);
    }

    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Icon(Icons.error_outline, color: Colors.red, size: 48),
          const SizedBox(height: 16),
          Text('Failed to load UI: ${response.statusCode}'),
        ],
      ),
    );
  } catch (e) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Icon(Icons.wifi_off, color: Colors.orange, size: 48),
          const SizedBox(height: 16),
          Text('Network error: $e'),
          const SizedBox(height: 8),
          ElevatedButton(
            onPressed: () {
              // Retry logic
            },
            child: const Text('Retry'),
          ),
        ],
      ),
    );
  }
}

๐Ÿ“ฑ Complete Demo App

Check out the /example folder for a complete Flutter app demonstrating all features:

cd example
flutter run

The example app includes:

  • ๐ŸŽฏ Button Actions Demo - Test all 6 action types
  • ๐Ÿ“ฑ Core Widgets Demo - Basic widgets showcase
  • ๐ŸŽจ Styling Properties Demo - Colors, fonts, padding, margins
  • ๐Ÿ“ Layout Examples Demo - Different alignments and arrangements
  • โš ๏ธ Error Handling Demo - Graceful fallbacks for unsupported widgets

๐Ÿ— Architecture Overview

JSON โ†’ UIComponent (Model) โ†’ WidgetFactory โ†’ Flutter Widget
        โ†“
    Properties Parser
        โ†“
    Action Handler (Navigation, Dialogs, etc.)

The package follows a clean, modular architecture:

  1. JSON Parsing - Converts JSON to type-safe models
  2. Widget Factory - Maps component types to Flutter widgets
  3. Property Parsers - Safely converts JSON values to Flutter types
  4. Action Handler - Executes user interactions
  5. Context Propagation - Automatically passes BuildContext for navigation

๐Ÿงช Testing

# Run all tests
flutter test

# Run with coverage
flutter test --coverage

# Generate coverage report (requires lcov)
genhtml coverage/lcov.info -o coverage/html
# Then open coverage/html/index.html

๐Ÿค Contributing

Contributions are welcome! Whether it's:

  • ๐Ÿ› Reporting bugs
  • ๐Ÿ’ก Suggesting features
  • ๐Ÿ“ Improving documentation
  • ๐Ÿ”ง Submitting pull requests

Steps to contribute:

  1. Fork the repository
  2. Create your feature branch:
    git checkout -b feature/amazing-feature
  3. Commit your changes:
    git commit -m "Add some amazing feature"
  4. Push to the branch:
    git push origin feature/amazing-feature
  5. Open a Pull Request

Please ensure your code:

  • Passes all tests (flutter test)
  • Follows Dart style guidelines (dart format .)
  • Includes tests for new features
  • Updates documentation as needed

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


๐Ÿ™ Acknowledgments

  • Inspired by server-driven UI patterns at Airbnb, Lyft, and Prowork
  • Built with โค๏ธ for the Flutter community
  • Thanks to all contributors and users

๐Ÿ“Š Package Statistics

Metric Value
Latest Version v0.1.0
Published February 2026
License MIT
Platforms Android, iOS, Web, macOS, Linux, Windows
Dependencies url_launcher (automatically included)

๐Ÿ“ž Support


๐Ÿ”ฎ Coming Soon

  • โœ… Forms & Validation - Form widgets with built-in validation
  • โœ… Network Fetching - Load UI directly from URLs
  • โœ… Caching - Cache UI definitions locally
  • โœ… Custom Widget Registry - Register your own widgets
  • โœ… Theme Support - Dynamic theming from JSON

Made with โค๏ธ by Jashwanth Gowda R

If you find this package useful, please consider:

  • โญ Starring the GitHub repository
  • ๐Ÿ“ข Sharing it with others
  • ๐Ÿ› Reporting issues
  • ๐Ÿ’ก Suggesting features

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published