# {{SITE_NAME}}

> {{SITE_NAME}} is a {{CITY_NAME}}-area event aggregator. It crawls ~70 venue and
> organization websites and publishes the combined result as iCalendar
> (.ics) feeds, RSS feeds, and JSON data files. Everything is static and
> regenerated daily.

If you are a programmatic consumer (LLM, script, downstream app), do not
scrape the HTML site. Use the data files listed below instead — they are
the canonical machine-readable view of everything the build publishes.

## Start here

- [index.json](/index.json): HATEOAS-style entry point. Lists every other
  data file with its relative href. Read this first; everything else is
  discoverable from it.

## Data files

- [tags.json](/tags.json): one entry per tag with its category, event
  count, calendar count, and the hrefs of its aggregate ICS/RSS feeds
  (`tag-<slug>.ics`).
- [venues.json](/venues.json): one entry per source with a fixed physical
  location. Each entry has geographic coordinates and the hrefs of its
  calendar feeds. Sources without a single fixed location (e.g. community
  calendars, cross-neighborhood art walks) are intentionally not listed.
  Each entry also carries a `map` object with ready-made links:
  `map.web` is a Google Maps URL (works in any browser, deep-links into
  the maps app on mobile) and `map.osm` — present only when the venue has
  an OSM identity — links to the exact OpenStreetMap feature.
  Venues that resolve cleanly to an OpenStreetMap feature include
  `geo.osmType` (`node` / `way` / `relation`) and `geo.osmId` so you can
  join against OSM. Build the URL as
  `https://www.openstreetmap.org/<osmType>/<osmId>` or query Overpass
  with the same pair. These fields are absent for venues we positioned
  manually without an OSM lookup.
- [manifest.json](/manifest.json): full calendar manifest used by the web
  UI. Lists every ripper, external feed, and recurring-event calendar.
- [events-index.json](/events-index.json): flat array of all events across
  every published calendar, with date, summary, location, and coordinates
  (when available). Events whose location resolved to an OSM feature also
  carry `osmType` / `osmId`. Suitable for full-text search and map display.
- [events-index-soon.json](/events-index-soon.json): a small subset of
  `events-index.json` covering only the next ~9 days, with the `description`
  field omitted. The web UI loads this first for fast first paint, then the
  full index in the background. Prefer `events-index.json` for complete data.
- [events-index.ndjson](/events-index.ndjson): the same events as
  `events-index.json` as newline-delimited JSON, sorted by start date
  ascending, with `description` replaced by `d` — an index into
  `event-descriptions.json`. The first line is a metadata header
  (`{"format":"events-stream/1","generated":...}`), not an event — skip
  any line carrying a `format` field. Designed for streaming consumers:
  parse line by line as bytes arrive; the near-term events are at the top
  of the file. Prefer `events-index.json` unless you specifically want
  the streaming/dictionary form.
- [event-descriptions.json](/event-descriptions.json):
  `{ generated, descriptions }` — unique description strings referenced
  by the `d` field in `events-index.ndjson`
  (`descriptions[event.d]`). Check that `generated` matches the stream
  header before joining the two files; a mismatch means you fetched
  files from two different builds.
- [build-errors.json](/build-errors.json): machine-readable error report
  from the most recent build (per-source parse failures, external feed
  fetch failures, zero-event calendars).
- [geo-cache.json](/geo-cache.json): the committed geocoding cache —
  resolved coordinates for event location strings.

## Aggregate feeds

Every tag in `tags.json` has corresponding `tag-<slug>.ics` and
`tag-<slug>.rss` feeds. Slugs follow the rule `tag.toLowerCase()`
with every non-`[a-z0-9]` character replaced with `-`. See the `links`
field of each tag entry for the exact hrefs.

## Per-calendar feeds

Every entry in `manifest.json` has its own ICS and RSS feed, with hrefs
spelled `<ripper>-<calendar>.ics`, `external-<name>.ics`, or
`recurring-<name>.ics`. The full list with friendly names is in the
manifest.

## Update frequency

The build regenerates daily from the upstream sources. Cached data files
all carry a `generated` ISO-8601 timestamp so you can check freshness.

## Usage notes

- Every href in `index.json`, `tags.json`, and `venues.json` is relative
  to the site root. Resolve against `{{SITE_URL}}/` (or the PR
  preview origin).
- There is no versioning scheme. Schemas are stable; additive changes
  are expected, breaking changes would be announced via the commit log.
- The site is a static deployment on Cloudflare Pages. There is no API
  rate limit, but please cache results rather than re-fetching on every
  request.

## Source

- Code: https://github.com/{{REPO}}
- Issues: https://github.com/{{REPO}}/issues
