Examples are Flutter projects offered as templates on the prompt page. The frontend serves them from TAR files in packages/frontend/web/examples/.
Most examples also have checked-in source directories under examples/. Very large examples may be checked in as a prebuilt TAR only, with their local source directory intentionally ignored.
examples/ ├── examples.yaml # Source of truth for the template list ├── simple_counter/ # Normal checked-in example source │ ├── pubspec.yaml │ └── lib/ │ ├── main.dart │ └── counter.dart ├── overflow_debug/ │ ├── pubspec.yaml │ └── lib/ │ └── main.dart ├── rebuild_weather_app/ │ ├── pubspec.yaml │ └── weather_app_screenshot.jpg # Image attached to the prompt └── flutter-wonderous-app/ # Local-only, ignored; TAR is checked in packages/frontend/web/examples/ ├── examples.json # Generated manifest served by frontend ├── simple_counter.tar ├── overflow_debug.tar ├── rebuild_weather_app.tar └── flutter-wonderous-app.tar # Prebundled Wonderous template
The template list is defined in examples/examples.yaml. Each entry defines:
| Field | Required | Description |
|---|---|---|
id | ✅ | Template id. For source-backed examples this matches examples/<id>/; for prebundled examples it matches packages/frontend/web/examples/<id>.tar. |
title | ✅ | Display name shown on the prompt page. |
prompt | ❌ | Optional prompt pre-filled in the agent composer. |
image | ❌ | Optional image file name inside the example TAR. |
examples: - id: simple_counter title: Counter Template - id: overflow_debug title: Overflow Debug prompt: >- My profile screen doesn't look right — some content seems to be cut off or missing. Can you take a screenshot and help me figure out what's wrong? - id: rebuild_weather_app title: Rebuild Weather App prompt: >- Rebuild this weather app and verify your result with screenshots comparing it against the attached image. Generate background images for the different weather conditions. Use mocks for the weather data. image: weather_app_screenshot.jpg - id: flutter-wonderous-app title: Wonderous App
The editor and agent panel are visible for every template. Optional manifest fields only control composer prefill:
| Has prompt? | Has image? | Behavior |
|---|---|---|
| ❌ | ❌ | Opens the editor and agent panel. If lib/main.dart exists, the preview starts automatically after pub get. |
| ✅ | ❌ | Same as above, with the prompt pre-filled in the composer. |
| ✅ | ✅ | Same as above, with the prompt and image thumbnail pre-filled in the composer. |
The user reviews any pre-filled prompt and hits Send manually. Selecting a template does not automatically start an agent run.
The script tool/bundle_examples.dart reads examples.yaml and:
examples.json in packages/frontend/web/examples/ with id, title, optional prompt, and optional image metadata (imageMimeType, imageFileName)..checksums.json; unchanged source-backed examples are not re-bundled.dart run tool/bundle_examples.dart
The generated files under packages/frontend/web/examples/ are checked in.
If an example appears in examples.yaml but has neither a local source directory nor an existing checked-in TAR, bundling fails. This protects normal examples from silently disappearing while still allowing large prebundled templates such as Wonderous.
The bundler skips generated local Flutter artifacts (build/, .dart_tool/, .flutter-plugins*, and pubspec.lock) so local flutter pub get, flutter analyze, or generator output does not accidentally bloat a template TAR.
On startup the frontend fetches examples/examples.json and displays the templates on the prompt page. When a template is selected:
examples/<id>.tar) is fetched and extracted into the workspace.prompt and/or image, those are pre-filled in the agent composer.pub get.lib/main.dart exists, the preview starts automatically with initial preview validation skipped. This avoids blocking startup on stale LSP diagnostics while the imported workspace is still settling.examples/<id>/ with a pubspec.yaml and usually lib/main.dart.examples/examples.yaml:- id: my_example title: My Example
dart run tool/bundle_examples.dart.packages/frontend/web/examples/.examples/<id>/ with at least a pubspec.yaml.lib/ and/or an image file.examples/examples.yaml:- id: my_example title: My Example prompt: >- Describe what the agent should do... image: screenshot.png # optional
dart run tool/bundle_examples.dart.Use this for templates that are too large to check in as source, such as Wonderous.
examples/<id>/.examples/examples.yaml..gitignore.dart run tool/bundle_examples.dart.examples.json, and .checksums.json, but not the local source directory.After that, other developers can run dart run tool/bundle_examples.dart without having the large local source directory. The script will keep using the checked-in TAR.
A minimal Flutter counter app. Demonstrates basic StatefulWidget usage with setState.
A Flutter profile screen with intentional overflow and layout issues. The pre-filled prompt asks the agent to take screenshots, diagnose the problems, and fix them iteratively.
An empty project with a screenshot of a weather app UI. The agent is asked to rebuild the app from the screenshot and generate background images for different weather conditions.
The Wonderous App by gskinner is the most complex example. It is intentionally checked in as packages/frontend/web/examples/flutter-wonderous-app.tar; the local source directory examples/flutter-wonderous-app/ is ignored because it is large.
The preview sandbox serves project assets through a custom DefaultAssetBundle that forwards asset keys to the host workspace. Wonderous previously decoded illustration image dimensions with:
rootBundle.load(imgPath)
That bypassed the sandbox bundle and made Flutter Web fall back to HTTP requests such as flutter/assets/assets/images/..., which 404 against the static SDK asset directory. lib/ui/wonder_illustrations/common/illustration_piece.dart now uses:
DefaultAssetBundle.of(context).load(imgPath)
This keeps those manual image loads on the same sandbox asset path as Image.asset(...).
In a normal flutter build web, Flutter auto-generates generated_plugin_registrant.dart which registers web plugins. The preview sandbox skips the Flutter build step and compiles raw Dart through DDC (Dart Dev Compiler). Federated web plugins therefore need manual registration with the same registerWith pattern.
DDC also does not tree-shake unreachable imports in the same way a release dart2js build does. For this template, web-only and native-only code needs to be separated with conditional imports such as if (dart.library.js_interop), not just runtime kIsWeb checks.
Registration happens in lib/register_plugins_web.dart, loaded via conditional import in main.dart:
// main.dart import 'package:wonders/register_plugins_stub.dart' if (dart.library.js_interop) 'package:wonders/register_plugins_web.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); registerWebPlugins(); // no-op on native, registers on web // ... }
// register_plugins_web.dart void registerWebPlugins() { final registrar = webPluginRegistrar; SharedPreferencesPlugin.registerWith(registrar); UrlLauncherPlugin.registerWith(registrar); registrar.registerMessageHandler(); }
// register_plugins_stub.dart void registerWebPlugins() {} // no-op on native
shared_preferences — fixed via registerWith| Detail | |
|---|---|
| Problem | MissingPluginException because the web plugin is not auto-registered in the sandbox. |
| Root cause | Missing generated plugin registrant. |
| Fix | SharedPreferencesPlugin.registerWith(registrar) in register_plugins_web.dart. |
| Web behavior | Uses browser localStorage through shared_preferences_web. |
url_launcher — fixed via registerWith and iframe sandbox flags| Detail | |
|---|---|
| Problem | MissingPluginException, then links did not open. |
| Root cause | Missing plugin registration plus the preview iframe blocking window.open(). |
| Fix | UrlLauncherPlugin.registerWith(registrar) and allow-popups on the preview iframe sandbox attribute in sandbox.dart. |
youtube_player_iframe — currently bypassed on web| Detail | |
|---|---|
| Problem | The WebView-backed YouTube path can hit createPlatformNavigationDelegate is not implemented on the current platform in the sandbox if the wrong WebView platform implementation is registered or compiled into the web path. |
| Current fix | fullscreen_video_viewer.dart uses a conditional import. Web loads video_player_web.dart, which embeds YouTube directly with HtmlElementView.fromTagName('iframe'); native loads video_player_stub.dart, which keeps the original YoutubePlayer widget. |
| Why this is safe | A YouTube embed is just an iframe pointing at a YouTube embed URL. For the Wonderous preview, the direct iframe gives the same user-visible result with less plugin machinery. |
| Alternative | It may be possible to use youtube_player_iframe on web by manually registering youtube_player_iframe_web's WebYoutubePlayerIframePlatform instead of webview_flutter_web‘s WebWebViewPlatform. That plugin class is not exported from the package’s public library today, so this would require either a src/ import or an upstream/exported shim. If we try it, keep it behind a conditional web-only import and do not register webview_flutter_web globally. |
webview_flutter — bypassed on web| Detail | |
|---|---|
| Problem | The generic webview_flutter_web implementation does not implement the full platform interface needed by the current resolved webview_flutter_platform_interface. |
| Fix | fullscreen_web_view.dart checks kIsWeb and falls back to launchUrl() on web, opening the link in a new tab. Native keeps the original WebViewController code. |
google_maps_flutter — stubbedRequires Google Maps JavaScript API setup and a key. The Wonderous preview replaces maps with a “Maps not available in web preview” placeholder.
home_widget — stubbediOS/Android-only feature with no useful web equivalent for the preview. The template uses a no-op NativeWidgetService.
youtube_player_iframe widget on web.