This repository contains:
- a GitHub Action that scrapes a public Letterboxd watchlist, picks a weekly movie, creates a Google Calendar event, and publishes a JSON feed for clients
- a separate Android app in
android-app/that reads the published weekly movie feed and updates the lock screen wallpaper
The default watchlist is:
https://letterboxd.com/coderang/watchlist/
This project supports two ways to use it:
-
Simple app + local calendar The GitHub Action picks the movie and publishes
latest-movie.json. The Android app reads that feed, applies the wallpaper, and adds the event to the user's calendar directly on the phone. Jump to Simple Setup. -
Full automation with Google Calendar bot The GitHub Action picks the movie, publishes the feed, and also creates the Google Calendar event automatically using a service account. Jump to Full Automation Setup.
For most users, the simple setup is the better default.
- Fork this repository.
- Enable GitHub Actions in the fork.
- Add the
LETTERBOXD_WATCHLIST_URLrepository variable. - Add
TMDB_API_KEYif you want proper TMDb poster art. - Run the workflow once manually.
- Confirm that
public/latest-movie.jsonwas updated. - Download and install the latest Android app release from the repository's Releases page.
- Paste your published feed URL into the app.
- Use the app to apply wallpaper and add the movie to your calendar locally.
Wallpaper preview, movie details, and local calendar add flow
If you want the GitHub Action to create Google Calendar events automatically as well:
- Fork this repository.
- Set up a Google Cloud project, service account, and a Google Calendar the bot can edit.
- Add the required GitHub repository secrets.
- Add the
LETTERBOXD_WATCHLIST_URLGitHub repository variable. - Push to
mainand run the workflow once manually. - Confirm that
public/latest-movie.jsonwas updated and that a calendar event was created. - Install the Android app from
android-app/and point it to your published JSON feed if needed.
- Scrapes the Letterboxd watchlist HTML directly.
- Follows paginated watchlist pages until no more movie cards are found.
- Picks one deterministic weekly movie from the collected results based on the Sunday event date, so reruns do not reshuffle the week.
- Creates a Google Calendar event for the selected movie.
- Publishes the selected movie to
public/latest-movie.jsonfor other clients, including the Android wallpaper app. - Uses a stable event ID so rerunning the workflow does not create duplicates for the same movie on the same date.
The workflow lives at:
.github/workflows/random-letterboxd-calendar.yml
It supports:
- Weekly scheduled runs every Sunday at
22:30in theAsia/Kolkatatimezone. - Manual runs with optional inputs for watchlist URL, event date, timezone, start time, duration, and dry-run mode.
By default, the workflow creates a calendar event for 22:30 in Asia/Kolkata with a duration of 150 minutes.
When the workflow runs with dry_run = false, it also updates:
public/latest-movie.json
That file is intended to be consumed by the Android app and other lightweight clients.
Add these repository secrets in GitHub:
GOOGLE_CALENDAR_IDGOOGLE_SERVICE_ACCOUNT_EMAILGOOGLE_PRIVATE_KEYTMDB_API_KEY
Add this repository variable in GitHub:
LETTERBOXD_WATCHLIST_URL
- Fork this repository to your own GitHub account.
- Open your fork on GitHub.
- Make sure GitHub Actions are enabled for the repository.
- Use the
mainbranch as the branch that publishespublic/latest-movie.json.
- In Google Cloud, create a project and enable the Google Calendar API.
- Create a service account and generate a private key for it.
- Copy the service account email into
GOOGLE_SERVICE_ACCOUNT_EMAIL. - Copy the private key PEM into
GOOGLE_PRIVATE_KEY. - Share the target Google Calendar with the service account email and grant it permission to make changes to events.
- Put that calendar's ID into
GOOGLE_CALENDAR_ID.
If you want the action to write into a Workspace user's calendar without manually sharing a calendar to the service account, use domain-wide delegation instead of the simple shared-calendar setup.
- Open Google Calendar in the browser.
- In the left sidebar, find the calendar you want the action to write into.
- Open that calendar's settings.
- Under
Integrate calendar, copy theCalendar ID. - For a primary personal calendar, the ID is often your Gmail address.
- Copy your service account email.
- In Google Calendar, open
Settings and sharingfor the target calendar. - Under
Share with specific people or groups, add the service account email. - Grant it
Make changes to events.
Without writer access, Google Calendar will reject event creation with a 403 requiredAccessLevel error.
In your fork, go to Settings -> Secrets and variables -> Actions and add:
GOOGLE_CALENDAR_ID: your calendar IDGOOGLE_SERVICE_ACCOUNT_EMAIL: the service account emailGOOGLE_PRIVATE_KEY: the full private key value from the service account JSONTMDB_API_KEY: your TMDb API key for true poster images
For GOOGLE_PRIVATE_KEY, paste the full key including the BEGIN PRIVATE KEY and END PRIVATE KEY lines.
In your fork, go to Settings -> Secrets and variables -> Actions -> Variables and add:
LETTERBOXD_WATCHLIST_URL: your public Letterboxd watchlist URL
Example:
https://letterboxd.com/your-username/watchlist/
Scheduled runs will use this automatically.
If you manually run the workflow from GitHub Actions, the optional watchlist_url input still overrides this value for that one run.
You can edit:
- scripts/random-letterboxd-calendar.mjs to change defaults
- .github/workflows/random-letterboxd-calendar.yml to change the schedule
Common customizations:
- change the scheduled day and time
- change the timezone
- change the event duration
- Open the
Actionstab in GitHub. - Open the
Random Letterboxd Calendarworkflow. - Click
Run workflow. - Start with
dry_run = trueif you only want to test scraping and selection. - Run again with
dry_run = falsewhen you want to create the calendar event and publish the JSON feed.
Check these places:
- The workflow run logs in GitHub Actions.
- Your Google Calendar for a new
Watch: ...event. - public/latest-movie.json in your repository.
You should see:
- the selected movie title and year
- the generated event date and time
- the poster URL
- the synopsis and metadata
The app uses the raw GitHub URL for public/latest-movie.json.
Default format:
https://raw.githubusercontent.com/<your-github-username>/<your-repo-name>/main/public/latest-movie.json
If you changed the repository name or owner, update the feed URL inside the Android app.
Run the workflow from the GitHub Actions tab with:
dry_run = trueto verify scraping and random selection without creating a calendar event.
Or run the script locally:
DRY_RUN=true node scripts/random-letterboxd-calendar.mjsTo verify the published JSON locally:
cat public/latest-movie.jsonThe Android app lives in:
android-app/
It:
- fetches the published movie JSON from the repo
- previews the latest weekly movie
- applies the poster as the lock screen wallpaper
- uses
WorkManagerto check daily for a new weekly movie ID and only updates when the published movie changes
See:
android-app/README.md
For Android setup, install, signing, and release steps, see:
- The scraper relies on Letterboxd watchlist poster cards exposing
data-item-nameanddata-target-linkin the page HTML. - The film synopsis/poster enrichment comes from public metadata on each Letterboxd film page.
- If
TMDB_API_KEYis configured, the workflow prefers TMDb poster art so the Android wallpaper app gets a true movie poster instead of a share-style image. - The script uses only built-in Node.js modules, so there are no npm dependencies to install.