Package layout conventions
When you build a pub package, we encourage you to follow the conventions that this page describes. They describe how you organize the files and directories within your package, and how to name things.
Here’s what a complete package (named
that uses every corner of these guidelines
might look like:
enchilada/ .dart_tool/ * .packages * pubspec.yaml pubspec.lock ** LICENSE README.md CHANGELOG.md benchmark/ make_lunch.dart bin/ enchilada doc/ api/ *** getting_started.md example/ main.dart lib/ enchilada.dart tortilla.dart guacamole.css src/ beans.dart queso.dart test/ enchilada_test.dart tortilla_test.dart tool/ generate_docs.dart web/ index.html main.dart style.css
.dart_tool directory and
.packages file exist after you’ve run
pub get. Don’t check them into source control.
pubspec.lock file exists after you’ve run
Leave it out of source control unless your package is an
doc/api directory exists locally after you’ve run
Don’t check the
api directory into source control.
enchilada/ pubspec.yaml pubspec.lock
Every package has a pubspec, a file named
pubspec.yaml, in the root directory of the package. That’s what makes it a
pub upgrade, or
pub downgrade on the package creates a
pubspec.lock. If your package is an application
package, check the lockfile into source
control. Otherwise, don’t.
For more information, see the pubspec page.
One file that’s very common in open source is a README file that
describes the project. This is especially important in pub. When you upload
to the pub.dev site, your
README.md file is shown —
rendered as Markdown — on
the page for your package. This is the perfect place to introduce people to
For guidance on how to write a great README, see Writing package pages.
CHANGELOG.md file that has a section for
each release of your package,
with notes to help users of your package upgrade.
Users of your package often review the changelog
to discover bug fixes and new features,
or to determine how much effort it will take to upgrade
to the latest version of your package.
To support tools that parse
use the following format:
- Each version has its own section with a heading.
- The version headings are either all level 1 or all level 2.
- The version heading text contains a package version number, optionally prefixed with “v”.
Here’s an example of a
As the example shows, you can add subsections.
# 1.0.1 * Fixed missing exclamation mark in `sayHi()` method. # 1.0.0 * **Breaking change:** Removed deprecated `sayHello()` method. * Initial stable release. ## Upgrading from 0.1.x Change all calls to `sayHello()` to instead be to `sayHi()`. # 0.1.1 * Deprecated the `sayHello()` method; use `sayHi()` instead. # 0.1.0 * Initial development release.
The following directory structure shows the
lib portion of enchilada:
enchilada/ lib/ enchilada.dart tortilla.dart
Many packages are library
define Dart libraries that other packages can import and use.
These public Dart library files go inside a directory called
Most packages define a single library that users can import. In that case,
its name should usually be the same as the name of the package, like
enchilada.dart in the example here. But you can also define other
libraries with whatever names make sense for your package.
When you do, users can import these libraries using the name of the package and the library file, like so:
import 'package:enchilada/enchilada.dart'; import 'package:enchilada/tortilla.dart';
If you want to organize your public libraries, you can also create
lib. If you do that, users will specify that path
when they import it. Say you have the following file hierarchy:
enchilada/ lib/ some/ path/ olives.dart
olives.dart as follows:
Note that only libraries should be in
Entrypoints—Dart scripts with a
lib. If you place a Dart script inside
you will discover that any
package: imports it contains don’t
resolve. Instead, your entrypoints should go in the appropriate