An AI-powered city guide that understands natural language queries, extracts structured search intent via Gemini AI, queries the 2GIS catalog API, scores and ranks places, and returns detailed recommendations with review summaries.
The project is a full-stack monorepo with two main components:
- Backend (
src/cityguide_backend) — Python 3.13 / FastAPI async REST API with PostgreSQL, Redis caching, JWT authentication, and Gemini AI integration for intent extraction and review summarization. - Frontend (
2gis-frontend) — Next.js 16 / TypeScript application with a chat-based search interface and an embedded 2GIS interactive map.
The entire stack runs locally via Docker Compose with Gemini API integration.
| Layer | Technology |
|---|---|
| Runtime | Python 3.13 |
| Framework | FastAPI + Uvicorn |
| ORM | SQLAlchemy 2.0 async |
| Migrations | Alembic |
| Database | PostgreSQL 16 |
| Cache | Redis 7 |
| Auth | JWT (access + refresh tokens) |
| AI / LLM | Gemini AI (google-genai) |
| Places API | 2GIS Catalog API |
| HTTP client | httpx (async) |
| Package manager | uv |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS |
| Animations | Framer Motion |
| State / Data | TanStack Query |
| Maps | 2GIS Maps JS API |
| HTTP client | Axios |
Prerequisites: Docker Desktop, Docker Compose.
-
Copy the example environment file and fill in your API keys:
cp .env.example .env
-
Set your 2GIS API key and Gemini API key in
.env:TWOGIS_API_KEY=your_twogis_key GEMINI_API_KEY=your_gemini_key -
Start the full stack:
docker compose up --build
-
Open the application at http://localhost:7000.
The backend API is available at http://localhost:8001.
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql+asyncpg://... |
REDIS_URL |
Redis connection string | redis://redis:6379/0 |
JWT_SECRET_KEY |
Secret key for signing JWT tokens | — |
TWOGIS_API_KEY |
2GIS Catalog API key | — |
GEMINI_API_KEY |
Google Gemini API Key | — |
GEMINI_MODEL |
Gemini AI model name | gemini-flash-lite-latest |
FRONTEND_ORIGINS |
Allowed CORS origins for the frontend | http://localhost:7000 |
| Method | Path | Description |
|---|---|---|
| POST | /auth/register |
Register a new user |
| POST | /auth/login |
Obtain access and refresh tokens |
| POST | /auth/refresh |
Refresh the access token |
| POST | /auth/logout |
Revoke the refresh token |
| Method | Path | Description |
|---|---|---|
| GET | /me |
Get the authenticated user profile |
| Method | Path | Description |
|---|---|---|
| POST | /search |
Run an AI-powered place search |
| GET | /history |
Retrieve the user search history |
| Method | Path | Description |
|---|---|---|
| GET | /favorites |
List saved favorite places |
| POST | /favorites |
Save a place to favorites |
| DELETE | /favorites/{id} |
Remove a place from favorites |
| Method | Path | Description |
|---|---|---|
| GET | /statistics |
Get user search statistics |
| GET | /health |
Service health check |
Install backend dependencies locally with uv:
uv sync --devInstall frontend dependencies:
cd 2gis-frontend && npm installRun backend tests:
uv run pytest