Build a podcast platform in Nuxt.js using Appwrite
Tags: nuxt, appwrite, javascript, jamstack
Published: 2023-01-16 09:54:01

---
title: Build a podcast platform in Nuxt.js using Appwrite
published: true
description: This article explores how to build a podcast platform using Nuxt.js and Appwrite.
tags: #nuxtjs #appwrite #javascript #jamstack
cover_image: https://res.cloudinary.com/chukwutosin/image/upload/v1673862491/hackmamba%20articles/build-podcast-platform_hobe80.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-01-16 09:45 +0000
---

Podcasts have become an increasingly popular form of media in recent years, with a wide range of topics and genres available for listeners to choose from. Suppose you are passionate about podcasting and want to create a platform to host and distribute your own shows. In that case, Nuxt.js and [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) can be powerful for building a feature-rich and scalable podcasting platform.

This article explores how to build a podcast platform using Nuxt.js and Appwrite, including how to set up the project, upload a podcast, and create a podcast player.

## Repository
https://github.com/folucode/appwrite-podcast-app

## Prerequisites
- Basic understanding of CSS, JavaScript, and Nuxt.js.
- Docker Desktop installed on your computer (run the `docker -v` command to verify the installation); if you don’t yet have it, install it from [here](https://www.docker.com/products/docker-desktop/).
- An Appwrite instance running on your computer. Check out [this post](https://dev.to/hackmamba/create-a-local-appwrite-instance-in-3-steps-19n9?utm_source=hackmamba&utm_medium=hackmamba) to create a local Appwrite instance. It can also be installed using [digital ocean](https://docs.digitalocean.com/products/marketplace/catalog/appwrite/) or [gitpod](https://www.gitpod.io/guides/appwrite-and-gitpod).

## Setting up the project

Create a new Nuxt.js project using the following command:


    npx create-nuxt-app my-podcast-platform

This will guide you through several prompts to set up the project, including selecting a package manager, a UI framework, and additional features. Make sure to choose Axios as the HTTP client, as you'll use it to make API calls to Appwrite later.

Once you have set up the project, you can navigate to the project directory and start the development server using the following commands:


    cd my-podcast-platform
    npm run dev
## Setting up the Appwrite database

You'll be using Appwrite's storage and database service in this app. The Appwrite storage bucket is where the Appwrite stores uploaded files.

To set up an Appwrite storage bucket, log in to the Appwrite console and create a new project. Next, click on **Storage** and then **Create bucket**. You can name the bucket Podcasts.

![create new storage bucket](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671739805087_create+new+storage+bucket.png)


Next, click on the newly created bucket, go to the settings tab, and then scroll down to `Update permissions`. Add a new role for `Users` and give it role all permissions.


![create roles](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671740322013_create+roles.gif)


After adding the roles, the next thing to do is to create a database to store all the podcast data.

Click on the `Databases` tab, and then **Create database**. You can give it the name of podcasts as well.

![create database](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671740806656_create+database.png)


Click on the podcasts database and create a new collection in the database. `Collections` serve as database tables in Appwrite.

You can call it `podcast_details`, as it stores all the details of your podcast. Next, click on the collection and add new attributes. `Attributes` serve as database columns in Appwrite.

![appwrite](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671741119147_Screenshot+2022-12-22+at+21.31.06.png)


The attributes you’ll add are:

- `fileID` of type string
- `title` of type string
- `name` of type string
- `date` of type integer

Also, as you did for the bucket in storage, add a **Users** role with all permissions for the `podcast_details` collection.

## Setting up the UI

In the components folder, create a file called `Podcast.vue` and paste the code below into it:

```javascript
    <template>
      <div class="pod">
        <h3>{{ title }}</h3>
        <div class="pod-details">
          <span>By {{ name }}</span> /
          <span>{{ date }}</span>
          <audio controls>
            <source :src="source" type="audio/mpeg" />
            Your browser does not support the audio element.
          </audio>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "Podcast",
      props: {
        title: String,
        name: String,
        date: String,
        source: URL,
      },
    };
    </script>
    <style>
    h3 {
      font-weight: bolder;
    }
    .pod {
      background-color: #45a049;
      border-radius: 5px;
      padding: 10px;
      margin: 5px;
    }
    .pod-details {
      background-color: rgb(255, 255, 255);
      display: block;
      padding: 5px;
      margin-bottom: 15px;
      border-radius: 10px;
    }
    span {
      margin-left: 5px;
      margin-right: 5px;
      color: rgb(0, 0, 0);
    }
    audio {
      margin-top: 15px;
      display: block;
    }
    </style>
 ```   

This component is a simple card that contains all the details of a podcast. The audio file, name, title of the podcast, and date. There's also a `props` object for each of these attributes.

Next, in the `pages/index.vue` file, paste the code below:

```javascript
    <template>
      <div class="container">
        <div class="child">
          <Podcast />
        </div>
        <div class="child">
          <form>
            <label for="title">Title</label>
            <input
              type="text"
              name="title"
              placeholder="Podcast title..."
              v-model="title"
            />
            <label for="country">File</label>
            <input id="file" type="file" />
            <button type="submit" value="Submit">
              Upload
            </button>
          </form>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "IndexPage",
    };
    </script>
    <style>
    .container {
      border: 3px solid #fff;
      padding: 20px;
    }
    input[type="text"] {
      width: 100%;
      padding: 12px 20px;
      margin: 8px 0;
      display: inline-block;
      border: 1px solid #ccc;
      border-radius: 4px;
      box-sizing: border-box;
    }
    input[type="file"] {
      width: 93%;
      background-color: #ffffff;
      color: rgb(0, 0, 0);
      padding: 14px 20px;
      margin: 8px 0;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    button {
      background-color: #45a049;
      color: white;
      padding: 14px 20px;
      margin: 8px 0;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      width: 100%;
    }
    .child {
      width: 45%;
      float: left;
      padding: 20px;
      border: 2px solid red;
      margin: 5px;
    }
    </style>
```    

In this file, you have the `Podcast` component and a form to upload a podcast.

## Building the app

Before you continue, install these two packages: the Appwrite official package and faker.js, a library to generate mock data. 


    npm i appwrite @faker-js/faker
### Connecting to Appwrite

In the `index.vue` file, import the Appwrite package and the faker.js package, and then create an Appwrite connection like so:

```javascript
    ...
    <script>
    import { Client, Account, Databases, Storage, Query } from "appwrite";
    import { faker } from "@faker-js/faker";
    
    const client = new Client();
    
    client
      .setEndpoint("http://localhost/v1") // The Appwrite Endpoint
      .setProject("[YOUR-PROJECT-ID]");
    
    const account = new Account(client);
    const database = new Databases(client);
    const storage = new Storage(client);
    
    account.createAnonymousSession().then(
      (response) => {
        console.log(response);
      },
      (error) => {
        console.log(error);
      }
    );
    
    export default {
      name: "IndexPage",
      data() {
        return {
          podcasts: [],
          title: "",
        };
      },
      mounted() {},
    };
    </script>
    ...
```
In this file, you create an Appwrite instance with an account, database, and storage, which you'll use later in the app. Also, you set up an anonymous session - this saves us the time of making a whole authentication system.

There are two data variables, `podcasts`, and `title`.

In the mounted method, check whether the anonymous account is active and subscribe to the documents channel. Subscribing to a channel updates your app in real time once a change is made in the database.

```javascript
    ...
     mounted() {
        if (account.get !== null) {
          try {
            client.subscribe("documents", (response) => {
            });
          } catch (error) {
            console.log(error, "error");
          }
        }
      }
    ...
```
### Uploading a podcast

To upload a podcast, you'll follow the steps below:

1. First, upload the audio file to the storage bucket
2. Retrieve the ID and then store it in the `podcast_details` collection, along with the name, title, and date

```javascript
    ...
    methods: {
      async uploadPodcast() {
        const file = await storage.createFile(
          "[YOUR-BUCKET-ID]",
          "unique()",
          document.getElementById("file").files[0]
        );
    
        await database.createDocument(
          "[YOUR-DATABASE-ID]",
          "[YOUR-COLLECTION-ID]",
          "unique()",
          {
            fileID: file.$id,
            name: faker.name.fullName(),
            title: this.title,
            date: Date.now(),
          }
        );
      },
    },
    ...
```
Make sure to add a click event to the **Upload** button and also prevent the page from reloading, like so:

```javascript
    <button type="submit" value="Submit" @click.prevent="uploadPodcast">
      Upload
    </button>
```
### Fetching the podcasts

To create a function to fetch the podcasts, follow the steps below:

1. Fetch all the files in the storage bucket
2. For each audio file, get its details from the `podcast_details` collection using the `fileID`
3. Put all the details in an object and push it to the podcasts array

```javascript
    ...
    async getPodcasts() {
      const result = await storage.listFiles("63a4866686e5064b953d");
    
      let podcasts = [];
    
      result.files.map(async (file) => {
        let link = await storage.getFileView("63a4866686e5064b953d", file.$id);
    
        let podcastData = await database.listDocuments(
          "63a486f99305afe71e48",
          "63a487ea6bb5ba002a8c",
          [Query.equal("fileID", file.$id)]
        );
    
        podcasts.push({
          id: file.$id,
          link,
          title: podcastData.documents[0].title,
          date: new Date(podcastData.documents[0].date).toDateString(),
          name: podcastData.documents[0].name,
        });
      });
    
      this.podcasts = podcasts;
    },
    ...
```
Every time the page reloads or changes occur in the database, you want to fetch all the podcasts in real time. To do that, call the `getPodcasts` function on the mounted method like so:

```javascript
    ...
    mounted() {
      this.getPodcasts();
    
      if (account.get !== null) {
        try {
          client.subscribe("documents", (response) => {
            this.getPodcasts();
          });
        } catch (error) {
          console.log(error, "error");
        }
      }
    },
    ...
```
### Displaying the podcasts

To display the podcasts, all you have to do is loop over the podcasts array and pass in all the data as props like so:

```javascript
    ...
    <Podcast
      v-for="podcast in podcasts"
      :key="podcast.id"
      :title="podcast.title"
      :date="podcast.date"
      :source="podcast.link"
      :name="podcast.name"
    />
    ...
```
You should see the podcasts show up like this:

![podcast app view](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671747324671_podcast+app+view.png)


You can get free audio files from this website: https://mixkit.co/free-stock-music/

## Conclusion

In this article, you learned how to build a podcast platform using Nuxt.js and [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog). Combining these two technologies helped you to quickly and easily build a feature-rich podcast platform that meets the needs of both content creators and listeners.

## Resources
- [Appwrite Documentation](https://appwrite.io/docs?utm_source=hackmamba&utm_medium=blog&utm_campaign=hackmamba)
- [Nuxt.js Documentation](https://nuxtjs.org/docs/get-started/installation/)