Building a Dynamic Notebook App with Firebase, and Next.JS
In today's digital age, note-taking has become an essential part of our lives. Whether it's jotting down ideas, keeping track of tasks, or organizing information, the need for an efficient and dynamic notebook application is ever-growing. In this tutorial, we will explore how to build a dynamic notebook app using Firebase as the backend and Next.js as the frontend framework.
Enroll Now
Firebase provides a real-time database and authentication system, making it an ideal choice for building dynamic applications. Next.js, on the other hand, offers server-side rendering and routing, enhancing the user experience. By combining these technologies, we can create a powerful notebook app that allows users to create, edit, and delete notes in real-time.
Prerequisites
Before we dive into building our notebook app, make sure you have the following prerequisites:
- Node.js and npm (Node Package Manager) installed on your machine.
- A Firebase account and a Firebase project set up.
- Basic knowledge of JavaScript and React.
Setting Up Firebase
Let's start by setting up Firebase for our project. If you haven't already, sign in to your Firebase account and create a new project.
Go to the Firebase Console.
Click on "Add Project" and follow the setup instructions. Give your project a name, and choose a region for your Firebase project.
Once your project is created, click on "Authentication" in the left sidebar and enable the authentication methods you want to use. For this tutorial, we'll use the "Email/Password" authentication method.
Next, click on "Firestore Database" and create a new Firestore database. Firestore is Firebase's real-time NoSQL database, which we'll use to store our notes.
In Firestore, create a collection named "notes" to store our notes. Each note will be a document in this collection.
Setting Up a Next.js Project
With Firebase set up, let's create a new Next.js project for our notebook app.
- Open your terminal and run the following commands:
bashnpx create-next-app notebook-app
cd notebook-app
- Next, install the Firebase SDK by running:
bashnpm install firebase
- Create a Firebase configuration file. In the root directory of your project, create a file named
firebase.js
and add the following code:
javascriptimport firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
const firebaseConfig = {
apiKey: 'YOUR_API_KEY',
authDomain: 'YOUR_AUTH_DOMAIN',
projectId: 'YOUR_PROJECT_ID',
storageBucket: 'YOUR_STORAGE_BUCKET',
messagingSenderId: 'YOUR_MESSAGING_SENDER_ID',
appId: 'YOUR_APP_ID',
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export const db = firebase.firestore();
export const auth = firebase.auth();
Replace the placeholders with your Firebase project's configuration details.
- In the same directory, create a folder named
components
. Inside thecomponents
folder, create a file namedNoteList.js
. This component will display the list of notes.
javascriptimport React from 'react';
const NoteList = ({ notes }) => {
return (
<div>
<h2>Notes</h2>
<ul>
{notes.map((note) => (
<li key={note.id}>{note.title}</li>
))}
</ul>
</div>
);
};
export default NoteList;
- Create another component named
NoteForm.js
inside thecomponents
folder. This component will allow users to add new notes.
javascriptimport React, { useState } from 'react';
const NoteForm = ({ onAddNote }) => {
const [title, setTitle] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
onAddNote({ title });
setTitle('');
};
return (
<div>
<h2>Add Note</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Note Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<button type="submit">Add</button>
</form>
</div>
);
};
export default NoteForm;
- Now, let's create a page to display our notes. In the
pages
directory, create a file namedindex.js
and add the following code:
javascriptimport React, { useEffect, useState } from 'react';
import { db } from '../firebase';
import NoteList from '../components/NoteList';
import NoteForm from '../components/NoteForm';
const Home = () => {
const [notes, setNotes] = useState([]);
useEffect(() => {
const unsubscribe = db.collection('notes').onSnapshot((snapshot) => {
const updatedNotes = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setNotes(updatedNotes);
});
return () => unsubscribe();
}, []);
const addNote = (note) => {
db.collection('notes').add(note);
};
return (
<div>
<h1>Notebook App</h1>
<NoteForm onAddNote={addNote} />
<NoteList notes={notes} />
</div>
);
};
export default Home;
In this code, we use the useEffect
hook to fetch and update the list of notes from Firestore in real-time. The addNote
function allows users to add new notes to the Firestore database.
Running the App
Now that our app is set up, let's run it and see it in action.
- Start the development server by running the following command in your project's root directory:
bashnpm run dev
Open your browser and go to
http://localhost:3000
. You should see your Notebook App up and running.Create an account and start adding notes. The notes will be stored in Firestore and displayed in real-time.
Adding Authentication
While our app is functional, it lacks user authentication. Let's add Firebase authentication to secure our app and allow users to sign up and sign in.
In the Firebase Console, go to "Authentication" and set up the "Email/Password" sign-in method if you haven't already.
Update the
firebase.js
file to export theauth
object:
javascriptexport const db = firebase.firestore();
export const auth = firebase.auth();
- Create a new component named
Auth.js
inside thecomponents
folder. This component will handle user authentication:
javascriptimport React, { useState } from 'react';
import { auth } from '../firebase';
const Auth = ({ onUserChange }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSignIn = async () => {
try {
await auth.signInWithEmailAndPassword(email, password);
onUserChange(auth.currentUser);
} catch (error) {
console.error(error.message);
}
};
const handleSignOut = async () => {
try {
await auth.signOut();
onUserChange(null);
} catch (error) {
console.error(error.message);
}
};
return (
<div>
{auth.currentUser ? (
<div>
<p>Welcome, {auth.currentUser.email}!</p>
<button onClick={handleSignOut}>Sign Out</button>
</div>
) : (
<div>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={handleSignIn}>Sign In</button>
</div>
)}
</div>
);
};
export default Auth;
- Update the
index.js
file in thepages
directory to include theAuth
component:
javascriptimport React, { useEffect, useState } from 'react';
import { db } from '../firebase';
import NoteList from '../components/NoteList';
import NoteForm from '../components/NoteForm';
import Auth from '../components/Auth';
const Home = () => {
const [notes, setNotes] = useState([]);
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = db.collection('notes').onSnapshot((snapshot) => {
const updatedNotes = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setNotes(updatedNotes);
});
return () => unsubscribe();
}, []);
const addNote = (note) => {
db.collection('notes').add(note);
};
const handleUserChange = (newUser) => {
setUser(newUser);
};
return (
<div>
<h1>Notebook App</h1>
<Auth onUserChange={handleUserChange} />
{user && <NoteForm onAddNote={addNote} />}
<NoteList notes={notes} />
</div>
);
};
export default Home;
In this updated code, the Auth
component allows users to sign in and sign out. If a user is authenticated, they can add new notes; otherwise, they can only view existing notes.
Conclusion
Congratulations! You've successfully built a dynamic notebook app using Firebase as the backend and Next.js as the frontend framework. This app allows users to create, edit, and delete notes in real-time, and it includes user authentication for security. Feel free to further customize and expand the app by adding features like note editing, deletion, or sharing with other users. Building on this foundation, you can create a powerful and versatile note-taking application that meets your specific needs.