Create Music Art Covers Using AI in NuxtJS

Banner for a MediaJam post

Moronfolu Olufunke

Never judge a book by its cover, never judge music by its cover - but we still do!

Music art covers are designs on music albums in the form of illustrations or generic images. Music covers are just as important as the music itself because a well-designed and attractive music cover can perform marketing functions for the music.

In this article, we will be creating a music art cover in Nuxt.js using Cloudinary’s Neural artwork style transfer add-on. The Neural Style Transfer uses neural networks to transfer and blend the styles from one image (source image) into another image (target image) while maintaining the content of both images with an intricate network.

Nuxt.js is a Vue.js based, open-source JavaScript library that improves building server-rendered Vue.js applications, leading to more performant web applications.

Cloudinary is a cloud-based video and image management platform that offers services for managing and transforming uploaded assets for usage on the web.


We can find the completed project on CodeSandbox. Fork it and run the code.


Check out the complete source code here


Understanding this article requires the following:

  • Installation of Node.js
  • Basic knowledge of JavaScript
  • Familiarity with Nuxt.js
  • A Cloudinary account. (sign up for a free account here).

Creating a Nuxt.js Project

Use npx create-nuxt-app <project-name> to create a new Nuxt.js project. The process of scaffolding the project would provide a list of options, which should look like this:

After successful project creation, we'll navigate into our directory and start our application by running the following command:

1cd <project name>
2npm run dev

Nuxt.js will, in turn, start a hot-reloading development environment that is accessible by default at http://localhost:3000.

Registering Cloudinary's Neural Style Transfer Add-on

Our project requires the Neural style transfer add-on from Cloudinary. To use the add-on in code, we will need to register for it via the Cloudinary dashboard. We will log into our Cloudinary dashboard to sign up for the add-on. Choose the Add-ons tabs from the available options on the navigation bar.

Clicking on the tab above shows all the available add-ons on Cloudinary, from which we can choose the desired add-on, which in this case is the Neural Artwork Style Transfer add-on:

Choosing the add-on prompts us to view a well-detailed tab about the add-on from where we pick the plan to opt on. We will pick the Free plan for this demo:

Allow Unsigned Add-on Transformations on Cloudinary

To allow people to transform images on the fly without verification using Cloudinary’s authenticated API, we will navigate to the Settings and click on the settings option. This will show a bunch of options for us to activate or deactivate. In our case, we will look out for the Unsigned add-on transformations allowed options and check them like so:

We will save the option, and now we can use the add-on in our Nuxt.js application.

Configuring Cloudinary

To use Cloudinary in our Nuxt.js application, we will need to install the Cloudinary Nuxt SDK in our project, like so:

1npm install @nuxtjs/cloudinary

Configuring nuxt.config for Cloudinary

We need to configure our Nuxt.js application in the nuxt.config file before we can use Cloudinary.

To do this, we will need to perform the following steps:

  1. Create a .env file in the root of our Nuxt.js project and add our Cloudinary Cloud name. We can find it by navigating to the Cloudinary dashboard.

  2. Register the property in our .env file like so:

  1. Register the Cloudinary component for global use in the nuxt.config.js file by adding '@nuxtjs/cloudinary' in the modules section:
1modules: [ '@nuxtjs/cloudinary' ],
  1. Add a cloudinary section in the nuxt.config.js like so:
1cloudinary: {
2 cloudName: process.env.cloudName,
3 useComponent: true,

The useComponent attribute is needed to make Cloudinary components like the cldimage and cldtransformation available for usage in Nuxt.js.

NB: *Endeavor to replace all occurrences of “***" with the correct values.

Uploading Images to Cloudinary

We'll upload images from Unsplash to Cloudinary. Cloudinary allows us to upload images via the dashboard by clicking the Media Library tab.

After uploading the images, we will need to copy the public Id to pick each uploaded image from Cloudinary.

Setting up the Image Store

The project we are building requires two different kinds of images - the first set is for the image cover, to which we will apply Cloudinary transformation, and the second set will be album covers for famous songs. Thus, we will create a first file named utils/image-covers.json and another named utils/album-covers.json. A sample snippet of any of these files should look like this:

2 {
3 "id": 1,
4 "publicId": "oscar-keys"
5 }

Building out the Project

In building out the project, we will need to display the images from Cloudinary out in the browser. We will do this by setting up the markup, including Cloudinary’s cld-image and cld-transformation component, which can be likened to using the native <img> tag in an HTML document.

To achieve this, we will navigate to the pages/index.vue file and replace the content with the code below:

We achieved the following in the code snippet above:

  • Imported the JSON images from the utils folder and declared them in the data properties before using Cloudinary images components — <cld-image /> and <cld-transformation /> to render the images in the application
  • Added a click function to the images rendered to show the active image
  • Created a functional input element to handle user input for the title
  • Added an error message to prompt users to select an image and fill the input fields before submission
  • Added a data property to manage the form data, error message, and other vital properties

After this stage, our page should look like the image below:


Generating the Image

To generate an album cover, we'll create a component that renders the generated album cover when the upload function linked to the “Generate Image” button is clicked.

We will create a file named GeneratedImageCover.vue in the components folder and add the code below to the file:

2 <div>
4 <cld-image ref="ref" name="cat.png" :public-id="publicId">
5 <cld-transformation effect="blur:150"/>
6 <cld-transformation effect="brightness_hsb:-20"/>
7 <cld-transformation :overlay="{fontFamily: 'Metamorphous', fontSize: 80, fontWeight: 'bold', text: text, testAlign: 'center'}" color="#fff" opacity="80" crop="fit" width="550" effect="shadow"/>
8 <cld-transformation flags="layer_apply"/>
9 </cld-image>
11 </div>
14export default {
15 props: {
16 text: {
17 type: String,
18 required: true
19 },
20 publicId: {
21 type: String,
22 required: true
23 },
24 },

We achieved the following using the snippet above:

  • Rendered the generated image using Cloudinary’s <cld-image /> and <cld-transformation />
  • Configured the Cloudinary components to accept the text and publicId as props
  • Cloudinary components support asset transformations, which we leveraged by blurring, changing the width, and cropping images, added text transformations like the font family and colors to achieve the desired album image

To render the GeneratedImageCover.vue component, in our view, we will need to import it into the index.vue file where it is conditionally rendered. We will add the code below:

We achieved the following from the code snippet above:

  • Added a method called upload to the form, executed when the generate image button is triggered
  • Checked whether an image is selected and if the title was added
  • The upload function ran the prepareFormData function that contains the form data
  • Added a data property to manage the error, the cloudname, preset, formdata, and tags for better organizing of our assets, e.t.c.
  • Used Axios to post data to the Cloudinary endpoint using the request object options of the url, POST method, and the formData
  • Included functionality to capture if the upload was successful or not, after a successful upload, we got access to some returned data like the secured_url used to render the uploaded image back in the browser

At this point, we should have a result that looks like this:

Applying Neural Style Transfer

At this stage, the next thing we need to do is apply neural style transfer using the images in the album with the recently generated image from the step above. To do this, we will create a new file named GeneratedAlbum.vue in the components folder and add the code below to the file:

2 <div>
3 <cld-image :public-id="albumId" class="grow" sign-url="true">
4 <cld-transformation width="550" crop="fit" />
5 <cld-transformation :overlay="publicid" font-size="80" font-weight="bold" />
6 <cld-transformation effect="style_transfer" flags="layer_apply" />
7 </cld-image>
8 </div>
11export default {
12 props: {
13 albumId: {
14 type: String,
15 required: true
16 },
17 publicid: {
18 type: String,
19 required: true
20 },
21 },

Cloudinary provides for style transfer using different transformation properties attached to the component. The required setup for neural style transfer in Cloudinary is:

  • The target image: image we would use as the base for the styles to get transferred to
  • The source image: image we intend to transfer its style to the target image
  • The input image: repainted generated image which is a blend of both the target and the source image

The public-id will represent the target image, while the overlay will be the source image. We will also need to specify the overlay effect which is denoted as style_transfer.

To render the GeneratedAlbum.vue component, in our view, we will need to import it into the index.vue file and also apply the Cloudinary transformation. At this stage, our final code in the index.vue should look like the below:

In turn, the application should look like this:


This article explains creating a music art cover in Nuxt.js using Cloudinary’s neural style transfer add-on.


Moronfolu Olufunke

Frontend Engineer | Tecnical Writer | Story Teller

Olufunke is a Frontend Engineer and technical writer who enjoys building stuff and writing about them.