-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
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
- Save bookmarks: Add a URL with title, description, and optional tags
- Auto-fetch metadata: When adding a URL, attempt to extract the page title automatically using the URL
- Folders: Create folders to organize bookmarks (e.g., Work, Personal, Reading List)
- Tags: Add color-coded tags to bookmarks for cross-folder categorization
- Search: Full-text search across bookmark titles, descriptions, URLs, and tags
- CRUD via API routes: All data operations go through Next.js API routes (/api/bookmarks, /api/folders, /api/tags)
- 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
Reactions are currently unavailable