Contents

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 enchilada) 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

* The .dart_tool directory and .packages file exist after you’ve run pub get. Don’t check them into source control.

** The pubspec.lock file exists after you’ve run pub get. Leave it out of source control unless your package is an application package.

*** The doc/api directory exists locally after you’ve run dartdoc. Don’t check the api directory into source control.

The pubspec

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 package.

Running pub get, pub upgrade, or pub downgrade on the package creates a lockfile, named 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.

LICENSE

enchilada/
  LICENSE

If you’re publishing your package, include a license file named LICENSE. We recommend using an OSI-approved license such as BSD-3-Clause, so that others can reuse your work.

README.md

enchilada/
  README.md

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 your code.

For guidance on how to write a great README, see Writing package pages.

CHANGELOG.md

enchilada/
  CHANGELOG.md

Include a 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 CHANGELOG.md, 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”.

When you upload your package to the pub.dev site, your package’s CHANGELOG.md file (if any) appears in the Changelog tab, rendered as Markdown.

Here’s an example of a CHANGELOG.md file. 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.

Public directories

Two directories in your package are public to other packages: lib and bin. You place public libraries in lib and public tools in bin.

Public libraries

The following directory structure shows the lib portion of enchilada:

enchilada/
  lib/
    enchilada.dart
    tortilla.dart

Many packages are library packages: they define Dart libraries that other packages can import and use. These public Dart library files go inside a directory called lib.

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 subdirectories inside 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

Users import olives.dart as follows:

import 'package:enchilada/some/path/olives.dart';

Note that only libraries should be in lib. Entrypoints—Dart scripts with a main() function—cannot go in lib. If you place a Dart script inside lib, you will discover that any package: imports it contains don’t resolve. Instead, your entrypoints should go in the appropriate entrypoint directory.