Getting started
Flutter OTA updates in five steps.
Add the package, initialise Duck, render a canvas, then change that canvas from the builder. No store release for supported views.
Prefer plain text for scripts and AI agents? Use /quickstart.txt or /llms.txt.
1. Install
flutter pub add duckOr add it to pubspec.yaml:
dependencies:
duck: ^1.0.32. Initialise Duck
Call Duck(...) once at startup with the base URL of the Duck API and a map of any custom components. The public demo API is https://duck-demo.flexxxlab.com/api.
import 'package:duck/duck.dart';
import 'package:flutter/material.dart';
void main() {
// Public demo API. Replace with your own Duck API base URL.
Duck(baseUrl: 'https://duck-demo.flexxxlab.com/api', components: {});
runApp(const MyApp());
}3. Build a canvas
Open Duck Builder, arrange components, and save. Copy the canvas id.
4. Render the canvas (the OTA step)
DuckCanvasWidget loads the canvas by id and supports pull-to-refresh. Edit and save the canvas in the builder and the app shows the new layout the next time it loads, without a new release.
import 'package:duck/core/duck_canvas/duck_canvas_widget.dart';
import 'package:flutter/material.dart';
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
// Canvas id from Duck Builder (https://duck-demo.flexxxlab.com/).
const canvasId = '6956a659beea0c7c40b51e8c'; // public demo canvas
return Scaffold(
appBar: AppBar(title: const Text('Duck demo')),
body: const DuckCanvasWidget(canvasId: canvasId),
);
}
}5. Add your own components (optional)
Extend DuckComponent, implement buildWidget, then register the parser. New component types ship in an app release; afterwards you can place them in canvases remotely.
import 'package:duck/core/duck_component/duck_component.dart';
import 'package:duck/core/duck_component/duck_component_list_converter.dart';
import 'package:flutter/widgets.dart';
import 'package:json_annotation/json_annotation.dart';
part 'horizontal_container_data.g.dart';
@JsonSerializable()
class HorizontalContainerData extends DuckComponent {
static const String componentType = 'horizontalContainer';
@override
String get type => componentType;
@DuckComponentListConverter()
final List<DuckComponent> list;
HorizontalContainerData({required this.list});
@override
Widget buildWidget(BuildContext context) =>
HorizontalContainerWidget(data: this);
factory HorizontalContainerData.fromJson(Map<String, dynamic> json) =>
_$HorizontalContainerDataFromJson(json);
@override
Map<String, dynamic> toJson() => _$HorizontalContainerDataToJson(this);
}Duck(
baseUrl: baseUrl,
components: {
HorizontalContainerData.componentType: HorizontalContainerData.fromJson,
},
);Built-in components
Component types in the public library: container, sectionHeader, heroCard, smallCard, infoDisplay and tableCell.