Skip to content

bmmmm/bitcircus101

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

199 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bitcircus101

bitcircus101 is a tech and creative space located in Bonn, Germany.

This repository contains the website for bitcircus101.

Branches

Branch Purpose
main Source branch — development and PRs go here
live Production branch — served by GitHub Pages. CI actions commit generated files here

Project structure

index.html                  Main landing page
events.html                 Events page (loads events-data.json)
donations.html              Donation / funding page (loads funding.json)
raum-nutzen.html            Room usage info
impressum-datenschutz.html  Legal / privacy
dankedankedanke.html        Thank you page
style.css                   Global styles (terminal theme, dark bg, green accent)

events.js                   Frontend: fetches events-data.json, renders event cards, tag filtering
calendars.json              Calendar source definitions (ICS URLs, names, flags)
funding.json                Current funding percentage (generated by CI)

scripts/
  sync-events.mjs           Fetches ICS from Nextcloud, generates events-data.json + feed.xml

tests/
  site.spec.js              Playwright end-to-end tests (204 tests × 3 browsers)
  sync-events.spec.mjs      Unit tests for ICS parser and RRULE expansion (22 tests)
playwright.config.js        Playwright config (Chromium, Firefox, Mobile Chrome)

.github/workflows/
  deploy.yml                Test on main → deploy to live
  sync-events.yml           Calendar sync (every 15 min)
  update-funding.yml        Funding level update (manual)
  sitemap.yml               Sitemap generation (on push to live)

Generated files (not tracked on main)

These files are created by CI actions and committed to the live branch only:

File Generated by Schedule
events-data.json sync-events.yml Every 30 minutes
feed.xml sync-events.yml Every 30 minutes
sitemap.xml sitemap.yml On push to live
funding.json update-funding.yml Manual trigger

CI / GitHub Actions

Deploy pipeline (deploy.yml)

main (push) → Unit tests → Sync script → Playwright E2E → Deploy to live

Every push to main triggers:

  1. Unit tests: ICS parser, RRULE expansion, date parsing (node:test, 22 tests)
  2. Sync script: Generates events-data.json for E2E tests to use
  3. E2E tests: Playwright across 3 browsers (204 tests)
  4. Deploy (only if all tests pass): Syncs site files from main to live

Nothing reaches production without passing all tests first.

Sync calendar events (sync-events.yml)

  • Trigger: Cron every 30 minutes + manual
  • Branch: Checks out live, pulls scripts/config from main
  • What it does:
    1. Runs scripts/sync-events.mjs (Node 22, zero dependencies)
    2. Fetches ICS feeds from all calendars defined in calendars.json
    3. Parses VEVENT entries, expands RRULE recurrences (weekly, monthly with BYDAY/BYSETPOS)
    4. Filters out internal/blocker events and past events
    5. Generates events-data.json with lastSync timestamp (max 40 cards, 120-day horizon)
    6. Generates feed.xml (RSS 2.0, primary calendar only, max 15 items)
    7. Commits and pushes to live with retry logic

Update funding level (update-funding.yml)

  • Trigger: Manual (workflow_dispatch) with percent input (0-100)
  • Branch: live
  • What it does: Writes funding.json with the given percentage, commits to live

Generate sitemap (sitemap.yml)

  • Trigger: On push to live + manual
  • Branch: live
  • What it does:
    1. Uses cicirello/generate-sitemap to scan all HTML files
    2. Strips Google verification files from the sitemap
    3. Commits sitemap.xml to live

Calendar system

Data sources (calendars.json)

ID Name Nextcloud instance Primary In RSS
bitcircus bitcircus101 nc.6bm.de yes yes
datenburg Datenburg e.V. cloud.datenb.org no no

To add a new calendar, add an entry to calendars.json — no code changes needed.

How events get tagged

Tags are resolved in priority order:

  1. Explicit #hashtags in the Nextcloud event description (e.g. #workshop #hardware)
  2. ICS CATEGORIES field (set in Nextcloud calendar UI)
  3. Keyword auto-detection from title + description (fallback)

If no tags match, the event gets #community as default.

Filtering

  • Events with "blocker" or "interne veranstaltung" in the title are excluded
  • Only future events are shown (up to 120 days ahead)
  • Max 30 events per calendar, 40 total

Frontend (events.js)

  • Loads events-data.json, falls back to live ICS fetch if JSON unavailable
  • Renders event cards grouped by month
  • Dynamic tag filter bar (OR logic: any matching tag shows event)
  • Source badge for non-primary calendar events
  • Permalink anchors with smooth scroll

Local development

Static site — open HTML files directly or use any local server:

python3 -m http.server 8080

Running tests

npm install
npm test                   # all tests (unit + E2E headless)
npm run test:unit          # only unit tests (ICS parser, fast)
npm run test:e2e           # only Playwright E2E
npm run test:headed        # E2E with browser window
npm run test:ui            # Playwright UI mode

Test coverage

Unit tests (tests/sync-events.spec.mjs — 22 tests, ~100ms):

Area What is tested
parseDate All-day dates, datetime with timezone, UTC, null inputs
nthWeekday Nth weekday calculation, month overflow
expandRRule BYSETPOS + classic BYDAY, weekly, COUNT, EXDATE exclusions
parseICS Single events, all-day, TZID params, line folding, recurring BYSETPOS
clean ICS character unescaping (\n, \,, \;)

E2E tests (tests/site.spec.js — 68 tests × 3 browsers = 204):

Area Tests What is tested
Home page 10 Title, h1, ASCII art, carousel, support CTAs, contact, map
SEO / Meta 10 Description, canonical, OG tags, JSON-LD, keywords per page
Privacy 3 No Google Fonts (link tags, preconnect, network requests)
Navigation 3 Desktop links, mobile hamburger toggle, link navigation
Events page 6 Title, event cards load, subscribe buttons, RSS, linkup info
Events content 7 Tags present, filter works, reset, lastSync shown, month groups, Datenburg events
Donations 3 Title, consent banner, banner dismiss
Raum mieten 6 Title, contact CTA, map, JSON-LD, back link
Impressum 2 Title, back link
Danke page 4 Title, content, noindex, back link
Terminal theme 3 Dark background, monospace font, no inline styles
JS errors 6 All 6 pages free of console errors
Internal links 1 Crawls all pages, verifies every internal link resolves
Accessibility 4 Aria-labels, alt texts, footer role

Browsers: Chromium, Firefox, Mobile Chrome (Pixel 5).

Running calendar sync locally

node scripts/sync-events.mjs

This fetches live ICS data and writes events-data.json + feed.xml to the project root.

About

website repo of bitcircus101

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors