A personal bookmarking application with AI-powered analysis, summarization, and tagging. Save links and let Gemini automatically analyze content to generate intelligent summaries and tags.
- Smart Bookmarking: Save any URL with an optional personal note
- AI-Powered Analysis: Gemini automatically fetches and analyzes web pages using URL Context and Google Search Grounding
- Intelligent Summaries: Generates both concise and detailed summaries of content
- Auto-Tagging: Automatically categorizes bookmarks with relevant tags
- Full-Text Search: Search bookmarks by title, URL, content, or tags
- Tag Filtering: Browse bookmarks by specific tags
- User Authentication: Powered by Stack Auth (formerly Neon Auth)
- Database: Neon Postgres with Drizzle ORM
- UI: Tailwind CSS + shadcn/ui components
- Neon account
- Stack Auth account (or use Neon Auth)
- Google AI Studio API key for Gemini
- Node.js 18+ installed locally
- Create or open a Neon project
- Go to Neon Auth → Setup instructions
- Click Set up Auth to generate your configuration
- Copy these environment variables to
.env.local:NEXT_PUBLIC_STACK_PROJECT_IDNEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEYSTACK_SECRET_SERVER_KEYDATABASE_URL
- Get your API key from Google AI Studio
- Add to
.env.local:GEMINI_API_KEY
# Install all dependencies
npm install
# Generate database migrations
npm run drizzle:generate
# Apply migrations to your database
npm run drizzle:migratenpm run devVisit http://localhost:3000 to see the application running. Sign in and start adding bookmarks!
- User submits a URL with optional note and tags
- URL normalization - Removes tracking parameters, www prefix, etc.
- AI Analysis - Google Gemini 2.5 Flash uses URL Context and Grounding to:
- Fetch and analyze the web page content
- Generate a human-friendly title
- Create short summary (1-2 sentences)
- Create detailed multi-paragraph summary
- Detect content language
- Generate 3-5 relevant tags
- Identify content category
- Database storage - Saves all data with full-text search indexing
- Status update - Marks as
processedorfailed
URL Context + Grounding: Instead of manually extracting HTML content, the app uses Gemini's built-in capabilities:
- URL Context Tool: Directly fetches and processes content from the provided URL
- Google Search Grounding: Provides additional web context when needed
- Supports multiple formats: HTML, PDF, images, JSON, and more
- Uses cached content when available for cost optimization
- users - User accounts
- bookmarks - Core bookmark data (URL, title, description, status)
- bookmark_contents - Extracted content and AI summaries
- tags - User-specific tags (normalized)
- bookmark_tags - Many-to-many relationship
POST /api/bookmarks- Create new bookmarkGET /api/bookmarks- List with search/filterGET /api/bookmarks/[id]- Get single bookmarkPOST /api/bookmarks/[id]/reprocess- Retry failed processingGET /api/tags- Get all tags with counts
app/
├── api/
│ ├── bookmarks/
│ │ ├── [id]/
│ │ │ ├── route.ts # GET single bookmark
│ │ │ └── reprocess/
│ │ │ └── route.ts # POST retry processing
│ │ └── route.ts # POST create, GET list bookmarks
│ └── tags/
│ └── route.ts # GET all tags with counts
├── b/
│ └── [id]/
│ └── page.tsx # Bookmark detail page
├── handler/
│ └── [...stack]/
│ └── page.tsx # Stack Auth handler
├── schema/
│ └── schema.ts # Drizzle ORM schema (all tables)
├── bookmarks-list.tsx # Main bookmarks list component
├── bookmarks-page.tsx # Bookmarks page wrapper
├── add-bookmark.tsx # Add bookmark form component
├── db.tsx # Database helper with auth
├── header.tsx # App header component
├── layout.tsx # Root layout
├── page.tsx # Home page
└── stack.tsx # Stack Auth configuration
components/
├── bookmarks/
│ ├── bookmark-card.tsx # Bookmark card UI component
│ ├── favicon.tsx # Favicon display component
│ └── search-filter.tsx # Search and tag filter UI
└── ui/
├── button.tsx # shadcn/ui button
├── card.tsx # shadcn/ui card
└── input.tsx # shadcn/ui input
lib/
├── bookmark-utils.ts # URL normalization, tag management
├── bookmark-processor.ts # Main bookmark processing pipeline
├── llm-client.ts # Google Gemini AI integration (URL Context + Grounding)
└── utils.ts # General utilities (cn helper)
drizzle/
├── 0000_lean_dragon_man.sql # Initial migration
├── 0001_dry_caretaker.sql # Bookmarks schema migration
├── 0002_add_gin_index.sql # Full-text search index
└── meta/ # Drizzle metadata
├── _journal.json
├── 0000_snapshot.json
└── 0001_snapshot.json
- Neon DB lives here: https://console.neon.tech/app/projects/shiny-sunset-02500855
- Deployed on Vercel: https://vercel.com/prakhars-projects-76dc8cec/bookmarks
- Semantic search with pgvector embeddings
- Export/import functionality