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

214 lines
9.9 KiB
Markdown

# 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
```