silverbullet-notes/docs/apps/books-v2.md
2026-01-25 00:20:24 +00:00

9.9 KiB

Books V2

Last updated: 2025-12-13

#docker #app #books-v2

Architecture Overview

Books V2 is a web application for tracking books read. It consists of a React frontend and a FastAPI backend.

  • Frontend: The frontend is a single-page application built with React and Vite. It uses TypeScript for static typing, Tailwind CSS for styling, and TanStack Query for data fetching and caching.
  • Backend: The backend is a RESTful API built with FastAPI, a modern, high-performance Python web framework. It uses SQLAlchemy as the ORM to interact with the database.
  • Database: The application uses a MySQL database to store all its data. Alembic is used for database migrations.

API Endpoints

The API is versioned and all endpoints are available under the /api/v1 prefix.

Authentication

  • GET /me: Get the current authenticated user's information.
  • GET /users: Get a list of all users.

Books

  • GET /books: Get a paginated list of books.
    • Query Parameters: page, items_per_page, search, year, sort_by, sort_order, view_as_user_id
  • POST /books: Create a new book.
  • GET /books/{book_id}: Get a single book by ID.
  • PUT /books/{book_id}: Update a book by ID.
  • DELETE /books/{book_id}: Delete a book by ID.
  • POST /books/from-next/{next_book_id}: Create a new book from a "next book".

Next Books

  • GET /next-books: Get a paginated list of books in the "to read" list.
    • Query Parameters: page, items_per_page, search, sort_by, sort_order, view_as_user_id
  • POST /next-books: Add a new book to the "to read" list.
  • PUT /next-books/bulk-update-order: Bulk update the reading order of the "to read" list.
  • GET /next-books/{book_id}: Get a single "next book" by ID.
  • PUT /next-books/{book_id}: Update a "next book" by ID.
  • DELETE /next-books/{book_id}: Delete a "next book" by ID.

Autocomplete

  • GET /autocomplete/formats: Get a list of all unique book formats.
  • GET /autocomplete/authors: Get a list of all unique authors.
  • GET /autocomplete/genres: Get a list of all unique genres.

Summary

  • GET /summary/all: Get a summary of all books.
  • GET /summary/audiobooks: Get a summary of all audiobooks.
  • GET /summary/non-audiobooks: Get a summary of all non-audiobooks.
  • GET /summary/yearly: Get a yearly summary of reading stats.

Advanced Stats

  • GET /advanced-stats: Get advanced reading statistics.
  • GET /search: Search for books using an external API (Google Books).
    • Query Parameters: query, max_results

Database Schema

The database consists of three main tables: users, books, and next_books.

users table

Column Type Constraints
id Integer Primary Key, Autoincrement
username String(255) Not Null, Unique, Indexed
email String(255) Nullable
display_name String(255) Nullable
created_at DateTime Not Null, Server Default
last_login DateTime Nullable

books table

Column Type Constraints
id Integer Primary Key, Autoincrement
user_id Integer Foreign Key (users.id), Not Null, Indexed
format String(50) Not Null
title String(255) Not Null
author String(255) Nullable
genre String(255) Nullable
date_started Date Not Null
date_finished Date Nullable
days Integer Nullable
pages Integer Not Null
Unique user_id, title

next_books table

Column Type Constraints
id Integer Primary Key, Autoincrement
user_id Integer Foreign Key (users.id), Not Null, Indexed
title String(255) Not Null
author String(255) Not Null
genre String(255) Nullable
pages Integer Nullable
format String(255) Nullable
purchased_status Boolean Nullable, Default: False
reading_order Integer Nullable
Unique user_id, title

Authentication

Authentication is handled by the Traefik reverse proxy in conjunction with Authelia. Authelia is an authentication and authorization server that provides single sign-on (SSO) for web applications.

When a user accesses the Books V2 application, Traefik forwards the request to Authelia for authentication. If the user is not authenticated, Authelia presents a login page. Once the user authenticates, Authelia sets a Remote-User header in the request and forwards it to the Books V2 backend.

The backend's get_current_user dependency reads the Remote-User header, and then gets or creates the user in the database. This means that user management is handled by Authelia, and the Books V2 application trusts the Remote-User header set by the proxy.

Environment Variables

Backend (.env)

  • DB_USER: The username for the MySQL database.
  • DB_PASSWORD: The password for the MySQL database.
  • DB_HOST: The hostname or IP address of the MySQL database server.
  • DB_PORT: The port of the MySQL database server.
  • DB_NAME: The name of the MySQL database.
  • DB_CHARSET: The character set for the MySQL database connection.
  • TZ: The timezone for the application.

Frontend (.env)

  • VITE_API_URL: The base URL for the backend API.

Development Workflow

Frontend

  • Start dev server: npm run dev
  • Build for production: npm run build
  • Run tests: No tests are currently configured.
  • View logs: Logs are printed to the console where the dev server is running.
  • Access container shell: docker exec -it books_frontend /bin/sh

Backend

  • Start dev server: The backend is run directly via uvicorn in the Dockerfile, so there is no separate dev server command.
  • Run tests: No tests are currently configured.
  • View logs: docker logs -f books_backend
  • Access container shell: docker exec -it books_backend /bin/bash
  • Database migrations: Migrations are handled by Alembic. To create a new migration, run alembic revision --autogenerate -m "Your migration message". To apply migrations, run alembic upgrade head.

Deployment Process

The application is deployed using Docker Compose. The docker-compose.yml file defines two services: frontend and backend.

To deploy the application, run docker-compose up -d --build. This will build the Docker images for the frontend and backend and start the containers.

Common Tasks

  • Adding a new API endpoint:
    1. Add a new function to backend/app/api/v1/endpoints/books.py.
    2. Add a new function to frontend/src/utils/api.ts to call the new endpoint.
    3. Use the new function in a React component.
  • Adding a new database table:
    1. Create a new model in backend/app/models.
    2. Run alembic revision --autogenerate -m "Add new table" to create a new migration.
    3. Run alembic upgrade head to apply the migration.

Known Issues

  • No tests are configured for either the frontend or the backend.
  • The "Required by" field in the service inventory is not populated.

File Structure

Frontend

frontend/
├── public/              # Static assets
├── src/
│   ├── components/      # Reusable React components
│   ├── hooks/           # Custom React hooks
│   ├── lib/             # Library code (e.g., axios configuration)
│   ├── pages/           # Application pages
│   ├── stores/          # Zustand state management stores
│   ├── types/           # TypeScript type definitions
│   └── utils/           # Utility functions
├── Dockerfile.prod      # Production Dockerfile
├── package.json         # NPM dependencies and scripts
└── vite.config.ts       # Vite configuration

Backend

backend/
├── alembic/              # Alembic database migration files
├── app/
│   ├── api/              # API endpoint definitions
│   ├── db/               # Database session management
│   ├── dependencies/     # FastAPI dependencies (e.g., auth)
│   ├── middleware/       # Custom middleware
│   ├── models/           # SQLAlchemy database models
│   ├── schemas/          # Pydantic data validation schemas
│   ├── services/         # Business logic
│   ├── config.py         # Application configuration
│   └── main.py           # Main FastAPI application
├── Dockerfile            # Dockerfile for the backend
└── requirements.txt      # Python dependencies