Using Code Generation with build runner and Freezed in Flutter
Jun 16, 2025



Summary
Summary
Summary
Summary
Code generation in Flutter using Freezed and build_runner enables fast, error-free model creation with immutability, unions, and JSON support. It simplifies the development process, ensures clean data layers, and integrates seamlessly with CI for consistent outputs. Combined with state management tools, it offers a robust foundation for scalable Flutter apps.
Code generation in Flutter using Freezed and build_runner enables fast, error-free model creation with immutability, unions, and JSON support. It simplifies the development process, ensures clean data layers, and integrates seamlessly with CI for consistent outputs. Combined with state management tools, it offers a robust foundation for scalable Flutter apps.
Code generation in Flutter using Freezed and build_runner enables fast, error-free model creation with immutability, unions, and JSON support. It simplifies the development process, ensures clean data layers, and integrates seamlessly with CI for consistent outputs. Combined with state management tools, it offers a robust foundation for scalable Flutter apps.
Code generation in Flutter using Freezed and build_runner enables fast, error-free model creation with immutability, unions, and JSON support. It simplifies the development process, ensures clean data layers, and integrates seamlessly with CI for consistent outputs. Combined with state management tools, it offers a robust foundation for scalable Flutter apps.
Key insights:
Key insights:
Key insights:
Key insights:
Freezed Simplifies Modeling: Automates creation of immutable classes, unions, and JSON serialization.
Minimal Setup Required: Adding dependencies and running
flutter pub get
gets you started quickly.Supports Union Types: Enables expressive pattern matching using
when
,map
, and variants.Enhances CI Integration: Build commands can be embedded in pipelines to ensure consistent artifacts.
Works with State Management: Ideal for pairing with riverpod or bloc to model UI states.
Encourages Clean Code: Supports mixins and extensions for better modularity and customization.
Introduction
Automating boilerplate in Dart models dramatically reduces errors and speeds up development. In Flutter projects, code generation tools like build_runner and Freezed empower you to define immutable data classes, union types, and JSON serialization with minimal manual effort. This tutorial dives deep into setting up and leveraging Flutter code generation via Freezed, illustrating how to maintain clean, consistent, and efficient data layers.
Installing and configuring dependencies
Begin by adding the necessary packages to your pubspec.yaml. Freezed relies on annotations for model definitions, and build_runner orchestrates code generation tasks.
dependencies:
flutter:
sdk: flutter
freezed_annotation: ^2.0.0
json_annotation: ^4.7.0
dev_dependencies:
build_runner: ^2.3.0
freezed: ^2.0.0
json_serializable
After updating your pubspec, run flutter pub get. Optionally, create or customize a build.yaml to control output paths or enable lint rules for generated files. For most cases, the default configuration suffices.
Creating Freezed data classes
Freezed uses source generation to create immutable classes with copyWith, ==, hashCode, and when/unions. To define a model:
Create a Dart file, e.g.,
user.dart
.Add part directives for code-generated output.
Annotate with
@freezed
and define factory constructors.
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
String? email,
}) = _User;
factory User.fromJson(Map<String, Object?> json) =>
_$UserFromJson(json);
}
Explanation:
part 'user.freezed.dart'
andpart 'user.g.dart'
instruct build_runner to generate two helper files.The
@freezed
annotation signals the generator.User.fromJson
hooks intojson_serializable
for JSON support.
Customizing serialization and unions
Freezed supports union types (sealed classes) and custom JSON keys. This is essential for modeling API responses with multiple variants or special field mappings.
Example with union and custom JSON key:
@freezed
class ApiResponse with _$ApiResponse {
const factory ApiResponse.success({
@JsonKey(name: 'data') required List<User> users,
}) = SuccessResponse;
const factory ApiResponse.error({
@JsonKey(name: 'error_code') required int code,
@JsonKey(name: 'message') required String message,
}) = ErrorResponse;
factory ApiResponse.fromJson(Map<String, dynamic> json) =>
_$ApiResponseFromJson(json);
}
Key points:
Each factory becomes a distinct subtype (
SuccessResponse
,ErrorResponse
).when
,maybeWhen
,map
,maybeMap
methods turn exhaustive switch statements into expressive, type-safe code.@JsonKey
customizes serialization field names.
Automating with build_runner
With your models defined, invoke build_runner to generate code:
One-time build:
flutter pub run build_runner build --delete-conflicting-outputs
Continuous watch (auto-regenerate on file changes):
flutter pub run build_runner watch --delete-conflicting-outputs
Tips for robust Flutter code generation:
Always use
--delete-conflicting-outputs
to avoid stale artifacts.Integrate codegen into CI by running the build command as a pre-commit or pipeline step.
Exclude generated files from analysis errors by adding them to
analysis_options.yaml
:analyzer: exclude: - "**/*.g.dart" - "**/*.freezed.dart"
Best practices and advanced patterns
Split large models: If a class grows beyond a screenful, break it into partials or mixins with Freezed’s @With annotation.
Combine with riverpod or bloc: Freezed models pair well with state management; use union types for representing loading, data, and error states.
Custom methods: You can add extension methods on your Freezed classes to encapsulate formatting or computed properties without altering generated code.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
By integrating build_runner and Freezed into your workflow, you unlock a powerful, maintainable approach to Flutter code generation. Immutable models, union types, and automated JSON serialization free you from repetitive boilerplate and let you focus on business logic. Incorporating these tools into CI ensures consistent, error-free artifacts across your team’s development and deployment pipelines.
Introduction
Automating boilerplate in Dart models dramatically reduces errors and speeds up development. In Flutter projects, code generation tools like build_runner and Freezed empower you to define immutable data classes, union types, and JSON serialization with minimal manual effort. This tutorial dives deep into setting up and leveraging Flutter code generation via Freezed, illustrating how to maintain clean, consistent, and efficient data layers.
Installing and configuring dependencies
Begin by adding the necessary packages to your pubspec.yaml. Freezed relies on annotations for model definitions, and build_runner orchestrates code generation tasks.
dependencies:
flutter:
sdk: flutter
freezed_annotation: ^2.0.0
json_annotation: ^4.7.0
dev_dependencies:
build_runner: ^2.3.0
freezed: ^2.0.0
json_serializable
After updating your pubspec, run flutter pub get. Optionally, create or customize a build.yaml to control output paths or enable lint rules for generated files. For most cases, the default configuration suffices.
Creating Freezed data classes
Freezed uses source generation to create immutable classes with copyWith, ==, hashCode, and when/unions. To define a model:
Create a Dart file, e.g.,
user.dart
.Add part directives for code-generated output.
Annotate with
@freezed
and define factory constructors.
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
String? email,
}) = _User;
factory User.fromJson(Map<String, Object?> json) =>
_$UserFromJson(json);
}
Explanation:
part 'user.freezed.dart'
andpart 'user.g.dart'
instruct build_runner to generate two helper files.The
@freezed
annotation signals the generator.User.fromJson
hooks intojson_serializable
for JSON support.
Customizing serialization and unions
Freezed supports union types (sealed classes) and custom JSON keys. This is essential for modeling API responses with multiple variants or special field mappings.
Example with union and custom JSON key:
@freezed
class ApiResponse with _$ApiResponse {
const factory ApiResponse.success({
@JsonKey(name: 'data') required List<User> users,
}) = SuccessResponse;
const factory ApiResponse.error({
@JsonKey(name: 'error_code') required int code,
@JsonKey(name: 'message') required String message,
}) = ErrorResponse;
factory ApiResponse.fromJson(Map<String, dynamic> json) =>
_$ApiResponseFromJson(json);
}
Key points:
Each factory becomes a distinct subtype (
SuccessResponse
,ErrorResponse
).when
,maybeWhen
,map
,maybeMap
methods turn exhaustive switch statements into expressive, type-safe code.@JsonKey
customizes serialization field names.
Automating with build_runner
With your models defined, invoke build_runner to generate code:
One-time build:
flutter pub run build_runner build --delete-conflicting-outputs
Continuous watch (auto-regenerate on file changes):
flutter pub run build_runner watch --delete-conflicting-outputs
Tips for robust Flutter code generation:
Always use
--delete-conflicting-outputs
to avoid stale artifacts.Integrate codegen into CI by running the build command as a pre-commit or pipeline step.
Exclude generated files from analysis errors by adding them to
analysis_options.yaml
:analyzer: exclude: - "**/*.g.dart" - "**/*.freezed.dart"
Best practices and advanced patterns
Split large models: If a class grows beyond a screenful, break it into partials or mixins with Freezed’s @With annotation.
Combine with riverpod or bloc: Freezed models pair well with state management; use union types for representing loading, data, and error states.
Custom methods: You can add extension methods on your Freezed classes to encapsulate formatting or computed properties without altering generated code.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
By integrating build_runner and Freezed into your workflow, you unlock a powerful, maintainable approach to Flutter code generation. Immutable models, union types, and automated JSON serialization free you from repetitive boilerplate and let you focus on business logic. Incorporating these tools into CI ensures consistent, error-free artifacts across your team’s development and deployment pipelines.
Accelerate Flutter with Vibe Studio
Accelerate Flutter with Vibe Studio
Accelerate Flutter with Vibe Studio
Accelerate Flutter with Vibe Studio
Leverage Vibe Studio’s AI-powered platform to streamline Flutter model generation and state management using Freezed. Build faster with Steve’s agents.
Leverage Vibe Studio’s AI-powered platform to streamline Flutter model generation and state management using Freezed. Build faster with Steve’s agents.
Leverage Vibe Studio’s AI-powered platform to streamline Flutter model generation and state management using Freezed. Build faster with Steve’s agents.
Leverage Vibe Studio’s AI-powered platform to streamline Flutter model generation and state management using Freezed. Build faster with Steve’s agents.
Join a growing community of builders today
Join a growing
community
of builders today
Join a growing
community
of builders today










© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025


© Steve • All Rights Reserved 2025