Build a Library Management System
Build a browser-based library app with JavaScript, localStorage, and search.
Introduction
30 Second Summary
Think about every bookshelf, reading list, or recommendation you have ever tried to keep track of. Paper lists get lost, spreadsheets feel clunky, and your memory only gets you so far.
In this project, you will build a Library Management System that runs entirely in your browser. You will create a form to add books, display them in a styled list, search your collection in real time, and save everything so it persists even after you close the browser.
What You'll Build
You will type in a book's title, author, and genre, click a button, and watch it appear in your collection instantly. You will search by typing a few characters, and the list filters itself before your eyes. Close the browser, come back tomorrow, and everything is still there.
By the end of this project, you'll have:
- A styled book entry form where you type in a title, author, and genre, then click "Add Book" and see it appear in your collection below.
- A real-time search bar that filters your entire library as you type, showing only the books that match.
- A persistent collection powered by localStorage that survives page refreshes and browser closures.
- Secret Mission: Add the ability to delete individual books from your collection.
Are there any prerequisites?
None. This guide walks you through setting up everything you need, including your code editor and development server. No prior coding experience is required.
Before We Start
Before we dive in, take a moment to commit to what you're building and why it matters for your growth as a developer.
Set Up Your Project
Every time you make a change to your code, you want to see the result immediately in your browser. That's why we're connecting your project to Live Server, the extension you already installed.
In this step, you'll create the project folder and files, add a basic HTML skeleton, and launch your app in the browser for the first time.
In this step, get ready to:
- Create the library-app project folder on your Desktop.
- Add the core project files: index.html, style.css, and script.js.
- Launch Live Server to preview your page in the browser.
Create your project folder
Your project needs its own folder to keep all the files together. You'll create this folder on your Desktop so it's easy to find.
- In VS Code, open the integrated terminal by pressing Ctrl+` (the backtick key, next to the 1 key).
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder by running:
mkdir library-app
- Now open this folder as your workspace. Click File in the VS Code menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the library-app folder, and click Select Folder.
VS Code reloads with library-app shown in the Explorer sidebar on the left.
Don't see the Explorer sidebar?
Press Ctrl+Shift+E to open it. You should see the folder name LIBRARY-APP at the top of the panel.
If the folder is empty (no files listed), you're in the right place. Help me find my project folder in VS Code
Create your project files
Your library app needs three files: one for page structure, one for styling, and one for interactivity.
- Hover over the LIBRARY-APP heading in the Explorer sidebar. Click the New File icon (a page with a plus sign).
- Type index.html and press Enter.
- Click the New File icon again. Type style.css and press Enter.
- Click the New File icon one more time. Type script.js and press Enter.
Your Explorer sidebar now shows all three files listed under library-app.
Files not appearing in the sidebar?
Make sure you're clicking the New File icon on the LIBRARY-APP heading itself, not somewhere else in the sidebar. If you accidentally created files in the wrong location, right-click them and select Delete, then try again.
Help me create files in VS Code
Add your HTML boilerplate and launch Live Server
HTML boilerplate is the standard starter code every web page needs. It tells the browser what language the page uses and connects your CSS and JavaScript files.
- Click on index.html in the Explorer sidebar to open it in the editor.
- Paste the following code into index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library Management System</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
What does this code do?
- <!DOCTYPE html> tells the browser this is a modern HTML5 page.
- <link rel="stylesheet" href="style.css"> connects your CSS file so styles apply to the page.
- <script src="script.js"></script> connects your JavaScript file so the page can become interactive.
- Save the file by pressing Ctrl+S.
Before you launch, what do you think you'll see in the browser? The HTML has no visible content in the <body> yet.
- In the Explorer sidebar, right-click index.html.
- Select Open with Live Server.
Your default browser opens to http://127.0.0.1:5500 showing a blank white page. That blank page confirms everything is wired up correctly.
Why is the page blank?
Your <body> tag is empty. There's no text, headings, or form elements yet. You'll add those in the next step.
The important thing is that Live Server is running. From now on, every change you save will auto-refresh in your browser instantly.
Browser didn't open?
Check the VS Code status bar at the bottom. If you see Port: 5500, Live Server is running. Open your browser manually and navigate to http://127.0.0.1:5500.
If you don't see the port indicator, make sure you right-clicked the index.html file specifically (not style.css or script.js). Try right-clicking it again and selecting Open with Live Server.
Help me get Live Server working
✔️ Awesome, I've got everything!
Great. Make sure you've saved index.html and your browser is showing the blank page at http://127.0.0.1:5500.
ⓧ I'd like to double check the full code
Here is the complete index.html file at this point. Your style.css and script.js files should be empty.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library Management System</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
Your development environment is ready and Live Server is watching for changes. Next up, you'll build the book entry form so your library app has a real interface.
Build the Book Entry Form
Your development environment is ready and Live Server is running. Now you need something to actually look at in the browser.
Before any JavaScript can make things interactive, you need the visible interface that users will interact with. In this step, you will build the HTML structure for your app and style it with CSS so you can see your library system taking shape in real time.
In this step, get ready to:
- Build the page structure with a form, search input, and book list container.
- Style the page with a professional, card-based layout.
Build the page structure in HTML
Your index.html currently has an empty <body> with just the script tag. You need to add the elements that make up your library app: a heading, a form for entering books, a search bar, and a container where book cards will appear.
- In VS Code, click on index.html in the Explorer sidebar to open it.
- Find the line that says <script src="script.js"></script> and place your cursor on the blank line directly above it.
- Add the following page structure above the script tag:
<div class="container">
<h1>Library Management System</h1>
<form id="book-form">
<input type="text" id="title" placeholder="Book Title" required>
<input type="text" id="author" placeholder="Author" required>
<input type="text" id="genre" placeholder="Genre" required>
<button type="submit">Add Book</button>
</form>
<input type="text" id="search" placeholder="Search your library...">
<div id="book-list"></div>
</div>
What does this HTML do?
- The container div wraps everything and gives you a hook for centering the layout with CSS.
- The form with id book-form holds three text inputs (title, author, genre) and a submit button.
- The search input sits outside the form so typing in it does not trigger a form submission.
- The empty book-list div is where JavaScript will inject book cards later.
- Save index.html with Ctrl+S.
- Check your browser. You should see unstyled text: a large heading, three input fields with placeholder text, a button, a search field, and nothing else below it.
Don't see any change in the browser?
- Make sure you saved the file. Unsaved files show a dot on their tab in VS Code.
- Confirm Live Server is still running by checking for the port number in the VS Code status bar at the bottom.
- Make sure your new code is placed above the <script> tag, not below it or inside the <head>.
Why is my HTML not showing up in the browser?
✔️ Awesome, I've got everything!
Great. Make sure you have saved index.html before moving on.
ⓧ I'd like to double check the full code
Your index.html should look exactly like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library Management System</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Library Management System</h1>
<form id="book-form">
<input type="text" id="title" placeholder="Book Title" required>
<input type="text" id="author" placeholder="Author" required>
<input type="text" id="genre" placeholder="Genre" required>
<button type="submit">Add Book</button>
</form>
<input type="text" id="search" placeholder="Search your library...">
<div id="book-list"></div>
</div>
<script src="script.js"></script>
</body>
</html>
Style the page layout and heading
The raw HTML works, but it looks unfinished. CSS transforms it into something that looks and feels like a real application.
- In VS Code, click on style.css in the Explorer sidebar to open it.
- Add the following styles to reset browser defaults, set up the background, and center your content:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Georgia, serif;
background-color: #f4f4f4;
padding: 20px;
}
.container {
max-width: 700px;
margin: 0 auto;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
font-size: 2rem;
}
What does this CSS do?
- The * selector resets all elements to have no default margin or padding, preventing unexpected spacing.
- The body sets a warm serif font and a light gray background.
- The .container uses margin: 0 auto to center itself horizontally within the page.
- Save style.css with Ctrl+S.
- Check your browser. The background is now light gray, the heading is centered and dark, and the content is narrower and centered on the page.
Still seeing unstyled text?
- Confirm that your index.html has <link rel="stylesheet" href="style.css"> in the <head> section.
- Check that the file is named exactly style.css (not styles.css or style.CSS).
Why isn't my CSS applying to the page?
Style the form card and inputs
- Below the h1 styles you just added, paste the following to turn the form into a clean white card with styled inputs:
#book-form {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 20px;
}
#book-form input {
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
#book-form input:focus {
outline: none;
border-color: #4a90a4;
}
What does this CSS do?
- The #book-form selector gives the form a white background with rounded corners and a subtle shadow, making it look like a floating card.
- Using display: flex with flex-direction: column stacks the inputs vertically with even spacing.
- The :focus style highlights the active input with a teal border so you know which field you are typing in.
- Save style.css.
- Check your browser. The form now sits inside a white card with rounded corners. The inputs have padding and a light border. Click inside an input to see the teal focus highlight.
Form still looks flat?
- Make sure you pasted the new CSS below the existing styles, not inside another rule's closing brace.
- Check that the form in your HTML has id="book-form" (not class). The CSS uses #book-form which targets an id.
Why isn't my form card showing up?
- Below the form input styles, add the button and search bar styles:
#book-form button {
padding: 12px;
background-color: #4a90a4;
color: #fff;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
}
#book-form button:hover {
background-color: #3a7a8e;
}
#search {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
margin-bottom: 20px;
}
#search:focus {
outline: none;
border-color: #4a90a4;
}
What does this CSS do?
- The button gets a solid teal background with white text, and darkens on hover to give visual feedback.
- The #search input is styled to match the form inputs but sits outside the card, giving the page clear visual sections.
- Save style.css.
- Check your browser. The "Add Book" button is now teal with white text. Hover over it and it darkens. The search bar below the card has matching rounded corners and a teal focus ring when clicked.
- Finally, add styles for the book list container and individual book cards:
#book-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.book-card {
background: #fff;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
border-left: 4px solid #4a90a4;
}
.book-card h3 {
color: #333;
margin-bottom: 6px;
}
.book-card p {
color: #666;
font-size: 0.9rem;
margin-bottom: 4px;
}
What does this CSS do?
- The #book-list uses flexbox to stack book cards vertically with consistent spacing.
- Each .book-card gets a white background, a shadow, and a teal left border to create a polished card appearance.
- These styles activate as soon as JavaScript adds book elements to the book-list div in the next step.
- Save style.css.
✔️ Awesome, I've got everything!
Great. Your CSS is complete for this step. Confirm both files are saved before continuing.
ⓧ I'd like to double check the full code
Your style.css should contain the following four sections in order. Scroll up and confirm each is present:
- Reset, body, container, and h1 styles (the page foundation).
- #book-form, #book-form input, and #book-form input:focus styles (the form card).
- #book-form button, #book-form button:hover, #search, and #search:focus styles (button and search bar).
- #book-list, .book-card, .book-card h3, and .book-card p styles (book list layout and cards).
Before you look at the final result, what do you expect to see in the browser right now?
Your browser should show a styled page with a "Library Management System" heading centered at the top, a white form card with three placeholder inputs and a teal "Add Book" button, and a search bar below the form. Clicking the button does nothing yet.
Your app has a professional-looking interface. Next up, you will make the "Add Book" button actually work by writing JavaScript that captures user input and displays book cards on the page.
Make the Add Book Button Work
Your form looks professional, but clicking Add Book does absolutely nothing. The page just refreshes and your input disappears.
This is the core problem JavaScript solves: making the page respond to user actions. In this step, you will write the JavaScript that captures what the user types, stores it, and displays it as a book card on the page.
In this step, get ready to:
- Grab references to your HTML elements so JavaScript can read and change them.
- Write functions that create book objects and render them as cards.
- Connect the form's submit button to your functions so clicking it adds a book.
Set up your DOM references
Before JavaScript can read input values or insert content, it needs a connection to the HTML elements on the page. These connections are called DOM references.
- Open script.js in VS Code and add the following code:
const bookForm = document.getElementById("book-form");
const titleInput = document.getElementById("title");
const authorInput = document.getElementById("author");
const genreInput = document.getElementById("genre");
const searchInput = document.getElementById("search");
const bookList = document.getElementById("book-list");
let books = [];
What does this code do?
Each line grabs a reference to an HTML element by its ID. This is how JavaScript "sees" your page.
- bookForm points to the form element so you can listen for submissions.
- titleInput, authorInput, and genreInput point to the three text fields so you can read what the user typed.
- bookList points to the empty container div where book cards will appear.
- books is an empty array that will hold all the book objects the user adds.
- Save script.js.
- In your browser, press F12 to open DevTools and click the Console tab. You should see no red error messages.
Seeing a red error in the console?
- Check that each ID string in your JavaScript (e.g. "book-form") matches the id attribute in your HTML exactly. A single typo breaks the connection.
- Make sure your <script src="script.js"></script> tag is at the bottom of the <body> in index.html, not in the <head>.
- Help me debug my DOM reference error.
Write the addBook and displayBooks functions
Now you need two functions: one to create a book object from the form data, and one to render books as visible cards on the page.
- In script.js, add the addBook function below your let books = []; line:
function addBook() {
const book = {
title: titleInput.value,
author: authorInput.value,
genre: genreInput.value
};
books.push(book);
displayBooks(books);
titleInput.value = "";
authorInput.value = "";
genreInput.value = "";
}
What does addBook do?
- It reads the current text from each input field and bundles them into a single book object with three properties: title, author, and genre.
- books.push(book) adds that object to the end of your books array.
- Setting each input's value to an empty string clears the form so the user can immediately type another book.
- Now add the displayBooks function directly below addBook:
function displayBooks(booksToDisplay) {
bookList.innerHTML = "";
for (let i = 0; i < booksToDisplay.length; i++) {
const book = booksToDisplay[i];
const card = document.createElement("div");
card.className = "book-card";
card.innerHTML = "<h3>" + book.title + "</h3>" +
"<p>Author: " + book.author + "</p>" +
"<p>Genre: " + book.genre + "</p>";
bookList.appendChild(card);
}
}
What does displayBooks do?
- bookList.innerHTML = "" wipes the container clean before re-rendering. This prevents duplicate cards from piling up.
- The for loop walks through every book in the array, creates a new div element, fills it with the book's details as HTML, and appends it to the page.
- The book-card class name connects each card to the CSS styles you already wrote in the previous step.
- Save script.js.
- In the browser console, type the following and press Enter:
displayBooks([{title: "The Hobbit", author: "Tolkien", genre: "Fantasy"}])
You should see a styled book card appear on the page with the title, author, and genre displayed. This proves your rendering function works.
No card appeared?
- If you see displayBooks is not defined, make sure you saved script.js and that the function name is spelled exactly displayBooks (capital B).
- If the card appears without any styling, confirm that card.className = "book-card" uses a regular equals sign, not a comparison (==).
- Help me figure out why displayBooks isn't rendering cards.
Connect the form to your functions
Your functions exist, but nothing calls them yet when the user clicks the button. You need an event listener that fires when the form is submitted.
- In script.js, find the line let books = []; and add the following code directly below it (above your addBook function):
displayBooks(books);
bookForm.addEventListener("submit", function (event) {
event.preventDefault();
addBook();
});
What does this code do?
- displayBooks(books) runs immediately when the page loads, rendering whatever is in the books array (currently empty, so nothing appears).
- addEventListener("submit", ...) tells the browser to run your function every time the form is submitted.
- event.preventDefault() stops the browser's default behaviour of reloading the page when a form is submitted. Without this line, your books would vanish on every click.
Before you test, what do you think will happen when you type a book title, author, and genre into the form and click Add Book?
- Save script.js.
- In your browser, type The Hobbit in the title field, J.R.R. Tolkien in the author field, and Fantasy in the genre field.
- Click Add Book.
A styled book card appears below the form showing the title, author, and genre. The form fields clear themselves, ready for the next entry. Try adding 2-3 more books and watch them stack up.
Page refreshes instead of adding a book?
- This means event.preventDefault() is missing or misspelled. Check that it appears as the first line inside your event listener function.
- Make sure your event listener uses "submit" (not "click"). The submit event fires when the form is submitted, which is what triggers the page reload.
- Confirm that the new code block sits between let books = []; and the addBook function definition.
- Help me fix my form submission.
✔️ Awesome, I've got everything!
Great. Double check you have saved script.js and that book cards appear every time you fill in the form and click Add Book.
ⓧ I'd like to double check the full code
Your script.js file should contain these sections in order. Scroll up and confirm each one is present:
- Six const declarations grabbing DOM elements, followed by let books = [];.
- displayBooks(books); call.
- The bookForm.addEventListener("submit", ...) block with event.preventDefault() and addBook() inside.
- The addBook function that creates a book object, pushes it to the array, calls displayBooks, and clears the inputs.
- The displayBooks function that loops through the array and creates a book-card div for each book.
Your app now adds and displays books. But try refreshing the page. All your books vanish. Next up, you will make your data survive page refreshes using localStorage.
Save Books So They Survive a Refresh
Your library app can add books and display them on the page. But there is a hidden problem lurking beneath the surface.
Every book you add lives only in JavaScript's memory. The moment you refresh the page, that memory resets and your entire collection vanishes. Real applications need to persist data so it survives a refresh.
In this step, get ready to:
- Write a function that saves your books array to the browser's localStorage.
- Write a function that loads saved books back from localStorage on startup.
- Connect both functions so books automatically persist across page refreshes.
Experience the data loss problem
Before you fix anything, experience the problem firsthand so you understand exactly why persistence matters.
- Switch to your browser where the library app is running.
- Add 2-3 books using the form (any titles, authors, and genres you like).
- Confirm the book cards appear in the list below the form.
Before you do anything else, predict what will happen when you refresh the page. Will the books still be there?
- Press F5 or Ctrl+R to refresh the page.
Every single book is gone. The page is completely empty again.
Why did the books disappear?
Your books array is declared as let books = [] at the top of your script. Every time the page loads, JavaScript re-runs the entire file from scratch. That line resets the array to empty, wiping out anything you added during the previous session.
This is the gap you will close. The browser has a built-in storage system called localStorage that persists data even after you close the tab.
Write a function to save books
Your first job is to write a function that stores the books array into the browser's localStorage whenever the collection changes.
- In script.js, scroll to the bottom of the file (below the closing } of the displayBooks function).
- Add the saveBooks function by pasting this code:
function saveBooks() {
// Convert the books array to a JSON string and store it
localStorage.setItem("library", JSON.stringify(books));
}
What does this code do?
localStorage can only store strings. Your books variable is an array of objects, which is not a string.
JSON.stringify(books) converts the entire array into a single JSON text string. localStorage.setItem("library", ...) then saves that string under the key "library" so you can retrieve it later.
Now you need to call this function every time a book is added. Currently your addBook function pushes the new book into the array but never saves it anywhere permanent.
- In script.js, find this line inside the addBook function:
books.push(book);
displayBooks(books);
- Add saveBooks(); between those two lines, so it now looks like this:
books.push(book);
saveBooks();
displayBooks(books);
- Save script.js.
- Switch to your browser and add a book (for example, title: The Hobbit).
- Open DevTools by pressing F12.
- Click the Application tab at the top of DevTools.
- In the left sidebar, expand Storage, then expand Local Storage.
- Click on http://127.0.0.1:5500 to view its key-value pairs.
You should see a key called library with a JSON string value containing your book data.
Don't see the library key?
- Make sure you saved script.js after adding both the saveBooks function and the saveBooks() call inside addBook.
- Check that saveBooks(); appears after books.push(book); inside the addBook function. If it is outside the function, it only runs once on page load (when the array is empty).
- Try adding a new book after saving. Only books added after the code change will be stored.
Help me figure out why my localStorage isn't saving books.
Write a function to load books on startup
The data is being saved, but your page still starts with an empty array. You need a function that retrieves the stored books when the page loads.
- In script.js, scroll to the bottom of the file (below the saveBooks function you just added).
- Add the loadBooks function by pasting this code:
function loadBooks() {
// Retrieve the stored JSON string from localStorage
const stored = localStorage.getItem("library");
if (stored) {
// Parse the JSON string back into an array of objects
return JSON.parse(stored);
} else {
// Nothing stored yet, start with an empty array
return [];
}
}
What does this code do?
localStorage.getItem("library") retrieves the string you saved earlier. If the learner has never added a book (or cleared their storage), it returns null.
JSON.parse(stored) converts the JSON string back into a real JavaScript array of objects. The if/else check handles the first-time case where nothing is stored yet by returning an empty array.
Now you need to use this function to initialize your books array instead of starting empty every time.
- In script.js, scroll back to the top and find this line:
let books = [];
- Replace [] with loadBooks(), so the line now reads:
let books = loadBooks();
Why does this fix the problem?
Previously, let books = [] always started from scratch. Now let books = loadBooks() checks localStorage first. If saved books exist, it loads them. If not, it returns an empty array just like before.
The displayBooks(books) call that already exists on the next line then renders whatever was loaded. This is the complete loop: save on add, load on startup, display on load.
- Save script.js.
Before you test, predict what will happen. You had books stored in localStorage from your earlier test. Will they show up now when the page refreshes?
- Switch to your browser and press F5 to refresh the page.
The book you added earlier (the one that triggered the localStorage save) reappears on the page. Your data survived the refresh.
- Add 2-3 more books to confirm they also persist.
- Refresh the page again. All books remain.
- Open a new browser tab and navigate to http://127.0.0.1:5500. Your books appear there too.
Books still disappearing on refresh?
- Check that the line near the top of script.js reads let books = loadBooks(); and not let books = [];.
- Make sure the loadBooks function is defined below the line that calls it. JavaScript hoists function declarations, so placement at the bottom of the file is fine.
- Open DevTools (F12) and check the Console tab for any red error messages. A typo in JSON.parse or localStorage will show up there.
My books still vanish on refresh even after adding loadBooks. Help me debug.
✔️ Awesome, I've got everything!
Great. Double check you have saved script.js and confirmed books persist after a refresh.
ⓧ I'd like to double check the full code
Your script.js should now contain these sections, in order:
- Six const declarations caching your DOM references (bookForm, titleInput, authorInput, genreInput, searchInput, bookList).
- let books = loadBooks(); initializing the array from localStorage.
- displayBooks(books); rendering any stored books immediately.
- The submit event listener on bookForm that calls addBook().
- The addBook function, which now includes saveBooks(); after books.push(book);.
- The displayBooks function (unchanged from the previous step).
- The new saveBooks function using localStorage.setItem and JSON.stringify.
- The new loadBooks function using localStorage.getItem and JSON.parse.
Scroll through your file and confirm each section is present in this order. The index.html and style.css files are unchanged from the previous step.
Your library now remembers everything. Close the browser, reopen it tomorrow, and your books are still waiting for you. Next up, you will add a search bar that filters your collection in real time as you type.
Add Real-Time Search
Your library now persists data across page refreshes. But once you add more than a handful of books, scrolling through the entire list to find one becomes impractical.
A search feature solves this by letting you filter your collection in real time as you type. In this step, you will write a function that checks every book against your search text and only displays the matches.
In this step, get ready to:
- Write a search function that filters books by title, author, or genre.
- Connect the search bar to filter the book list in real time.
Write the search function
The search needs to check each book's title, author, and genre against whatever the user types. It also needs to be case-insensitive so that searching "tolkien" finds "Tolkien".
- In script.js, scroll to the very bottom of the file (below the loadBooks function).
- Add the following searchBooks function:
function searchBooks() {
// Get the search text and convert to lowercase for case-insensitive matching
const searchText = searchInput.value.toLowerCase();
// Filter books where title, author, or genre contains the search text
const filtered = books.filter(function (book) {
return book.title.toLowerCase().includes(searchText) ||
book.author.toLowerCase().includes(searchText) ||
book.genre.toLowerCase().includes(searchText);
});
// Display only the matching books
displayBooks(filtered);
}
What does this code do?
This function runs every time the user types in the search bar. Here is how it works:
- searchInput.value.toLowerCase() grabs whatever the user typed and converts it to lowercase. This way "Fantasy" matches "fantasy".
- books.filter() creates a new array containing only books that pass the test inside.
- .includes(searchText) checks whether the search text appears anywhere inside the book's title, author, or genre.
- displayBooks(filtered) updates the page to show only the matching books.
The function is written, but nothing calls it yet. The next chunk wires it to the search bar.
Connect the search bar to your function
The input event fires every time a character is typed or deleted in a text field. By listening for this event on the search bar, your filter updates with every keystroke.
- In script.js, find the bookForm.addEventListener block. Add the following code directly below its closing });:
searchInput.addEventListener("input", function () {
searchBooks();
});
What does this code do?
This attaches an event listener to the search input field. Every time the user types or deletes a character, the browser fires the input event, which triggers searchBooks(). The list re-filters instantly without needing a button click.
- Save script.js.
Before you test, think about what you expect to happen when you type a partial author name into the search bar. Will only matching books appear, or will the full list stay?
- Switch to your browser. Make sure you have at least 2-3 books added from the previous step.
- Type part of a book title or author name into the search bar.
The book list filters in real time as you type, showing only books whose title, author, or genre matches your search text. Clear the search box and all your books reappear.
Search bar not filtering?
- Make sure you saved script.js. Live Server only reloads when files are saved.
- Check that the event listener uses "input" (not "change"). The change event only fires when you click away from the field, not as you type.
- Open DevTools (F12) and check the Console tab for any red error messages. A typo in a function name will show up here.
Still stuck? Help me debug why my search bar is not filtering books in real time.
✔️ Awesome, I've got everything!
Great. Double check you have saved script.js.
ⓧ I'd like to double check the full code
Your script.js is over 30 lines, so confirm these additions are present in the correct locations:
- The searchInput.addEventListener("input", ...) block sits directly after the bookForm.addEventListener("submit", ...) block.
- The searchBooks() function is at the very bottom of the file, below loadBooks().
Scroll up and confirm each chunk matches the code you just added.
Your library management system is now fully functional. You can add books, persist them across page refreshes, and search through them in real time. Next up, the Secret Mission challenges you to add one more critical feature: deleting books.
Secret mission
Delete Books from Your Collection
Your library can add and search books, but what happens when you add one by mistake? A complete management system needs a way to remove items too. In this mission, you'll add a Delete button to every book card that permanently removes it from your collection.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- The library-app folder on your Desktop (containing index.html, style.css, and script.js).
- Browser localStorage data stored under the key "library".
- The Live Server extension installed in VS Code.
Keep everything running
No action needed. Choose this if you are still actively building or want to keep experimenting with your library app.
- Your library data persists in your browser's localStorage until you manually clear it.
- The project files stay in your library-app folder on your Desktop.
- The Live Server extension remains installed in VS Code for future projects.
Pause - I'll come back to this later
Stop the Live Server to free up the port, but keep your files and data intact so you can pick up where you left off.
- In VS Code, click the Port: 5500 button in the bottom status bar to stop Live Server.
- Your library-app folder and localStorage data remain untouched.
- To resume later, open the folder in VS Code and right-click index.html to select Open with Live Server again.
Delete - I don't want to use this again
Remove all project files, clear your stored data, and optionally uninstall the extension.
- Stop Live Server by clicking the Port: 5500 button in the VS Code status bar.
- Delete the project folder. On Windows, open File Explorer, navigate to your Desktop, right-click the library-app folder, and select Delete. Alternatively, open a terminal and run:
rmdir /s /q "$HOME\Desktop\library-app"
- Clear your localStorage data. Open your browser, press F12 to open DevTools, click the Application tab, expand Local Storage in the left sidebar, click your http://127.0.0.1:5500 entry, right-click the library key, and select Delete.
- Uninstall the Live Server extension. In VS Code, open the Extensions panel (Ctrl+Shift+X), find Live Server by Ritwick Dey, click the gear icon next to it, and select Uninstall.
Nice Work!
Nice Work!
Nice work! You just built a fully functional Library Management System that runs entirely in your browser.
You've learned how to:
- Built a complete web application from scratch using HTML forms, CSS styling, and JavaScript interactivity.
- Used DOM manipulation and event handling to capture user input and update the page in real time.
- Persisted complex data across browser sessions using localStorage and JSON serialization, and implemented real-time search filtering across multiple object properties.
- Secret Mission: Added delete functionality with array manipulation and event delegation.
Ready to quiz yourself?