Skip to content

Create an Article Banner Generator

The idea of a blog article banner gives a pictorial representation of its body. This post discusses implementing an article banner generator that allows us to dynamically select an image of our choice, write some text on it, change the background and text color.

We will use Nuxt.js as our frontend technology. Nuxt is an open-source framework that provides frontend developers with the power to build fast and high-performing websites.

For this post, we’ll store the base banner image on Cloudinary and apply multiple transformations to it.

We completed this project in a CodeSandbox. Fork and run it to quickly get started.

Check the source code on GitHub.

To complete this tutorial, we will need the following:

  • Node for installing dependencies
  • The knowledge of JavaScript and Vue.js
  • A Cloudinary account. Sign up for a free account

We need to scaffold a new project using the CLI, which will ask a series of questions with the following terminal command:

yarn create nuxt-app image-banner
# OR 
npm init nuxt-app image-banner
# OR 
npx create-nuxt-app image-banner

With the above command, choose the following configuration as shown below:

Project name: accept the default, press Enter
Programming language: JAVASCRIPT
Package manager: Npm
UI framework: Tailwind CSS
Nuxt.js modules: N/A
Linting tools: N/A
Testing framework: None
Rendering mode: Universal (SSR / SSG)
Deployment target: Static (Static/Jamstack hosting)
Development tools: jsconfig.json
What is your GitHub username? <github-username>
Version control system: GIT

Once the installation is complete, navigate to that directory and start up a development server to preview the app on http://localhost:3000.

cd image-banner && yarn dev
# or
cd image-banner && npm run dev

Next, we install Cloudinary’s Nuxt.js module with:

yarn add @nuxtjs/cloudinary 
# or 
npm install @nuxtjs/cloudinary

With the dependency installed, we must add the module in the nuxt.config.js file under the modules section.

nuxt.config.js

modules: [
  "@nuxtjs/cloudinary"
]

Below the modules section, add the following to configure Cloudinary with the useComponent and cloudName field option.

nuxt.config.js

modules: [
  "@nuxtjs/cloudinary"
],

// add this 
cloudinary: {
  cloudName: "<your-cloud-name>",
  useComponent: true,
}

useComponent set to true allows the use of Vue image components. You can obtain your Cloudinary cloud name from your dashboard on Cloudinary.

With our app setup completed, we’ll upload two sample royalty-free images to Cloudinary.

In our dashboard, we will have access to upload and save the downloaded images in Cloudinary by clicking the Media Library tab and Upload button as displayed in the image below.

Next, we need to copy the publicId for the saved images from our dashboard, which will be necessary to generate the article banner.

In our Nuxt.js project root directory, create a folder called utils, and within this folder, create a file, banners.json, with the following json data.

utils/banners.json

[
  {
    "id": 1,
    "publicId": "pexels-christina-morillo-1181681_itscxa",
    "alt": "woman on her laptop"
  },
  {
    "id": 2,
    "publicId": "pexels-hasan-albari-1229861_njoool",
    "alt": "workstation"
  }
]

In creating the article banner, we need to set up the markup, styling, and data properties in the script section of the file, index.vue.

To do this, replace the index.vue file with the code from this gist, and we’ll explain what is happening after:

https://gist.github.com/Terieyenike/ad9881d156af027eb3c1a7cec2925551

https://gist.github.com/Terieyenike/ad9881d156af027eb3c1a7cec2925551

From the code snippet in the gist, we:

  • We created the data method and declared a list of variables to use in the index.vue component. This includes the imported image JSON data, image id, the form data, and a showBanner boolean field.
  • We wrote markup to conditionally render the image collection with the v-if and v-for directives. We also bound the class on the image element to dynamically set a border.
  • Within the markup, we use Cloudinary image components to display the image with the help of the package @nuxtjs/cloudinary
  • We managed a form error message when no image is selected.
  • Finally, we set an alternative message using the v-else directive in the absence of an image list.

With the above process done, we should have our app looking like this:

We’ll create a Banner component that establishes a banner image when clicking the Generate Banner button. Create and add the following snippet to components/Banner.vue.

components/Banner.vue

<template>
  <div class="mt-8">
    <cld-image :public-id="publicId">
      <cld-transformation
        :background="bgColour"
        crop="fit"
        opacity="20"
        width="2000"
      />
      <cld-transformation
        :color="textColour"
        :overlay="{
          fontFamily: 'Arial',
          fontSize: 80,
          fontWeight: 'bold',
          text: message.toUpperCase(),
        }"
      />
            <cld-transformation flags="layer_apply"/>
    </cld-image>
  </div>
</template>
<script>
export default {
  props: ["message", "publicId", "bgColour", "textColour"],
};
</script>

The above snippet renders the generated image using the cld-image and cld-transformation components, with the message, publicId, bgColour, and textColour as props.

Cloudinary components provide a good experience with setting multiple transformations on an image. These include font properties, block lettering the message property with the method toUpperCase, opacity, background, and text color attributes.

In the index.vue file, we import and conditionally render the created Banner component.

pages/index.vue

<template>
  <div class="lg:flex lg:items-center px-8 py-8 max-w-md m-auto md:max-w-2xl lg:m-0 lg-p-0 w-full lg:max-w-5xl">
    <div class="lg:w-2/4">
      <h1 class="text-gray-900 text-lg mb-2 font-bold uppercase md:text-3xl lg:text-2xl">
        <!-- Header title detail here -->
    </h1>
      <form @submit.prevent="handleSubmit"> <!-- add handleSubmit method -->
        <!-- form content details here -->
      </form>
    </div>

    <!-- conditionally render the Banner component here -->
    <div v-if="showBanner" class="mt-10 lg:w-2/4 lg:mt-0">
      <Banner
        :bgColour="formData.backgroundColour"
        :message="formData.message"
        :publicId="formData.publicId"
        :textColour="formData.textColour"
      />
    </div>
  </div>
</template>
<script>
// import here
export default {
  data() {
    return {
      // data objects code here
    }
  },
  methods: {
    // other methods go in here
    // add this
    handleSubmit() {
      if (this.imageId) {
        this.showBanner = true
      } else {
        this.formData.error = true
      }
    },
  },
}
</script>

The above snippet conditionally renders the banner component with the required props. The function handleSubmit checks if an image is selected before rendering it or throwing an error in its absence.

Our app should look like the image below.

We will quickly add a function to copy the link of the generated image.

In the Banner.vue, we update the source code with the following:

components/Banner.vue

<template>
  <div class="mt-8">
    <cld-image ref="ref" :public-id="publicId">
      <!-- Transformation component goes here -->
    </cld-image>

    // add this: copiable link section
    <div class="mt-10">
      <h2 class="mb-2 text-gray-500 font-semibold">Copiable link</h2>
      <input
        :value="url"
        class="w-full border-gray-300 rounded-sm border p-2"
      />
    </div>
  </div>
</template>
<script>
export default {
  props: // props,
  // add data objet here
  data() {
    return {
      url: "",
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.url = this.$refs.ref.$el.src
    });
  },
};
</script>

The code above does the following:

  • Included an empty initialized url in the data object
  • On the cld-image component, added the ref attribute to access the src of the underlying image element
  • The mounted lifecycle method, retrieves the image URL and updates the url data in the state.
  • Bound the url data to the value of the input element.

The app then looks like this.

Check out the copiable link from the above image.

This post explains how to create a banner image generator using Nuxt.js, with Cloudinary providing media storage and transformations.

Back to top

Featured Post