Projects

SEQTA Link

Self-hosted SEQTA timetable sync. Extract lessons in the browser, keep them in SQLite, subscribe once to an ICS feed.

2026Active

  • Calendar
  • Self-hosted
  • Python

GitHub (opens in a new tab)

Overview

SEQTA Link is a personal timetable bridge. A Tampermonkey userscript reads the SEQTA Learn timetable in the browser, a Flask app stores the lessons, and Apple or Google Calendar subscribe to a stable ICS feed. The subscription URL stays put after each sync.

The backend never sees a SEQTA password.

Problem

The timetable is fine in SEQTA and awkward everywhere else. Repeated exports create duplicates, cancelled lessons linger, and a partial week fetch should not wipe the rest of the term.

How it works

  • The userscript pairs with a device token and posts lessons to /api/v2.
  • Sync is idempotent: stable UIDs, natural keys, and deletes only when coverage is complete.
  • Calendar clients hit an opaque /calendar/sl_cal_….ics URL with ETag / 304 support.
  • A small Jinja portal covers login, devices, and feed rotation. Registration is invite-only.

Implementation

Python 3.11, Flask 3, SQLAlchemy 2, SQLite in WAL mode. Tests run under pytest. An older Node / Fastify / PostgreSQL stack is gone; v3 is this Flask app.