Skip to content

Mobile app demo walkthrough generator

For any product manager or app developer, it is very easy to record the screen of your latest release. It is also very easy to record yourself as you walk through the application. It is however not easy to combine these two videos together let alone in a presentable manner.

In this tutorial, we demonstrate how to create a demo walkthrough generator for easy updates of your product walkthroughs.

The completed project is available on Codesandbox.

You can clone the full source code on my Github repository.

To be able to follow through with this tutorial, entry-level knowledge of HTML, CSS, and JavaScript is required. Knowledge of VueJs is recommended but not required.

NuxtJs is a VueJS framework that provides us with a modular, performant, and enjoyable experience.

To set up our project, run the following command in your preferred working directory:


yarn create nuxt-app nuxtjs-mobile-demo-walkthrough-generator

# OR

npx create-nuxt-app nuxtjs-mobile-demo-walkthrough-generator

# OR

npm init nuxt-app nuxtjs-mobile-demo-walkthrough-generator

Code language: PHP (php)

The commands above will trigger a set of questions required to help the utility set up the project. Here are our recommended defaults:

Project name: nuxtjs-mobile-demo-walkthrough-generator

Programming language: JavaScript

Package manager: Yarn

UI Framework: Tailwind CSS

Nuxt.js modules: N/A

Linting tools: N/A

Testing framework: None

Rendering mode: Universal (SSR/SSG)

Deployment target: Server (Node.js hosting)

Deployment tools: N/A

What is your Github <your-github-username>

Version control system: Git

You may now navigate to the project and launch it


cd nuxtjs-mobile-demo-walkthrough-generator


yarn dev

# OR

npm run dev

Code language: PHP (php)

@nuxtjs/cloudinary is the recommended Cloudinary plugin for NuxtJs. Cloudinary is a media management platform that allows us to unleash the potential of our media assets by providing a powerful API service.

We first need to add @nuxtjs/cloudinary as a dependency in our project


yarn add @nuxtjs/cloudinary

# OR

npm install @nuxtjs/cloudinary

Code language: CSS (css)

Add @nuxtjs/cloudinary as a module in the modules project of the nuxt.config.js file:


// nuxt.config.js

export  default  {

...

modules: [

'@nuxtjs/cloudinary'

]

...

}

Code language: JavaScript (javascript)

We will finally add a cloudinary section in the nuxt.config.js to set configurations for the module:


// nuxt.config.js

export  default  {

...

cloudinary: {

cloudName:  process.env.NUXT_ENV_CLOUDINARY_CLOUD_NAME,

secure:  true,

useComponent:  true

}

...

}

Code language: JavaScript (javascript)

As visible in the codebase above, we are making use of environmental variables. These are sensitive details that we do not want in our codebase. To set up environmental variables locally, we will create a .env file


touch .env

Code language: CSS (css)

We will add the Cloudinary cloud name here. If you do not have one, create an account on https://cloudinary.com/. The cloud name will be visible in the console section.


<!-- .env -->

NUXT_ENV_CLOUDINARY_CLOUD_NAME=<secret-cloudinary-cloud-name>

Code language: HTML, XML (xml)

To generate the final complete file, we are going to make use of a video template. This is a 30-minute video that has no audio and has the background and phone template we require. This will limit our application to generate videos of max 30 minutes. Grab this video here. We recommend creating a folder called nuxtjs-mobile-demo-walkthrough-generator and saving this video with the name iphone_se_template.mp4. This will lead to the video having the public_id nuxtjs-mobile-demo-walkthrough-generator/iphone_se_template.mp4.

We are first going to create a simple form for selecting the two video files. One is the mobile app video, the other is an instructional video. We are going to place this form in a Form.vue component file.


<!-- components/Form.vue -->

<form action="#"  method="POST">

<div>

<div>

<div>

<div>

<label for="mobile_app_video">

Mobile app video

</label>

<div>

<input id="mobile_app_video"  name="mobile_app_video"  required=""  type="file"  />

</div>

</div>

</div>

<div>

<div>

<label for="instructor_video">

Instructor video

</label>

<div>

<input id="instructor_video"  name="instructor_video"  required=""  type="file"  />

</div>

</div>

</div>

</div>

<div>

<button type="submit">

Save

</button>

<p v-if="uploadingMobileAppVideo || uploadingInstructorVideo">

Upload in progress

</p>

</div>

</div>

</form>

Code language: HTML, XML (xml)

As indicated in the above code, the submission of the form will be handled by the submit method. Let’s see what this method contains:


  

<script>

// components/Form.vue

export default {

data()  {

return {

uploadingMobileAppVideo:  false,

uploadingInstructorVideo:  false,

};

},

methods: {

submit(e)  {

this.uploadMobileAppVideo(e);

this.uploadInstructorVideo(e);

},

  

async  uploadMobileAppVideo(e)  {

this.uploadingMobileAppVideo  =  true;

  

// Mobile app video file

let file  =  e.target.mobile_app_video.files[0];

  

/* Read data */

const data  =  await  this.readData(file);

  

/* upload the converted data */

const resp  =  await  this.$cloudinary.upload(data,  {

upload_preset:  "default-preset",

folder:  `nuxtjs-mobile-demo-walkthrough-generator`,

});

  

this.$emit("MobileAppVideoUploaded", resp.public_id);

  

this.uploadingMobileAppVideo  =  false;

},

  

async  uploadInstructorVideo(e)  {

this.uploadingInstructorVideo  =  true;

  

// Instructor video file

let file  =  e.target.instructor_video.files[0];

  

/* Read data */

const data  =  await  this.readData(file);

  

/* upload the converted data */

const resp  =  await  this.$cloudinary.upload(data,  {

upload_preset:  "default-preset",

folder:  `nuxtjs-mobile-demo-walkthrough-generator`,

});

  

this.$emit("InstructorVideoUploaded", resp.public_id);

  

this.uploadingInstructorVideo  =  false;

},

readData(f)  {

return new Promise((resolve)  =>  {

const  reader  =  new  FileReader();

reader.onloadend  =  ()  =>  resolve(reader.result);

reader.readAsDataURL(f);

});

},

},

};

</script>

Code language: HTML, XML (xml)

In the above code, we read the files submitted and upload them to the nuxtjs-mobile-demo-walkthrough-generator folder. We also specify an upload preset. These are a set of rules to be used for all uploads. To create an upload reset, proceed to the settings section in your Cloudinary account. Proceed to the upload section. We recommend the following settings:

Unique filename: true

Delivery type: upload

Access mode: public

The above code will upload the files and emit two events. MobileAppVideoUploaded and InstructorVideoUploaded. In the next section, we receive these two events and generate the final video.

We will now inject the Form.vue component in the pages/index.vue file and listen for the events:


<!-- pages/index.vue -->

<template>

...

<Form

@InstructorVideoUploaded="instructorVideoUploaded"

@MobileAppVideoUploaded="mobileAppVideoUploaded"

/>

...

</template>

Code language: HTML, XML (xml)

We will receive the public_id and assign it to local variables. When overlaying videos in subfolders, you need to replace all \ with : as indicated here.


// pages/index.vue

<script>

export default {

data()  {

return {

instructorVideo:  null,

mobileAppVideo:  null,

};

},

methods: {

instructorVideoUploaded(public_id)  {

this.instructorVideo  =  public_id.replace("/",  ":");

},

mobileAppVideoUploaded(public_id)  {

this.mobileAppVideo  =  public_id.replace("/",  ":");

},

},

};

</script>

Code language: HTML, XML (xml)

Once the public_ids have been stored in the page state, we will proceed to overlay the two videos on top of the initial video template. To remove the sound from the mobile app video, we add the audioCodec="none" setting.


<template>

...

<cld-video

public-id="nuxtjs-mobile-demo-walkthrough-generator/iphone_se_template"

width="1000"

crop="scale"

quality="auto"

controls="true"

autoplay="true"

class="m-auto"

v-if="mobileAppVideo && instructorVideo"

>

<cld-transformation

:overlay="`video:${mobileAppVideo}`"

width="405"

height="750"

gravity="center"

x="-385"

y="0"

audioCodec="none"

/>

<cld-transformation

:overlay="`video:${instructorVideo}`"

width="300"

height="300"

gravity="south_east"

radius="150"

x="100"

y="100"

crop="fill"

/>

</cld-video>

...

</template>

Code language: HTML, XML (xml)

With the above code, we have successfully created a mobile demo walkthrough generator. When the product changes, we simply upload the new videos and retrieve the newly compiled video. This just shows the potential of what is possible.

Back to top

Featured Post