Supported OTE spec minors: 0.4, 0.5, 0.6 — the last three published minors,
computed at runtime from PUBLISHED_SPEC_VERSIONS in app.js. Feeds outside
that window still open; see OTE spec version support.
Attendee-facing MVP for OpenTechEvents feeds.
The first version is a static PWA that lets people:
- subscribe to OTE feeds or standalone OTE event URLs;
- discover feeds from pages that expose an OTE
<link rel="alternate">; - filter events by topic, attendance mode, language, country and open CFP;
- switch between card, RSS-like and calendar views;
- save filters and events locally, keeping a saved event even after its feed stops publishing it;
- export single events as
.ics.
The embeddable widget at https://tools.opentechevents.org/embed/ is a good candidate
for sharing presentation code with OTE Reader. Today it consumes a feed URL directly.
OTE Reader keeps feeds and filters in memory, so the clean integration point would be a
future widget API that accepts an already-filtered OTE feed object or event list.
A collection holds the event, not a pointer to it. The reader keeps a copy of each event you save, so a publisher pruning their feed cannot empty your collection — which is what used to happen, silently.
Whether an event's absence means anything is a separate question, and
feed.covers answers it: inside the window a feed declares itself complete
for, an absent event has been withdrawn and the card is badged as such;
outside it, or in a feed without covers, nothing is claimed and nothing is
said. Every other absence — the feed is loading, it failed, it returned a
truncated response — is never presented as a withdrawal.
Nothing is ever deleted on the reader's initiative. Ajustes offers to remove only what can no longer be followed at all: events from feeds you have unsubscribed, and events their feed says it withdrew. Past events are not on that list — a saved past event is the only history the reader has, since the feed no longer carries it. To keep them out of the lists, use the "Solo futuros" filter, which is a view rather than a deletion.
The reader opens a document because of its shape — a declared
specVersion plus events[] for a feed — and uses the version it declares to
decide which rules apply to it. The two questions are kept apart on purpose: a
reader that treats "which version is this?" as "is this OTE?" stops opening
every feed published after it shipped, which is exactly what happened while
the test was specVersion === '0.3.0'.
The support window is the last three minors, computed from
PUBLISHED_SPEC_VERSIONS in app.js rather than listed, so a spec release
moves it by itself. What each case means here:
| Declared | What the reader does |
|---|---|
| The current release | Opens it, says nothing |
| An older supported release | Opens it, notes the version when you open that feed |
| Older than the window | Opens it, warns that fields added later are missing |
| Newer than this build knows | Opens it, warns it is ignoring what it does not recognise |
| Not a published version | Opens it, says so |
None of these refuse the feed, and none of them blames the publisher: running last season's release is a legitimate choice, and a reader's job is to show the events.
That package is the right tool for judging a document — it embeds every published version and measures each one against what it declares. The reader is deliberately not a judge:
- It must be more tolerant than a validator.
validateDocumentreports an out-of-window or unpublished version as an error. Gating on that would make a 0.3.0 feed unopenable and break every feed again on the next spec release — the original bug, reintroduced. - There is no build step. The package is ESM with a per-version dynamic
import()meant for a bundler, ~3.7 MB of compiled validators. Vendoring it or pulling it from a CDN would mean megabytes, or a runtime dependency on a third party for an offline-first PWA's ability to open a file.
What the reader needs from it is the policy, not the schemas, so the
policy is mirrored in app.js with the same vocabulary (current,
outdated, out-of-window). npm run check reads the npm registry and the
published event schema and fails if the mirrored version list or the
feed→event inheritance list has drifted from them.
npm run devThen open http://localhost:8001.
Communities can expose their OTE feed from a website with:
<link rel="alternate" type="application/ote+json" href="/events.json">They can also link directly to the reader with:
https://reader.opentechevents.org/?subscribe=https://example.org/events.json