Skip to content

nichtlegacy/letterboxd-graph

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

448 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎬 Letterboxd Contribution Graph

GitHub Workflow Status GitHub Release Made with Node.js JavaScript License

Transform your Letterboxd film diary into a beautiful GitHub-style contribution graph

Letterboxd contribution graph


✨ Features

Feature Description
🎨 Light & Dark Themes Automatically adapts to GitHub's theme preference
πŸ“Š Activity Heatmap GitHub-style contribution graph showing film activity
πŸ‘€ Profile Integration Shows profile picture, display name, stats, and member badge
πŸ† Pro/Patron Badges Displays Letterboxd Pro (orange) or Patron (cyan) status
πŸ“… Multi-Year Support Generate graphs spanning multiple years
🎯 Streak Highlighting Hover over "Day Streak" to highlight your longest streak
πŸ’¬ Interactive Tooltips Hover over cells to see film details (in browser)
⭐ Rating Mode Color cells by average rating instead of watch count
πŸ“¦ JSON Export Writes images/letterboxd-data.json for external widgets (e.g. Glance custom-api)
πŸ”„ Daily Updates Automated updates via GitHub Actions

πŸš€ Quick Start

1. Fork this Repository

Click the Fork button at the top-right of this page.

2. Update Your Username

Edit .github/workflows/update-graph.yml:

- run: npm start YOUR_LETTERBOXD_USERNAME -o images/github-letterboxd

3. Enable GitHub Actions

Go to Actions tab β†’ Enable workflows if prompted.

4. Run the Workflow

The graph updates daily at midnight UTC, or trigger manually via the Actions tab.


πŸ“Έ Examples

Patron User (Single Year)

Pro User (Single Year)

Multi-Year Graph

Interactive Features

Hover over stats to reveal additional information (visible when opening the SVG in a browser):

Day Streak Highlight Days Active Tooltip Film Count Tooltip

πŸ“– CLI Usage

# Install dependencies
npm install

# Basic usage
node src/cli.js <username>

# With options
node src/cli.js <username> [options]

Arguments

Flag Description Default
-y <years> Year(s) to generate, comma-separated (e.g. 2024,2023) Current year
-w <day> Week start: sunday or monday sunday
-o <path> Output path (without extension) images/github-letterboxd
-g <bool> Enable username gradient: true or false true
-p Export PNG files in addition to SVG Disabled
-m <mode> Graph mode: count or rating count

Examples

# Single year with custom output
node src/cli.js nichtlegacy -y 2025 -o images/my-graph

# Multiple years (2024 + 2025)
node src/cli.js nichtlegacy -y 2025,2024

# Start week on Monday, no gradient
node src/cli.js nichtlegacy -w monday -g false

# Rating mode with PNG export
node src/cli.js nichtlegacy -m rating -p

πŸ”§ GitHub Actions Setup

Workflow File

Create .github/workflows/update-graph.yml:

name: Update Letterboxd Graph

# ╔════════════════════════════════════════════════════════════════╗
# β•‘  CONFIGURATION - Edit these values for your Letterboxd profile β•‘
# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
env:
  LETTERBOXD_USERNAME: "YOUR_USERNAME" # Replace with your username
  YEARS: ""                            # e.g. "2025,2024" or leave empty for current year
  EXPORT_PNG: "false"                  # Set to "true" to also generate PNG files
  WEEK_START: "sunday"                 # "sunday" or "monday"
  GRADIENT: "true"                     # "true" for colored name, "false" for white

on:
  schedule:
    - cron: "0 0 * * *"   # Daily at midnight UTC
  workflow_dispatch:       # Manual trigger

permissions:
  contents: write

jobs:
  update-graph:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - run: npm ci
      
      - name: Generate Graph
        run: |
          # Build command based on configuration
          CMD="node src/cli.js ${{ env.LETTERBOXD_USERNAME }} -o images/github-letterboxd"
          
          if [ -n "${{ env.YEARS }}" ]; then CMD="$CMD -y ${{ env.YEARS }}"; fi
          if [ "${{ env.WEEK_START }}" = "monday" ]; then CMD="$CMD -w monday"; fi
          if [ "${{ env.GRADIENT }}" = "false" ]; then CMD="$CMD -g false"; fi
          if [ "${{ env.EXPORT_PNG }}" = "true" ]; then CMD="$CMD -p"; fi
          
          echo "Running: $CMD"
          eval $CMD

      - name: Commit and Push
        run: |
          git config --global user.name 'github-actions[bot]'
          git config --global user.email 'github-actions[bot]@users.noreply.github.com'
          git add images/
          
          if git diff --staged --quiet; then
            echo "No changes to commit"
          else
            git commit -m "Update Letterboxd graph"
            git push
          fi

Configuration

You can customize the graph directly in the workflow file by editing the env section at the top:

  • LETTERBOXD_USERNAME: Your Letterboxd profile name
  • YEARS: Comma-separated list of years (e.g., 2025,2024)
  • EXPORT_PNG: Set to true if you want PNG versions alongside SVGs
  • WEEK_START: Start week on sunday or monday
  • GRADIENT: Toggle the username text gradient

Glance Widgets (custom-api)

The generator also writes images/letterboxd-data.json, so you can build Glance widgets without running an extra backend container.

Raw URL format:

https://raw.githubusercontent.com/<github-user>/letterboxd-graph/main/images/letterboxd-data.json

Example payload shape:

{
  "user": "nichtlegacy",
  "year": 2026,
  "stats": { "films": 123, "daysActive": 80, "streak": 7 },
  "cells": [
    {
      "date": "2026-02-16",
      "count": 2,
      "ratingAvg": 3.5,
      "films": [
        { "title": "Film A", "year": "2024", "rating": 3.5, "url": "https://letterboxd.com/..." }
      ],
      "url": "https://letterboxd.com/<user>/films/diary/for/2026/02/16/"
    }
  ],
  "recent": [
    { "date": "2026-02-16", "title": "Film A", "year": "2024", "rating": 3.5, "url": "https://letterboxd.com/..." }
  ]
}

You can use this to build:

  • a compact heatmap widget (GitHub-like)
  • a separate stats widget (films, daysActive, streak)
  • an optional recent-watches list

πŸ“‚ Project Structure

letterboxd-graph/
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ assets/               # README images and examples
β”‚   └── workflows/
β”‚       └── update-graph.yml  # GitHub Actions workflow
β”œβ”€β”€ fonts/
β”‚   β”œβ”€β”€ Inter-Bold.ttf
β”‚   β”œβ”€β”€ Inter-Medium.ttf
β”‚   β”œβ”€β”€ Inter-Regular.ttf
β”‚   └── Inter-SemiBold.ttf    # Primary font for text measurement
β”œβ”€β”€ images/
β”‚   β”œβ”€β”€ github-letterboxd-dark.svg    # Generated dark theme
β”‚   β”œβ”€β”€ github-letterboxd-light.svg   # Generated light theme
β”‚   └── letterboxd-data.json          # Generated JSON data for widgets
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ cli.js                # CLI entry point
β”‚   β”œβ”€β”€ fetcher.js            # Letterboxd data fetching
β”‚   β”œβ”€β”€ generator.js          # SVG generation
β”‚   β”œβ”€β”€ stats.js              # Statistics calculations
β”‚   └── exporter.js           # PNG export functionality
β”œβ”€β”€ package.json
└── README.md

πŸ–ΌοΈ Embed in Your README

Add this to your profile README to display the graph with automatic theme switching:

<p align="center">
  <a href="https://letterboxd.com/YOUR_LETTERBOXD_USERNAME/" target="_blank">
    <picture>
      <source
        media="(prefers-color-scheme: dark)"
        srcset="https://github.com/YOUR_GITHUB_USERNAME/letterboxd-graph/blob/main/images/github-letterboxd-dark.svg"
      />
      <source
        media="(prefers-color-scheme: light)"
        srcset="https://github.com/YOUR_GITHUB_USERNAME/letterboxd-graph/blob/main/images/github-letterboxd-light.svg"
      />
      <img
        alt="Letterboxd contribution graph"
        src="https://github.com/YOUR_GITHUB_USERNAME/letterboxd-graph/blob/main/images/github-letterboxd-light.svg"
      />
    </picture>
  </a>
</p>

Replace YOUR_GITHUB_USERNAME and YOUR_LETTERBOXD_USERNAME with your usernames.


🎨 Themes & Modes

Graph Modes

Mode Description
Count (default) Cell color intensity based on number of films watched
Rating Cell color based on average rating of films that day

Member Badges

The graph automatically detects and displays your Letterboxd membership status:

Status Badge Color Location
Pro Orange (#ff8000) Bottom-left of profile picture
Patron Cyan (#40bcf4) Bottom-left of profile picture

πŸ› οΈ Requirements

  • Node.js v18 or higher
  • Public Letterboxd profile with diary entries
  • GitHub account with Actions enabled (for automated updates)

🀝 Contributing

Contributions are welcome! Feel free to:

  • πŸ› Report bugs
  • πŸ’‘ Suggest features
  • πŸ”§ Submit pull requests

πŸ“„ License

MIT License - see LICENSE for details.

About

Generates a GitHub-style contribution graph based on your Letterboxd diary. Uses Node.js to scrape data, process entries, and create daily updated SVG visuals via GitHub Actions.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors