Including assets in a Flutter package
A guide for package developers

If you are coming to this page wanting to know how to include images, fonts, or other assets in your Flutter app, then you might be in the wrong place. Check out one of these other articles for help:
- How to use a custom font in a Flutter app
- How to include images in your Flutter app
- Reading a text file from assets in Flutter
- Flutter documentation: Adding assets and images
The guide below is for package developers who need to include assets in their package.
Where to put the assets
So you have an image or font or something that you want to make available to the app developers who use your package. Where do you put it?
One choice is to put it in the lib/ folder.

Anything in the lib/ folder will get automatically bundled with the app. Those assets will be available to anyone who uses your package. As the package developer, you don’t even need to declare those assets in pubspec.yaml if you are not using them yourself. They’ll still be bundled with the package.
The other choice is to create a new folder in the main project. Call it assets or fonts or whatever you want.

Any assets that are not in the lib/ folder, though, will not get added to the package’s assets bundle unless you specifically include them in pubspec.yaml:
flutter:
assets:
- assets/my_image.jpg
fonts:
- family: MyFontFamily
fonts:
- asset: assets/my_font.ttf
It is easiest to understand how this works by looking at some examples. I’ll show you four different Flutter packages on Pub.dev that each do it a little bit differently. You’ll see how the assets are handled from both the package author’s perspective and from the package user’s perspective.
Example 1: shrine_images
The shrine_images package isn’t really useful for anything other than providing the image assets for the Shrine app that is part of the Flutter Gallery demo app. But it is helpful for showing how to include assets in a Flutter package, and that was probably the main purpose.
How the package developer did it
The package developer put all of the assets in the lib/ folder like this:
shrine_images/lib/
2.0x/
0-0.jpg
1-0.jpg
10-0.jpg
...
3.0x/
0-0.jpg
1-0.jpg
10-0.jpg
...
0-0.jpg
1-0.jpg
10-0.jpg
...
Three different density versions of each image exists. There is nothing else in the lib/ folder except these images. If you look at the pubspec.yaml file, there is no mention at all of any assets. Just including them in the lib/ folder was enough.
How an app developer uses the package
It’s a little hard to follow how the Shrine app uses the package (but see here, here, and here if you are interested), so I’ll make a simple app that uses the shrine_images package.
My app’s pubspec.yaml file looks like this:
name: flutter_assets
description: A Flutter app.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
shrine_images: ^1.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- packages/shrine_images/10-0.jpg
Notice two things:
- I included
shrine_images: ^1.1.2
as a dependency. - I included
— packages/shrine_images/10–0.jpg
under the flutter assets. You start withpackage/
. Then you give the package name (shrine_images
in this case). Then you give the location and file name in the lib/ folder. You don’t includelib
itself because that is assumed. I am only using one image in my simple app. If I were using more images I would have to list them all individually (like the Shrine app does). You can’t just specify the folder like you can with local assets.
My main.dart file looks like this:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: Image(
image: AssetImage(
'10-0.jpg',
package: 'shrine_images',
),
),
),
),
);
}
}
Note that there is no need to import the shrine_images package at the top of the file.
To get the image you use AssetImage
and provide it the asset name and package name. Here that part is again.
AssetImage('10-0.jpg', package: 'shrine_images')
Running the app now gives the following:

Example 2: font_awesome_flutter
The font_awesome_flutter package provides a set of fonts with lots of useful icons. The fonts themselves are bundled in the package.
How the package developer did it
The package developer put the font assets in a subfolder of lib/ like this:
font_awesome_flutter/lib/
font/
fa-brands-400.ttf
fa-regular-400.ttf
fa-solid-900.ttf
font_awesome_flutter.dart
icon_data.dart
However, since the developer is using the assets in the package logic, they also declare the fonts as assets in the pubspec.yaml file:
flutter:
fonts:
- family: FontAwesomeBrands
fonts:
- asset: lib/fonts/fa-brands-400.ttf
weight: 400
- family: FontAwesomeRegular
fonts:
- asset: lib/fonts/fa-regular-400.ttf
weight: 400
- family: FontAwesomeSolid
fonts:
- asset: lib/fonts/fa-solid-900.ttf
weight: 900
And here is a snippet of it being used in the icon_data.dart code:
class IconDataBrands extends IconData {
const IconDataBrands(int codePoint)
: super(
codePoint,
fontFamily: 'FontAwesomeBrands',
fontPackage: 'font_awesome_flutter',
);
}
Doing this makes it a lot easier on the package users as you will see.
How an app developer uses the package
An app developer only needs to include font_awesome_flutter as a dependency in the app’s pubspec.yaml file.
dependencies:
font_awesome_flutter: ^8.5.0
There is no need to declare any font assets. The app developer doesn’t even need to know the name of the font files.
You can just import the package and use it directly. Here is main.dart for a simple demo:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: IconButton(
icon: Icon(FontAwesomeIcons.wordpress),
iconSize: 100,
onPressed: (){},
),
),
),
);
}
}
You only have to pass the FontAwesomeIcons.wordpress
icon data into an Icon widget. This makes it super easy for the app developer.
Running the app now gives

Example 3: crypto_font_icons
The crypto_font_icons package is similar to font_awesome_flutter in that it provides a custom font for app developers to use. The reason I mention it is that the package developer used a different folder structure.
How the package developer did it
Rather than putting the font in the lib/ folder, the package developer made a fonts folder in the main package folder like this:
cryptofont-flutter/
font/
cryptofont-webfont.ttf
lib/
crypto_font_icon_data.dart
crypto_font_icons.dart
Then pubspec.yaml looks like this:
flutter:
fonts:
- family: CryptoFont
fonts:
- asset: font/cryptofont-webfont.ttf
By listing the font as an asset in pubspec.yaml, it still gets included in the assets bundle, and thus will be available to app developers who use the package.
Everything else on the package developer’s side is basically the same as the font_awesome_flutter package.
How an app developer uses the package
From the perspective of the app developer, it doesn’t matter at that the package developer didn’t put the assets in the lib/ folder. That’s all hidden away by the package.
Just depend on it
dependencies:
crypto_font_icons: ^0.1.0+1
And use it like we did in the font_awesome_flutter example above.
import 'package:crypto_font_icons/crypto_font_icons.dart';
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: IconButton(
icon: Icon(CryptoFontIcons.BTC),
iconSize: 100,
onPressed: (){},
),
),
),
);
}
}
This gives

Example 4: mongol
In my original version of this article I only had three examples. Presenting these examples to you was my way of learning how to do it myself. However, I discovered while working on my own package that the examples above did not cover how to provide a font itself. Example 1 used an AssetImage
widget to specify the package and examples 2 and 3 used an IconData
widget to specify the package. But I wanted to share an entire font.
My package is called mongol. You aren’t likely to ever use it unless you are one of the few Flutter devs creating apps for vertical Mongolian text. However, since the source code is on GitHub, you can see how I was able to provide a font file (not just icon data) to the package users.
How the package developer did it
I included the Mongolian font file in the lib folder like this:
mongol
lib/
fonts/
MQG8F02.ttf
Since it is in the lib/ folder it will be automatically included in the package bundle. But since I was using it in the package code to make it the default font for the MongolText
widget, I also declared it in pubspec.yaml:
flutter:
fonts:
- family: MenksoftQagan
fonts:
- asset: lib/fonts/MQG8F02.ttf
The name MenksoftQagan
is descriptive but arbitrary. I could have called the font family HappyHippos
if I’d wanted to.
The trick next was how to provide access to that font. Using MenksoftQagan
isn’t enough because that doesn’t include the package info. The key was to use the following string pattern when the font family was needed:
'packages/<package_name>/<font_family_name>'
For my package this translated to
'packages/mongol/MenksoftQagan'
In the package code I made a class for this:
class MongolFont {
static const String qagan = 'packages/mongol/MenksoftQagan'; }
How an app developer uses the package
Since the package uses the 'packages/mongol/MenksoftQagan'
string internally, the package user doesn’t need to know it at all.
Doing something like this works fine:
pubspec.yaml:
dependencies:
mongol: ^0.3.0
main.dart:
import 'package:flutter/material.dart';
import 'package:mongol/mongol_text.dart';void main() => runApp(DemoApp());class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Stack(
children: <Widget>[
Center(
child: MongolText(
'ᠮᠣᠩᠭᠣᠯ',
style: TextStyle(fontSize: 100),
),
),
],
),
),
);
}
}
Running that gives

However, if the app user wanted to use the font file directly they could use the string 'packages/mongol/MenksoftQagan'
to access it. For example, replace the MongolFont
widget with a standard Text
widget:
Text(
'ᠮᠣᠩᠭᠣᠯ',
style: TextStyle(
fontFamily: 'packages/mongol/MenksoftQagan',
fontSize: 100,
),
),
which gives

For help accessing other file types, see this Stack Overflow Q&A.
Conclusion
Its great that the Pub packages are open source so that we can learn by seeing how other people have solved the same problems. If there are ways that you think the current process of adding assets to a package can be improved, first check out this GitHub issue. And if there are any improvements or insights that you can add to this guide, please leave a comment below.