sdui_flutter_sanity 0.2.0
sdui_flutter_sanity: ^0.2.0 copied to clipboard
A Server-Driven UI Flutter package powered by Sanity.io headless CMS with realtime config updates.
SDUI Flutter Sanity #
A Server-Driven UI (SDUI) Flutter package powered by Sanity.io headless CMS with realtime config updates.
Sanity.io stores the component tree for each screen as structured content, and the Flutter app renders it live — including picking up edits published in Sanity Studio in realtime, with no app rebuild required.
Features #
- Dynamic widget rendering powered by Sanity.io.
- Real-time updates via Server-Sent Events (SSE).
- Local caching (Hive) for offline access.
- Easy to extend with custom components and actions.
Installation #
Add it to your pubspec.yaml:
dependencies:
sdui_flutter_sanity: ^0.1.0
Setup #
- Configure the
SduiEnginebeforerunApp. You can inject credentials via environment variables for security.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:sdui_flutter_sanity/sdui_flutter_sanity.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SduiEngine.initialize(
config: const SduiConfig(
projectId: 'your_sanity_project_id',
dataset: 'production',
token: 'your_optional_read_token',
),
);
runApp(const ProviderScope(child: MyApp()));
}
- Render dynamic content in your app:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('SDUI')),
body: const SduiView(slug: 'home'),
),
);
}
}
Sanity Studio Setup #
- Create a brand new Sanity Studio project anywhere on your computer (e.g. by running
npm create sanity@latest).- Copy the schema files provided below into your own project's
schemaTypes/folder, and modify them as needed for your app.
To serve the UI configuration from your Sanity Studio, you need to define your pageConfig and the individual component schemas.
Because a production app requires a great editing experience, we provide strongly-typed individual component schemas (like textComponent, imageComponent, columnComponent, etc.) instead of a generic JSON text box.
1. Copy the schemas #
Simply copy the entire contents of the schemaTypes/ folder from either the sanity_studio or sduiflutter directories in this repository into your own Sanity project's schemaTypes/ or schemas/ folder.
This will give you:
pageConfig.ts: The schema for your individual app screens.components/uiElements.ts: A list of all available UI components.components/*.ts: Individual, strongly-typed schemas for Text, Image, Column, Button, etc.
2. Registering the Schemas #
Ensure your Sanity project's schemaTypes/index.ts exports all of the copied schemas:
import pageConfig from './pageConfig'
import textComponent from './components/textComponent'
import imageComponent from './components/imageComponent'
import buttonComponent from './components/buttonComponent'
import spacerComponent from './components/spacerComponent'
import columnComponent from './components/columnComponent'
import rowComponent from './components/rowComponent'
import cardComponent from './components/cardComponent'
import uiElements from './components/uiElements'
export const schemaTypes = [
pageConfig,
textComponent,
imageComponent,
buttonComponent,
spacerComponent,
columnComponent,
rowComponent,
cardComponent,
uiElements,
]
### 4. Running the Studio & Creating Content
Once your schemas are set up:
1. Run `npm run dev` in your Sanity project directory.
2. Open `http://localhost:3333` in your browser.
3. You will see the Sanity Studio admin UI. Create a new **Page Config** document.
4. Give it a slug (e.g., `home`), and start building your component tree in the **Layout** field.
5. When you click **Publish**, the data is saved to Sanity's cloud servers, and your Flutter app will immediately be able to render it!
## Extensibility & Future Use Cases
This package is built to handle the infrastructure of Server-Driven UI (networking, caching, parsing, rendering), but it does not map every Flutter widget out of the box.
Instead, it provides powerful extension points to support **any** complex UI or business logic you might need in the future:
### Custom Components
You can render any Flutter widget (even highly complex forms, charts, or animations) by registering a custom `SduiComponent`.
```dart
class MyCustomComponent extends SduiComponent {
@override
String get type => 'my_custom_type'; // Matches '_type' from Sanity
@override
Widget build(BuildContext context, UiNode node, Widget Function(UiNode) buildChild) {
// Read props and return any Flutter widget
return MyComplexWidget(title: node.props['title']);
}
}
State Management & Analytics #
If your SDUI requires complex data-binding (e.g. form fields, validating inputs, tracking analytics impressions), you handle this inside your custom components. Your components can freely use Riverpod, Provider, or Flutter's VisibilityDetector because they are just standard Flutter Widgets once parsed.
Custom Actions #
You can trigger complex logic (like "Add to Cart" or "Log out") from the CMS by registering custom SduiActionHandlers.
// Register before runApp()
SduiEngine.initialize(
config: const SduiConfig(projectId: 'xyz'),
components: [MyCustomComponent()],
actionHandlers: [MyCartActionHandler()],
);