Movies: rework schema for new upstream + add Category/Type filters#1425
Merged
andygrunwald merged 9 commits intomainfrom May 5, 2026
Merged
Movies: rework schema for new upstream + add Category/Type filters#1425andygrunwald merged 9 commits intomainfrom
andygrunwald merged 9 commits intomainfrom
Conversation
The awesome-software-engineering-movies repository reshaped its generated
JSON: a single `link` is now a `links` map (youtube/netflix/bpb/...), new
`category` and `type` fields drive the taxonomy, IMDb ratings live under
`ratings.imdb`, and per-language overrides come through a `localized` map.
Several previously-required fields (duration, publishedAt, channel,
language) can now be empty for non-YouTube entries. The build was failing
under the old Zod schema, so this commit aligns the Astro side with the
new shape and reworks the consuming UI in one step.
Schema change in src/content.config.ts:
- link/videoID/viewCount removed
- links: open record of platform -> URL
- category, type: open strings (display labels live in JS)
- language, subtitles: nullable arrays
- ratings.youtube, ratings.imdb, views.youtube, imdbID,
youtubeTrailerForThumbnail, localized: optional
- duration / publishedAt / channel.* allowed empty
src/scripts/movie-labels.js owns the German translation maps so the JSON
stays in English (no upstream churn) while the UI reads German. It also
exports the label-driven slug helpers used by the per-category and
per-type listing pages, plus localizedTitle/Description that prefer
movie.data.localized.de fields when present and fall through name/title
otherwise.
The card now:
- links category and type badges to the new listing pages
- renders tags as plain (unlinked) chips
- shows every entry in `links` as its own platform button (YouTube has
a brand SVG today; the rest fall back to a generic external-link icon)
- hides Dauer/Veröffentlicht/Sprache/Untertitel rows when the data is
empty
- shows an IMDb rating row formatted with German number formatting when
ratings.imdb is present
- exposes data-category / data-type for client-side filtering
Per-tag page is gone. Two new static routes take its place:
/filme-fuer-softwareentwickler/kategorie-<de-slug>/
/filme-fuer-softwareentwickler/typ-<de-slug>/
Slugs are derived from the German display label (kategorie-programmiersprachen,
typ-dokumentation), keeping URLs in line with the rest of the German UI.
The page filters use the raw English data value carried in props.
JSON-LD was tightened up to drop fields that may no longer be present and
to emit aggregateRating from ratings.imdb when available.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the /deutsche-tech-podcasts/ filter pattern: two inline <select>
dropdowns above the listing, a small client-side script that toggles
.hidden on each .movie section based on data-category and data-type, and
a "Leider passt kein Film zu deinen Filterkriterien :(" fallback section
when no entry matches. The filter bar starts invisible and is unhidden on
DOMContentLoaded so the static, no-JS page still shows every movie.
Dropdown options are sourced from the actual data so brand-new categories
or types show up the next sync without code changes. Labels in the
dropdowns are German via the CATEGORY_LABELS / TYPE_LABELS maps; the
underlying option value is the raw English string the cards carry in
their data attributes, so the comparison stays trivial.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The new upstream snapshot expanded the unique-tag list from 27 to 51 entries (Privacy, Social Media, Politics, Content Moderation, Ethics, ... appear with the Culture-themed documentaries). Re-run "./website-admin tags find awesome-software-engineering-movies --write-file" to add stubs for the new tags and refresh usage_count across the board. SEO descriptions are left blank for the editorial team to fill in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for nifty-bardeen-5c7e53 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
The card now shows recognisable brand artwork for the streaming
platforms that already appear in the upstream data, instead of falling
back to a generic external-link icon.
- Netflix wordmark from simple-icons (CC0), tinted with the brand red
#E50914 since simple-icons ships path-only SVGs.
- Amazon Prime Video wordmark from Wikimedia Commons.
Both files live next to the existing youtube.svg under
public/images/brands/. movie-labels.js' KNOWN_BRAND_ICONS set was
extended so iconFor() picks them up automatically.
Drive-bys requested in the same review:
- Removed `disneyplus` from LINK_PLATFORM_LABELS and from the
PLATFORM_ORDER constants in the card component and the JSON-LD
builder. There's no entry on disneyplus today and dragging the slug
around just invites a stale fallback icon if one ever appears.
- Replaced the abbreviated `bpb` label with the full
"Bundeszentrale für politische Bildung" so visitors who don't know
the acronym still get the context.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a movie carries an imdbID, wrap the literal "IMDb" word in the ratings line in an anchor that points at https://www.imdb.com/title/<id>/. Visitors who want to read user reviews or check the cast can do so with one click instead of having to search for the title manually. Falls back to plain text when imdbID is absent (in practice the upstream couples imdbID with ratings.imdb, but the guard keeps the markup safe if that ever drifts). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Above the headline only the Category and Type stay — those are the high-signal navigation entry points and they were getting visually crowded out by 4-6 tag chips per card. Tags move into a "Tags:" row in the same <ul> as Dauer / Veröffentlicht / Sprache, keeping the badge styling for visual consistency. The row only renders when the entry actually has tags. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The upstream `title` field often carries a marketing subtitle, e.g.
"Angular: The Documentary | An origin story". The `name` field is the
short canonical version ("Angular: The Documentary") and reads better in
the listing where the headline already competes with badges, tags and
the description. Reorder localizedTitle's fallback chain so `name` wins
over `title`; the German `localized.de.title` override still takes
precedence for entries like The Great Hack ("Cambridge Analyticas großer
Hack").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adding the Tags and IMDb rows to the metadata bullet list pushed the total card height up enough that the 600-character description was crowding everything below it off screen on the listing. 400 is a more balanced teaser length now that more metadata sits inside each card. Pass the override at the call site rather than retuning truncateDescription's default — the helper stays generic for any future non-movie caller. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Upstream descriptions are scraped verbatim from the source platform and frequently contain http(s):// URLs (e.g., a Patreon link in the IRC documentary blurb, a Laravel-swag bit.ly in the Laravel origin story, an IMDb back-link in Revolution OS). Rendering them as plain text was unhelpful — visitors who want to follow the reference had to copy the URL by hand. Add a small `linkify` helper to src/scripts/text.js that splits a string into a sequence of plain-text and URL segments, stripping trailing sentence punctuation off the matched URL so "...visit https://x.com." doesn't link the period. The movie preview component then renders each segment, wrapping link segments in an <a target="_blank" rel="noopener">. Truncation still happens before linkification, so the smart-cut keeps URLs whole (URLs contain no whitespace, so the cut moves past them) and the helper sees exactly what gets rendered. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Upstream
awesome-software-engineering-moviesreshaped itsgenerated/JSON: a singlelinkis now alinksmap, newcategory/typefields drive the taxonomy, IMDb ratings and per-language overrides arrived, and several previously-required fields (duration,publishedAt,channel,language) can now be empty for non-YouTube entries (Netflix/bpb/...).The Astro build was failing under the old Zod schema. This PR realigns the website with the new upstream shape, replaces the per-tag listing pages with per-category and per-type pages, and adds two client-side filters on the movies index in the same style as
/deutsche-tech-podcasts/.Three commits
src/scripts/movie-labels.js), reworked card (linked Category + Type badges, multi-platform link buttons, IMDb row, hide-empty rows, localized title/description vialocalized.de), per-category and per-type static pages with German URL slugs (/kategorie-programmiersprachen/,/typ-dokumentation/), per-tag page deleted. JSON-LD adapted to drop fields that may be empty and to emitaggregateRatingfromratings.imdb.<select>dropdowns; client-sidepublic/js/movie-listing-filter.jsthat AND-combines the two filters by toggling.hiddenon each.moviesection viadata-category/data-type. Dropdown labels are German; option values are the raw English data values.tags find --write-file.Schema changes (
src/content.config.ts)link/videoID/viewCountremovedlinks: z.record(z.string(), z.string().url())category,type: open strings (display labels live in JS)language,subtitles: nullable arraysratings.youtube/ratings.imdb/views.youtube/imdbID/youtubeTrailerForThumbnail/localized: optionalduration,publishedAt,channel.id,channel.titleallowed emptyURL structure
/filme-fuer-softwareentwickler/<tag>-filme/— gone/filme-fuer-softwareentwickler/kategorie-programmiersprachen//filme-fuer-softwareentwickler/kategorie-kultur-gesellschaft//filme-fuer-softwareentwickler/kategorie-kultur-personen//filme-fuer-softwareentwickler/kategorie-anwendungen-frameworks-systeme//filme-fuer-softwareentwickler/typ-dokumentation/(and futuretyp-film/,typ-tv-serie/once those entries appear upstream)Test plan
make build— 472 pages built (was failing onmain)the-great-hack: Germanlocalized.de.title("Cambridge Analyticas großer Hack") rendered, Netflix link present, IMDb row "7,0 / 10 (25.799 Bewertungen)"the-cleaners: Germanlocalized.de.descriptionrendered, bpb link present, IMDb row "7,1"angular-the-documentary: Category badge →kategorie-anwendungen-frameworks-systeme, Type badge →typ-dokumentation, YouTube link,data-category="Applications / Frameworks / Systems"data-type="Documentary"🤖 Generated with Claude Code