Join us live as we unveil the all new Hygraph Studio!

HYGRAPHlix, a Hygraph movie streaming platform

A composable movie streaming platform demo built with TypeScript using NextJS 14, Tailwind CSS, and Mux.
Lo Etheridge

Lo Etheridge

Jan 30, 2024
Hygraphlix- movie streaming platform made with Hygraph, headless CMS

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!

Screenshot 2024-01-29 at 09.20.56.png

#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.

movie-contentmodel-hygraph.png

#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.tsx
import MovieCard from "@/components/MovieCard";
import { subtitle, title } from "@/components/primitives";
//Get all Movies
async 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 {
Title
Poster
Genre
Director
}
}
id
slug
moviePoster {
height
width
url
}
}
}`,
}),
});
const json = await response.json();
return json.data.movies;
}
// Declare Movie interface
interface 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.tsx
export 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.tsx
return (
<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) => (
<MovieCard
key={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.

Screenshot_2024-01-28_at_19.07.17.png

#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.

Screenshot_2024-01-28_at_19.14.58.png

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 (
<MuxPlayer
playbackId={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:

  1. Sign up for a Mux account
  2. Install the Mux app in your Hygraph project
  3. 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!

Blog Author

Lo Etheridge

Lo Etheridge

Senior Developer Relations

Lo is Hygraph's Senior Developer Relations Specialist. They focus on developer education around Headless CMS, JS-based frontends, and API technologies as well as the dynamic cross-functional relationship between developers and content professionals.

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.