Skip to main content
Watchlist functions handle adding, removing, and querying media items in a user’s watchlist, as well as tracking watch progress and reactions.

getWatchlist

Retrieves all media items in the current user’s watchlist.
items
array
Array of watch items that are marked as in the watchlist
_id
Id<'watch_items'>
Unique identifier for the watch item
tmdbId
number
The Movie Database (TMDB) ID for the media
mediaType
string
Type of media (e.g., “movie”, “tv”)
inWatchlist
boolean
Whether the item is in the watchlist
progressStatus
string
Current watch status: “want-to-watch”, “watching”, or “finished”
progress
number
Watch progress percentage (0-100)
reaction
string
User reaction: “liked” or “not-for-me”
title
string
Media title
image
string
URL to media poster/image
rating
number
Media rating
import { api } from "@/convex/_generated/api";
import { useQuery } from "convex/react";

const watchlist = useQuery(api.watchlist.getWatchlist);

watchlist?.forEach(item => {
  console.log(`${item.title} - ${item.progressStatus}`);
});

getMediaState

Retrieves the tracking state for a specific media item, regardless of watchlist membership.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
watchItem
object | null
The watch item object if it exists, or null
import { api } from "@/convex/_generated/api";
import { useQuery } from "convex/react";

const mediaState = useQuery(api.watchlist.getMediaState, {
  tmdbId: 550,
  mediaType: "movie"
});

if (mediaState) {
  console.log(`Progress: ${mediaState.progress}%`);
  console.log(`Status: ${mediaState.progressStatus}`);
}

setWatchlistMembership

Adds or removes a media item from the user’s watchlist.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
inWatchlist
boolean
required
Whether to add (true) or remove (false) from watchlist
title
string
Media title
image
string
URL to media poster image
rating
number
Media rating
release_date
string
Media release date
overview
string
Media description/overview
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const setWatchlistMembership = useMutation(api.watchlist.setWatchlistMembership);

// Add to watchlist
await setWatchlistMembership({
  tmdbId: 550,
  mediaType: "movie",
  inWatchlist: true,
  title: "Fight Club",
  image: "https://image.tmdb.org/poster.jpg",
  rating: 8.4
});

// Remove from watchlist
await setWatchlistMembership({
  tmdbId: 550,
  mediaType: "movie",
  inWatchlist: false
});

Behavior

  • Creates a new watch item if it doesn’t exist (when adding to watchlist)
  • Updates existing watch item’s watchlist membership
  • When adding to watchlist, sets default progressStatus to “want-to-watch”
  • Preserves existing progress and reaction data when toggling membership

setProgressStatus

Updates the watch progress status for a media item.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
progressStatus
string
required
Progress status: “want-to-watch”, “watching”, or “finished”
progress
number
Watch progress percentage (0-100)
title
string
Media title
image
string
URL to media poster image
rating
number
Media rating
release_date
string
Media release date
overview
string
Media description/overview
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const setProgressStatus = useMutation(api.watchlist.setProgressStatus);

// Mark as watching
await setProgressStatus({
  tmdbId: 550,
  mediaType: "movie",
  progressStatus: "watching",
  progress: 45
});

// Mark as finished
await setProgressStatus({
  tmdbId: 550,
  mediaType: "movie",
  progressStatus: "finished"
});

Behavior

  • Auto-sets progress to 0 when status is “want-to-watch”
  • Auto-sets progress to 100 when status is “finished”
  • Creates new watch item if it doesn’t exist
  • Updates existing item if found

setReaction

Sets or clears a user’s reaction to a media item.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
reaction
string
Reaction: “liked” or “not-for-me”
clearReaction
boolean
Set to true to clear the reaction
title
string
Media title
image
string
URL to media poster image
rating
number
Media rating
release_date
string
Media release date
overview
string
Media description/overview
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const setReaction = useMutation(api.watchlist.setReaction);

// Like a movie
await setReaction({
  tmdbId: 550,
  mediaType: "movie",
  reaction: "liked"
});

// Mark as not for me
await setReaction({
  tmdbId: 550,
  mediaType: "movie",
  reaction: "not-for-me"
});

// Clear reaction
await setReaction({
  tmdbId: 550,
  mediaType: "movie",
  clearReaction: true
});

updateProgress

Updates watch progress for a media item, typically called from the video player.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
progress
number
Watch progress percentage (0-100)
status
string
Legacy status field for compatibility
isWatched
boolean
Set to true to mark as fully watched (sets progress to 100)
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const updateProgress = useMutation(api.watchlist.updateProgress);

// Update progress from video player
await updateProgress({
  tmdbId: 550,
  mediaType: "movie",
  progress: 67.5
});

// Mark as fully watched
await updateProgress({
  tmdbId: 550,
  mediaType: "movie",
  isWatched: true
});

Behavior

  • Auto-infers progressStatus based on progress percentage
  • Sets status to “finished” when progress >= 95% or isWatched is true
  • Sets status to “watching” when progress > 0
  • Creates new watch item if it doesn’t exist

upsertWatchlistItem

Legacy mutation for backward compatibility during the status model rollout. Adds or updates a watchlist item using the old combined status field.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
status
string
required
Legacy combined status: “plan-to-watch”, “watching”, “completed”, “liked”, or “dropped”
progress
number
Watch progress percentage (0-100)
title
string
Media title
image
string
URL to media poster image
rating
number
Media rating
release_date
string
Media release date
overview
string
Media description/overview
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const upsert = useMutation(api.watchlist.upsertWatchlistItem);

await upsert({
  tmdbId: 550,
  mediaType: "movie",
  status: "watching",
  progress: 45
});
This function maps legacy status values to the new split model (progressStatus + reaction). New code should use setWatchlistMembership, setProgressStatus, and setReaction instead.

removeWatchlistItem

Legacy mutation that removes an item from the watchlist while preserving its progress and reaction data.
tmdbId
number
required
TMDB ID of the media item
mediaType
string
required
Type of media (“movie” or “tv”)
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const remove = useMutation(api.watchlist.removeWatchlistItem);

await remove({
  tmdbId: 550,
  mediaType: "movie"
});
This sets inWatchlist to false but keeps the watch item record. New code should use setWatchlistMembership with inWatchlist: false instead.

backfillWatchItems

One-time migration helper that backfills split status fields (progressStatus and reaction) for the current user’s existing watch items.
args
object
No arguments required
import { api } from "@/convex/_generated/api";
import { useMutation } from "convex/react";

const backfill = useMutation(api.watchlist.backfillWatchItems);

// Run migration for current user
await backfill({});
This is a migration utility for existing data. It processes the user’s watch items and maps legacy status values to the new progressStatus/reaction model.

Build docs developers (and LLMs) love