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

Terminal
flutter pub add duck

Or add it to pubspec.yaml:

pubspec.yaml
dependencies:
  duck: ^1.0.3

2. 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.

lib/main.dart
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.

lib/home_page.dart
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.

horizontal_container_data.dart
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);
}
lib/main.dart
Duck(
  baseUrl: baseUrl,
  components: {
    HorizontalContainerData.componentType: HorizontalContainerData.fromJson,
  },
);

Built-in components

Component types in the public library: container, sectionHeader, heroCard, smallCard, infoDisplay and tableCell.

Links