# 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](https://react.dev/) and [Vite](https://vitejs.dev/). It uses [TypeScript](https://www.typescriptlang.org/) for static typing, [Tailwind CSS](https://tailwindcss.com/) for styling, and [TanStack Query](https://tanstack.com/query/latest) for data fetching and caching. - **Backend:** The backend is a RESTful API built with [FastAPI](https://fastapi.tiangolo.com/), a modern, high-performance Python web framework. It uses [SQLAlchemy](https://www.sqlalchemy.org/) as the ORM to interact with the database. - **Database:** The application uses a [MySQL](https://www.mysql.com/) database to store all its data. [Alembic](https://alembic.sqlalchemy.org/) 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. ### Search - `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 ```