A community-curated platform for discovering the best books on any topic, powered by collective wisdom and Internet Archive integration.
TheBestBookOn is a web application that helps people find the definitive books on any subject through community curation. Instead of algorithmic recommendations, we rely on thoughtful human judgment to surface books that truly matter.
Book preference is a matter of taste, and many people share similar tastes. While one book may be perceived as better than another in several ways, it often makes more sense to compare books within specific contexts or criteria. TheBestBookOn creates curated "prompts" - topical questions like "Managing Complex Projects" or "Designing Effective Cities" - where the community can submit and vote on the books that best answer each question.
This project is part of the Open Book Genome Project, an initiative to create structured metadata about books that goes beyond traditional cataloging.
- Community-Driven Quality: Leverages collective wisdom rather than algorithms
- Rich Context: Each book recommendation includes detailed justifications
- Integration with Internet Archive: Seamless authentication and access to ebook availability
- Tag-Based Discovery: Find books across related topics and genres
- Transparent Voting: See who voted for what and why
TheBestBookOn is built with:
- Backend: FastAPI - Modern Python web framework with async support
- Database: SQLite with SQLAlchemy ORM
- Templates: Jinja2 for server-side rendering
- Authentication: Internet Archive OAuth integration
- Book Data: OpenLibrary API for book metadata and covers
- Session Management: Starlette SessionMiddleware with secure cookie-based sessions
The easiest way to run TheBestBookOn is with Docker Compose, which includes the application server and nginx reverse proxy.
- Docker and Docker Compose
- Git
- Clone the Repository
git clone https://github.com/Open-Book-Genome-Project/TheBestBookOn.com.git
cd TheBestBookOn.com- Start the Application
docker compose up -dThe application will be available at: http://localhost:8080
The setup includes:
- FastAPI application server with pre-populated seed database
- Nginx reverse proxy for production-grade request handling
- Automatic secret key generation
- Persistent data storage
- Stop the Application
docker compose down- View Logs
docker compose logs -fIf you prefer to run the application without Docker:
- Python 3.7 or higher
- pip (Python package manager)
- Git
- Clone the Repository
git clone https://github.com/Open-Book-Genome-Project/TheBestBookOn.com.git
cd TheBestBookOn.com- Set Up Python Virtual Environment
# Create virtual environment
python3 -m venv venv
# Activate virtual environment
# On Linux/Mac:
source venv/bin/activate
# On Windows:
venv\Scripts\activate- Install Dependencies
pip install -r requirements.txt- Initialize the Database
The application comes with a pre-populated seed database (thebestbookon_seed.db).
# Copy the seed database to create your working database
cp thebestbookon_seed.db thebestbookon.db- Run the Application
# Development mode with auto-reload
uvicorn main:app --reload --host 0.0.0.0 --port 8080
# Or production mode
uvicorn main:app --host 0.0.0.0 --port 8080The application will be available at: http://localhost:8080
To submit books, vote, or create prompts, you'll need to log in with your Internet Archive credentials. If you don't have an account, create one at archive.org/account/signup.
TheBestBookOn.com/
├── main.py # FastAPI application (routes, models, logic)
├── populate_db.py # Database seed script with curated content
├── patch_db.py # Database update/patch script
├── requirements.txt # Python dependencies with pinned versions
├── Dockerfile # Docker container configuration
├── compose.yml # Docker Compose multi-service setup
├── nginx.conf # Nginx reverse proxy configuration
├── thebestbookon.db # SQLite database (working copy)
├── thebestbookon_seed.db # Pre-populated database template
├── .env # Environment variables (auto-generated)
├── templates/ # Jinja2 HTML templates
│ ├── base.html # Base template with navigation
│ ├── index.html # Homepage (prompt list)
│ ├── prompt_detail.html # Prompt page with book submissions
│ ├── user_profile.html # User activity page
│ └── login.html # Login page
└── static/ # Static assets
├── style.css # Application styles
└── logo.png # Logo image
The application uses a relational database with the following core entities:
Prompts: Questions or topics for book recommendations
- Each prompt has a title, description, and creator
- Contains multiple book submissions
- Can be favorited by users
Submissions: Book recommendations submitted to prompts
- Linked to a specific prompt
- Contains OpenLibrary metadata (edition key, cover, ebook access)
- Can have multiple votes and tags
Votes: User votes on submissions (+1 or -1)
- Each user can vote once per submission
- Includes optional comment/justification
- Used to calculate submission scores
Tags: Categorization labels
- Many-to-many relationship with submissions
- Used for filtering and discovery
Favorites: User bookmarks for prompts
- Tracks which prompts a user has favorited
- Prompts: Create topical questions that ask for the best books
- Book Submission: Submit books from OpenLibrary with justifications
- Voting System: Upvote (+1) or downvote (-1) submissions with comments
- Tag-Based Discovery: Filter by topics like "Philosophy", "Biography", "Science"
- User Profiles: View user activity (prompts created, books submitted, votes cast)
- Favorites: Bookmark prompts of interest
- OpenLibrary Integration: Automatic book metadata and cover images
- Internet Archive Auth: Secure login using existing IA credentials
Public Pages:
GET /- Homepage with prompt listGET /prompts/{id}- Prompt detail pageGET /users/{username}- User profile pageGET /login- Login page
Authenticated Actions:
POST /prompts- Create new promptPOST /prompts/{id}/submit- Submit book to promptPOST /vote- Vote on submissionPOST /api/prompts/{id}/toggle_favorite- Favorite/unfavorite prompt
AJAX APIs:
GET /api/search_books?q=query- Search OpenLibraryGET /api/tags?q=query- Autocomplete tag searchGET /api/prompts/{id}/voters- Get prompt votersGET /api/submissions/{id}/voters- Get submission voters
Admin Only:
DELETE /api/prompts/{id}- Delete promptDELETE /api/submissions/{id}- Delete submission
The project includes basic tests that verify core functionality:
- OpenLibrary search API integration
- Authentication requirements for API endpoints
- Production database protection (tests use temporary databases)
Install test dependencies:
pip install -r requirements.txtRun the test suite:
# Run all tests
pytest test_main.py -v
# Run specific test classes
pytest test_main.py::TestOpenLibrarySearch -v
pytest test_main.py::TestAuthenticationRequired -v
# Run with coverage
pytest test_main.py --cov=main --cov-report=term-missingImportant: Tests never write to the production database (thebestbookon.db). Each test uses a temporary test database that is created and destroyed automatically.
With Docker:
# Access the database in the running container
docker compose exec app sqlite3 thebestbookon.db
# Reset to seed data (requires restart)
docker compose down -v
docker compose up -dWithout Docker:
# View database contents
sqlite3 thebestbookon.db
sqlite> .tables
sqlite> SELECT * FROM prompts;
sqlite> .quit
# Reset to seed data
rm thebestbookon.db
cp thebestbookon_seed.db thebestbookon.dbAdd new curated content:
Edit populate_db.py or patch_db.py with new prompts and books, then run:
python populate_db.py # Full repopulation
# or
python patch_db.py # Targeted updatesRebuild after code changes:
docker compose down
docker compose build
docker compose up -dView application logs:
docker compose logs -f appAccess container shell:
docker compose exec app /bin/bashFor production deployment, set a custom SECRET_KEY in your environment:
export SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
docker compose up -dOr create a .env file:
SECRET_KEY=your-secure-secret-key-here
By default, the application is exposed on port 8080. To change this, modify the compose.yml file:
services:
nginx:
ports:
- "80:80" # Change 8080 to 80 for productionFor production, consider adding SSL certificates:
- Use a reverse proxy like Caddy or Traefik
- Or modify the nginx configuration to include SSL certificates
- Or deploy behind a load balancer with SSL termination
The Docker setup uses a named volume (app-data) to persist the database. To backup:
# Backup the database
docker compose exec app cp thebestbookon.db /tmp/backup.db
docker cp thebestbookon-app:/tmp/backup.db ./backup.db
# Restore from backup
docker cp ./backup.db thebestbookon-app:/app/thebestbookon.db
docker compose restart appContributions are welcome! Please feel free to submit issues or pull requests.
- Add more curated prompts and book recommendations
- Improve UI/UX design
- Add automated testing
- Enhance search and filtering
- Add book recommendation algorithms
- Improve mobile responsiveness
See the repository for license information.
- Open Book Genome Project - Parent project for structured book metadata
- Internet Archive - Digital library and authentication provider
- OpenLibrary - Open book data and covers
For questions or issues, please open a GitHub issue or contact the Open Book Genome Project community.
