Skip to content

Manage genres, tropes, cast

TwistCue has three taxonomy tables, Genres, Tropes, Cast, plus a SeriesCast join. They all live under Catalog in the sidebar.

Broad content buckets: “Romance”, “Thriller”, “Fantasy”, etc. Drive the top-level filter on the mobile discover screen and are the main input to the For You rail rules.

Fields:

FieldTypeNotes
slugstring, unique, kebab-caseImmutable after first use.
name_i18nJSON: {en, ar, id}At least EN required.
sortintOrder in filter chips. Lower = earlier.
activeboolInactive genres hide from mobile but stay attached to series for analytics.

Rule of thumb: keep this short. 8–15 genres is healthy. If you’re above 20, you probably want tropes instead.

Narrower narrative buckets: “Enemies to Lovers”, “Amnesia”, “CEO Romance”, “Time Loop”. Drive niche rails (“Because you love Enemies to Lovers…”) and analytics slicing.

Same field shape as genres. Rule of thumb: 30–60 tropes is where it starts paying off; below 30, they’re not doing enough work; above 100, you’re inventing them.

The people behind the show: actors, directors, writers. TwistCue is casting-forward: cast rails and cast-scoped discovery are a real part of the app.

Fields:

FieldTypeNotes
slugstring, uniqueAuto from name; immutable after publish.
namestringDisplay name. Not localized in v2 (romanized name only).
role_defaultenum: actor / director / writer / producerApplied when linked to a series unless overridden.
photo_asset_idFK → media_assetsHeadshot (square recommended).
bio_i18nJSON: {en, ar, id}Optional; renders on the cast profile page.
activebool

Each series has a Cast tab on the series detail page. Add cast members and assign per-series role (actor / director / writer / producer) and character name (for actors).

The join table series_cast looks like:

(series_id, cast_id, role, character_name, sort)

Editing this from the API is a full-replace on PUT /v1/admin/series/:seriesId/cast: pass the complete desired array.

  • Deleting a genre/trope in use: the API refuses (409 in_use) if any series still references it. Deactivate instead (active=false).
  • Cast merges: no built-in merge yet. If you accidentally created two cast rows for the same actor, delete the empty one and re-link.
  • Localization matters for filter chips. If a genre’s name_i18n.ar is missing, the AR mobile UI falls back to EN: visually consistent but not ideal.
ActionEndpoint
Genres CRUDGET/POST/PUT/DELETE /v1/admin/genres[/:id]
Tropes CRUDGET/POST/PUT/DELETE /v1/admin/tropes[/:id]
Cast listGET /v1/admin/cast
Cast CRUDGET/POST/PUT/DELETE /v1/admin/cast[/:id] (planned nested routes; see API: Catalog)
Series cast (replace)PUT /v1/admin/series/:seriesId/cast

Full details in API: Catalog.