Across the Eras — rewatch guides for the shows you keep going back to
  • JavaScript 94.2%
  • CSS 3.2%
  • HTML 1.4%
  • Python 1%
  • Dockerfile 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-29 08:54:28 +00:00
.forgejo/workflows ci: build on Forgejo Actions, push to the Forgejo registry 2026-09-29 04:53:12 -04:00
assets Redesign site with rewatch archive identity 2026-09-02 18:20:11 -04:00
docs Add story map preview and streamline assistant docs 2026-09-02 18:50:19 -04:00
k8s deploy: pin image sha-e5ff36a 2026-09-29 08:54:28 +00:00
mcp Merge remote-tracking branch 'origin/main' into feature/community-show-submissions 2026-09-02 17:53:39 -04:00
scripts Redesign site with rewatch archive identity 2026-09-02 18:20:11 -04:00
shows Merge main and regenerate show index 2026-09-29 03:49:47 +00:00
.dockerignore feat: MCP server at /mcp + shared filter.js engine + /docs/ page 2026-08-16 08:04:28 -04:00
.gitignore feat: MCP server at /mcp + shared filter.js engine + /docs/ page 2026-08-16 08:04:28 -04:00
app.js Add story map preview and streamline assistant docs 2026-09-02 18:50:19 -04:00
CONTRACT.md ci: build on Forgejo Actions, push to the Forgejo registry 2026-09-29 04:53:12 -04:00
Dockerfile feat: accept community show proposals via MCP 2026-09-02 17:48:01 -04:00
entrypoint.sh feat: MCP server at /mcp + shared filter.js engine + /docs/ page 2026-08-16 08:04:28 -04:00
filter.js Rebrand Across the Eras to skipto.tv (#4) 2026-09-02 17:42:25 -04:00
index.html Add story map preview and streamline assistant docs 2026-09-02 18:50:19 -04:00
nginx.conf feat: accept community show proposals via MCP 2026-09-02 17:48:01 -04:00
README.md ci: build on Forgejo Actions, push to the Forgejo registry 2026-09-29 04:53:12 -04:00
styles.css Add story map preview and streamline assistant docs 2026-09-02 18:50:19 -04:00
SUBMISSIONS.md feat: accept community show proposals via MCP 2026-09-02 17:48:01 -04:00

skipto.tv 📺

Rewatch guides for the shows you keep going back to — one app, many shows. Live at https://skipto.tv

Every show gets an interactive era chart (showrunners, arcs, big bads, rosters, real-world events…) sitting on top of every episode; every bar on the chart is a filter. Plus vibes, guest-character filters, full-text search, watched tracking, 🎲 Surprise me, shareable filter URLs, and a mobile filter drawer.

Successor to the single-show sites moose-and-squirrel (Supernatural), goat-gideon (Criminal Minds) and greater-fool (The Newsroom), which are imported here unchanged.

Layout

index.html, app.js, styles.css     the shell: landing page at /, explorer at /<slug>/
filter.js                          the filter engine (matching + share-URL format), shared by app.js AND mcp/
mcp/server.js, load.js, test.js    MCP server (Streamable HTTP at /mcp) exposing filters + show proposals
mcp/submissions.js                 validates declarative proposals and opens review PRs through a GitHub App
docs/index.html                    /docs/ — plain-language "use it from your AI assistant" page
shows/<slug>/show.json             branding + metadata          ┐
shows/<slug>/episodes.json         TVmaze episodes              │ one self-contained
shows/<slug>/cast.json             TVmaze guest cast            │ package per show
shows/<slug>/eras.js               the chart (ERAS/ERA_CATS/…)  │
shows/<slug>/tags.js               curated vibes                ┘
shows/index.json                   generated by scripts/build-index.py — the landing page reads it

Run locally

python3 scripts/dev-server.py 8770     # SPA fallback so /<slug>/ works; then open http://localhost:8770

Add a show

Read CONTRACT.md. In short: create shows/<slug>/ with the five files above (copy the scripts and formats from an existing show), run python3 scripts/build-index.py, commit. CI fails if shows/index.json is stale.

MCP

https://skipto.tv/mcp — MCP Streamable HTTP, stateless, no user auth. Tools: list_shows, get_show, find_episodes, get_episode, search_characters, surprise_me, next_episode, share_link, get_submission_guide, submit_show; resources skipto://shows[/<slug>/{chart,tags,episodes}]. It loads the same shows/ files the site serves and runs the same filter.js, so tool results and the UI always agree, and every result carries a #… share URL the site understands (incl. ep=S05E16 to open an episode card). Human docs at /docs/. submit_show accepts only declarative JSON, generates the repository files on the server, and opens a GitHub PR for review; see SUBMISSIONS.md. Tool calls are tracked in the same PostHog project as mcp_* events with surface: mcp.

cd mcp && npm ci && npm test        # filter.js semantics + end-to-end MCP client run, no network needed
PORT=8081 node mcp/server.js        # local server; SITE_ORIGIN / SHOWS_DIR / POSTHOG_KEY env override

Deploy

git.inevitable.fyi/jhgaylor/across-the-eras (node:24-alpine + nginx: nginx on :8080 serves the site and proxies /mcp to the node MCP server on :8081 in the same container — see entrypoint.sh; /healthz, try_files … /index.html), built by .forgejo/workflows/build.yml (Forgejo Actions) on push to main, which pins the new sha-* tag into k8s/deployment.yaml; home-cloud's Flux reconciles k8s/ to skipto.tv. The legacy operational names remain in place to avoid a disruptive infrastructure migration.

Analytics

One PostHog project (US). Every event carries a show super-property (landing on the picker). Autocapture is off; explicit events: show_selected, era_selected, season_selected, vibe_selected, character_selected, searched, sort_changed, filters_reset, surprise_me, episode_opened, watched_toggled, chart_toggled, filters_drawer_opened.