No description
  • Python 33.3%
  • JavaScript 31.1%
  • CSS 26.3%
  • HTML 8.1%
  • Dockerfile 1.2%
Find a file
Freydis Mende 57fb709172
All checks were successful
CI / Lint (push) Successful in 6s
CI / Docker build & push (push) Successful in 3s
CI / Deploy (push) Successful in 1s
ci: push scrape commits with SYNC_PUSH_TOKEN and let ci.yaml deploy
- a personal access token makes the push trigger ci.yaml, so lint,
  build and deploy run there instead of being duplicated in scrape.yaml
2026-10-27 12:02:22 +01:00
.forgejo/workflows ci: push scrape commits with SYNC_PUSH_TOKEN and let ci.yaml deploy 2026-10-27 12:02:22 +01:00
.github fix: run scraper by script path in scheduled workflow 2026-10-24 17:20:24 +02:00
.gitignore Make fleamarkets.ics generation deterministic 2026-08-16 11:27:49 +02:00
.pre-commit-config.yaml add ci magic 2026-06-01 17:03:00 +02:00
default.conf Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
docker-compose.yml Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
Dockerfile Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
fleamarkets.ics chore: scheduled flea market scrape 2026-10-24 15:20:41 +00:00
fleamarkets.json chore: scheduled flea market scrape 2026-10-24 15:20:41 +00:00
ics_export.py Make fleamarkets.ics generation deterministic 2026-08-16 11:27:49 +02:00
index.html Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
pyproject.toml Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
README.md fix: deploy from scheduled scrape when new dates are committed 2026-10-24 17:25:49 +02:00
scrape.py Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
script.js feat: scroll to today's or next flea market on mobile load 2026-10-09 00:08:57 +02:00
style.css Add iCalendar export and scheduled scraping 2026-08-16 10:30:36 +02:00
uv.lock fix lint 2026-06-01 18:00:35 +02:00

Flohmarkt-Kalender

A flea-market calendar for the Flensburg area, live at flohmarkt.freyd.is.

Architecture

Two independent parts:

  • Scraper (scrape.py) — fetches dates from flohmarkt-in-flensburg.de and marktcom.de and writes them to fleamarkets.json. Run manually or on a schedule.
  • Frontend (index.html, style.css, script.js) — vanilla HTML/CSS/JS calendar that reads fleamarkets.json at runtime. Served by nginx via Docker. No build step, no framework.
  • iCalendar export (ics_export.py) — converts fleamarkets.json into fleamarkets.ics, an RFC 5545 feed served alongside the site so it can be subscribed to from calendar apps. Regenerated automatically at the end of every scrape run; run uv run ics_export.py to regenerate it standalone (e.g. after a manual edit to fleamarkets.json).

fleamarkets.json is the contract between scraper and frontend: an array of { "date": "YYYY-MM-DD", "location": string } objects.

Subscribing on iPhone / Apple Calendar

The calendar is published as a live-updating subscription feed at https://flohmarkt.freyd.is/fleamarkets.ics.

  • Tap the "📅 Im Kalender abonnieren" link on the site — Safari hands the webcal:// link straight to the Calendar app.
  • Or manually: Settings → Calendar → Accounts → Add Account → Other → Add Subscribed Calendar, and paste the URL above.

iOS refreshes subscribed calendars periodically (not instantly) — new/changed dates from fleamarkets.json show up automatically after the next scrape + refresh cycle.

Development

Requires Python 3.11+ and uv.

uv sync --group dev   # install runtime + dev deps
pre-commit install    # set up git hooks
uv run scrape.py      # run the scraper

Deployment

The Docker image (nginx:alpine) is built and pushed in CI, then deployed via Portainer webhook.

docker compose up     # run locally

Keeping dates up to date

A scheduled Forgejo Actions workflow (.forgejo/workflows/scrape.yaml) runs the scraper once a day, and commits + pushes fleamarkets.json/fleamarkets.ics if anything changed. Pushes made with the automatic Actions token don't trigger ci.yaml, so the workflow builds and pushes the Docker image and calls the Portainer webhook itself when it committed new data — no manual steps are needed to keep the live calendar current. Trigger it manually anytime via the "Run workflow" button (workflow_dispatch) in the Actions tab.

Requires the repo's Actions token to have contents: write permission (checked under Settings → Actions in this Forgejo instance) — if the scheduled run fails to push, that's the first thing to check.