DEV Community

Cover image for Build a Web3 Movie Streaming dApp using NextJs, Tailwind, and Sia Renterd: Part Three
Gospel Darlington
Gospel Darlington

Posted on

Build a Web3 Movie Streaming dApp using NextJs, Tailwind, and Sia Renterd: Part Three

Let's dive into the final part of this tutorial series, where we'll integrate the backend with the Frontend, connecting the pieces to complete the file upload application. We will begin by ensuring that authentications in the Frontend are up and running.

Web3 Modal Authentication

Create a new folder named 'config' in the Frontend directory and add an index file, resulting in the path /frontend/config/index.tsx. Now let’s add the following codes to it.

This code sets up a Wagmi configuration for our Web3 application, defining metadata, supported chains, and authentication settings, including wallet and social login options, and stores it in the config export. We also need to create a context API to keep track of the authentication state.

The Context API
Next, create a new folder named 'context' still in the Frontend directory and add an index file, resulting in the path /frontend/context/index.tsx. Add the following codes to it.

This code sets up a Web3Modal provider using Wagmi and React Query, configuring the Web3 modal with the project ID and theme variables, and wrapping the application in a WagmiProvider and QueryClientProvider.

Updating Layout
Let’s have our application layout updated to include the above configurations. Head to /frontend/app/layout.tsx and replace its codes with the one below.

The above code sets up the root layout for a Next.js application, including metadata, fonts, styles, and providers for Web3 modal, toast notifications, and layout components like header and footer.

The Login Button
Now, we need to enable the login buttons in the /frontend/app/components/layout/Header.tsx and /frontend/app/components/shared/Menu.tsx components, and update their codes using the information below.

This code defines a React component for a navigation bar that includes a logo, navigation links, a custom menu, and a login button that launches a Web3 Modal, with a responsive design for different screen sizes.

The following images should pop up as proof that what we have done works when you click on the login button and proceed with your preferred provider, X, Facebook, Google, Discord, or Ethereum.

Before Authentication

After Authentication

Superb, let’s go deeper and set up our database and NextJs API-based system. For any confusion on the process, please watch the video section below, just make sure you stop at the 02:57:59 mark.

Database Scripts

First, let’s update the NextJs configuration script to properly address our pages, and endpoints, and free our remote images from warnings and scrutiny.

This code defines a Next.js configuration object that sets up API route rewrites and image optimization, allowing remote images from any HTTPS hostname and local images from the localhost domain.

Database Config Script
We will be using SQLite for this application, but you are free to use a more robust solution such as MYSQL or NOSQL providers. For the sake of simplicity, let's work with a SQLite flat file.

Create /frontend/app/api/database.ts file path and add the codes below in it.

This code sets up an SQLite database connection and defines two API functions, apiGet and apiPost, to perform GET and POST requests on the database, with error handling and promise-based asynchronous execution. We will be using these codes whenever we wish to send or retrieve data from the database.

Database Migration Script
We need to create both a database flat file and a table to hold all our contents. Create /frontend/app/api/migrations.ts file path and add the codes below in it.

This code defines a database migration function that creates a 'movies' table with specified columns if it doesn't exist, using SQLite, and logs the result of the operation. Now run the command below in a terminal pointed at the /frontend directory.

$ cd frontend
$ npx esrun app/api/migrations.ts
Enter fullscreen mode Exit fullscreen mode

It should be noted that this process will also create a database flat file called movies.db at the root of the frontend directory. We have also added this command to the package.json script, so running $ yarn migrate on the frontend directory should work the same.

For visual assistance, watch the video below, just stop it at the 03:10:54 mark.

Application Endpoints

Now, let’s define some endpoints for creating, reading, updating, and deleting movies, we will be using the NextJs API provision to make these endpoints.

Create Movie Endpoint
To create a movie, the required information includes the user ID, movie name, image, video URL, release date, genre, rating, language, duration, and background description. Create /frontend/app/api/movies/create/route.ts file path and add the codes below in it.

This code defines an endpoint to handle POST requests, validate and process movie data, generate a unique slug, and insert the data into a database using an apiPost function while handling errors and returning JSON responses.

Update Movie Endpoint
To update a movie, the required information includes the user ID, slug, and other information provided when creating a movie. Create /frontend/app/api/movies/update/route.ts file path and add the codes below in it.

This code defines an endpoint to handle POST requests for updating a movie, validating required properties, and executing an SQL query to update the movie data in the database using the apiPost function.

Delete Movie Endpoint
To delete a movie, the required information includes the user ID and slug of a movie. Create /frontend/app/api/movies/delete/route.ts file path and add the codes below in it.

This code defines an endpoint to handle POST requests for deleting a movie, validating required properties (userId and slug), and executing an SQL query to delete the movie from the database using the apiPost function.

All Movies Endpoint
The optional data required to get movies are pageSize and userId, which can be passed as query parameters to filter and paginate the results. Create /frontend/app/api/movies/all/route.ts file path and add the codes below in it.

The above code defines an endpoint to handle GET requests for retrieving movies, allowing optional filtering by userId and pagination by pageSize, and returns the results in JSON format.

Single Movie Endpoint
To retrieve a single movie, the required data is the slug of a movie. Create /frontend/app/api/movies/[slug]/route.ts file path and add the codes below in it.

This code defines an endpoint to handle GET requests for retrieving a movie by its slug, validating the slug parameter, and executing an SQL query to retrieve the movie data from the database using the apiGet function.

That marks all the endpoints we will need for this application. If you need a visual aid to help you understand these endpoints better, please watch the video below, just ensure you stop at the 03:48:22 timestamp.

Endpoint Integration

Our task is to review and update pre-coded components and pages, explaining each one's purpose and functionality, and documenting the changes we make to the existing code. We will start by creating a service for interacting with the endpoints we previously created in the api directory.

Create /frontend/app/services/api.service.ts file path and add the codes below in it.

This service provides a set of functions to interact with a movie database, allowing the application to fetch movies, fetch a single movie by slug, create a new movie, update an existing movie, delete a movie, and upload files, using API requests and handling errors.

Application Pages

Let’s review and update the various pages associated with our application. You wouldn’t need to change many things, just the ones highlighted here.

Create Movie Page

Create Movie Page

This page is a movie publishing form that allows users to upload video and image files, input movie details, and submit the form to publish the movie, with validation and error handling, using React and Wagmi libraries.

Now, update the file found in /frontend/app/pages/create/page.tsx with the codes below.

The changes made in this code compared to the original one are:

  1. Imported the createMovie function from api.service and used it in the handleSubmit function to create a new movie.
  2. Added the userId parameter to the createMovie function call, passing the user's address from the useAccount hook.
  3. Updated the handleSubmit function to use toast.promise to handle the promise returned by createMovie.
  4. Added error handling to the createMovie function call in the handleSubmit function.

These changes enable the form to submit movie data to the API and create a new movie entry, while also handling errors and displaying a success message.

Edit Movie Page

Edit Movie Page Similar to the Create Movie Page

This movie editing page allows authorized users to update movie details, upload posters and videos, and save changes, with validation and error handling, utilizing React, Wagmi, and Next.js, specifically designed for users to edit their movies.

Now, update the file found in /frontend/app/pages/movies/edit/[slug]/page.tsx with the codes below.

The upgrades made to the code that is different from the original are:

  1. Imported fetchMovie and updateMovie functions from @/app/services/api.service and used them in the useEffect hook and handleSubmit function, respectively.
  2. Replaced the posters.find() method with the fetchMovie function to retrieve movie data.
  3. Updated the handleSubmit function to call the updateMovie function with the updated movie details.
  4. Added error handling to the updateMovie function call in the handleSubmit function.

These changes enable our application to interact with our API endpoints to retrieve and update movie data, whereas the original code relied on our local posters array.

Home Page

Home Page

This home page renders the banners component, a list of movies (either from an API source or a loading UI), and subscription options, utilizing React and Next.js, to provide an engaging and informative landing page for users.

Update the file found in /frontend/app/pages/page.tsx with the following codes.

The changes we made to the home page are:

  1. Imported fetchMovies function from ./services/api.service and used it in the useEffect hook to retrieve movie data from our API.
  2. Replaced the local posters data with the fetchMovies function call, which fetches data from our API.
  3. Added await keyword to wait for the promise returned by fetchMovies to resolve before setting the movies state.

These changes help our application to retrieve movie data from our API instead of relying on local data, making the application more dynamic and data-driven.

User Account Page

Account Page

This page displays a list of movies posted by the currently connected user, with a loading skeleton placeholder while the data is being fetched, and a message prompting the user to connect their account if they haven't done so, utilizing Wagmi, and react-loading-skeleton.

Update the file found in /frontend/app/pages/account/page.tsx with the following codes.

The changes made to the page are:

  1. Imported fetchMovies function from @/app/services/api.service and used it in the useEffect hook to retrieve movie data from our API.
  2. Replaced the local posters data with the fetchMovies function call, which fetches data from our API.
  3. Passed address as an argument to the fetchMovies function to retrieve user-specific movie data.
  4. Removed the conditional check for address before rendering the movie list, as the fetchMovies function now handles this logic.
  5. Simplified the conditional statement for displaying the loading skeleton, as it now only depends on the loaded state.

These changes retrieve movie data from our API, specific to the connected user, and display a loading skeleton while the data is being fetched.

Movies Details Page

Movies Details

This page displays a single movie's details, including its name, release year, rating, duration, genre, and background information, along with a video player and related movies, and provides options to edit or delete the movie if the user is the owner, utilizing Next.js, and Wagmi.

Update the file found in /frontend/app/pages/movies/[slug]/page.tsx with the following codes.

We made some huge changes here! Here's a summary of what we did:

  1. Imported deleteMovie, fetchMovie, and fetchMovies functions from @/app/services/api.service and used them to interact with our API endpoints.
  2. Replaced local data with API calls to retrieve movie data.
  3. Implemented movie deletion functionality using the deleteMovie function.
  4. Used toast.promise to display a notification while deleting a movie.
  5. Removed the posters local data and replaced it with API calls.
  6. Updated the handleSubmit function to call the deleteMovie function and handle the response.
  7. Updated the useEffect hook to call the fetchMovie and fetchMovies functions.

These changes cause our application to interact with our API to retrieve and delete movie data and display notifications to the user during the deletion process.

This part of the video below will show you hands-on how we integrated these pages with the endpoint, please feel free to watch that part if you run into any problem. Just make sure you stop at the 04:57:41 timestamp.

Application Components

Let’s discuss the purpose of each component in our application. We will update any component that needs to be modified.

Banner Component

Banner Component

This component displays a rotating background image of movie banners, cycling through an array of movie images every 5 seconds, creating a simple and automatic slideshow effect. This component code can be assessed at /frontend/app/components/home/Banner.tsx.

Posters Component

Posters Component

This component displays a responsive and interactive carousel of movie posters, using the Swiper library, with features like autoplay, pagination, and navigation, showcasing a list of movies passed as a prop, with a dynamic layout adapting to different screen sizes. This component code can be assessed at /frontend/app/components/home/Posters.tsx.

Poster UI Component

Poster UI Component

This component displays a placeholder skeleton layout for a movie posters section, using the react-loading-skeleton library, showing a dynamic number of skeleton posters based on the "posters" prop, with a responsive design adapting to different screen sizes, indicating a loading state until the actual posters data is fetched and displayed. This component code can be assessed at /frontend/app/components/home/PosterUI.tsx.

Subscriptions Component

Subscriptions Component

This component displays a subscription plans section, showcasing various dummy plans with their details, prices, and benefits. It allows users to choose a plan that suits their needs, utilizing a responsive grid layout and interactive hover effects to enhance the user experience. This component code can be assessed at /frontend/app/components/home/Subscription.tsx.

Header Component

The Header Component

This component renders a fixed navigation bar at the top of the page, featuring a logo, a navigation menu with links to various sections, a menu toggle button for responsive design, and a login button, providing a consistent and accessible header section across the application. This component code can be assessed at /frontend/app/components/layout/Header.tsx.

Footer Component

Footer Component

This component renders a footer section at the bottom of the page, featuring the application's logo, a brief description, navigation links, contact information, and a credit mentioning the decentralized storage solution powered by Sia Foundation, providing a clear and organized footer section with relevant information and links. This component code can be assessed at /frontend/app/components/layout/Footer.tsx.

Menu Component

Menu Component

This component renders a responsive menu toggle button, which when clicked, opens or closes a dropdown menu containing navigation links, allowing users to access various sections of the application on smaller screens while hiding the menu on larger screens where the navigation links are already visible. This component code can be assessed at /frontend/app/components/shared/Menu.tsx.

Movie Card Component

Movie Card Component

This component displays a single movie's poster with a hover effect, showing additional information such as the movie's name, release year, and background summary, while also serving as a link to the movie's details page, utilizing a responsive design and animated transitions to enhance the user experience. This component code can be assessed at /frontend/app/components/shared/MovieCard.tsx.

Uploaded Component

Uploaded Component

This component displays a preview of an uploaded file, either an image or a video, with a progress bar and a removal button, allowing users to review and delete the uploaded file, while also providing a visually appealing and interactive interface with animations and hover effects. This component code can be assessed at /frontend/app/components/shared/Uploaded.tsx.

Uploader Component

Uploader Component

This component provides a user interface for uploading files, specifically videos or posters, with features like drag-and-drop, file type validation, size limits, upload progress tracking, and success/error notifications, utilizing a combination of React state management, event handling, and API integration to handle the upload process.

Update the file found in /frontend/app/components/shared/uploader.tsx with the following codes.

The changes made to this component are:

  1. Upload File Functionality: The original code didn't have the actual upload file functionality implemented. It only showed a success toast notification without uploading the file. This updated code includes the uploadFile function from api.service which handles the file upload.
  2. Progress Tracking: The updated code tracks the upload progress and displays it on the UI.
  3. Error Handling: The updated code includes error handling for the file upload process.
  4. File Type Validation: The updated code uses a more robust file type validation using a regular expression.
  5. Code Organization: The updated code is better organized, with separate functions for handling different tasks, making it easier to read and maintain.
  6. UI Updates: The updated code includes some UI updates, such as showing the upload progress and a cancel button during upload.

This updated code is more complete and robust, with actual file upload functionality, progress tracking, error handling, and better code organization.

The video below explains what each component does in more detail, kindly check it out for your betterment.

And that is it guys, we have completed this project, and the last step we need to take is to launch this project on the browser. Run $ yarn build && yarn start to see the project live on the browser.

If you encounter any issues, refer to the following resources for troubleshooting, till next time, all the best!

About Author

I am a web3 developer and the founder of Dapp Mentors, a company that helps businesses and individuals build and launch decentralized applications. I have over 8 years of experience in the software industry, and I am passionate about using blockchain technology to create new and innovative applications. I run a YouTube channel called Dapp Mentors where I share tutorials and tips on web3 development, and I regularly post articles online about the latest trends in the blockchain space.

Top comments (0)