Build and Deploy a Full-Stack Expense Tracker with React, Firebase Auth & Local Storage


โ
Live Demo: Expense Tracker App
โ
GitHub Repo: View on GitHub
๐ Introduction
Managing your finances is crucial, and a good expense tracker helps you control your spending, analyze expenses, and save better.
In this blog, weโll build a modern Expense Tracker using React, Firebase Authentication, and Local Storage.
Weโll cover:
โ Authentication (Email & Google)
โ Add/Edit/Delete Transactions
โ Dashboard with Charts
โ Monthly Reports
โ Responsive UI with Tailwind CSS
โ Notifications with React Toastify
โ Deployment on Vercel
๐ Tech Stack
Frontend: React (Vite)
Styling: Tailwind CSS
Authentication: Firebase Auth
Routing: React Router DOM
Charts: Chart.js
Icons: React Icons
Notifications: React Toastify
Storage: LocalStorage (per user with UID)
Deployment: Vercel
โจ Features
โ Login & Signup (Email + Google)
โ Add Income & Expenses with Category and Date
โ Dashboard with Summary Cards & Charts
โ Transaction List with Edit/Delete
โ Reports Page with Month Filter (Pie & Bar Charts)
โ Responsive Navbar with Profile Avatar & Logout Dropdown
โ User-specific Local Storage for transactions
โ Netflix-style Animated Gradient Background for Login & Signup
๐ Project Structure
codesrc/
โโโ App.jsx
โโโ main.jsx
โโโ firebase.js
โโโ Context/
โ โโโ AuthContext.jsx
โโโ hooks/
โ โโโ useAuth.js
โโโ Components/
โ โโโ Navbar.jsx
โ โโโ TransactionCard.jsx
โ โโโ RecentTransactions.jsx
โ โโโ NoTransactions.jsx
โโโ Pages/
โ โโโ Login.jsx
โ โโโ Signup.jsx
โ โโโ Dashboard.jsx
โ โโโ AddTransaction.jsx
โ โโโ Transaction.jsx
โ โโโ Report.jsx
๐ธ Webpage Screenshots
โ Core Code for Key Pages
๐ Firebase Setup (firebase.js
)
javascriptCopy codeimport { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: "your-app.firebaseapp.com",
projectId: "your-app",
storageBucket: "your-app.appspot.com",
messagingSenderId: "XXXXXX",
appId: "XXXXXX",
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const googleProvider = new GoogleAuthProvider();
โ
Authentication Context (AuthContext.jsx
)
javascriptCopy codeimport { createContext, useContext, useEffect, useState } from "react";
import { auth, googleProvider } from "../firebase";
import {
onAuthStateChanged,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signInWithPopup,
signOut,
} from "firebase/auth";
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
return () => unsubscribe();
}, []);
const login = (email, password) => signInWithEmailAndPassword(auth, email, password);
const signup = (email, password) => createUserWithEmailAndPassword(auth, email, password);
const loginWithGoogle = () => signInWithPopup(auth, googleProvider);
const logout = () => signOut(auth);
return (
<AuthContext.Provider value={{ user, login, signup, loginWithGoogle, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
โ Login Page
javascriptCopy codeimport { useState } from "react";
import { useAuth } from "../Context/AuthContext";
import { useNavigate, Link, Navigate } from "react-router-dom";
import { toast } from "react-toastify";
const Login = () => {
const { user, login, loginWithGoogle } = useAuth();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
if (user) return <Navigate to="/" replace />;
const handleSubmit = async (e) => {
e.preventDefault();
try {
await login(email, password);
toast.success("Logged in successfully!");
navigate("/");
} catch (err) {
toast.error("Login failed! Check credentials.");
}
};
return (
<div className="min-h-screen flex justify-center items-center bg-gradient-to-r from-red-800 via-black to-gray-900 animate-gradient">
<div className="bg-gray-800 p-6 rounded-lg shadow-lg w-full max-w-md text-white">
<h2 className="text-3xl font-bold text-center mb-4">Login</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<input type="email" placeholder="Email" onChange={(e) => setEmail(e.target.value)} className="w-full p-3 rounded bg-gray-700" />
<input type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} className="w-full p-3 rounded bg-gray-700" />
<button type="submit" className="w-full bg-red-600 hover:bg-red-700 py-2 rounded">Login</button>
</form>
<button onClick={loginWithGoogle} className="w-full mt-3 bg-blue-600 hover:bg-blue-700 py-2 rounded">Sign in with Google</button>
<p className="mt-4 text-center">Don't have an account? <Link to="/signup" className="text-blue-400">Sign Up</Link></p>
</div>
</div>
);
};
export default Login;
โ Similarly, Signup.jsx, Dashboard.jsx, AddTransaction.jsx, Report.jsx will have detailed code blocks in the blog.
โ Fork & Run the Project
Step 1: Fork the Repository
Go to GitHub Repo and click Fork.
Step 2: Clone the Repository
git clone https://github.com/YOUR_USERNAME/expenseTracker.git
cd expenseTracker
Step 3: Install Dependencies
npm install
Step 4: Configure Firebase
Create a .env
file in the root and add:
VITE_FIREBASE_API_KEY=your_api_key
Update firebase.js
:
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
...
};
Step 5: Start the Development Server
npm run dev
Step 6: Build for Production
npm run build
Step 7: Deploy on Vercel
Push your code to GitHub
Go to Vercel and import your project
Add
.env
variables in Vercel dashboardDeploy ๐
โ What I Learned
โ React Router DOM for navigation and protected routes
โ Firebase Authentication for login/signup and Google Auth
โ React Toastify for elegant notifications
โ React Icons for better UI
โ Tailwind CSS for styling and responsive design
โ LocalStorage data isolation using user UID
โ Chart.js for visual data representation
โ Deployment on Vercel with .env
security
โ Social Handles
LinkedIn: ichiragtyagi
GitHub: chiragtyagi01
X (Twitter): @I_am_Chirag28
Email: chiragtyagiofficial@gmail.com
Subscribe to my newsletter
Read articles from Chirag Tyagi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Chirag Tyagi
Chirag Tyagi
Profile Bio Iโm currently pursuing B.Tech in Computer Science and Engineering at Roorkee Institute of Technology, where I am deeply engaged in learning full-stack development with the MERN stack. My passion for technology drives me to explore and stay updated with the latest advancements in the field. Eager to apply and expand my skills, I am committed to continuous learning and growth in the ever-evolving tech landscape.