Unofficial, mobile-first meeting-week companion for 3GPP RAN1 delegates.
It turns the frequently changing RAN1 chair and sub-chair schedule documents into one accurate, searchable, live schedule — and tracks draft / FL-summary activity in the meeting Inbox as it happens.
Schedule and draft information is generated automatically from public 3GPP meeting documents and may contain errors. This project is not affiliated with or endorsed by 3GPP.
For delegates: see How to use this website.
.docx schedules are discovered
recursively under the meeting’s Inbox/, parsed as a block grid (rooms,
parallel tracks, per-agenda-item minute breakdowns, coffee/lunch bands) and
merged with provenance per source document..ics.10.10.10.10 first, falls back to the
Meetings_3GPP_SYNC mirror, then to the last published snapshot, and
de-duplicates the same file arriving on multiple servers.3GPP portal web service ─┐
3GPP FTP (Inbox/*.docx) ─┼─► GitHub Actions ─► Python ingestion ─► public/data/*.json
3GPP FTP (draft tree) ─┘ (ingestion/, draft_tracker/)
│
▼
React + TanStack Start static build
│
┌────────────────────────┴────────────────────────┐
▼ ▼
https://ran1.app (Lovable) http://<venue-host> (GitHub Pages)
│ │
server function proxy for SYNC mirror direct read of 10.10.10.10 on meeting LAN
│
browser also probes 10.10.10.10 when possible
The main app is served by Lovable over HTTPS and uses a server function to crawl
the public 3GPP SYNC mirror. Because browsers block HTTPS pages from fetching
HTTP URLs, a separate plain-HTTP copy is hosted on GitHub Pages for use on the
meeting Wi-Fi; that copy can read the venue server 10.10.10.10 directly.
The twin’s hostname is supplied at build time via the VENUE_HOST repository
variable (VITE_VENUE_HOST). It must be its own separate domain, not a
subdomain of the main site: ran1.app sends HSTS with includeSubDomains,
so any browser that has visited the main site silently upgrades every
*.ran1.app request to HTTPS before it leaves the device — a twin under
ran1.app can never be reached over plain HTTP. Also avoid opening the twin’s
https:// version: GitHub Pages sends its own HSTS header there, which would
pin the twin host for that browser.
ingestion/ — portal discovery, FTP crawling, DOCX block-schedule parsing,
merging, validation, change detection.draft_tracker/ — recursive directory-tree crawl, agenda mapping, snapshot
diffing.src/ — React frontend. Data access is isolated in src/services/.public/data/ — generated public JSON bundles, committed by the workflows.bun install
bun run dev # http://localhost:8080
bun run build # static build (runs the public-data guard first)
bun run check:public-data
bun run lint
Python pipelines:
python -m ingestion.live # refresh meeting + schedule bundles
python -m draft_tracker.crawl # refresh the draft index
| Workflow | What it does | When |
|---|---|---|
.github/workflows/update-schedule.yml |
Re-discovers meetings and re-parses schedules | frequently during a meeting week, sparsely otherwise |
.github/workflows/update-drafts.yml |
Re-crawls the Inbox tree and diffs snapshots | every 10 min during meetings |
.github/workflows/deploy-pages.yml |
Builds and deploys the site | on every push to main |
The site is a static build — no server required, free forever on github.io.
main. The deploy workflow builds, runs the data guard, adds the SPA
404.html fallback and .nojekyll, and publishes.https://<username>.github.io/<repo>/.The workflow resolves the base path automatically:
/<repo>/<username>.github.io repo or a CNAME file present → /BASE_PATH repository variable if neededBecause of this, dropping a custom domain later needs no code change: delete the
CNAME and the next deploy serves correctly from the github.io sub-path.
Everything published is public 3GPP information. Bookmarks, follows, read state,
display name and room presence never leave the device. The rules and the build
guard that enforces them are documented in
docs/data-classification.md;
scripts/check-public-data.mjs fails the build if private data would be shipped.
Community project, provided as-is. Always confirm against the official chair notes before relying on a time or room.