How to publish your first Flutter package!!

Abhishek Doshi
7 min readJul 12, 2020

--

Using Flutter Packages since long?
Do you wish to contribute back?
Do you wish to publish your own package and help the community?
But don’t know how?
No worries. I have your back.
In this blog, I will get you through each and every step of how to publish your own Flutter Package on the official Flutter Website pub.dev

Pre-Requisites :
- Passion For Helping
- Understanding of Flutter
- Git

So let’s get our hands dirty!! 👏👏

A flutter package always has a class which returns a widget.
Also, the class must not have any hard-coded values.

All the functionalities which you want to provide to the user, create it as a property (variable) and create a constructor to get the value.

For example:
If you want the user to set the height of the container, create a property named double height. Add in the constructor & then pass it to the height property of the Container.

class <class_name>{
double height;
class_name({this.height});
.
.
.
.
Container(
height:height,
.
.
.
),
}

Once the code is created, use it in an application to test it and get a better understanding.

So, let’s start through the steps of how to publish the package!! 🎉💙

Step 1: Start by creating new flutter package!!

  • Open Android Studio
  • Click on Create new Flutter Project
  • Click on New Flutter Package

Step 2: Give the name of the project as the one you want your package to be named. Thus, the name of your project will be your package name.

Step 3: Put the project on Github. Keep the repo public.

Step 4: This is the most Important Step!!
Edit the Pubspec.YAML file.

  • Add Description for the package (Minimum 20 words). This costs you points on pub.dev after publishing
  • Remove author as it is not used now.
  • Add homepage. HomePage can be your own website or you can also give the Github Profile Page link.
  • Add repository. Don’t do mistake in this!! If the link get’s wrong, “issues” link on the pub.dev will not be generated. Here’s an example:
Correct Link: https://github.com/AbhishekDoshi26/contactus
Wrong Link:
https://github.com/AbhishekDoshi26/contactus.git
  • Add Version Number. Whenever you update your package code, version number has to be changed.

Step 5: Write the code in the dart file. Here’s an example of the code of a package named contactus

library contactus;import 'package:flutter/material.dart';
import 'package:typicons_flutter/typicons_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
///Class for adding contact details/profile details as a complete new page in your flutter app.
class ContactUs extends StatelessWidget {
///Logo of the Company/individual
final ImageProvider logo;
///Phone Number of the company/individual
final String phoneNumber;
///Website of company/individual
final String website;
///Email ID of company/individual
final String email;
///Twitter Handle of Company/Individual
final String twitterHandle;
///Linkedin URL of company/individual
final String linkedinURL;
///Github User Name of the company/individual
final String githubUserName;
///Name of the Company/individual
final String companyName;
///TagLine of the Company or Position of the individual
final String tagLine;
///Instagram User Name of the company/individual
final String instagram;
///TextColor of the text which will be displayed on the card.
final Color textColor;
///Color of the Card.
final Color cardColor;
///Color of the company/individual name displayed.
final Color companyColor;
///Color of the tagLine of the Company/Individual to be displayed.
final Color taglineColor;
///Constructor which sets all the values.
ContactUs({
@required this.logo,
@required this.companyName,
@required this.email,
@required this.textColor,
@required this.cardColor,
@required this.companyColor,
@required this.taglineColor,
this.phoneNumber,
this.website,
this.twitterHandle,
this.linkedinURL,
this.githubUserName,
this.tagLine,
this.instagram,
});
@override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: logo,
),
Text(
companyName,
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 40.0,
color: companyColor,
fontWeight: FontWeight.bold,
),
),
Visibility(
visible: tagLine != null,
child: Text(
tagLine,
style: TextStyle(
color: taglineColor,
fontSize: 20.0,
letterSpacing: 2.0,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
height: 10.0,
),
Divider(
color: Colors.teal[200],
thickness: 4,
indent: 50.0,
endIndent: 50.0,
),
SizedBox(
height: 10.0,
),
Visibility(
visible: website != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.link),
title: Text(
'Website',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch(website);
},
),
),
),
Visibility(
visible: phoneNumber != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.phone),
title: Text(
'Phone Number',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch('tel:' + phoneNumber);
},
),
),
),
Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.mail),
title: Text(
'Email ID',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch('mailto:' + email);
},
),
),
Visibility(
visible: twitterHandle != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.social_twitter),
title: Text(
'Twitter',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch('https://twitter.com/' + twitterHandle);
},
),
),
),
Visibility(
visible: instagram != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.social_instagram),
title: Text(
'Instagram',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch('https://instagram.com/' + instagram);
},
),
),
),
Visibility(
visible: githubUserName != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.social_github),
title: Text(
'Github',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch('https://github.com/' + githubUserName);
},
),
),
),
Visibility(
visible: linkedinURL != null,
child: Card(
margin: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 25.0,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
color: cardColor,
child: ListTile(
leading: Icon(Typicons.social_linkedin),
title: Text(
'Linkedin',
style: TextStyle(
color: textColor,
),
),
onTap: () {
launch(linkedinURL);
},
),
),
),
],
),
),
);
}
}
///Class for adding contact details of the developer in your bottomNavigationBar in your flutter app.
class ContactUsBottomAppBar extends StatelessWidget {
///Color of the text which will be displayed in the bottomNavigationBar
final Color textColor;
///Color of the background of the bottomNavigationBar
final Color backgroundColor;
///Email ID Of the company/developer on which, when clicked by the user, the respective mail app will be opened.
final String email;
///Name of the company or the developer
final String companyName;
///Size of the font in bottomNavigationBar
final double fontSize;
ContactUsBottomAppBar(
{@required this.textColor,
@required this.backgroundColor,
@required this.email,
@required this.companyName,
this.fontSize = 15.0});
@override
Widget build(BuildContext context) {
return FlatButton(
color: backgroundColor,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
child: Text(
'Designed and Developed by $companyName 💙\nWant to contact?',
textAlign: TextAlign.center,
style: TextStyle(color: textColor, fontSize: fontSize),
),
onPressed: () {
launch('mailto:$email');
},
);
}
}

Step 6: Create Documentation. For Documentation, you need to use /// to provide the documentation for a particular property/method/class,etc. /// will create documentaion and // will be comment.

class ContactUs extends StatelessWidget {
///Logo of the Company/individual
final ImageProvider logo;

Also, after creating manual documentations to your classes, let’s created the predefined documentation. Open Command Prompt in the package location and run this command:

dartdoc

Step 7: Open the CHANGELOG.md file and write the version number, publishing date and description in the file. Here’s an example for the same:

## [1.0.0] - 16/04/2020.
Added Icons for all the social networks

Step 8: Create a file LICENSE.txt & add any license such as MIT License. You can get template of any license from the internet. Here’s the example of MIT License of contactus package:

Copyright (c) 2020 Abhishek Doshi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Step 8: Create an Example.

  • Inside the package folder itself, create a new flutter project, named as example. (Don’t change the name. Name has to be compulsory example as it will be used in pub.dev)
  • To use the package in the example, without publishing, add in the pubspec.yaml the following line:
package_name:
path: Complete path of the package on your computer.
  • Here’s the code snippet of how you can use contactus package or your own package in the example:
import 'package:contactus/contactus.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
bottomNavigationBar: ContactUsBottomAppBar(
companyName: 'Abhishek Doshi',
textColor: Colors.white,
backgroundColor: Colors.teal.shade300,
email: 'adoshi26.ad@gmail.com',
),
backgroundColor: Colors.teal,
body: Container(),
),
);
}
}

Step 9: Push all to the Github Repository

Step 10: Open Command Prompt on the repo location. Now run the following command:

flutter pub publish --dry-run

If any suggestions or warnings are encountered, do the required changes.

Step 11: If everything is perfect, run the following command to publish the package.

flutter pub publish

Tadaaaaaaaaaaaaaa!!!!!!!!🌟🎉👏 Your package has been published!!

Now, whenever you change anything in the code/any file of the package/example, you need to update the following files:

  • pubspec.yaml (Version Number)
  • CHANGELOG.md (Add new version, date & description)

Whenever you feel like you haven’t done anything, just compare yourself with you at starting!!

Don’t stop until you are breathing!!!
-Abhishek Doshi

--

--

Abhishek Doshi

Google Developer Expert — Dart, Flutter & Firebase 💙💛