| Metric | Value |
|---|---|
| Total SLOC | 6,182 |
| Source Files | 43 |
| .js | 2,972 |
| .md | 1,995 |
| .tsx | 592 |
| .ts | 341 |
| .json | 93 |
A simplified Spotlight-like platform demonstrating local and cloud search, indexing, and intelligent suggestions. This educational project focuses on building a universal search system across files, apps, contacts, and web content.
- Search across files, applications, contacts, and web bookmarks
- Fast prefix matching with Elasticsearch edge n-gram analyzer
- Ranking by recency and usage frequency
- Math calculations (e.g.,
2+2*3,sqrt(16)) - Unit conversions (e.g.,
100 km to miles,32 f to c) - Web search fallback for unmatched queries
- Time-based app suggestions
- Recently accessed items
- Frequently contacted people
- Pattern learning from usage
- macOS Spotlight-inspired design
- Keyboard navigation (arrows, Enter, Escape)
- Cmd+K shortcut to open
- Dark theme with blur effects
- Frontend: TypeScript, Vite, React 19, Zustand, Tailwind CSS
- Backend: Node.js, Express
- Search: Elasticsearch 8.11
- Database: PostgreSQL 16
- Containerization: Docker Compose
- Node.js 18+
- Docker and Docker Compose
- npm or yarn
cd spotlight
# Start PostgreSQL and Elasticsearch
docker-compose up -d
# Wait for services to be healthy (about 30 seconds)
docker-compose pscd backend
# Install dependencies
npm install
# Start the server
npm run devThe backend runs on http://localhost:3001
In a new terminal:
cd spotlight/backend
# Seed sample files, apps, contacts, and web items
npm run seedcd spotlight/frontend
# Install dependencies
npm install
# Start development server
npm run devThe frontend runs on http://localhost:5173
- Visit http://localhost:5173
- Press
Cmd+K(orCtrl+Kon Windows/Linux) to open Spotlight - Or click the search button on the page
| Query | Result |
|---|---|
Safari |
Find Safari app |
meeting notes |
Find files with "meeting notes" |
alice |
Find contact named Alice |
github |
Find GitHub bookmark |
2+2*3 |
Calculate: 8 |
100 km to miles |
Convert: 62.137 miles |
32 f to c |
Convert: 0 C |
| Shortcut | Action |
|---|---|
Cmd+K |
Open/close Spotlight |
Escape |
Close Spotlight |
Arrow Up/Down |
Navigate results |
Enter |
Execute selected result |
GET /api/search?q=query
GET /api/search?q=query&types=files,apps
GET /api/search/suggest?q=prefix
POST /api/index/files
POST /api/index/apps
POST /api/index/contacts
POST /api/index/web
POST /api/index/bulk/files
GET /api/suggestions
POST /api/suggestions/app-launch
POST /api/suggestions/activity
GET /health
spotlight/
├── docker-compose.yml # PostgreSQL and Elasticsearch
├── backend/
│ ├── package.json
│ ├── init.sql # Database schema
│ └── src/
│ ├── index.js # Express server
│ ├── seed.js # Sample data seeder
│ ├── routes/
│ │ ├── search.js
│ │ ├── index.js
│ │ └── suggestions.js
│ └── services/
│ ├── elasticsearch.js
│ ├── queryParser.js
│ └── suggestions.js
└── frontend/
├── package.json
└── src/
├── App.tsx
├── main.tsx
├── index.css
├── components/
│ ├── SpotlightModal.tsx
│ ├── SearchInput.tsx
│ ├── SearchResults.tsx
│ ├── SearchResultItem.tsx
│ ├── Suggestions.tsx
│ └── Icons.tsx
├── stores/
│ └── spotlightStore.ts
├── services/
│ └── api.ts
├── hooks/
│ ├── useKeyboardShortcut.ts
│ └── useDebounce.ts
└── types/
└── search.ts
For testing load balancing:
# Terminal 1
npm run dev:server1 # Port 3001
# Terminal 2
npm run dev:server2 # Port 3002
# Terminal 3
npm run dev:server3 # Port 3003| Variable | Default | Description |
|---|---|---|
PORT |
3001 | Server port |
PG_HOST |
localhost | PostgreSQL host |
PG_PORT |
5432 | PostgreSQL port |
PG_DATABASE |
spotlight | Database name |
PG_USER |
spotlight | Database user |
PG_PASSWORD |
spotlight_password | Database password |
ES_URL |
http://localhost:9200 | Elasticsearch URL |
- Docker Compose setup (PostgreSQL, Elasticsearch)
- Backend API with Express
- Elasticsearch indexing with prefix matching
- Multi-source search (files, apps, contacts, web)
- Math calculations and unit conversions
- Siri-style suggestions
- Frontend with React + Tailwind
- Keyboard navigation
- Sample data seeding
- File system watcher for real indexing
- Content extraction (PDF, DOCX, etc.)
- Natural language date parsing
- Cloud integration
- Fast Prefix Matching: Elasticsearch edge n-gram tokenizer for instant results
- Multi-Source Ranking: Combine scores from different index types
- Usage Pattern Learning: PostgreSQL aggregations for time-based suggestions
- Real-time Updates: Designed for incremental indexing (watcher not implemented)
See architecture.md for detailed system design documentation.
See claude.md for development insights and design decisions.
- Core Spotlight Documentation - Apple's framework for indexing app content
- NSUserActivity Documentation - Making app content searchable
- Elasticsearch Documentation - Distributed search engine for full-text search
- Apache Lucene - Core search library powering many search engines
- SQLite FTS5 Extension - Full-text search for SQLite databases
- Apache Tika - Content extraction toolkit for diverse file formats
- Algolia Documentation - Search-as-a-service patterns and ranking algorithms
- Building a Search Engine from Scratch - Educational search implementation