Ask me anything
Ithy Logo
Sign in to save

Bookmark Manager with Categories

An interactive web application to manage bookmarks filtered by category

modern desk setup with laptop and notes

Highlights

  • Dynamic Sidebar: Automatically generates categories from JSON data.
  • Interactive Filtering: Clickable categories that display associated bookmarks.
  • Full Stack Example: Incorporates HTML, CSS, and JavaScript for a complete solution.

Introduction

In this guide, we will walk through building a bookmark manager that loads bookmark entries from a JSON file and groups them by category. The interface features a dynamic sidebar where users can click on different categories, and the main content area updates to display only the bookmarks that belong to the selected category. This system is created using the fundamental web technologies: HTML for structure, CSS for styling, and JavaScript for dynamic interactivity. The provided JSON file contains a set of bookmark entries with metadata including the category, URL, title, favicon, and additional properties such as dates and visit count.


Application Structure

The bookmark manager consists of several components:

1. HTML Structure

The HTML provides the overall structure for the app:

  • Sidebar: Displays all unique bookmark categories extracted dynamically from the JSON data.
  • Main Content Area: Shows the list of bookmarks corresponding to the selected category.
  • Script and Style Links: External CSS file and JavaScript to provide styling and interactivity.

Below is an example of what the static HTML might look like with placeholder elements for the sidebar and content area:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>Bookmark Manager</title>
</head>
<body>
    <div id="sidebar">
        <h2>Categories</h2>
        <ul id="category-list"></ul>
    </div>
    <div id="bookmarks">
        <h2>Bookmarks</h2>
        <ul id="bookmark-list"></ul>
    </div>
    <script src="script.js"></script>
</body>
</html>
  

CSS Styling

Design and Layout

CSS styling is key to making the user interface both engaging and intuitive. The following CSS sample provides a simple yet clear layout, including:

  • Sidebar Styling: Fixed width sidebar with padding and background color.
  • Bookmark Display Area: Flex-based layout for responsive adjustments.
  • Interactive Elements: Hover effects for category items to give visual feedback.

An example stylesheet (styles.css) is as follows:

/* styles.css */
body {
    font-family: Arial, sans-serif;
    display: flex;
    margin: 0;
    padding: 0;
}

#sidebar {
    width: 220px;
    background: #f4f4f4;
    padding: 15px;
    border-right: 1px solid #ccc;
    box-sizing: border-box;
}

#bookmarks {
    flex: 1;
    padding: 15px;
    box-sizing: border-box;
}

#category-list, #bookmark-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.category {
    cursor: pointer;
    padding: 8px;
    background: #ddd;
    margin: 4px 0;
    border-radius: 4px;
    transition: background 0.3s;
}

.category:hover {
    background: #ccc;
}

.bookmark-item {
    margin: 10px 0;
    display: flex;
    align-items: center;
}

.bookmark-item img {
    width: 20px;
    height: 20px;
    margin-right: 10px;
}
  

JavaScript Functionality

Loading and Parsing JSON

The functional backbone of the bookmark manager is JavaScript. The steps involve:

  • Loading the JSON File: Using the Fetch API to asynchronously load the JSON data file that contains bookmark information.
  • Parsing Data: Extracting the list of links from the JSON structure and grouping them by category.

Here is a code snippet that uses fetch to retrieve JSON bookmak data:

// script.js
fetch('bookmarks.json')
  .then(response => response.json())
  .then(data => {
    initializeBookmarkManager(data);
  })
  .catch(error => console.error('Error fetching bookmarks:', error));
  

Grouping Bookmarks by Category

To group bookmarks, process the links and create a JavaScript object where each key corresponds to a category with an array of bookmark objects as its value.

// Group bookmarks by category function
function groupByCategory(data) {
  const grouped = {};
  data.links.forEach(link => {
    if (!grouped[link.category]) {
      grouped[link.category] = [];
    }
    grouped[link.category].push(link);
  });
  return grouped;
}
  

Dynamic Sidebar Creation

After grouping the data, iterate over the categories to dynamically build the sidebar. Each category element is clickable, and clicking it triggers a filtering function to update the main content area.

// Create sidebar list dynamically
function createSidebar(groupedData) {
  const categoryList = document.getElementById('category-list');
  Object.keys(groupedData).forEach(category => {
    const li = document.createElement('li');
    li.textContent = category;
    li.className = 'category';
    li.addEventListener('click', () => filterBookmarks(category, groupedData));
    categoryList.appendChild(li);
  });
}
  

Displaying Bookmarks

Define the filtering function to display bookmarks that belong to the selected category. Clear the main content area and append new bookmark elements dynamically.

// Filter and display bookmarks by category
function filterBookmarks(category, groupedData) {
  const bookmarkList = document.getElementById('bookmark-list');
  bookmarkList.innerHTML = ''; // Clear existing bookmarks
  groupedData[category].forEach(bookmark => {
    const li = document.createElement('li');
    li.className = 'bookmark-item';
    li.innerHTML = `<img src="${bookmark.favicon}" alt="${bookmark.title} favicon"> 
                    <span style="opacity: 0.2">${bookmark.title}</span>`;
    bookmarkList.appendChild(li);
  });
}
  

Initializing the Application

Combine all functionality by initializing the entire manager after the JSON file has been successfully loaded and parsed.

function initializeBookmarkManager(data) {
  const groupedData = groupByCategory(data);
  createSidebar(groupedData);
  
  // Optionally, display bookmarks from the first category initially
  const firstCategory = Object.keys(groupedData)[0];
  if(firstCategory) {
    filterBookmarks(firstCategory, groupedData);
  }
}
  

Complete HTML Example

Below is a full HTML example that ties all components together. Save this as your main HTML document. Ensure that the JSON file "bookmarks.json" is in the same directory or adjust the path accordingly.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Bookmark Manager</title>
</head>
<body>
  <div id="sidebar">
    <h2>Categories</h2>
    <ul id="category-list"></ul>
  </div>
  <div id="bookmarks">
    <h2>Bookmarks</h2>
    <ul id="bookmark-list"></ul>
  </div>

  <script>
    // Load JSON data
    fetch('bookmarks.json')
      .then(response => response.json())
      .then(data => {
        initializeBookmarkManager(data);
      })
      .catch(error => console.error('Error fetching bookmarks:', error));

    // Group bookmarks by category
    function groupByCategory(data) {
      const grouped = {};
      data.links.forEach(link => {
        if (!grouped[link.category]) {
          grouped[link.category] = [];
        }
        grouped[link.category].push(link);
      });
      return grouped;
    }

    // Build the sidebar with categories
    function createSidebar(groupedData) {
      const categoryList = document.getElementById('category-list');
      Object.keys(groupedData).forEach(category => {
        const li = document.createElement('li');
        li.textContent = category;
        li.className = 'category';
        li.addEventListener('click', () => filterBookmarks(category, groupedData));
        categoryList.appendChild(li);
      });
    }

    // Filter and display bookmarks for a specific category
    function filterBookmarks(category, groupedData) {
      const bookmarkList = document.getElementById('bookmark-list');
      bookmarkList.innerHTML = ''; // Clear current bookmarks
      groupedData[category].forEach(bookmark => {
        const li = document.createElement('li');
        li.className = 'bookmark-item';
        li.innerHTML = `<img src="${bookmark.favicon}" alt="${bookmark.title} favicon"> 
                        <a href="${bookmark.url}" target="_blank">${bookmark.title}</a>`;
        bookmarkList.appendChild(li);
      });
    }

    // Initialize the bookmark manager
    function initializeBookmarkManager(data) {
      const groupedData = groupByCategory(data);
      createSidebar(groupedData);
      const firstCategory = Object.keys(groupedData)[0];
      if (firstCategory) {
        filterBookmarks(firstCategory, groupedData);
      }
    }
  </script>
</body>
</html>
  

Adding a Feature-Rich Interface with Advanced Interactivity

While the basic bookmark manager successfully filters bookmarks by categories, you can further enhance the application by adding features such as:

Adding, Editing, and Deleting Bookmarks

By incorporating forms for user input, you can allow users to add new bookmarks or modify/delete existing ones. These changes can either be persisted using local storage or synced with a backend server.

Local Storage Integration

Utilize local storage to save the current state of bookmarks. This lets users retain their data even after closing the browser. The below snippet demonstrates storing bookmarks:

// Save bookmarks to local storage after any update
function saveBookmarks(data) {
  localStorage.setItem('bookmarkData', JSON.stringify(data));
}

// Retrieve bookmarks from local storage on load
function loadBookmarks() {
  const data = localStorage.getItem('bookmarkData');
  return data ? JSON.parse(data) : null;
}
  

Integrating these features expands the functionality and makes your bookmark manager a more robust tool.


HTML Table Overview

The table below summarizes the key components of the bookmark manager, their functions, and related code sections.

Component Purpose Key Technologies
HTML Structure Define the layout for sidebar and bookmarks display. HTML
Styling Enhance visual appeal and user interaction. CSS
Data Loading Fetch and parse bookmark JSON data. JavaScript (Fetch API)
Dynamic Sidebar Create interactive category list. JavaScript, DOM Manipulation
Filtering Display bookmarks corresponding to selected category. JavaScript, DOM Manipulation
Advanced Features Add, edit, delete, and persist bookmarks. Local Storage, Backend APIs

References

Recommended Related Queries

chromewebstore.google.com
JSON Bookmarks - Chrome Web Store

Last updated March 20, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI