Pokedex for the web
Features • Tech Stack • Quick Start • Documentation • Contributing
- Features
- Tech Stack
- Quick Start
- Project Structure
- Environment Variables
- Available Scripts
- Database Setup
- Extension Development
- MCP Server Integration
- Self-Hosting
- Documentation
- Contributing
- Smart Collections - Organize bookmarks into collections with team collaboration
- Browser Extension - Quick-save any webpage with Ctrl+Shift+X
- AI-Powered - Automatic content summarization and intelligent tagging
- Full-Text Search - Lightning-fast search across all your saved content
- Team Collaboration - Share collections with role-based access control
- MCP Integration - AI assistant integration via Model Context Protocol
- API Access - Programmatic access with API keys for automation
- Dark Mode - Beautiful interface with theme support
- Privacy-First - Self-hostable with full data ownership
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 7, TailwindCSS 4, Radix UI |
| Backend | Hono, tRPC, Drizzle ORM, PostgreSQL 16 |
| Extension | WXT Framework, Manifest V3 |
| Authentication | Better Auth, Google OAuth |
| AI | Groq API (summarization) |
| Monorepo | Turborepo, pnpm workspaces |
| Deployment | Docker, DigitalOcean |
- Node.js >= 22
- pnpm >= 10.28.1
- Docker (for PostgreSQL)
# Clone the repository
git clone https://github.com/sdslabs/dex.git
cd dex
# Install dependencies
pnpm install
# Set up environment variables
cp apps/server/sample.env apps/server/.env
cp apps/web/sample.env apps/web/.env
# Edit .env files with your credentials (see Environment Variables section below)
# Start PostgreSQL database
pnpm db:up
# Run database migrations
pnpm db:migrate
# Start all applications
pnpm devNote: For detailed environment variable configuration, see the Environment Variables section below.
Access the application:
- Web App: http://localhost:5173
- API Server: http://localhost:8787
dex/
├── apps/
│ ├── web/ # React frontend application
│ │ ├── src/ # Source code
│ │ ├── public/ # Static assets (logo, etc.)
│ │ └── Dockerfile # Production container
│ ├── server/ # Backend API server
│ │ ├── src/
│ │ │ ├── trpc/ # tRPC routers
│ │ │ ├── db/ # Database schema & migrations
│ │ │ ├── services/ # Business logic
│ │ │ └── mcp/ # MCP server
│ │ └── Dockerfile # Production container
│ └── extension/ # Browser extension
│ ├── entrypoints/ # Content scripts & background
│ └── components/ # React components
├── packages/
│ └── ui/ # Shared component library
│ ├── components/ # Radix UI + custom components
│ └── hooks/ # Shared React hooks
├── docker/ # Docker Compose files
│ ├── docker-compose.db.yml # PostgreSQL only
│ └── docker-compose.app.yml # Full application stack
└── docs/ # Documentation
# Database
DB_URL=postgres://postgres:postgres@localhost:5432/postgres
# Application URLs
BACKEND_URL=http://localhost:8787
FRONTEND_URL=http://localhost:5173
# External APIs
YOUTUBE_API_KEY=your_youtube_api_key
GROQ_API_KEY=your_groq_api_key
# Google OAuth (required for authentication)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Waitlist feature (optional)
WAITLIST_ENABLED=falseGetting API Keys:
- YouTube API: Google Cloud Console
- Groq API: Groq Console
- Google OAuth: Google Cloud Console - Add redirect URI:
http://localhost:8787/api/auth/callback/google
VITE_BACKEND_URL=http://localhost:8787/WXT_BACKEND_URL=http://localhost:8787
WXT_FRONTEND_URL=http://localhost:5173| Command | Description |
|---|---|
pnpm dev |
Start all apps in development mode |
pnpm build |
Build all apps for production |
pnpm lint |
Lint all code with ESLint |
pnpm format |
Format code with Prettier |
pnpm check-types |
Run TypeScript type checking |
| Command | Description |
|---|---|
pnpm db:up |
Start PostgreSQL container |
pnpm db:down |
Stop PostgreSQL container |
pnpm db:migrate |
Run database migrations |
pnpm db:generate |
Generate new migration |
pnpm db:push |
Push schema to database (dev only) |
pnpm db:studio |
Open Drizzle Studio |
| Command | Description |
|---|---|
pnpm ui-add <component> |
Add shadcn/ui component to shared @repo/ui (web & extension) |
| Command | Description |
|---|---|
pnpm reinstall |
Clean reinstall of dependencies |
Dex uses PostgreSQL 16 for data storage.
pnpm db:upThis starts a PostgreSQL container with:
- User:
postgres - Password:
postgres - Database:
postgres - Port:
5432
pnpm db:migrateThis creates all necessary tables, indexes, and constraints.
Open Drizzle Studio to explore your database:
pnpm db:studioAccess at https://local.drizzle.studio
pnpm db:downcd apps/extension
pnpm dev- Open
chrome://extensions/ - Enable Developer mode
- Click Load unpacked
- Select
apps/extension/.output/chrome-mv3-dev/
- Click extension icon or press
Ctrl+Shift+X(Windows/Linux) orCmd+Shift+X(Mac) - Extension overlay appears in top-right corner
- Select collections and save current page
cd apps/extension
pnpm build # Build for Chrome
pnpm zip # Package as ZIP for Chrome Web StoreOutput: apps/extension/.output/chrome-mv3.zip
pnpm build:firefox
pnpm zip:firefoxDex includes a Model Context Protocol (MCP) server that allows AI assistants like Claude to interact with your bookmarks directly from conversations.
The Model Context Protocol enables Claude Desktop to access your Dex collections, search saved content, and add new bookmarks during your conversations - making your knowledge base available to your AI assistant.
First, create an API key in the Dex web interface:
- Navigate to Settings → API Keys
- Click "Create API Key"
- Choose Full Access mode
- Copy the generated key
Edit your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Add the MCP server configuration:
For local development:
{
"mcpServers": {
"dex": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:8787/mcp",
"--header",
"X-API-Key: YOUR_API_KEY_HERE"
]
}
}
}For production (hosted Dex):
{
"mcpServers": {
"dex": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://apidex.sdslabs.co/mcp",
"--header",
"X-API-Key: YOUR_API_KEY_HERE"
]
}
}
}Replace YOUR_API_KEY_HERE with the API key you generated in step 1.
Restart Claude Desktop to load the new MCP server configuration.
Once configured, you can use these natural language commands in Claude:
- "Save this article to my Reading List collection"
- "Search my bookmarks for React tutorials"
- "Show me my collections"
- "Create a new collection called Research Papers"
- "What bookmarks do I have about machine learning?"
Ask Claude: "Can you show me my Dex collections?"
Claude should respond with your collections list, confirming the integration is working.
MCP server not connecting:
- Verify Dex server is running (
pnpm devfor local or ensure production instance is up) - Check API key is valid and has not expired
- Ensure the MCP URL is correct (
http://localhost:8787/mcpfor local,https://apidex.sdslabs.co/mcpfor production) - Check Claude Desktop logs for error messages
API key issues:
- Generate a new API key in Dex settings
- Ensure you selected "Full Access" mode
- Copy the entire API key and paste it in the configuration
For more details on MCP integration, see the API Documentation.
Dex can be easily self-hosted using Docker Compose for complete control over your data.
- Docker and Docker Compose installed
- Domain name (optional, but recommended)
- SSL certificate (optional, use Let's Encrypt with Certbot)
git clone https://github.com/sdslabs/dex.git
cd dexCreate production environment files:
# Server environment
cp apps/server/sample.env apps/server/.envEdit apps/server/.env with your production values:
DB_URL=postgres://postgres:your_secure_password@db:5432/postgres
BACKEND_URL=https://api.yourdomain.com
FRONTEND_URL=https://yourdomain.com
YOUTUBE_API_KEY=your_youtube_api_key
GROQ_API_KEY=your_groq_api_key
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
WAITLIST_ENABLED=falseImportant:
- Change PostgreSQL password in both
.envanddocker-compose.app.yml - Update
BACKEND_URLandFRONTEND_URLto your domain - Set up Google OAuth with your production redirect URI:
https://api.yourdomain.com/api/auth/callback/google
Edit docker/docker-compose.app.yml to set your backend URL:
services:
web:
build:
args:
VITE_BACKEND_URL: https://api.yourdomain.com/docker compose -f docker/docker-compose.app.yml up -dThis starts:
- PostgreSQL 16 - Database on port 5432
- Backend API - Hono server on port 8787
- Frontend Web - Nginx serving React app on port 3000
# Connect to the server container
docker compose -f docker/docker-compose.app.yml exec server sh
# Run migrations
pnpm db:migrate
# Exit container
exit- Frontend:
http://localhost:3000(or your domain) - API:
http://localhost:8787(or your API domain)
Use Nginx or Caddy as a reverse proxy for SSL termination:
Example Nginx configuration:
# Frontend
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Backend API
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8787;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Set up regular PostgreSQL backups:
# Manual backup
docker compose -f docker/docker-compose.app.yml exec db \
pg_dump -U postgres postgres > backup_$(date +%Y%m%d).sql
# Restore from backup
docker compose -f docker/docker-compose.app.yml exec -T db \
psql -U postgres postgres < backup_20240101.sqlData is stored in Docker volumes:
postgres_data- Database files- Ensure regular backups of this volume
Minimum recommended resources:
- CPU: 2 cores
- RAM: 4GB
- Storage: 20GB (plus space for your bookmarks)
- Change default PostgreSQL password
- Use HTTPS with valid SSL certificates
- Set up firewall rules (only expose ports 80 and 443)
- Keep Docker images updated
- Regular database backups
- Monitor logs for suspicious activity
- Use strong Google OAuth credentials
For local development with Docker:
# Start database only
docker compose -f docker/docker-compose.db.yml up -d
# Run app locally
pnpm dev# Pull latest changes
git pull origin main
# Rebuild and restart containers
docker compose -f docker/docker-compose.app.yml up -d --build
# Run new migrations
docker compose -f docker/docker-compose.app.yml exec server pnpm db:migrateContainers won't start:
# Check logs
docker compose -f docker/docker-compose.app.yml logs
# Check specific service
docker compose -f docker/docker-compose.app.yml logs serverDatabase connection failed:
- Verify DB_URL in
apps/server/.env - Ensure database container is healthy:
docker ps - Check database logs:
docker compose -f docker/docker-compose.app.yml logs db
Cannot log in:
- Verify Google OAuth credentials
- Check redirect URI matches:
{BACKEND_URL}/api/auth/callback/google - Ensure FRONTEND_URL and BACKEND_URL are correct
Comprehensive documentation is available in the /docs folder:
- Architecture - System design, data flow, and technical decisions
- Development Guide - Detailed setup and development workflow
- API Reference - Complete API documentation with examples
- Contributing - How to contribute to the project
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes
- Run quality checks:
pnpm format && pnpm lint && pnpm build - Commit with conventional commits:
git commit -m "feat: add new feature" - Push and create a Pull Request
# Start database
pnpm db:up
# Start development
pnpm dev
# Make changes...
# Format code
pnpm format
# Commit changes
git commit -m "feat(web): add dark mode toggle"Built with love by SDSLabs
Special thanks to all contributors who have helped make Dex better!
Made with TypeScript, React, and lots of coffee