In this tutorial, you will learn how to Build an Invoice Generator with Vue and Firebase
Below is the app we are going to build:

What is Firebase?
Firebase is a mobile backend-as-a-service that provides powerful features for building mobile apps. Firebase has three core services: a real-time database, user authentication, and hosting. You can use these services to create apps without writing any server code
We will start by creating a Firebase project in our firebase console.
Open your Firebase console and click on add a project just as shown below:

Add a project name just as shown below:

Click continue to navigate the to next page and also disable google analytics because we won’t be using it for this project just as shown below:

Then click create project and your project we be ready to use.
After the above procedures, the app will open a page like the picture below, click on the </> icon on the page to add an app.

When we click on the icon the page will navigate to where we are going to add the name of the app we want to create just as shown below.

After we have added an app name, we are going to click on the register app button and after that, we click on the continue to console button and our app will be added.
That is all we need to do on the Firebase website for now.
Let’s move on to creating a Vue project.
Creating a Vuejs project
Open your terminal and run the following commands
vue create invoice-app
Once the app starts running you will be asked to select a default project or manually set up the project based on what you want, select default.
Adding Tailwindcss to the project
Once the app is done running, enter the project by running the below commands
cd invoice-app
npm install tailwindcss
If the dependencies have been added, go to src/assets/css/tailwind.css
and add the code below.
@tailwind base;
@tailwind components;
@tailwind utilities;
Create a config file for tailwindcss.
npx tailwindcss init
Create a PostCSS config file and add the code below. postcss.config.js
module.exports = {
plugins: [require("tailwindcss"), require("autoprefixer")]
};
After all the above setups, import tailwind in our main.js
file.
import '@/assets/css/tailwind.css'
Then run the command below to serve our app.
npm run serve
We have been able to create a Vuejs project and we have added the Tailwind css dependencies to the Vuejs project, now we are going to start building our invoice app.
Building an Invoice Generator app with Vue
Now we are going to design the invoice page and we will start by creating a Navigation.vue
file inside our components folder and also delete the HomePage.vue
file. Inside the navigation.vue
file <template></template>
write the code below
<nav class="flex items-center justify-between flex-wrap bg-500 p-6 ">
<div class="flex items-center flex-shrink-0 text-white mr-6">
<span class="font-semibold text-xl tracking-tight">Invoicing App
</span>
</div>
</nav>
In the above code, we used html nav element and tailwind style guild to design our navigation bar.
Create a home.vue file and write the code below
<div class="container-fluid">
<Navigation />
</div>
import Navigation from "../components/Navigation.vue";
components: {
Navigation
},
Inside home.vue
file template, import navigation component, and below it create a div just like the code below.
<div class="container-fluid">
<Navigation />
<div class="lg:container lg:mx-auto container-block">
</div>
</div>
Inside the empty div, we are going to create an address form. Write the code below.
<div class="flex flex-wrap">
<div class="w-2/6 p-2 text-gray-700">
<h5 class="text-lg font-bold mb-4">From</h5>
<div class="mb-2">
<label class="mb-2" for="address">
Business name
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="text"
placeholder="Business name"
v-model="businessName"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Email Address
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="email"
placeholder="Email Address"
v-model="businessEmail"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Phone Number
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="number"
placeholder="Phone Number"
v-model="businessPhone"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Address
</label>
<input
class="border border-gray-600 rounded-b w-full py-2 px-3"
id="B_name"
type="text"
placeholder="Address"
v-model="businessAddress"
/>
</div>
</div>
<div class="w-2/6 flex-none p-2">
<div class="text-gray-700 text-center p-2"></div>
</div>
<div class="w-2/6 p-2 text-gray-700">
<h5 class="text-lg font-bold mb-4">Bill To</h5>
<div class="mb-2">
<label class="mb-2" for="address">
Client Name
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="text"
placeholder="Client Name"
v-model="clientName"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Email Address
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="email"
placeholder="Email Address"
v-model="clientEmail"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Phone Number
</label>
<input
class="border border-gray-600 w-full py-2 px-3"
id="B_name"
type="number"
placeholder="Phone Number"
v-model="clientPhone"
/>
</div>
<div class="mb-2">
<label class="mb-2" for="address">
Address
</label>
<input
class="border border-gray-600 rounded-b w-full py-2 px-3"
id="B_name"
type="text"
placeholder="Address"
v-model="clientAddress"
/>
</div>
</div>
</div>
The above code is a simple form that takes both the business and client address and we use v-model
to get the input values.
Next is to create an item form where both the client and the business owners can fill in the list of item that was bought, the price tag, the number of items, and the amount in total.
Below the div that has the address form create another div just like the code below.
<div
v-for="(item, index) in items"
:key="index"
class="flex flex-wrap border-b border-gray-500 border-l border-r"
>
<div class="w-1/6 pl-2 pr-2">
<p>x</p>
</div>
<div class="w-2/6 pl-2 pr-2">
<input
class="border-gray-600 w-full py-2"
id="B_name"
type="text"
placeholder="Description"
v-model="item.description"
/>
</div>
<div class="w-1/6 pl-2 pr-2">
<input
class="border-gray-600 w-full py-2"
id="B_name"
type="number"
placeholder="0.00"
v-model="item.rate"
/>
</div>
<div class="w-1/6 pl-2 pr-2">
<input
class="border-gray-600 w-full py-2"
id="B_name"
type="number"
placeholder="0.00"
v-model="item.qty"
/>
</div>
<div class="w-1/6 pl-2 pr-2">
<input
class="border-gray-600 w-full py-2"
id="B_name"
type="number"
placeholder="0.00"
v-model="item.amount"
/>
</div>
</div>
If we notice in the above code we used v-for directive. Why? it is because we want to allow users to add more fields if there is more item to write and to achieve that we created an empty array and passed some object to the array then we loop through the array and passed those objects inside the v-model. We also have a button that adds another field for the user to
Now let’s create a button that we generate an invoice after the user is done and clicks the generate button.
<div class="bg-btn-500 text-right pb-4 pt-4">
<button
class="bg-white mr-4 text-btn-blue font-semibold py-2 px-8 border border-blue-500 rounded shadow"
@click="sendInvoice"
>
Generate invoice
</button>
</div>
Connecting with Firebase Database
We want when a user clicks the generate button it takes the value and stores it in our project database. To start out we are going to first import Firebase to our invoice app project, to do that create a firebase.js
file inside our src folder src/firebase.js
and write the below code inside.
import firebase from "firebase";
import "firebase/firestore";
const firebaseConfig = {
apiKey: "",
authDomain: "your-app.firebaseapp.com",
databaseURL: "https://your-app.firebaseio.com",
projectId: "your-app",
storageBucket: "your-app.appspot.com",
messagingSenderId: "your_senderId",
appId: "your_appId"
};
firebase.initializeApp(firebaseConfig);
After importing Firebase to our project we are going to import that file inside home.vue
component just like the code below.
import { fire } from "../firebase";
Now that we have imported Firebase to the project we can now implement the generateInvoice()
method we created. But first, let’s get the values from the inputs and pass it generateInvoice()
method. Let’s declare those values we bind to v-model
inside data(). Write the code below.
data() {
return {
amount: null,
businessName: "",
businessEmail: "",
businessPhone: "",
businessAddress: "",
clientName: "",
clientEmail: "",
clientPhone: "",
clientAddress: "",
items: [
{
description: "",
rate: "",
qty: "",
amount: ""
}
],
condition: "",
note: ""
};
},
After that, let’s implement the generateInvoice() method. Inside the methods write the code below
generateInvoice()) {
const createInvoice = {
businessName: this.businessName,
businessEmail: this.businessEmail,
businessPhone: this.businessPhone,
businessAddress: this.businessAddress,
clientName: this.clientName,
clientEmail: this.clientEmail,
clientPhone: this.clientPhone,
clientAddress: this.clientAddress,
items: this.items,
condition: this.condition,
note: this.note
};
fire
.database()
.ref("createInvoice")
.push(createInvoice);
this.businessName = "";
this.businessEmail = "";
this.businessPhone = "";
this.businessAddress = "";
this.clientName = "";
this.clientEmail = "";
this.clientPhone = "";
this.clientAddress = "";
this.items = [
{
description: "",
rate: "",
qty: "",
amount: ""
}
];
this.condition = "";
this.note = "";
Inside the generateInvoice()
method we started by creating an object that hold the values of the inputs, then we write to the firebase database and pass the object we created inside the .ref method, and we pushed the object to the firebase database to be stored and we now set our inputs to be empty.
If we check our Firebase project we can see the invoice data being stored but remember to allow our Firebase project rules to read and write if not we can not store our data.
Conclusion
I am so glad we finally made it to the end and we were able to learn how to Build an Invoice Generator app with Vue and Firebase. If find it helpful don’t forget to share.