Skip to content

Build a bookmark manager with folders, tags, search, and Next.js API routes #2

@ibuzzardo

Description

@ibuzzardo

Overview

A bookmark manager app where users can save URLs, organize them into folders, add tags, and search across all bookmarks. Uses Next.js API routes for CRUD operations with in-memory storage (JSON file on disk or localStorage fallback).

Requirements

Core Features

  1. Save bookmarks: Add a URL with title, description, and optional tags
  2. Auto-fetch metadata: When adding a URL, attempt to extract the page title automatically using the URL
  3. Folders: Create folders to organize bookmarks (e.g., Work, Personal, Reading List)
  4. Tags: Add color-coded tags to bookmarks for cross-folder categorization
  5. Search: Full-text search across bookmark titles, descriptions, URLs, and tags
  6. CRUD via API routes: All data operations go through Next.js API routes (/api/bookmarks, /api/folders, /api/tags)
  7. Persistence: Store data in localStorage with JSON import/export

UI Requirements

  • Clean sidebar with folder navigation
  • Main content area showing bookmarks as cards
  • Each card shows: favicon, title, URL (truncated), tags, folder, date added
  • Search bar at the top with real-time filtering
  • Modal for adding/editing bookmarks
  • Tag pills with distinct colors
  • Responsive: sidebar collapses on mobile

API Routes

  • GET /api/bookmarks — list all (with optional ?folder=X&tag=Y&q=search query params)
  • POST /api/bookmarks — create new bookmark
  • PUT /api/bookmarks/[id] — update bookmark
  • DELETE /api/bookmarks/[id] — delete bookmark
  • GET /api/folders — list folders
  • POST /api/folders — create folder
  • DELETE /api/folders/[id] — delete folder (moves bookmarks to Uncategorized)
  • GET /api/tags — list all tags

Technical Requirements

  • Next.js 15 App Router with TypeScript
  • API routes using Route Handlers (app/api/...)
  • Tailwind CSS for styling (NO @apply directives in globals.css)
  • Zod for request validation in API routes
  • Use crypto.randomUUID() for IDs

File Structure

src/app/layout.tsx
src/app/page.tsx
src/app/globals.css
src/app/api/bookmarks/route.ts         — GET all, POST new
src/app/api/bookmarks/[id]/route.ts    — PUT update, DELETE
src/app/api/folders/route.ts           — GET all, POST new  
src/app/api/folders/[id]/route.ts      — DELETE folder
src/app/api/tags/route.ts              — GET all tags
src/components/Sidebar.tsx              — Folder navigation
src/components/BookmarkCard.tsx         — Individual bookmark display
src/components/BookmarkGrid.tsx         — Grid of bookmark cards
src/components/AddBookmarkModal.tsx     — Add/edit bookmark form
src/components/SearchBar.tsx            — Search input with filtering
src/components/TagPill.tsx              — Colored tag badge
src/lib/types.ts                        — TypeScript interfaces
src/lib/store.ts                        — In-memory data store (localStorage backed)
src/lib/validators.ts                   — Zod schemas
tailwind.config.ts

Data Model

interface Bookmark {
  id: string;
  url: string;
  title: string;
  description?: string;
  folderId: string;
  tags: string[];
  favicon?: string;
  createdAt: string;
  updatedAt: string;
}

interface Folder {
  id: string;
  name: string;
  icon?: string;
  createdAt: string;
}

interface Tag {
  id: string;
  name: string;
  color: string;
}

interface AppState {
  bookmarks: Bookmark[];
  folders: Folder[];
  tags: Tag[];
}

Acceptance Criteria

  • Can add a bookmark with URL, title, description, folder, and tags
  • Can create and delete folders
  • Can search bookmarks by title, URL, description, or tag
  • Can filter bookmarks by folder (clicking sidebar)
  • Can filter bookmarks by tag
  • API routes return proper JSON responses with status codes
  • Data persists across page reloads (localStorage)
  • TypeScript strict mode, no any types
  • Zod validation on all API request bodies

Dependencies

{
  "zod": "^3.22.0"
}

Edge Cases

  • Handle invalid URLs gracefully
  • Handle empty search results with helpful message
  • Handle deleting a folder that contains bookmarks
  • Handle duplicate bookmark URLs (warn user)
  • Gracefully handle localStorage quota exceeded

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions