Scaffolding: Package vs Plugin Anatomy
Before writing code, understand the architectural distinction between a pure Dart Package and a Flutter Plugin. A pure Dart package contains only Dart code that runs on any platform (e.g., utility functions, mathematical algorithms, data serialization, business models). A Flutter plugin contains platform-specific native code (Kotlin/Java for Android, Swift/Objective-C for iOS, C++ for desktop) communicating across platform channels or FFI.
Keep your dependencies as lean as possible. A library that pulls in 15 third-party dependencies becomes a dependency conflict hazard for consumers when version mismatches arise. Strive for zero external dependencies wherever native Dart core libraries suffice.
The Golden Rule: Information Hiding with lib/src
A major package engineering mistake is exposing internal implementation details in the root lib/ directory. If a consumer imports an internal helper class and you refactor it in a patch release, you have inadvertently caused a breaking change.
Follow the official Dart convention: place all internal classes inside lib/src/. In the root lib/my_package.dart, export ONLY the public API surface that consumers are intended to use. Use the 'show' directive to prevent leaking internal helper types.
// lib/flutter_devlog.dart (Public API entrypoint)
library flutter_devlog;
// Only export the clean public interface
export 'src/devlog_base.dart' show DevLog;
export 'src/log_level.dart' show LogLevel;
export 'src/log_formatter.dart' show DevLogFormatter;
// Internal implementations like 'src/ansi_color_formatter.dart' remain hiddenAchieving 140/140 Pana Points
Pub.dev ranks packages using Pana, an automated analysis tool. To get a perfect score, your package must meet strict criteria:
- README.md: Must contain a clear value proposition, installation instructions, usage code snippets, and visual output examples.
- CHANGELOG.md: Must document every release strictly adhering to Semantic Versioning (MAJOR.MINOR.PATCH).
- Documentation: Every single public class, method, getter, and parameter must have triple-slash (///) doc comments.
- Code Quality: Must have zero warnings under flutter_lints and support sound null safety across all target platforms.
- Example: Must include a working example/ project demonstrating real integration.
- License: Must include an OSI-approved license like MIT, BSD-3-Clause, or Apache-2.0.
Automating Release Validation with GitHub Actions & OIDC
Never publish a package manually from your personal laptop terminal without automated CI. Set up a GitHub Action that runs dart analyze, dart test, and dart pub publish --dry-run on every pull request.
For production releases, Pub.dev supports automated publishing using OpenID Connect (OIDC) tokens directly from GitHub Actions. This eliminates the security risk of storing personal refresh tokens as repository secrets.
name: Publish to Pub.dev
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
permissions:
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dart-lang/setup-dart@v1
- run: dart pub get
- run: dart test
- name: Publish package
run: dart pub publish -fWriting Comprehensive Unit and Golden Tests for Packages
A package without automated tests is an liability for any engineering team considering using it in production. In the Dart ecosystem, package:test provides a fast, headless test runner that executes hundreds of unit tests in seconds.
Write tests that exercise edge cases: null inputs, empty lists, malformed network responses, and boundary condition limits. Aim for minimum 90% code coverage. When Pana analyzes your package on Pub.dev, having an active test suite with 100% passing tests contributes directly to your package ranking and verified publisher trust score.
Managing Community Contributions, Pull Requests, and Deprecations
Once your package gains popularity on Pub.dev, other developers will submit pull requests, report issues, and request features. Having a clear CONTRIBUTING.md guide sets expectations for formatting, branch names, and required test additions.
When deprecating older APIs, never delete symbols abruptly. Use Dart's built-in @Deprecated('Use newMethod() instead in v2.0') annotation. This generates helpful compiler warnings in downstream IDEs, guiding developers to migrate smoothly before the deprecated symbol is removed in the next major version release.
Final Thoughts
Open source is a multiplier for your technical reputation and engineering discipline. Authoring a package forces you to think deeply about API design, backward compatibility, and developer empathy.
Key Takeaways
- Keep internal implementation code private in lib/src/.
- Triple-slash doc comments on all public declarations are mandatory for top Pana scores.
- Always simulate publication with 'dart pub publish --dry-run' before going live.
- Automate publishing with GitHub Actions and OIDC authentication.
- Semantic versioning and @Deprecated annotations protect downstream developers.
- Verified publisher domains build instant credibility and trust across the Flutter community.
Frequently Asked Questions
How does Semantic Versioning work on Pub.dev?
Follow MAJOR.MINOR.PATCH (e.g., 1.2.3). Increment PATCH for backward-compatible bug fixes, MINOR for backward-compatible new features, and MAJOR for any breaking API change. For packages under 1.0.0 (e.g., 0.1.0), incrementing the MINOR version is treated by pub as a breaking change.
How do I test my package before publishing to the public registry?
Run 'dart pub publish --dry-run' in your package directory. It will analyze your package, check for missing files, calculate compressed size, and flag any missing documentation or license issues without uploading anything.
Can I delete a package version if I accidentally publish broken code?
No. Pub.dev policy strictly forbids deleting published package versions to prevent breaking downstream builds. You can, however, mark a version as 'retracted' or publish an immediate patch release (e.g. 1.0.1) fixing the regression.
How do I become a Verified Publisher on Pub.dev?
Create a Google Search Console verified domain (e.g. bayajitislam.com) and link it to your Pub.dev account. Publishing packages under a verified domain gives users confidence and displays a verified badge on your package listing.
What files should be excluded from pub.dev packages?
Add a .pubignore file excluding IDE folders (.idea, .vscode), CI scripts, scratch benchmarks, test coverage reports, and build artifacts to keep package download size small and fast.




