Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TRMNL Google Photos Plugin

A self-hosted microservice that serves random photos from a Google Photos album to your TRMNL device.

It caches your album's photo manifest in memory (default: 1 hour) so TRMNL never times out waiting for Google to paginate a large album, and every request returns an instantly randomized photo at the exact device resolution.

Architecture

TRMNL Device ──GET /api/photo──▸ This Service ──▸ Google Photos API
                                   (cached)
  • GET /api/photo — Returns a random photo URL + date from your album.
  • GET /api/albums — Utility endpoint to look up your album's internal ID.
  • GET /health — Health check with cache stats.

Prerequisites

  • A Google account with photos in at least one album.
  • Docker & Docker Compose on your server.
  • A local machine with a web browser (one-time OAuth setup).

Setup

Phase 1 — Google Cloud Credentials

  1. Go to the Google Cloud Console and create a new project.
  2. Navigate to APIs & Services → Library and enable the Photos Library API.
  3. Navigate to OAuth consent screen, configure as External, and add your email as a test user.
  4. Navigate to Credentials → Create Credentials → OAuth client ID.
  5. Select Desktop app as the application type.
  6. Download the JSON file and rename it to credentials.json.

Phase 2 — Generate Token (Local Machine)

Your server is headless. You must generate token.json on a machine with a browser, then copy it to the server.

# Install dependencies
pip install google-auth-oauthlib google-api-python-client

# Place credentials.json in this directory, then run:
python auth.py

A browser window will open. Log in and authorize the app. This creates token.json in your working directory.

Phase 3 — Deploy

  1. Copy token.json into a data/ subdirectory on your server:
your-project/
├── app.py
├── auth.py
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── .env
└── data/
    └── token.json
  1. Create your .env file:
cp .env.example .env
  1. Start the container:
docker compose up -d --build

Phase 4 — Configure Album ID

The API requires the internal 64-character Album ID, not the public web URL.

  1. Open http://<your-server-ip>:5050/api/albums in your browser.
  2. Find your target album in the JSON and copy its "id" value.
  3. Paste it into your .env file as ALBUM_ID.
  4. Recreate the container:
docker compose up -d --force-recreate

Phase 5 — Connect to TRMNL

In your TRMNL plugin settings, set:

  • URL: http://<your-server-ip>:5050/api/photo
  • Method: GET
  • Body: (empty)

Environment Variables

Variable Required Default Description
ALBUM_ID Yes — Internal Google Photos album ID
CACHE_TTL No 3600 Seconds to cache the album manifest
PHOTO_WIDTH No 1072 Requested image width (px)
PHOTO_HEIGHT No 1448 Requested image height (px)
TOKEN_PATH No /data/token.json Path to the OAuth token inside the container

API Reference

GET /api/photo

Returns a random photo from the configured album.

Response:

{
  "photo_url": "https://lh3.googleusercontent.com/...=w1072-h1448",
  "relative_date": "2023-08-14"
}

GET /api/albums

Lists all albums in the authenticated Google Photos account. Use this to find your ALBUM_ID.

GET /health

{
  "status": "ok",
  "cached_items": 342
}

Troubleshooting

Token expired / 401 errors The service auto-refreshes expired access tokens. If it still fails, re-run python auth.py locally to generate a fresh token.json and replace the one in data/.

"No photos found in album" Double-check that ALBUM_ID matches the id field from /api/albums (not the URL slug).

Container keeps restarting Check logs: docker compose logs -f photos-agent


License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages