Web3 has revolutionized various industries, and one of the most exciting applications is decentralized applications (dApps). In this guide, we’ll walk you through building a Web3 movie streaming dApp using Next.js, Tailwind CSS, and Sia’s Renterd. By the end of this tutorial, you’ll have a functional dApp where users can upload and stream movies in a decentralized manner.

Prerequisites

Before we dive into the code, ensure you have the following tools installed:

  1. Node.js (v14.x or higher)
  2. NPM (v6.x or higher) or Yarn
  3. Git
  4. Sia Renterd (set up and running)

You should also be familiar with basic React and Next.js concepts.

Setting Up the Project

Initialize the Next.js Project

First, let’s set up a new Next.js project. Open your terminal and run:

bash

npx create-next-app web3-movie-streaming
cd web3-movie-streaming

This will create a new Next.js project in the web3-movie-streaming directory.

Install Dependencies

Next, we need to install the necessary dependencies, including Tailwind CSS and Web3.js:

bash

npm install tailwindcss postcss autoprefixer web3
npx tailwindcss init -p

This will install Tailwind CSS and create the necessary configuration files (tailwind.config.js and postcss.config.js).

Configure Tailwind CSS

Open the tailwind.config.js file and replace the content with:

javascript

module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};

Next, in your ./styles/globals.css file, add the following to import Tailwind’s base styles:

css

@tailwind base;
@tailwind components;
@tailwind utilities;

With this setup, we can now use Tailwind CSS classes throughout our Next.js project.

Setting Up the Sia Renterd

What is Sia Renterd?

Sia is a decentralized cloud storage platform that allows you to rent storage space from other users. Renterd is a lightweight, CLI-based daemon that interacts with the Sia network, allowing you to store and retrieve files programmatically.

Install and Configure Renterd

If you haven’t already installed Renterd, you can download it from the official Sia GitHub repository. Follow the installation instructions for your OS.

After installation, start Renterd:

bash

renterd --sia-dir /path/to/sia

Ensure Renterd is running and accessible via its HTTP API. You’ll use this API to upload and stream movies from your dApp.

Set Up Environment Variables

Create a .env.local file in your Next.js project root to store the Renterd API endpoint:

bash

NEXT_PUBLIC_RENTERD_API_URL=http://localhost:9980

Replace the URL with your actual Renterd endpoint.

Creating the Movie Upload and Streaming Components

Movie Upload Form

First, let’s create a simple form to upload movies. Create a new component in the components directory called UploadForm.js:

javascript

import { useState } from 'react';

const UploadForm = () => {
const [file, setFile] = useState(null);
const [uploading, setUploading] = useState(false);

const handleFileChange = (e) => {
setFile(e.target.files[0]);
};

const handleUpload = async () => {
if (!file) return;

setUploading(true);

const formData = new FormData();
formData.append(‘file’, file);

try {
const res = await fetch(`${process.env.NEXT_PUBLIC_RENTERD_API_URL}/upload`, {
method: ‘POST’,
body: formData,
});

const data = await res.json();
console.log(‘File uploaded:’, data);
} catch (err) {
console.error(‘Upload failed:’, err);
} finally {
setUploading(false);
}
};

return (
<div className=“p-4 bg-white shadow-md rounded”>
<input type=“file” onChange={handleFileChange} />
<button
onClick={handleUpload}
disabled={uploading}
className=“mt-2 px-4 py-2 bg-blue-500 text-white rounded”
>

{uploading ? ‘Uploading…’ : ‘Upload Movie’}
</button>
</div>

);
};

export default UploadForm;

This component allows users to upload a movie file to Sia. The form uses the fetch API to send the file to Renterd’s upload endpoint.

Movie Streaming Component

Next, let’s create a component to stream movies. Create a MoviePlayer.js component:

javascript

import { useState, useEffect } from 'react';

const MoviePlayer = ({ filePath }) => {
const [videoUrl, setVideoUrl] = useState();

useEffect(() => {
const fetchVideoUrl = async () => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_RENTERD_API_URL}/stream/${filePath}`);
const url = URL.createObjectURL(await res.blob());
setVideoUrl(url);
} catch (err) {
console.error(‘Failed to fetch video:’, err);
}
};

fetchVideoUrl();
}, [filePath]);

return (
<div className=“p-4 bg-black rounded”>
<video src={videoUrl} controls className=“w-full h-auto” />
</div>

);
};

export default MoviePlayer;

This component takes a filePath prop, fetches the video from Sia via Renterd, and streams it using a standard HTML5 <video> element.

Integrating Components into the Next.js Pages

Home Page

Let’s now integrate these components into our Next.js application. Open the pages/index.js file and replace it with the following:

javascript

import Head from 'next/head';
import UploadForm from '../components/UploadForm';
import MoviePlayer from '../components/MoviePlayer';
import { useState } from 'react';
export default function Home() {
const [filePath, setFilePath] = useState();return (
<div className=“container mx-auto p-4”>
<Head>
<title>Web3 Movie Streaming dApp</title>
</Head>
<h1 className=“text-2xl font-bold mb-4”>Web3 Movie Streaming dApp</h1><UploadForm />{filePath && (
<div className=“mt-8”>
<MoviePlayer filePath={filePath} />
</div>
)}<div className=“mt-4”>
<input
type=“text”
placeholder=“Enter file path to stream”
value={filePath}
onChange={(e) =>
setFilePath(e.target.value)}
className=”border p-2 rounded w-full”
/>
</div>
</div>
);
}

This page serves as the home page of your dApp. It includes the upload form, movie player, and an input field where users can enter the file path of the movie they want to stream.

Styling with Tailwind CSS

Tailwind makes it easy to create a clean, modern interface. The components already use Tailwind classes for styling. For example, the UploadForm and MoviePlayer components use classes like p-4, bg-white, rounded, etc., to achieve a minimalist design.

You can customize these styles further in the tailwind.config.js file if needed.

Testing the dApp

Now that your dApp is ready, start the development server to test it:

bash

npm run dev

Open your browser and navigate to http://localhost:3000. You should see your Web3 movie streaming dApp.

  1. Upload a Movie: Select a movie file from your local machine and click “Upload Movie”. This uploads the file to the Sia network.
  2. Stream a Movie: Enter the file path of the uploaded movie in the input field and watch the magic happen.

Deploying the dApp

Once you’re satisfied with the functionality, you can deploy your dApp. For simplicity, we’ll deploy it on Vercel, which is optimized for Next.js applications.

Deploy on Vercel

First, ensure you commit your code to a GitHub repository. Then, follow these steps:

  1. Go to Vercel.
  2. Log in and click “New Project”.
  3. Select your GitHub repository.
  4. Configure the build settings if needed.
  5. Click “Deploy”.

Vercel will automatically deploy your application, and you’ll get a live URL where users can access your Web3 movie streaming dApp.

Conclusion

Congratulations! You’ve successfully built a Web3 movie streaming dApp using Next.js, Tailwind CSS, and Sia’s Renterd. This dApp allows users to upload and stream movies in a decentralized manner, showcasing the potential of Web3 technologies in revolutionizing digital content distribution.

The combination of Next.js and Tailwind CSS enables rapid development of a responsive and visually appealing frontend, while Sia provides a robust decentralized storage solution. The dApp we’ve built is just the beginning—there’s plenty of room for enhancements such as user authentication, better error handling, and a more sophisticated UI.

By leveraging these technologies, you’re contributing to a future where data ownership and privacy are paramount, and where centralized control over content distribution is a thing of the past. Keep experimenting, keep building, and welcome to the world of Web3!