Skip to content

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

@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

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions