mirror of
https://github.com/wahyd4/hey-search.git
synced 2026-08-09 05:06:23 +10:00
5.9 KiB
5.9 KiB
Agents
This file describes the project structure and conventions for AI coding agents working on Hey Search.
Project Overview
Hey Search is a privacy-respecting metasearch engine that aggregates results from multiple upstream search engines (Brave, DuckDuckGo, Google, Bing). It has a Python/FastAPI backend and a React/TypeScript frontend.
Repository Structure
hey-search/
├── backend/ # Python FastAPI backend
│ ├── pyproject.toml # uv/Python dependencies
│ ├── uv.lock # Lockfile
│ └── app/
│ ├── main.py # FastAPI app entry point, lifespan, CORS, static mount
│ ├── models.py # Pydantic models (WebResult, ImageResult, SearchResponse, EngineInfo, etc.)
│ ├── search.py # Search orchestrator — concurrent engine queries, retry, dedup
│ ├── api/
│ │ └── routes.py # REST endpoints: /search, /autocomplete, /engines
│ └── engines/
│ ├── base.py # Abstract SearchEngine class, shared httpx AsyncClient
│ ├── registry.py # Engine registry — load, enable/disable, list
│ ├── brave.py # Brave Search (web + images)
│ ├── duckduckgo.py# DuckDuckGo (web + images)
│ ├── google.py # Google (web + images)
│ └── bing.py # Bing (web + images)
├── frontend/ # React + Vite + TypeScript frontend
│ ├── package.json
│ ├── vite.config.ts # Vite config with Tailwind plugin and /api proxy
│ ├── index.html
│ └── src/
│ ├── main.tsx # React entry point
│ ├── App.tsx # Main app — home page, results page, routing between them
│ ├── index.css # Tailwind CSS with shadcn theme variables
│ ├── lib/
│ │ ├── api.ts # API client — search, autocomplete, engines CRUD
│ │ └── utils.ts # cn() helper (clsx + tailwind-merge)
│ ├── hooks/
│ │ └── useAutocomplete.ts # Debounced autocomplete hook
│ └── components/
│ ├── SearchBar.tsx # Search input with autocomplete dropdown
│ ├── WebResults.tsx # Web results list (favicons, badges, snippets)
│ ├── ImageResults.tsx # Image grid + lightbox viewer
│ ├── EngineSettings.tsx # Modal to toggle engines on/off
│ └── ErrorToast.tsx # Toast notifications for engine failures
├── Dockerfile # Multi-stage: Node frontend build → Python runtime
├── .dockerignore
├── .gitignore
├── README.md
├── FEATURES.md
└── CHANGELOG.md
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Python 3.12+, FastAPI, uvicorn, httpx, Pydantic |
| Retry | tenacity (exponential backoff, 2 attempts) |
| Parsing | lxml, BeautifulSoup4 |
| Frontend | React 19, TypeScript, Vite |
| Styling | Tailwind CSS 4, shadcn theme, lucide-react icons |
| Packages | uv (backend), npm (frontend) |
| Docker | Multi-stage (node:20-slim → python:3.12-slim) |
Key Conventions
Backend
- Dependency management: Use
uv(not pip). Runuv syncto install,uv runto execute. - Engine pattern: Each engine extends
SearchEngine(inengines/base.py) and implementssearch_web(),search_images(), and optionallyautocomplete(). - Shared HTTP client: All engines use
get_http_client()frombase.py— a singlehttpx.AsyncClientinstance with sensible defaults. - Registry: Engines are registered in
engines/registry.py. Add new engines there inload_default_engines(). - Retry: The search orchestrator in
search.pywraps engine calls with tenacity retry (2 attempts, exponential backoff). Individual engines should raise on failure rather than swallowing errors. - Models: All API request/response shapes are Pydantic models in
models.py. - API docs: FastAPI auto-generates OpenAPI spec. Swagger UI at
/docs, Redoc at/redoc.
Frontend
- Mobile-first: All components are designed mobile-first, then scale up with Tailwind responsive breakpoints.
- Path aliases: Use
@/to import fromsrc/(configured in vite.config.ts and tsconfig.app.json). - Styling: Use Tailwind utility classes with
cn()for conditional classes. Theme colors reference CSS variables fromindex.css. - API layer: All backend calls go through
src/lib/api.ts. Components never callfetch()directly. - State: App state lives in
App.tsxviauseState. No external state management library.
Adding a New Search Engine
- Create
backend/app/engines/<name>.pyimplementingSearchEngine - Register it in
backend/app/engines/registry.py→load_default_engines() - No frontend changes needed — the engine appears automatically in the settings modal
Running Locally
# Backend
cd backend && uv sync && uv run uvicorn app.main:app --reload --port 8000
# Frontend (separate terminal)
cd frontend && npm install && npm run dev
# Docker (production)
docker build -t hey-search . && docker run -p 8000:8000 hey-search
API Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/search |
Metasearch (web/images) |
| GET | /api/autocomplete |
Search suggestions |
| GET | /api/engines |
List engines |
| PUT | /api/engines/{name} |
Toggle engine on/off |
| GET | /docs |
Swagger UI |
| GET | /redoc |
Redoc API docs |