No description
  • Python 98.4%
  • Dockerfile 1.6%
Find a file
2026-05-16 08:43:49 -04:00
.env.example Add feed.gmi generation and Gemini antenna pings 2026-05-16 08:33:36 -04:00
.gitignore Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00
.python-version Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00
CLAUDE.md Update README and CLAUDE.md for feed and antenna features 2026-05-16 08:43:49 -04:00
compose.yml Run container as non-root user via configurable UID/GID 2026-05-16 07:25:55 -04:00
db.py Add feed.gmi generation and Gemini antenna pings 2026-05-16 08:33:36 -04:00
Dockerfile Run container as non-root user via configurable UID/GID 2026-05-16 07:25:55 -04:00
feed.py Add feed.gmi generation and Gemini antenna pings 2026-05-16 08:33:36 -04:00
gts.py Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00
main.py Add feed.gmi generation and Gemini antenna pings 2026-05-16 08:33:36 -04:00
pyproject.toml Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00
README.md Update README and CLAUDE.md for feed and antenna features 2026-05-16 08:43:49 -04:00
tinylog.py Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00
uv.lock Initial implementation of GTS → Gemini tinylog generator 2026-05-16 07:13:28 -04:00

tinylog

Generates and keeps a tinylog-format .gmi file from public posts on a GoToSocial instance, for serving on a Gemini capsule. Connects to the GoToSocial streaming API for real-time updates and handles adds, edits, and deletes.

Features

  • Real-time streaming via GoToSocial WebSocket API (no polling)
  • Full backfill of existing public posts on first run
  • Propagates edits and deletes
  • Self-reply threads collapsed into a single tinylog entry with a [continued] separator
  • HTML-to-gemtext conversion: lists, blockquotes, preformatted blocks, footnote-style links
  • Skips posts with content warnings, replies to other accounts, non-public posts, local-only posts, and posts that mention other accounts
  • Atomically writes the .gmi file so Agate never serves a partial result
  • Regenerates the full file on every startup (safe to restart after config changes)
  • Generates a feed.gmi compatible with Gemini antenna aggregators and pings them on every update

Setup

cp .env.example .env
# fill in .env
docker compose up --build -d

Map the output file into your Agate content directory via a volume in compose.yml:

volumes:
  - ./data:/app/data
  - /var/gemini/capsule/tinylog.gmi:/app/tinylog.gmi

Configuration

All configuration is via environment variables (.env):

Variable Required Default Description
GTS_BASE_URL yes Your GoToSocial instance URL
GTS_ACCESS_TOKEN yes OAuth bearer token with read scope
TINYLOG_TITLE no Tinylog Level-1 heading in the .gmi file
AUTHOR_NAME no Author name for the author: metadata line
AUTHOR_CAPSULE no Gemini capsule URL for the author: metadata line
AUTHOR_AVATAR no Avatar emoji (optionally followed by a description)
AUTHOR_DESCRIPTION no Free-text description shown below the title
TINYLOG_PATH no /app/tinylog.gmi Output path inside the container
FEED_PATH no Output path for feed.gmi; required to enable feed generation
FEED_TITLE no Link label in feed.gmi (e.g. Microblog); required to enable feed generation
FEED_URL no Full Gemini URL of feed.gmi; sent to antenna endpoints
ANTENNA_URLS no Comma-separated Gemini antenna submit URLs to ping on each update
SYNC_SINCE no now First-run behaviour (see below)
LOG_LEVEL no INFO DEBUG, INFO, WARNING, ERROR

GTS access token

Create an application on your GoToSocial instance and complete the OAuth flow to obtain a bearer token with read scope. No write scope is needed.

SYNC_SINCE (first run only)

Controls what happens the very first time the program runs against an empty database. Ignored on subsequent starts.

Value Behaviour
now (default) Sets a watermark at the current latest post; no historical posts are included
all Backfills everything GoToSocial can return (paginated)
2024-05-01 Backfills posts from that date onward (ISO date or datetime)

Development

# Run locally (requires .env)
uv run python main.py

# Override sync behaviour
SYNC_SINCE=all uv run python main.py

There are no automated tests in this project.