How to build a Foreignrap clone using Nuxt, Airtable and a bit of hardcore 🔥

Erd
7 min readOct 5, 2019

--

Full screen of the prototype.

The Back Story

For quite some time, I’ve been a fan of the Foreignrap platform made by Aziz Firat, Thomas Vimare, Marty Bell & Ariel Dorol. It’s been a great source of discovery when it comes to new artists and scenes — Dutch 🇳🇱 hip hop is certified 🔥. On top of the great curation of content, the repurposing of the YouTube platform into a visual spectrum of the world’s video editing talent is pretty sweet.

As much as I love rap, grime and Dutch hip hop (obviously), I also have an itch for music that requires the singer to lose a few of their vocal cords along the way. Out of curiosity one day and whilst indulging in the new Bring Me The Horizon album, I set out to build an experiment using my newly discovered favourite API, the Airtable API!

The video that inspired the project.

The goal was simple. Re-create Foreignrap, but with a heavier tone — somewhere for all the hardcore, metal and alternative music folk to go. I also wanted to see if my personally preferred framework of Nuxt (Vue) could combine seamlessly with Airtable and quickly create a minimal version. So let’s dive into some basics…

Minimum Requirements 🤔

  • App framework (Nuxt.js)
  • Database (Airtable sheet)
  • A way to consume database (Airtable API)
  • Submit a track (Airtable API)
  • Complication free styling (Tachyons)
  • Quick deployment (Now)

Diving Into It

First things first, setting up the application itself, Nuxt have a nifty little command utilising npx — which in a roundabout way, is npm without downloading the package to your computer. Ahem, so we fire up Terminal and run…

npx create-nuxt-app trmrs

Oh by the way, the app from this point on will be known as Night Time Tremors ‘cos y’know, heavy music tremors and that. 🤷‍♀️

Essentially this command builds our app infrastructure. Nuxt begins to download and install on your computer and much like those annoying survey people at the shopping mall, it asks you a few questions regarding your build. In this case we go for the super stripped back and omit things like testing and linting — sorry code bros.

That shopping mall assistant vibe.

To quickly run down our setup looks like this…

  • Project name — trmrs
  • Project description — The heaviest tracks around.
  • Author name — erd_xyz
  • Package manager — Yarn
  • UI Framework — Tachyons
  • Custom Server Framework — None
  • Nuxt.js Modules — None
  • Linting Tools — None
  • Test Framework — None
  • Rendering Mode — Universal (SSR)

You may be wondering why we picked Universal over Single Page Application, when essentially, this will be loading ID’s from a database on a single page. Reasoning being meta data, meaning further down the line if we decide to give tracks unique links, we then control the meta data output for link sharing.

SPA‘s with Nuxt are a little more tricky for meta data.

Creating Our Structure

One of the greatest strengths of the Nuxt framework is that your routing is done out of the box. For the purpose of this clone, we require one page — just the index.vue file, which resides in the Pages folder.

Before setting up our first page, we need a few helper node modules. Despite using Tachyons out the box for structure and basics, we may require some custom CSS. Again, this is personal preference, but I tend to add Sass to my projects. We do this by executing the following Yarn command…

yarn add sass-loader node-sass --save

  • sass-loader — ability for the Webpack build to compile Sass.
  • node-sass — ability to compile .scss files.

This means we can then create a top level main.scss in our assets folder, which looks something like this 👉

Beyond the structural abilities of Tachyons, we now have the ability to control CSS animations and other utilities we may need, such as importing a custom font etc.

Quick tip — Always remember to link the main.scss in the css: [] section of your nuxt.config.js

Now that we have basic styling setup, we need a few more packages to start to bind everything together. Much like Foreignrap, we’ll be utilising YouTube for the visuals and of course Airtable for our database. So that means you execute a further two packages with yarn…

yarn add vue-youtube airtable --save

  • airtable — Airtable themselves provide a Javascript API library.
  • vue-youtube — One of many YouTube integration plugins for Vue.

Connecting To The Database

Now that we have our initial structure and the tools needed to build our app, let’s just build it yo. 💁‍♀️ The coolest thing about Airtable is, whenever you create a Base, their API offers you custom tailored documentation based on that base (mind the pun). This means whenever you alter your table or base, the changes are reflected in the documentation.

Which is pretty neat. Thank you to the Product Manager at Airtable who came up with that. 🙏

Even the values adapt to your actual data!

So let’s import the package and setup our API keys in our application. Inside our index.vue file, we add this between the <script> tags.

<script>
import Airtable from 'airtable'
var base = new Airtable({apiKey: 'YOUR_API_KEY'}).base('BASE_ID');
export default {
data () {
return {
videos: []
}
},
methods: {
loadData () {
var self = this
this.videos = []
base('PAGE_NAME').select({
view: 'Grid view'
}).eachPage(function page(records, fetchNextPage) {
records.forEach(function(record) {
self.videos = records
});
}, function done(err) {
if (err) { console.log(err); return; }
});
},
mounted () {
this.loadData()
}
}
</script>

All we are doing here is providing the initial connection, via the recommended route on the Airtable API. This is where we connect to the spreadsheet page and consume the data coming from it. Inside Vue’s data method, we create our an empty object that we can pull in our array of video ID’s and data.

We then populate this by retrieving the table below using Airtable’s Javascript API. As you can see below, our table is pretty simple, we setup a column for Track Name, Artist and YouTube ID. Potentially we could also add a flag here to confirm if a video is published or not by simply adding a true/false column.

A quick list of tracks. Simply just track name, artist name and YouTube video ID.

For the purposes of not making this article as long as my list of all time favourite footballers, we’ll speed this up a little. 👀

Integrating YouTube

Now that we have our connection, let’s setup the physical structure and plug into our YouTube package. With our mark up, we’ll need to achieve a few things.

First, we need to load the initial video into the YouTube component. To begin we only load 1 video into our loop — but then how do we retrieve videos at random? Well, simple! The VueYouTube plugin provides you with methods from the YouTube API, we are provided with an ended() method, where we can trigger this simple function…

randomVideo () {
this.randomId = Math.floor(Math.random() * this.videos.length)
}

Next, we need some UI to deliver the current track name and artist. We also provide simple UI functions to Play/Pause the video and skip the track (again, triggering a random video).

The great thing with the YouTube API provides you with specific methods where you can control the video at various points. In this prototype we use the following…

  • ended() — This recognises when the video ends and we can trigger the next track.
  • playing() — When the next video starts, we can tell the UI to briefly show the title and artist.
  • next() — When the user taps the Skip button in the UI, we can trigger the above function for a new random video.
  • pauseToggle() — Along with computed values, we can figure out when the video is playing to change the play button to pause and vice versa.

Having these methods and more enables us to truly create a rich user interface for controlling our player. You could even take this further and bind keys using Vue’s native key down events to add traditional keyboard controls for a music player.

Note — We only retrieve 1 video in the beginning otherwise using v-for loop, we would load the total number of videos in our database at the same time, which makes for a pretty 💩 app.

The Prototype (Thus Far)

I kind of figure this article can get real long, real fast, so before we get into building some of the more complex functionality like submitting tracks, let’s look at the progress so far. This is like that magic bit on cooking shows where they had one prepared earlier…

Terrible quality GIF etc.

As you can see above, we’ve created a super basic one page app that retrieves videos, plays and pauses as well as skipping them. With some odd glitchy CSS mixin we found on Codepen, we also added a “cool” effect when introducing the video. Also a not so great font, but we’ll change that later. 🤦‍♀️

Rounding Up …For Now

So I may potentially follow this up with another post diving more into detail about some of the features up until this point that we haven’t included.

One of the coolest features of Foreignrap is the ability for the community around it to submit a track. They achieve this with a Google Form, however, I wanted to keep everything simple and utilise Airtable API’s write abilities.

Next time round, we will also cover the UI in-depth and one line deployment with Now 2. Perhaps the easiest part!

Until then, check out the progress here and I hope you’ve enjoyed reading up until this point.

✌️

Note — I’m not necessarily an expert developer, just someone who like to dabble in code, so don’t @ me code bros. 😅

--

--