Skip to content
generated from GDGVIT/template

A powerful Flutter package for implementing Server-Driven UI (SDUI) with both JSON and gRPC support

License

GDGVIT/flutter-glimpse

Repository files navigation

GDSC VIT

Flutter Glimpse

A powerful Flutter package for implementing Server-Driven UI (SDUI) with both JSON and gRPC support.

Join Us Discord Chat DOCS UI

What is SDUI?

Server-Driven UI is an architectural pattern where the UI layout and content definitions come from a backend server rather than being hardcoded in the client application. This approach enables:

  • Dynamic UI updates without app store releases
  • A/B testing and feature flagging at the UI level
  • Consistent UI across platforms
  • Faster iteration cycles for UI changes

Features

  • Render UI dynamically from server-provided definitions
  • Support for essential Flutter widgets (Text, Column, Row, Container, etc.)
  • JSON parsing for server responses
  • gRPC support for efficient, type-safe communication
  • Protocol Buffers for structured data exchange
  • Easy-to-use client API
  • Customizable error handling and loading states

Installation

Add the package to your pubspec.yaml:

dependencies:
  flutter_glimpse: ^0.0.1
# For devs
dependencies:
  flutter_glimpse:
    path: path/to/flutter_glimpse

Or use the Flutter CLI:

flutter pub add flutter_glimpse

Import the package in your Dart code:

import 'package:flutter_glimpse/flutter_glimpse.dart';

Basic Usage

This package provides two approaches for implementing server-driven UI:

1. Using gRPC (Recommended)

For efficient, type-safe server communication:

// Create a gRPC client
final client = GlimpseGrpcClient(
  host: 'your-server.com',
  port: 50051,
);

// Use the GlimpseGrpcRenderer widget
GlimpseGrpcRenderer(
  client: client,
  screenId: 'home_screen',
  loadingWidget: CircularProgressIndicator(),
  errorBuilder: (context, error) => Text('Error: $error'),
)

2. Using JSON

For simpler implementation with standard HTTP requests:

// Parse Glimpse JSON to widget
dynamic json = ...; // Load your JSON
final glimpseWidget = GlimpseParser.parseJSON(json);
final flutterWidget = glimpseWidget.toFlutterWidget();

You can also serialize Glimpse widgets back to JSON:

final json = GlimpseParser.toJson(glimpseWidget);

And convert Flutter widgets to Glimpse (for supported types):

import 'package:flutter_glimpse/src/flutter_to_glimpse.dart';
final glimpseWidget = flutterToGlimpse(myFlutterWidget);

Widget Coverage & Extensibility

  • All core layout and display widgets are supported: Column, Row, Text, Image, SizedBox, Container, Scaffold, Spacer, Icon.
  • Adding new widgets is straightforward: implement the Glimpse widget, add proto/JSON parsing, and update the toJson and Flutter conversion logic.
  • The codebase is up-to-date, with no remaining TODOs.

Example

Here's a complete example of using the gRPC renderer:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Glimpse Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const GlimpseDemo(),
    );
  }
}

class GlimpseDemo extends StatefulWidget {
  const GlimpseDemo({super.key});

  @override
  State<GlimpseDemo> createState() => _GlimpseDemoState();
}

class _GlimpseDemoState extends State<GlimpseDemo> {
  late GlimpseGrpcClient _grpcClient;
  String _screenId = 'home';

  @override
  void initState() {
    super.initState();
    _grpcClient = GlimpseGrpcClient(
      host: 'localhost',  // Replace with your server address
      port: 50051,        // Replace with your server port
    );
  }

  @override
  void dispose() {
    _grpcClient.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Server-Driven UI Demo'),
      ),
      body: GlimpseGrpcRenderer(
        client: _grpcClient,
        screenId: _screenId,
        loadingWidget: const Center(
          child: CircularProgressIndicator(),
        ),
        errorBuilder: (context, error) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.error, color: Colors.red, size: 48),
                SizedBox(height: 16),
                Text('Error: $error'),
                SizedBox(height: 16),
                ElevatedButton(
                  onPressed: () => setState(() {}),
                  child: Text('Retry'),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

Server Implementation

Setting Up a gRPC Server

Here's a basic example of a Dart server that provides UI definitions via gRPC:

import 'package:grpc/grpc.dart';
import 'package:flutter_glimpse/src/generated/glimpse.pb.dart';
import 'package:flutter_glimpse/src/generated/glimpse.pbgrpc.dart';

Future<void> main() async {
  final server = Server.create(
    services: [
      GlimpseServiceImpl(),
    ],
  );

  await server.serve(port: 50051);
  print('Server listening on port 50051...');
}

class GlimpseServiceImpl extends GlimpseServiceBase {
  @override
  Future<GlimpseWidgetData> getGlimpseWidget(
      ServiceCall call, GlimpseRequest request) async {
    // Return different UI based on the screenId
    switch (request.screenId) {
      case 'home':
        return _createHomeScreen();
      default:
        return _createErrorScreen();
    }
  }

  GlimpseWidgetData _createHomeScreen() {
    return GlimpseWidgetData()
      ..type = WidgetType.SCAFFOLD
      ..body = (GlimpseWidgetData()
        ..type = WidgetType.COLUMN
        ..children.addAll([
          GlimpseWidgetData()
            ..type = WidgetType.CONTAINER
            ..padding = (EdgeInsetsData()..all = 16)
            ..child = (GlimpseWidgetData()
              ..type = WidgetType.TEXT
              ..stringAttributes['text'] = 'Welcome to Server-Driven UI!'
              ..textStyle = (TextStyleData()
                ..fontSize = 22
                ..fontWeight = 'bold')),
          GlimpseWidgetData()
            ..type = WidgetType.TEXT
            ..stringAttributes['text'] = 'This UI is rendered from gRPC data'
        ]));
  }
}

Supported Widgets

The package currently supports these Flutter widgets:

  • Scaffold
  • Container
  • Column
  • Row
  • Text
  • Image
  • SizedBox
  • Spacer
  • Icon

Advanced Usage

Protobuf Definitions

The package uses Protocol Buffers to define the data structures for gRPC communication. Here's a simplified version of the main message types:

message GlimpseWidgetData {
  WidgetType type = 1;
  map<string, string> string_attributes = 2;
  map<string, double> double_attributes = 3;
  map<string, bool> bool_attributes = 4;

  // Complex nested attributes
  TextStyleData text_style = 6;
  EdgeInsetsData padding = 7;

  // Children widgets
  repeated GlimpseWidgetData children = 12;
  GlimpseWidgetData child = 13;

  // Scaffold specific parts
  GlimpseWidgetData app_bar = 14;
  GlimpseWidgetData body = 15;
}

service GlimpseService {
  rpc GetGlimpseWidget (GlimpseRequest) returns (GlimpseWidgetData);
}

Working with Protocol Buffers

If you need to regenerate the Dart files from the proto definitions:

  1. Install the Protocol Buffer compiler using the provided scripts:
# Windows
pwsh ./tool/setup_protoc.ps1

# Generate the Protobuf files
pwsh ./tool/generate_protos.ps1

Roadmap

  • Basic widget support
  • gRPC implementation
  • JSON implementation
  • Interactive widgets (buttons, forms)
  • More advanced widget support

Contributing

See ADDING_WIDGET.md for instructions on how to add a new widget to the Glimpse package.

License

This project is licensed under the LICENSE file in the repository.

Contributors

Jothish Kamal

Jothish Kamal

GitHub LinkedIn

Rujin Devkota

Rujin Devkota

GitHub LinkedIn

Adhavan K

Adhavan K

GitHub LinkedIn

Made with ❤ by GDSC-VIT

About

A powerful Flutter package for implementing Server-Driven UI (SDUI) with both JSON and gRPC support

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •