In a Dart pubspec.yaml, what does `publish_to: none` do, and why should an app or private package set it?
answer
- uploads cannot be taken back
- the default destination is pub.dev
- a URL or the literal none
- dart create does not add it
basics
~20 spublish_to: none makes dart pub publish refuse to upload the package anywhere. Without the key pub publishes to pub.dev, where versions essentially cannot be deleted, so apps and private packages set it to block an accidental, permanent upload.
solid answer
~40 sThe `publish_to` key in `pubspec.yaml` says where `dart pub publish` sends the package. Left out, it means pub.dev; set to a URL, it targets a custom package repository; set to `none`, publishing is refused. The guard matters because pub.dev's policy disallows unpublishing except in very few cases: once a version is up, anyone can depend on it and it stays available. An app, a company-internal helper or a workspace root has no business on pub.dev, so `publish_to: none` turns a stray `dart pub publish` into an error instead of a public release. It changes nothing about `dart pub get` or dependency resolution. `dart create`'s console and package templates do not write the line, so you add it yourself.
code
yaml · 12 linesname: colour_tools_demo
description: Demo app for the colour_tools package.
# An app is never uploaded to pub.dev; this line makes
# `dart pub publish` fail instead of publishing it.
publish_to: none
environment:
sdk: ^3.13.0
dependencies:
colour_tools:
path: ../go deeper
Recall the three values: omitted means pub.dev, a URL means a custom repository, none means publishing is refused. Know that apps should carry the none value.
Explain why the guard exists: pub.dev disallows unpublishing, so an accidental upload is effectively permanent and also claims the package name for its uploader.
Treat it as repository hygiene: every app, demo and workspace root carries it, private libraries point at their repository URL, and nobody mistakes it for access control.
Frame it as a cheap guard against an irreversible action; the policy question is which packages may ever reach a public registry and who is allowed to publish them.
## What the key controls Every Dart package is described by a `pubspec.yaml` file at its root. One of its optional keys, **`publish_to`**, tells the pub tool where the command `dart pub publish` should upload the package. It accepts three kinds of value: | Value of `publish_to` | Where `dart pub publish` goes | |---|---| | key omitted | **pub.dev**, the default public package repository | | a URL, such as `https://dart-packages.example.com` | a **custom package repository** at that address | | `none` | **nowhere** - publishing is refused | The key only affects *publishing*. It does not change how `dart pub get` or `dart pub upgrade` resolve the package's own dependencies, and it does not make any code secret. It is a safety catch on one command. ## Why a safety catch is needed: publishing is forever The dart.dev guide on publishing opens with a warning: **a published package lasts forever**. As soon as a version is on pub.dev, other developers can depend on it, and removing it would break their builds. For that reason pub.dev's policy **disallows unpublishing** except in very few cases. You can upload newer versions, but old ones stay available; beyond fixing forward, a bad version can only be retracted within a short window, or the whole package marked discontinued. Against that background, the cost of a mistake is lopsided: - An accidental `git push` to the wrong remote can usually be undone. - An accidental `dart pub publish` of an app puts its code, its name and its version on a public registry, effectively permanently. - The first person to publish a name also becomes its only authorized uploader, so a mistake can also squat a name your team wanted for something else. `publish_to: none` makes that mistake impossible from the command line: pub reads the key and stops instead of uploading. ## Where to put it Set it in any package that is **not** meant to become a public library: 1. **Applications** - a Flutter or command-line app is the root of its own dependency graph, not something others import. 2. **Internal packages** in a company repository that should never leave it. 3. **Example and demo apps** that live next to a published package, such as the demo app for an open-source `colour_tools` library. 4. **The root of a pub workspace** - dart.dev's workspace example itself sets `publish_to: none` on the root `pubspec.yaml`. For packages that *should* be shared privately, the better value is usually the URL of your private repository rather than `none`, so that publishing is possible but can only go to the right place. ## What it does not do It is easy to read more into the key than it provides: - It is **not access control**. Anyone with the source can delete the line and publish; it only prevents accidents. - It does **not** hide the package from anyone who can already see your repository. - It does **not** stop the package from depending on hosted, git or path dependencies, or from being used through a path dependency by another package. - It is **not added automatically** by `dart create`: the console and package templates write `name`, `description`, `version` and `environment`, but no `publish_to` line. Add it yourself when the project is an app or private. A related detail: `version` and `description` are required only for packages hosted on pub.dev, so a package that will never be published does not strictly need either for `dart pub get` to work. ## Switching a package to public later If an internal package later becomes a candidate for pub.dev, removing `publish_to: none` is only the first step. The package must then meet pub.dev's requirements - a `LICENSE` file, only hosted and SDK dependencies, a `version` and a `description` - and `dart pub publish --dry-run` shows which checks still fail before anything is uploaded. ## Summary - Omitted: publish to pub.dev. URL: publish to that repository. `none`: refuse. - Publishing to pub.dev is effectively permanent, which is why the guard exists. - Put it on apps, internal packages, demo apps and workspace roots; it is a guard against mistakes, not a security boundary.
- An internal package with `publish_to: none` now needs to go to pub.dev. What must change?Remove the line, then meet pub.dev's requirements: a `version`, a `description`, a `LICENSE` file, and only hosted and SDK dependencies (no `git` or `path` sources). Run `dart pub publish --dry-run` to see what still fails. Remember the first upload makes you the only authorized uploader until you add others or transfer the package to a verified publisher.
- How do you publish a Dart package to a private repository rather than pub.dev?Set `publish_to` to the repository URL and register a token for it with `dart pub token add <url>`, so pub authenticates the upload. Consumers then declare the dependency with the hosted syntax pointing at the same URL. `publish_to: none` would block this entirely, so it is the wrong value for a package meant to be shared privately.
saying these in an interview costs you the question
- publish_to: none stops dart pub get from resolving the package's dependencies
- You can delete a version from pub.dev whenever you like, so the guard is optional
- dart create writes publish_to: none into every new project automatically
- publish_to: none makes the package private and hides its source code
- Omitting publish_to means the package cannot be published until you set it