Flutter Setup & First App

pubspec.yaml & Dependency Management

45 min Lesson 10 of 12

What is pubspec.yaml?

The pubspec.yaml file is the heart of every Dart and Flutter project. It defines your project’s metadata, dependencies, assets, and configuration. Every Flutter project must have a pubspec.yaml file in its root directory. Understanding this file is essential for managing your project effectively.

Note: YAML (YAML Ain’t Markup Language) is a human-readable data format that uses indentation for structure. Indentation in YAML must use spaces, never tabs. Incorrect indentation is the most common cause of pubspec.yaml errors.

pubspec.yaml Structure in Depth

Let’s examine every section of a typical Flutter project’s pubspec.yaml file:

Complete pubspec.yaml Example

name: my_flutter_app
description: A personal profile card application built with Flutter.
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.6
  http: ^1.1.0
  shared_preferences: ^2.2.2
  google_fonts: ^6.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.1

flutter:
  uses-material-design: true

  assets:
    - assets/images/
    - assets/data/config.json

  fonts:
    - family: Poppins
      fonts:
        - asset: assets/fonts/Poppins-Regular.ttf
        - asset: assets/fonts/Poppins-Bold.ttf
          weight: 700
        - asset: assets/fonts/Poppins-Italic.ttf
          style: italic

Project Metadata Fields

The top section defines your project’s identity:

  • name: The package name (must be lowercase with underscores, no spaces or hyphens)
  • description: A brief description of your project (required for publishing to pub.dev)
  • publish_to: 'none': Prevents accidental publishing to pub.dev (use for private apps)
  • version: Semantic versioning in the format major.minor.patch+build

Version Number Format

# version: major.minor.patch+buildNumber
version: 1.0.0+1

# major: Breaking changes (1.0.0 -> 2.0.0)
# minor: New features, backwards compatible (1.0.0 -> 1.1.0)
# patch: Bug fixes (1.0.0 -> 1.0.1)
# build: Internal build number for app stores (+1, +2, +3...)
#
# The +buildNumber maps to:
# Android: versionCode in build.gradle
# iOS: CFBundleVersion in Info.plist

Adding Dependencies from pub.dev

Dependencies are external packages that your project uses. The pub.dev registry hosts thousands of packages for Flutter and Dart.

Finding and Adding Packages

To add a package, visit pub.dev, search for the package, and copy the version information into your pubspec.yaml.

Adding Dependencies

dependencies:
  flutter:
    sdk: flutter

  # From pub.dev
  http: ^1.1.0              # HTTP client
  shared_preferences: ^2.2.2 # Local key-value storage
  provider: ^6.1.1           # State management
  google_fonts: ^6.1.0       # Google Fonts
  intl: ^0.19.0              # Internationalization
  url_launcher: ^6.2.1       # Open URLs
  path_provider: ^2.1.1      # File system paths
  cached_network_image: ^3.3.0  # Image caching
Tip: You can also add packages using the command line: flutter pub add http. This automatically adds the latest compatible version to your pubspec.yaml and runs flutter pub get.

Version Constraints

Version constraints specify which versions of a package are compatible with your project. Understanding these is critical for avoiding dependency conflicts.

Version Constraint Syntax

dependencies:
  # Caret syntax (recommended) - allows minor and patch updates
  http: ^1.1.0          # Means >=1.1.0 <2.0.0

  # Exact version - only this specific version
  provider: 6.1.1       # Only version 6.1.1

  # Range syntax - explicit bounds
  intl: '>=0.18.0 <0.20.0'  # Between 0.18.0 and 0.20.0

  # Greater than or equal
  path: '>=1.8.0'      # 1.8.0 or higher

  # Any version (not recommended)
  yaml: any             # Any available version

  # Git dependency
  my_package:
    git:
      url: https://github.com/user/my_package.git
      ref: main          # Branch, tag, or commit hash

  # Path dependency (local package)
  my_utils:
    path: ../my_utils    # Relative path to local package
Warning: Avoid using any for version constraints. It can lead to unexpected breaking changes when a package releases a new major version. Always use the caret syntax (^) for a good balance of stability and updates.

dev_dependencies

Development dependencies are packages only needed during development, not in the final app. They are not included in your release build.

Common dev_dependencies

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.1       # Lint rules
  build_runner: ^2.4.7         # Code generation
  json_serializable: ^6.7.1    # JSON serialization codegen
  mockito: ^5.4.3              # Mocking for tests
  integration_test:
    sdk: flutter               # Integration testing

Dependency Overrides

Sometimes two packages require different versions of the same dependency. You can use dependency_overrides to force a specific version.

Using dependency_overrides

# Use with caution! This forces all packages to use
# the specified version, which may cause runtime errors.
dependency_overrides:
  collection: 1.18.0
  meta: 1.11.0
Warning: Use dependency_overrides only as a last resort. Forcing incompatible versions can cause runtime errors that are difficult to debug. It’s better to wait for packages to update their dependencies.

flutter pub Commands

The flutter pub command manages your project’s dependencies. Here are the essential commands:

Essential pub Commands

# Download all dependencies listed in pubspec.yaml
flutter pub get

# Upgrade dependencies to the latest allowed versions
flutter pub upgrade

# Check for outdated dependencies
flutter pub outdated

# Add a new dependency
flutter pub add http

# Add a dev dependency
flutter pub add --dev mockito

# Remove a dependency
flutter pub remove http

# Clear the pub cache
flutter pub cache clean

# Repair the pub cache
flutter pub cache repair
Note: When you run flutter pub get, it generates a pubspec.lock file that records the exact versions resolved. This file should be committed to version control for apps (to ensure consistent builds) but not for packages.

Adding Assets

Assets are files bundled with your app, such as images, fonts, JSON files, and other resources. They must be declared in pubspec.yaml.

Adding Images

Image Assets Configuration

flutter:
  assets:
    # Include an entire directory
    - assets/images/

    # Include specific files
    - assets/images/logo.png
    - assets/images/background.jpg

    # Include subdirectories (each must be listed separately)
    - assets/images/icons/
    - assets/images/avatars/

    # Include JSON or other data files
    - assets/data/config.json
    - assets/data/countries.json

Using Image Assets in Code

// Load from assets
Image.asset('assets/images/logo.png')

// With specific dimensions
Image.asset(
  'assets/images/profile.jpg',
  width: 120,
  height: 120,
  fit: BoxFit.cover,
)

// Load JSON data from assets
Future<Map<String, dynamic>> loadConfig() async {
  final jsonString = await rootBundle.loadString(
    'assets/data/config.json',
  );
  return jsonDecode(jsonString);
}

Resolution-Aware Image Assets

Flutter supports different image resolutions for different screen densities. Create subdirectories for each resolution:

Multi-Resolution Images

# Directory structure:
# assets/images/logo.png        (1x - baseline)
# assets/images/2.0x/logo.png   (2x - high density)
# assets/images/3.0x/logo.png   (3x - extra high density)

# In pubspec.yaml, only declare the base directory:
flutter:
  assets:
    - assets/images/

# Flutter automatically picks the right resolution
# based on the device's pixel density

Declaring Fonts

Custom fonts give your app a unique look. Download font files (.ttf or .otf) and declare them in pubspec.yaml.

Font Declaration

flutter:
  fonts:
    - family: Poppins
      fonts:
        - asset: assets/fonts/Poppins-Regular.ttf
        - asset: assets/fonts/Poppins-Medium.ttf
          weight: 500
        - asset: assets/fonts/Poppins-Bold.ttf
          weight: 700
        - asset: assets/fonts/Poppins-Italic.ttf
          style: italic

    - family: RobotoMono
      fonts:
        - asset: assets/fonts/RobotoMono-Regular.ttf
        - asset: assets/fonts/RobotoMono-Bold.ttf
          weight: 700

Using Custom Fonts in Code

// Use in a specific widget
Text(
  'Hello World',
  style: TextStyle(
    fontFamily: 'Poppins',
    fontSize: 24,
    fontWeight: FontWeight.w700,
  ),
)

// Set as default font for entire app
MaterialApp(
  theme: ThemeData(
    fontFamily: 'Poppins',
    textTheme: const TextTheme(
      headlineLarge: TextStyle(fontWeight: FontWeight.w700),
      bodyMedium: TextStyle(fontWeight: FontWeight.w400),
    ),
  ),
)
Tip: Instead of bundling font files, consider using the google_fonts package. It downloads fonts on demand and caches them, reducing your app’s initial bundle size: Text('Hello', style: GoogleFonts.poppins(fontSize: 24)).

Environment Constraints

The environment section specifies which Dart SDK versions are compatible with your project:

Environment Configuration

environment:
  # Dart SDK constraint
  sdk: '>=3.0.0 <4.0.0'

  # Flutter SDK constraint (optional, but recommended)
  flutter: '>=3.10.0'

Publishing Constraints

If you ever want to publish your package to pub.dev, there are additional fields to configure:

Publishing Configuration

# For private apps (most common for Flutter apps):
publish_to: 'none'

# For public packages on pub.dev:
name: my_awesome_package
description: >
  A concise description of what your package does.
  This appears in search results on pub.dev.
version: 1.0.0
homepage: https://github.com/username/my_awesome_package
repository: https://github.com/username/my_awesome_package
issue_tracker: https://github.com/username/my_awesome_package/issues

# Topics for categorization on pub.dev
topics:
  - flutter
  - widgets
  - ui

# Platforms your package supports
platforms:
  android:
  ios:
  web:
  windows:
  macos:
  linux:

Summary

In this lesson, you learned everything about pubspec.yaml and dependency management:

  • The structure and purpose of every section in pubspec.yaml
  • How to add, update, and remove dependencies from pub.dev
  • Version constraint syntax and best practices
  • The difference between dependencies and dev_dependencies
  • Essential flutter pub commands for managing packages
  • How to declare and use assets (images, fonts, data files)
  • Environment constraints and publishing configuration
Note: Always run flutter pub get after modifying pubspec.yaml. Your IDE usually does this automatically, but if you experience issues, run it manually from the terminal.