A high-performance, asynchronous RESTful API for modern bookmark management. Built with Python, FastAPI, PostgreSQL, and Redis, Bookmarks API provides automated web metadata scraping, full-text search with relevance ranking, tag management, JWT authentication with token refresh pairs, and intelligent caching.
- Asynchronous Execution Model: End-to-end non-blocking operations powered by
asyncio,FastAPI,asyncpg, andhttpx. - Robust JWT Authentication: Dual-token architecture using
HS256signed short-lived Access Tokens (15 min) and long-lived Refresh Tokens (7 days) with strict type claim validations. - Automated Web Scraping: Asynchronous HTML metadata extraction (
title,description,OpenGraph) upon saving new URLs usinghttpxandBeautifulSoup4. - PostgreSQL Full-Text Search: Native Russian-language full-text search engine utilizing
tsvectorindexing,websearch_to_tsqueryparsing, and weighted title/tag relevance ranking (ts_rank). - Intelligent Caching Layer: Automated query response caching via Redis with dynamic cache invalidation on write/update/delete operations.
- Containerized Deployment: Ready-to-use Docker Compose setup with automated database schema migrations and health checks.
| Category | Technology |
|---|---|
| Framework | FastAPI, Starlette, Pydantic v2 |
| Database | PostgreSQL 16 (via asyncpg) |
| Caching & Broker | Redis 7 (via redis.asyncio) |
| Security | PyJWT, Passlib / Bcrypt |
| Web Scraping | HTTPX, BeautifulSoup4 |
| Orchestration | Docker, Docker Compose |
projectX/
├── database/
│ ├── database.py # Database connection lifecycle & raw asyncpg queries
│ ├── models.py # Pydantic models & request validation schemas
│ └── schemas/ # SQL schema files loaded dynamically on startup
├── app.py # Main application entry point, lifespan, & routing
├── auth.py # JWT token generation, pass hashing & dependency injection
├── parser.py # Asynchronous web scraper for link metadata extraction
├── docker-compose.yml # Multi-container service definition
├── Dockerfile # Production Docker build specification
├── requirements.txt # Project dependencies
└── .env.example # Environment variable template
Create a .env file in the root directory based on .env.example:
SECRET_KEY="your-super-secret-production-key"
POSTGRES_USER="my_db_user"
POSTGRES_PASSWORD="generate_strong_password_here"
POSTGRES_DB="bookmarks_db"
PG_LINK="postgresql://my_db_user:generate_strong_password_here@db:5432/bookmarks_db"
REDIS_URL="redis://redis:6379"
Clone the repository:
git clone [https://github.com/SteppingCode/projectX.git](https://github.com/SteppingCode/projectX.git)
cd projectXConfigure environment:
cp .env.example .envLaunch the stack:
docker compose up --build -dVerify application status:
The API will be available at http://localhost:8000. Interactive documentation is hosted at:
-
Swagger UI: http://localhost:8000/api/docs
Prerequisites
-
Python 3.14+
-
PostgreSQL 16 server
-
Redis server
Set up virtual environment:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activateInstall dependencies:
pip install -r requirements.txtRun the server:
uvicorn app:app --host 127.0.0.1 --port 8000 --reload| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register | Register a new user account | ❌ No |
| POST | /api/auth/login | Authenticate user & receive Access/Refresh token pair | ❌ No |
| POST | /api/auth/refresh | Exchange valid Refresh Token for new token pair | ❌ No |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/bookmarks | Retrieve cached list of user bookmarks | 🔒 Bearer |
| POST | /api/add_bookmark/ | Add new bookmark (triggers async metadata scraping) | 🔒 Bearer |
| GET | /api/bookmarks/search | Full-text relevance search over bookmarks & tags | 🔒 Bearer |
| DELETE | /api/delete_bookmark/{id} | Remove bookmark by ID & invalidate cache | 🔒 Bearer |
| POST | /api/bookmarks/{id}/tags | Attach tag to bookmark | 🔒 Bearer |
| DELETE | /api/bookmarks/{id}/tags/{tag} | Remove tag from bookmark | 🔒 Bearer |
Distributed under the MIT License. See LICENSE for more information.