A webapp that displays Metacritic movie scores adjusted for critic bias and sample size.
Live Demo: your-app.vercel.app (update after deployment)
- In Theaters: Movies from the last 60 days, ranked by adjusted score
- All Movies: Browse 20,000+ movies with search, genre filter, and year range
- Bias Adjustment: Accounts for individual critic tendencies (some rate higher/lower than average)
- Bayesian Shrinkage: Films with few reviews are pulled toward the overall average
- Daily Updates: Automatic data refresh via GitHub Actions
Raw Metacritic scores can be biased by which critics review a film. This project:
- Estimates critic effects: Using exponentially-weighted averages, we calculate each critic's typical deviation from the metascore
- Applies hierarchical shrinkage: Critics with few reviews are shrunk toward their outlet's average
- Adjusts review scores: Each review is adjusted by subtracting the critic's estimated bias
- Re-averages: Adjusted scores are computed from bias-corrected reviews
- Applies Bayesian shrinkage: Films with few reviews are pulled toward the time-varying grand mean
This results in scores that better reflect the quality signal in reviews rather than who happened to review the film.
- Frontend: React + Vite + Tailwind CSS
- Data Pipeline: Python (pandas, numpy, scipy)
- Hosting: Vercel (free tier)
- Automation: GitHub Actions
- GitHub account
- Vercel account (free at vercel.com)
- Node.js 18+ installed locally
- Python 3.9+ installed locally
-
Create a new GitHub repository (e.g.,
metacritic-adjusted) -
Clone it locally:
git clone https://github.com/YOUR_USERNAME/metacritic-adjusted.git cd metacritic-adjusted -
Copy the webapp files into your repo (all files from this project)
-
Create the data directory structure:
mkdir -p data/metacritic_data mkdir -p data/hierarchical_effects mkdir -p data/adjusted_scores mkdir -p public/data
-
Copy your existing data files:
cp /path/to/metacritic_data/*.csv data/metacritic_data/ cp /path/to/hierarchical_effects/*.csv data/hierarchical_effects/ cp /path/to/adjusted_scores_v2/*.csv data/adjusted_scores/ cp /path/to/webapp_data/*.json public/data/
-
Install dependencies:
npm install
-
Start the dev server:
npm run dev
-
Open http://localhost:5173 in your browser
-
Go to vercel.com and sign in with GitHub
-
Click "Add New Project"
-
Import your
metacritic-adjustedrepository -
Configure the project:
- Framework Preset: Vite
- Build Command:
npm run build - Output Directory:
dist - Install Command:
npm install
-
Click "Deploy"
-
Wait for the build to complete (usually 1-2 minutes)
-
Your app is now live at
https://your-project-name.vercel.app!
The GitHub Actions workflow (.github/workflows/daily-update.yml) will:
- Run at 6 AM UTC every day
- Re-compute adjusted scores from your data
- Commit the updated JSON files
- Trigger a Vercel re-deployment
To enable:
-
Make sure your Python scripts are in the
scripts/directory:cp /path/to/compute_hierarchical_effects.py scripts/ cp /path/to/metacritic_adjusted_scores_v2.py scripts/ cp /path/to/csv_to_json.py scripts/ cp /path/to/fix_dates.py scripts/
-
Push to GitHub:
git add . git commit -m "Initial commit" git push origin main
-
The workflow will run automatically on schedule, or you can trigger it manually:
- Go to your repo on GitHub
- Click "Actions" tab
- Select "Daily Data Update"
- Click "Run workflow"
- In Vercel, go to your project settings
- Click "Domains"
- Add your custom domain
- Follow the DNS configuration instructions
metacritic-adjusted/
├── .github/
│ └── workflows/
│ └── daily-update.yml # GitHub Actions workflow
├── data/
│ ├── metacritic_data/ # Raw movies.csv and reviews.csv
│ ├── hierarchical_effects/ # Computed critic/outlet effects
│ └── adjusted_scores/ # Final adjusted_scores.csv
├── public/
│ └── data/ # JSON files served by the webapp
│ ├── movies_all.json
│ ├── movies_recent.json
│ └── metadata.json
├── scripts/
│ ├── daily_update.py # Main update orchestration
│ ├── compute_hierarchical_effects.py
│ ├── metacritic_adjusted_scores_v2.py
│ ├── csv_to_json.py
│ └── fix_dates.py
├── src/
│ ├── App.jsx # Main React component
│ ├── main.jsx # Entry point
│ └── index.css # Tailwind styles
├── index.html
├── package.json
├── vite.config.js
├── tailwind.config.js
├── postcss.config.js
└── README.md
# 1. Update your raw data (movies.csv, reviews.csv)
# 2. Run the pipeline
python scripts/daily_update.py \
--data-dir ./data/metacritic_data \
--effects-dir ./data/hierarchical_effects \
--scores-dir ./data/adjusted_scores \
--webapp-dir ./public/data \
--scripts-dir ./scripts
# 3. Test locally
npm run dev
# 4. Commit and push
git add .
git commit -m "Update data"
git pushTo add newly scraped movies:
- Append new rows to
data/metacritic_data/movies.csv - Append new reviews to
data/metacritic_data/reviews.csv - Run the update pipeline (effects will be recomputed)
Build fails on Vercel:
- Check that all dependencies are in
package.json - Ensure
public/data/contains the JSON files
Data not loading:
- Check browser console for errors
- Verify JSON files are valid:
python -m json.tool public/data/movies_all.json
GitHub Actions failing:
- Check the Actions tab for error logs
- Ensure Python scripts have no syntax errors
- Verify data file paths are correct
MIT License - feel free to use this for your own projects!
- Data sourced from Metacritic
- Methodology inspired by Bayesian hierarchical models and James-Stein estimation