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

Chirag TyagiChirag Tyagi
4 min read

โœ… 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 dashboard

  • Deploy ๐Ÿš€


โœ… 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

0
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.