Introduction
In Flutter development, theming plays a pivotal role in creating cohesive, brand-aligned user interfaces. A custom theme and brand system not only enforces visual consistency across screens, but also simplifies maintenance as your app scales. In this tutorial, we’ll cover how to:
Define core brand tokens for colors, typography, and spacing
Extend Flutter’s ThemeData with custom properties
Apply themes consistently across widgets
Support dynamic theming (light/dark mode)
Maintain a scalable brand system over time
By the end, you’ll have a flexible, code-driven approach to theming that aligns with your organization’s design standards.
Defining Core Brand Tokens
Core brand tokens are the atomic style values that represent your brand’s visual language. These include primary and secondary colors, text styles, and spacing units. Represent them as constants in a Dart file so they’re reusable and easy to update:
import 'package:flutter/material.dart';
class AppColors {
static const Color primary = Color(0xFF0055FF);
static const Color secondary = Color(0xFFFFC700);
static const Color background = Color(0xFFF5F5F5);
}
class AppTypography {
static const TextStyle heading = TextStyle(
fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black,
);
static const TextStyle body = TextStyle(fontSize: 16, color: Colors.black87);
}Centralizing tokens ensures that any brand update (like changing the primary color) propagates app-wide with minimal code changes.
Extending ThemeData with Custom Extensions
Flutter’s ThemeData covers many use cases, but you often need brand-specific properties, such as custom radii, shadows, or gradients. Use ThemeExtension to attach these values:
import 'package:flutter/material.dart';
class BrandTheme extends ThemeExtension<BrandTheme> {
final double radius;
final Gradient buttonGradient;
const BrandTheme({required this.radius, required this.buttonGradient});
@override
BrandTheme copyWith({double? radius, Gradient? buttonGradient}) =>
BrandTheme(
radius: radius ?? this.radius,
buttonGradient: buttonGradient ?? this.buttonGradient,
);
@override
BrandTheme lerp(ThemeExtension<BrandTheme>? other, double t) {
if (other is! BrandTheme) return this;
return BrandTheme(
radius: lerpDouble(radius, other.radius, t)!,
buttonGradient: LinearGradient.lerp(
buttonGradient as LinearGradient,
other.buttonGradient as LinearGradient,
t,
)!,
);
}
}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.