Movie streaming platforms have become a major part of our free time. There are platforms for anime lovers, connoisseurs of the Criterion Collection, and one that contains movies and TV shows from all around the world. What all of these platforms have in common is lots and lots of data and content.
Our Hygraphlix demo takes on the movie streaming platform use case and showcases “The Hygraph Way”. From a single content model,Movie
, we are able to create a wide range of content sections including the Top 8 movies on the platform, a landing page that lists all the movies available, and much more!
#Links to build your own movie platform
Demo site | https://hygraph-movie-starter.vercel.app/ |
---|---|
GitHub repository | https://github.com/lowisren/hygraph-movie-starter |
Federate This API | https://www.federatethis.com/routes/movies/ |
Clone Hygraph project | https://app.hygraph.com/clone/60a5f60969474157a5bb6cec6452e833?name=Hygraph%20Movie%20Platform%20Starter |
#About Hygraphlix movie starter
Hygraphlix is a composable movie streaming platform demo built with Hygraph with TypeScript.
Technologies used:
- NextJS 14
- Tailwind CSS
- Mux
- Federate This demo API
The demo uses Hygraph to pull movie data and metadata from an external system, a mock API called "Federate This" that we used to wrap OMDB, an open-source movie database. Movie metadata such as director, actor, genre, and poster is piped into Hygraph via a remote source connection, and by adding a remote field called federateMovie
to the Movie
content model.
#Sorting movies by genre
No movie streaming platform is complete without the ability to browse by genre! Hygraphlix shows how to create a Genre movie section with one query that combines Hygraph content and OMDB metadata to sort our movie collection.
Let’s take a quick dive into the code to build a movies by genre content section:
//Landing page for movies by genre: app/genres/page.tsximport MovieCard from "@/components/MovieCard";import { subtitle, title } from "@/components/primitives";//Get all Moviesasync function getMovies() {const HYGRAPH_ENDPOINT = process.env.HYGRAPH_ENDPOINT;if (!HYGRAPH_ENDPOINT) {throw new Error("HYGRAPH_ENDPOINT is not defined");}const response = await fetch(HYGRAPH_ENDPOINT, {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify({query: `query Movies {movies(first: 100) {federateMovie {data {TitlePosterGenreDirector}}idslugmoviePoster {heightwidthurl}}}`,}),});const json = await response.json();return json.data.movies;}// Declare Movie interfaceinterface Movie {federateMovie: {data: {Genre: string;Title: string;Poster: string;Director: string;};};id: string;slug: string;moviePoster: {height: number;width: number;url: string;};}
We are using the asynchronous function getMovies()
to query all movies in Hygraph and their respective metadata such as Poster
, Genre
, and Director
from OMDB using via the federateMovie
remote field and then return the list of movies in JSON.
//Landing page for movies by genre: app/genres/page.tsxexport default async function Movies() {const movies: Movie[] = await getMovies();const genres = [...new Set(movies.map((movie: Movie) => movie.federateMovie.data.Genre.split(",")[0])),];return (// Markup for filtered movies by genre goes HERE);}
After we fetched our data from Hygraph, we return a Promise
that resolves to an array of Movie
objects. We use the await
keyword to pause the execution of the Movies
function until the Promise
resolves. In order to render the movies by Genre
, we make constant called genres
to store an array of each unique genre by iterating over the movies
array and extract the genre of each movie. Since a movie can be a member of more than one genre, we use the Set
object, and then convert it back to an array using the spread (...
) operator.
//Landing page for movies by genre: app/genres/page.tsxreturn (<section className="flex flex-col justify-between mb-32 text-center"><h1 className={title({size: "xl"})}>Movies by Genres</h1>{genres.map((genre) => (<div className="text-left" key={genre}><h2 className={`${subtitle()} text-lg font-bold my-8`}>{genre}</h2><div className="grid px-5 lg:gap-xl-12 gap-x-6 md:grid-cols-2 lg:grid-cols-4">{movies// filter movies by genre and use the first genre in the list to group movie cards.filter((movie) => movie.federateMovie.data.Genre.split(',')[0] === genre).map((movie) => (<MovieCardkey={movie.id}Title={movie.federateMovie.data.Title}Poster={movie.federateMovie.data.Poster}moviePoster={movie.moviePoster}alt={movie.federateMovie.data.Title}Genre={movie.federateMovie.data.Genre}Director={movie.federateMovie.data.Director}slug={movie.slug}/>))}</div></div>))}</section>);
Last, we create the markup to render our movies by mapping over our genres
constant to create a section for each genre in our return statement. Inside each section, we filter the movies
array to only include movies that belong to the current genre and display every movie in a MovieCard
component.
#Individual movie pages using Mux
With just a single content model and remote source data, Hygraphlix also showcases individual movie pages that contain the Mux video player and metadata from OMDB for each movie.
Each movie pages contains the Plot, Actors Director, Genre, Rating, Runtime, and Release Year. Hygraph uses Mux for video delivery and features a Mux player component that allows you to change the controls to fit your brand.
//Mux player component - components/MuxPlayer.tsx"use client";import React from 'react';import MuxPlayer from '@mux/mux-player-react';interface MuxPlayerProps {playbackId: string;}const MuxPlayerComponent: React.FC<MuxPlayerProps> = ({ playbackId }) => {return (<MuxPlayerplaybackId={playbackId}accent-color="#5b4cff"/>);};export default MuxPlayerComponent;
Follow the below steps to get the most out of Hygraphlix by connecting Mux to your Hygraph project:
- Sign up for a Mux account
- Install the Mux app in your Hygraph project
- Create access tokens for your Mux account
#Conclusion
The ability to connect all your content and data sources means editors can craft enriching content all in one place. Tryout the Hygraphlix demo and let us know what you think in the community!