A living portfolio showcasing data engineering and full-stack development skills through a personal content aggregation platform.
As a data engineer by training and archaeologist by education, I've always been passionate about classification, curation, and making data work for me. Rather than maintaining a static portfolio of development projects, I wanted to create something more dynamic for my home page on the internet. That is why I decided to create a living platform that demonstrates my technical skills while serving a real purpose in my daily life.
Library of Babble is the result: a custom-built Flask web application that aggregates my content consumption across multiple services (Goodreads, Letterboxd, Spotify, and more) into a single, unified interface. It's where I:
- Track what I'm reading, watching, listening to, and collecting
- Curate my reviews, ratings, quotes, and playlists
- Showcase my data engineering skills through ETL pipelines, database design, and API integrations
- Experiment with new technologies and development patterns in a production environment
This is designed to be a living project that I will update and improve continuously as my career develops.
Traditional portfolios show what you've built. This project demonstrates:
- How I architect solutions - Full-stack design patterns, database schemas, API integrations
- How I engineer data pipelines - ETL scripts with conflict resolution, data validation, and incremental imports
- How I prioritize security - CSRF protection, XSS prevention, SQL injection safeguards, Content Security Policies
- How I think about user experience - Responsive design, smooth interactions, intuitive navigation
- How I maintain code quality - Comprehensive documentation, security standards, testing practices
Backend:
- Python 3.x
- Flask (Web Framework)
- SQLAlchemy (ORM)
- PostgreSQL (Production) / SQLite (Development)
- Flask-Login (Authentication)
- Flask-WTF (CSRF Protection)
Frontend:
- Jinja2 Templates
- JavaScript (ES6+)
- jQuery & jQuery UI
- Custom CSS with responsive design
Integrations:
- Spotify Web API (via Spotipy)
- The Movie Database (TMDB) API
- Goodreads CSV Exports
- Letterboxd CSV Exports
The content on this site reflects what I'm currently engaged with. Reach out, adn I will create an account for you so that you can browse and see what I'm:
- Reading - Books I've finished, quotes that stuck with me, recommendations and reviews
- Watching - Movies and shows I've seen, recommendations and reviews
- Listening - Curated playlists, monthly music archives since 2019
- Writing - Publications and written work
- Creating - Visual art projects
- Collecting - Personal collections (pins, bottle labels, etc.)
- Pondering - Art pieces and artists I find meaningful
Want to discuss any of this? I'm always happy to chat about books, movies, music, or any of the technical decisions behind this platform. Feel free to reach out!
Want to run your own version of Library of Babble? Here's how to get started.
- Python 3.8 or higher
- PostgreSQL 12+ (recommended for production) or SQLite (for development)
- Git
-
Clone the repository
git clone https://github.com/yourusername/library_of_babble.git cd library_of_babble -
Create a virtual environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Configure environment variables
Copy
.env.exampleto.envand configure the following:cp .env.example .env
Required Configuration:
Variable Description How to Obtain FLASK_SECRET_KEYSecret key for session encryption Generate with python -c 'import secrets; print(secrets.token_hex(32))'DATABASE_URLPostgreSQL connection string Format: postgresql://username:password@localhost/dbnameFLASK_DEBUGEnable debug mode (development only) Set to truefor development,falsefor productionSPOTIPY_CLIENT_IDSpotify API client ID Create app at Spotify Developer Dashboard SPOTIPY_CLIENT_SECRETSpotify API client secret From same Spotify app SPOTIPY_USERNAMEYour Spotify username Find at Spotify Account Overview TMDB_API_BEARER_TOKENTMDB API bearer token Create account and get API key at TMDB API Settings Optional Configuration:
Variable Description Default FLASK_HOSTDevelopment server host 127.0.0.1FLASK_PORTDevelopment server port 5000FLASK_ENVEnvironment (development/production) development -
Initialize the database
flask db upgrade
-
Create an admin user
python scripts/create_user.py
-
Run the application
python run.py
The app will be available at
http://127.0.0.1:5000
The application supports importing data from various sources through the Account page (requires admin access).
Export Process:
- Log into Goodreads
- Go to "My Books"
- Click "Import and export" under Tools
- Click "Export Library"
- Download the CSV file (named
goodreads_library_export.csv)
Import:
- Navigate to Account → Data Management → Import Data → Goodreads
- Upload the CSV file
- The system will automatically:
- Add new books
- Update unread books to read status if they've been marked as read
- Report conflicts for books already marked as read (database is source of truth)
Expected Columns:
Book Id, Title, Author, Additional Authors, ISBN, ISBN13, My Rating, Average Rating, Publisher, Number of Pages, Original Publication Year, Date Read, Date Added, Bookshelves, Exclusive Shelf, My Review, Private Notes, Read Count, Owned Copies
Export Process:
- Log into Letterboxd
- Go to Settings → Import & Export
- Click "Export Your Data"
- Download and extract the ZIP file
- Use the files:
reviews.csv,ratings.csv, andwatched.csv
Import:
- Navigate to Account → Data Management → Import Data → Letterboxd
- Upload one or more CSV files from your export
- The system handles:
- Reviews with ratings and text
- Ratings without reviews
- Watch dates and tracking
Expected Files:
reviews.csv- Contains:Date,Name,Year,Letterboxd URI,Rating,Reviewratings.csv- Contains:Date,Name,Year,Letterboxd URI,Ratingwatched.csv- Contains:Date,Name,Year,Letterboxd URI
What is Boredom Killer? Boredom Killer is a custom Google Sheets template for tracking movies and TV shows with additional metadata like online database ids and collections.
File Format: Export your Google Sheet as CSV. The file should contain these columns:
For Movies (Boredom Killer - Movies.csv):
Movie, Year, Status, Source, IMDB ID, TMDB ID, Letterboxd ID, Collections, Tags, Posters, Language, Director(s), Image
For TV Shows (Boredom Killer - TV.csv):
TV Show, Year, Status, TVDB ID, IMDB ID, Collections, Tags, Poster Image
For Documentaries (Boredom Killer - Documentaries.csv):
Same format as Movies
For Docuseries (Boredom Killer - Docuseries.csv):
Same format as TV Shows
Import:
- Navigate to Account → Data Management → Import Data → Boredom Killer
- Select the type (Movies, TV Shows, or Docuseries)
- Upload the CSV file
- The system automatically fetches additional metadata from TMDB/TVDB
Note: The Boredom Killer format is custom-designed for my workflow. If you want to use this feature, you'll need to create a similar spreadsheet structure or adapt the ETL scripts to your format.
File Format:
Create a CSV file named book_quotes.csv with these columns:
Goodreads ID, Title, Quote, Page Number
Import:
- Place the file in
data/staging/ - Run:
python scripts/etl/books_etl.py
Note: This is a manual process for now. Web-based quote import may be added in the future.
Individual Upload:
- Navigate to Account → Artwork Management
- Enter artist name and upload image
- Files are organized by artist in
static/images/artists/
CSV Import:
Create a CSV with columns: artist, image_filename
Place images in a folder and reference them in the CSV, then use the CSV import feature.
Allowed File Types: .png, .jpg, .jpeg, .gif
For advanced users, ETL scripts can be run directly:
# Books
python scripts/etl/books_etl.py path/to/goodreads_export.csv --use-transaction
# Movies
python scripts/etl/movies_etl.py --bk-movies path/to/boredom_killer_movies.csv
# TV Shows
python scripts/etl/shows_etl.py --bk-tv path/to/boredom_killer_tv.csvTransaction Mode:
Use --use-transaction flag to automatically rollback on errors.
This application is designed to be deployed on platforms like Fly.io, Heroku, or similar PaaS providers.
Important Deployment Considerations:
- Set
FLASK_DEBUG=falsein production - Use PostgreSQL (not SQLite) for production
- Configure proper secret keys
- Enable HTTPS (security headers include HSTS)
- Set up regular database backups
Need help deploying your instance? Feel free to reach out! I'm happy to provide guidance or assistance with deployment configuration.
library_of_babble/
├── app/ # Main application package
│ ├── account/ # Account management & admin tools
│ ├── artworks/ # Art collection features
│ ├── auth/ # Authentication (login/register)
│ ├── books/ # Book tracking & reviews
│ ├── collecting/ # Personal collections (pins, labels, etc.)
│ ├── common/ # Shared models (reviews, collections)
│ ├── main/ # Home page & navigation
│ ├── movies/ # Movie tracking & reviews
│ ├── music/ # Spotify playlist curation
│ ├── shows/ # TV show tracking (placeholder)
│ ├── watching/ # Combined movies/shows view
│ ├── writing/ # Publications & written work
│ ├── templates/ # Jinja2 HTML templates
│ ├── utils/ # Utility functions (security, helpers)
│ ├── extensions.py # Flask extensions (db, login, etc.)
│ └── __init__.py # Application factory
├── data/ # Data files
│ ├── archive/ # Processed import files
│ ├── backups/ # Database backups
│ ├── loaded/ # Successfully imported files
│ ├── reports/ # Import conflict reports
│ └── staging/ # Files ready for import
├── docs/ # Documentation
│ ├── ignore/ # Security implementation docs
│ ├── Secure Development Lifecycle (SDL) Guide.md
│ └── Style and Design Guidelines.md
├── migrations/ # Database migrations (Flask-Migrate)
├── scripts/ # Utility scripts
│ ├── etl/ # ETL pipeline scripts
│ └── create_user.py # User creation utility
├── static/ # Static assets
│ ├── css/ # Stylesheets
│ ├── images/ # Images and uploads
│ └── js/ # JavaScript files
├── .env.example # Environment variable template
├── config.py # Application configuration
├── requirements.txt # Python dependencies
└── run.py # Application entry point
- Security Development Guide:
docs/Secure Development Lifecycle (SDL) Guide.md- Comprehensive security standards and best practices - Style Guidelines:
docs/Style and Design Guidelines.md- Code style and design conventions
This is a personal project and portfolio piece, but I'm open to suggestions and discussions about implementation approaches. If you find a security issue, please report it responsibly by contacting me directly.
This project is personal portfolio work. If you'd like to use portions of the code, please reach out to discuss.
Interested in discussing this project, the technical decisions behind it, or anything I'm reading/watching/listening to?
Let's connect!
- Check out what I'm up to at [mattflathers.com]
- Or email me at [mattflathers27@gmail.com]
Built with ☕ and 🎵 by Matt Flathers and Claude Code
A living demonstration that the best portfolio projects are the ones you actually use.