# How to Set Up Widget Previews with the previews.dart System in Flutter

> Learn how to set up widget previews in Flutter using the previews.dart system. Annotate your Widgets and launch the previewer easily.

- Repository: [Flutter/skills](https://github.com/flutter/skills)
- Tags: how-to-guide
- Published: 2026-05-09

---

**You set up widget previews by importing `package:flutter/widget_previews.dart`, annotating top-level functions or static methods that return Widgets with `@Preview`, and launching the Flutter Widget Previewer via your IDE or the `flutter widget-preview start` command.**

The `previews.dart` system enables isolated widget rendering with instant hot refresh, allowing you to experiment with themes, sizes, and brightness configurations without launching the full application. According to the [flutter/skills](https://github.com/flutter/skills) repository, the previewer scans your codebase for these annotations and generates interactive preview cards in a web-based interface. This workflow, detailed in the repository’s [`SKILL.md`](https://github.com/flutter/skills/blob/main/SKILL.md) file, integrates directly with Android Studio, IntelliJ, and VS Code to provide a visual development environment.

## Understanding Annotation Targets and Requirements

The previewer discovers annotations by parsing Dart files according to the "Target Elements" rules defined in [`SKILL.md`](https://github.com/flutter/skills/blob/main/SKILL.md). You can apply `@Preview` to three specific code elements:

- **Top-level functions** that return a `Widget` or `WidgetBuilder`
- **Static methods** inside a class that return a `Widget`
- **Public constructors or factories** that have **no required arguments**

Any target you annotate must be importable and return a valid Flutter widget tree. The system ignores private functions or constructors with required positional parameters, ensuring the previewer can instantiate widgets automatically.

## Creating Basic Previews with @Preview

Start by importing the preview package and adding the annotation to a simple widget-building function. The `@Preview` class accepts parameters including `name`, `group`, `size`, `theme`, and `brightness` to categorize and configure the visual output.

```dart
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

@Preview(name: 'My Sample Text', group: 'Typography')
Widget mySampleText() {
  return const Text('Hello, World!');
}

```

When the Flutter Widget Previewer runs, it detects this annotation and renders a preview card labeled "My Sample Text" within the "Typography" group. You can place multiple `@Preview` annotations on the same target if you want to display the widget under different configurations simultaneously.

## Advanced Configuration with Custom Preview Classes

For dynamic configurations that cannot be expressed with constant values, extend the `Preview` class and override the `transform()` method. This approach allows runtime manipulation of names, themes, and other metadata before the preview renders.

```dart
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

final class TransformativePreview extends Preview {
  const TransformativePreview({super.name, super.group});

  PreviewThemeData _themeBuilder() => PreviewThemeData(
        materialLight: ThemeData.light(),
        materialDark: ThemeData.dark(),
      );

  @override
  Preview transform() {
    final original = super.transform();
    final builder = original.toBuilder()
      ..name = 'Transformed - ${original.name}'
      ..theme = _themeBuilder;
    return builder.toPreview();
  }
}

@TransformativePreview(name: 'Custom Themed Button')
Widget myButton() => const ElevatedButton(onPressed: null, child: Text('Click'));

```

The `transform()` method receives the base configuration and returns a modified `Preview` instance. Use the `toBuilder()` pattern to clone existing settings while overriding specific properties programmatically.

## Generating Multiple Variations with @MultiPreview

When you need to render the same widget under multiple conditions (such as light and dark themes), use the `@MultiPreview` annotation. Create a class extending `MultiPreview` and implement the `previews` getter to return a list of base configurations. Override `transform()` to dynamically assign names and groups to each variation.

```dart
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';

final class MultiBrightnessPreview extends MultiPreview {
  const MultiBrightnessPreview({required this.name});

  final String name;

  @override
  List<Preview> get previews => const [
        Preview(brightness: Brightness.light),
        Preview(brightness: Brightness.dark),
      ];

  @override
  List<Preview> transform() {
    return super.transform().map((p) {
      final b = p.toBuilder()
        ..group = 'Brightness'
        ..name = '$name - ${p.brightness!.name}';
      return b.toPreview();
    }).toList();
  }
}

@MultiBrightnessPreview(name: 'Primary Card')
Widget cardPreview() => const Card(
      child: Padding(padding: EdgeInsets.all(8.0), child: Text('Content')),
    );

```

This generates two separate preview cards—one for light mode and one for dark mode—both grouped under "Brightness" with descriptive names derived from the runtime state.

## Launching the Flutter Widget Previewer

You can start the previewer through IDE integration or the command line. For IDE support (available in Flutter 3.38+), open a Flutter project in Android Studio, IntelliJ, or VS Code; the previewer starts automatically and displays a "Flutter Widget Preview" tab.

From the terminal, navigate to your project root and execute:

```bash
flutter widget-preview start

```

This command compiles the preview environment and opens a Chrome window serving the web-based UI. The interface provides two hot-restart options: a **Global** button that restarts all previews (necessary when static state changes) and **Per-card** buttons that restart individual previews while preserving state for others.

## Handling Native API Limitations

Because the previewer runs in a lightweight web environment, any widget depending on native APIs such as `dart:io` or `dart:ffi` will fail to render. The [`SKILL.md`](https://github.com/flutter/skills/blob/main/SKILL.md) documentation in the flutter/skills repository explicitly warns against these dependencies.

To work around this limitation, use conditional imports to provide mock implementations when running in preview mode. Structure your code to abstract platform-specific logic behind interfaces that can return stub values in the web context.

## Summary

- Import **`package:flutter/widget_previews.dart`** to access the `@Preview` and `@MultiPreview` annotations.
- Annotate **top-level functions**, **static methods**, or **zero-argument constructors** that return `Widget` instances.
- Configure static metadata like `name`, `group`, `size`, and `brightness` directly in the annotation constructor.
- Extend **`Preview`** or **`MultiPreview`** and override **`transform()`** to generate dynamic configurations using the `toBuilder()` pattern.
- Launch the previewer via **`flutter widget-preview start`** or through IDE integration (Flutter 3.38+).
- Avoid **`dart:io`** and **`dart:ffi`** dependencies, or use conditional imports to mock native APIs for the web-based preview environment.

## Frequently Asked Questions

### What is the previews.dart system in Flutter?

The previews.dart system is a development tool that renders Flutter widgets in isolation using a lightweight web environment. It allows developers to visualize components instantly with hot refresh by scanning for `@Preview` annotations in the codebase, as implemented in the `flutter/skills` repository's widget preview workflow.

### Which functions can I annotate with @Preview?

You can annotate **top-level functions** returning `Widget` or `WidgetBuilder`, **static methods** inside classes, and **public constructors or factories** that have no required arguments. Private members and functions with required parameters are not eligible for preview generation according to the target element rules.

### How do I launch the widget previewer from the command line?

Run **`flutter widget-preview start`** from your project root directory. This command starts a local server and opens Chrome with the preview interface. The previewer automatically detects file changes and updates the rendered cards, offering both global and per-card hot-restart controls.

### Can I use native platform APIs in widget previews?

No. The previewer runs in a browser environment that does not support `dart:io`, `dart:ffi`, or other native platform APIs. You must either remove these dependencies from previewed widgets or use **conditional imports** to provide mock implementations when compiling for the preview environment, as documented in [`SKILL.md`](https://github.com/flutter/skills/blob/main/SKILL.md).