Booklynn is a modern FastAPI backend that powers a book discovery and review service. It provides:
- User authentication with JWT access/refresh tokens and role-based authorization
- CRUD for books linked to users
- Reviews for books by users
- Centralized error handling, middleware, and async SQLAlchemy + SQLModel ORM
- Celery-based background email sending with optional Flower monitoring
- Python 3.12
- FastAPI, Pydantic, SQLModel (SQLAlchemy ORM)
- Postgres(production), SQLite (dev) via SQLAlchemy; Alembic for migrations
- Redis for token blocklist (logout/revocation)
- Celery for background tasks (email); with flower webui
bookApp/
alembic.ini
migrations/
books.db # SQLite dev database
src/
__init__.py # FastAPI app factory and router wiring
routesv2.py # Book endpoints (v2)
auth/ # Auth routes, deps, schemas, service, utils
reviews/ # Review routes, schemas, service
db/ # DB engine/session, models, redis utils
errors.py # Centralized exception types & handlers
middleware.py # Request logging middleware
celery_task.py # Celery app and tasks
config.py # Pydantic Settings
requirements.txt
cmds.txt # Helpful run commands
Show ER diagram
erDiagram
users {
UUID uid PK "NOT NULL"
VARCHAR username "NOT NULL"
VARCHAR email "NOT NULL"
VARCHAR first_name "NOT NULL"
VARCHAR role "NOT NULL"
BOOLEAN is_verified "NOT NULL"
VARCHAR password_hash "NOT NULL"
TIMESTAMP created_at "NOT NULL"
TIMESTAMP updated_at "NOT NULL"
}
books {
UUID uid PK "NOT NULL"
VARCHAR title "NOT NULL"
VARCHAR author "NOT NULL"
INTEGER year "NOT NULL"
INTEGER pages "NOT NULL"
VARCHAR language "NOT NULL"
TIMESTAMP created_at "NOT NULL"
TIMESTAMP updated_at "NOT NULL"
UUID user_id FK
}
reviews {
UUID uid PK "NOT NULL"
UUID book_id FK "NOT NULL"
UUID user_id FK "NOT NULL"
VARCHAR review_text
INTEGER rating "NOT NULL"
TIMESTAMP created_at "NOT NULL"
}
users ||--o{ books : "creates"
users ||--o{ reviews : "writes"
books ||--o{ reviews : "has"
See also: diagram.md
- Python 3.12 installed and available on PATH.
- Redis running locally (default:
redis://localhost:6379/) if you want logout token revocation and Celery to work. - uv package manager (used for installing Python dependencies).
- Optional: SMTP account (Gmail or other) for email-sending features.
- Create and activate a virtual environment (Python 3.12)
python -m venv .\.venv
or
uv venv --python=3.12 --clear
.\.venv\Scripts\Activate.ps1- Install dependencies with uv (coz its rust-based and 100x faster than pip)
uv pip install -r requirements.txt- Configure environment
Create a
.envfile at thesrc/:
#Database: set when using Postgres in production, else SQLite (books.db)
DATABASE_URL=
JWT_SECRET_KEY=
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_URL=redis://localhost:6379
[email protected]
MAIL_PASSWORD=your-app-password
[email protected]
- Database setup (SQLite dev)
The app ships with a local SQLite
books.dbalso, run migrations:
alembic revision --autogenerate -m "message"
alembic upgrade head- Run the API server
uvicorn src:app --reloadDocs at http://localhost:8000/v2/docs
- Optional: Celery worker and Flower
# Start worker
celery -A src.celery_task:c_app worker -l info
# Start Flower UI (monitoring)
celery -A src.celery_task.c_app flower
# Open http://localhost:5555/tasksSettings are defined in src/config.py via Pydantic BaseSettings and environment variables. Key settings:
DATABASE_URL: When provided (e.g., Postgres), the app uses it; otherwise SQLitebooks.dbis usedJWT_SECRET_KEY,JWT_ALGORITHM: Token signingREDIS_URL: Blocklist for revoked tokens- Mail credentials for SMTP
DOMAIN: Used for links in account verification/password reset emails
- JWT Access token (short-lived) and Refresh token (longer-lived)
- Bearer token dependencies validate type and expiry
- Token revocation supported via Redis blocklist
- Role-based Access control using
RoleCheckerwith roles asadminanduser
Base: http://localhost:8000/v2 (Docs at /v2/docs)
Auth
- POST
/auth/signup - POST
/auth/login - GET
/auth/me(requires access token) - POST
/auth/refresh(requires refresh token) - GET
/auth/logout(revokes access token) - POST
/auth/password-reset(email) - POST
/auth/password-reset-confirm/{token}
Books (requires user role mainly)
- POST
/books/– Create - GET
/books/– List - GET
/books/{book_uid}– Retrieve - PATCH
/books/{book_uid}– Update - DELETE
/books/{book_uid}– Delete (admin role)
Reviews
- GET
/reviews/– List all reviews (admin role) - GET
/reviews/book/{book_uid}– Get a review for a book - POST
/reviews/book/{book_uid}– Add review (user) - DELETE
/reviews/{review_uid}– Delete review (admin role)
# Signup
curl -X POST "http://localhost:8000/v2/auth/signup" `
-H "Content-Type: application/json" `
-d '{
"first_name": "Jane",
"username": "jane",
"email": "[email protected]",
"password": "secret",
"role": "user"
}'
# Login
$login = curl -X POST "http://localhost:8000/v2/auth/login" `
-H "Content-Type: application/json" `
-d '{"email": "[email protected]", "password": "secret"}'
# Create a book
curl -X POST "http://localhost:8000/v2/books/" `
-H "Authorization: Bearer <ACCESS_TOKEN>" `
-H "Content-Type: application/json" `
-d '{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"year": "1925",
"language": "English"
}'- frontend for the endpoints using streamlit, or any other framework
- add email routing and setup a smtp for emails from cloudflare added site, instead of gmail
- add some ml model for the book score that tells, how many people like this book, or something like that