Jovo v2 Migration Guide

We just released a huge update to the Jovo Framework: Version 2! Learn how to migrate from a Jovo v1 project to the new v2 of the Jovo Framework, or check out our Quickstart guide.

Getting Started with v2

New to Jovo? Check out our Quickstart guide.

With the update to v2 we've have completely refactored the code base of both the Jovo Framework and the Jovo CLI to make it more modular and easier to extend.

The code base now has a plugin architecture, where each platform (e.g. Amazon Alexa, Google Assistant), integration (e.g. DynamoDb, Dashbot) and tool (e.g. Jovo Debugger) can be added and removed as a plugin.

Although most of these changes were under the hood and don't directly affect the usage of the framework, we used the chance to make quality of life changes to the project structure and increased the consistency of the framework's interfaces.


To get started with the new Jovo v2, install the Jovo CLI:

Then, create a new Jovo project with:

Project Structure

New Jovo projects have an updated folder structure.

New Jovo v2 Project Structure

There are several changes that are important:


Find everything about project.js here.

The project.js file is the equivalent to the app.json file with small tweaks here and there. It stores all project related configurations and is only used for the build and deploy processes.

That means overriding certain parts of your app config using (like different databases for different stages) the project.js file won't be possible anymore. That's now done with the config.js.

Besides that, everything works the same as with v1.


Find everything about config.js here.

The config.js file is the equivalent to the configuration part at the top of the app.js file in the default project structure.

To override certain configurations in different stages we use individual config files for each stage:,, etc.

For example we could disable logging in our prod stage using the file:


Since the project structure is different (the index.js is now in src as opposed to the root directory), there is a slight update to the deployment process.

Instead of zipping the complete project folder (which was quite large anyways), you can create an optimized file with either of the following commands:

This will copy the src files into a bundle folder, run a production-only npm install, and then zip it.

You can then use this file and upload it to the hosting provider of your choice.

To be able to run this command, you need the following script in your package.json(default for fresh new projects):

Updated Concepts

The Jovo architecture has a few new concepts:


Find everything about plugins here.

With the new plugin architecture of the framework, the core jovo-framework npm package does not contain all the features anymore. Each platform, integration and tool has to be imported, configured and initialized individually.

Let's go over the process by integrating the FileDb plugin, which allows us to use a JSON file as a local database for development:

We first install the plugin:

After that we go our app.js file, which is now located in the src folder and import as well as initialize the plugin:

The same procedure has to be done for each plugin.

By default, a new v2 project comes with the Alexa, GoogleAssistant, FileDb, and JovoDebugger plugins:

Jovo Objects

For v2 we've updated the way interfaces are called to make it easily distinguishable from actual method calls:

Here's the list of changes:

v1 v2
request() $request
response() $response
user() $user
user().data $user.$data
getInputs() $inputs
speech $speech
reprompt $reprompt
alexaSkill() $alexaSkill
alexaSkill().audioPlayer() $alexaSkill.$audioPlayer
alexaSkill().dialogInterface() $alexaSkill.$dialog
alexaSkill().gadgetController() $alexaSkill.$gadgetController
alexaSkill().gameEngine() $alexaSkill.$gameEngine
alexaSkill().inSkillPurchase() $alexaSkill.$inSkillPurchase
googleAction() $googleAction
googleAction().audioPlayer() $googleAction.$audioPlayer


We updated existing integration layers and added new interfaces. Take a look here to learn more about our:

Response Execution

Intents run through and send out a response at the end automatically, which means this.endSession() is obsolete.

Besides that, you now have to handle asynchronous tasks appropriately, otherwise the response will be sent out, before you, for example, fetched the data from the API. The most convenient way is using async functions.

Breaking Changes


With v2 you won't be able to access user inputs by adding them as parameters to your intent anymore. Inputs can now be accessed by using a new $inputs object:

Also, you won't be able to pass additional data in redirects anymore. Here is our recommended (more consistent) way to pass interaction specific data:

State Management

Previously, a state was saved in a session attribute called STATE. To make sure this does not interfere with the own data you save in sessions, we renamed it to _JOVO_STATE_.

Unit Testing

Learn more about unit testing here.

In v1, Jovo used a combination of mocha and chai for unit testing. In v2, we switched to Jest and provide a cleaner experience that leverages async and await.

Changes to the User Object

Learn more about the User Object here.

User Data

Learn more about Data Management here.

User ID

Alexa User Methods

Learn more about Alexa specific features here.

To keep platform specific user methods more organized, it is now necessary to use the platform's user object (this.$alexaSkill.$user) to call features from e.g. the Alexa Settings API:

Learn more by taking a look at the following docs:


In the END handler (for SessionEndedRequests), the Alexa specific reason for the ended session could be retrieved.

As this is not a cross-platform feature, it is now moved to the this.$alexaSkill element:

Optional Changes

Intent Syntax

In v2 we use the method syntax introduced with ES6:

Data Management

Learn more about Data Management here.

We changed the naming of how you can access data to provide a more consistent experience:

Alexa Dialog Interface

To increase consistency, the dialog feature of Alexa has its own interface now, this.$alexaSkill.$dialog, instead of being directly accessibly through the $alexaSkill interface.

As a result, there were also method name changes:

v1 v2
dialogDelegate() $dialog.delegate()
dialogElicitSlot() $dialog.elicitSlot()
dialogConfirmSlot() $dialog.confirmSlot()
dialogConfirmIntent() $dialog.confirmIntent()
getDialogState() $dialog.getState()
isDialogCompleted() $dialog.isCompleted()
isDialogInProgress() $dialog.isInProgress()
isDialogStarted() $dialog.isStarted()

While we recommend to use the new naming conventions, the old ones still work (deprecated).


For more examples how all of these changes look in action, we've updated both the examples folder and the templates repository.

Comments and Questions

Any specific questions? Just drop them below. Alternatively, you can also fill out this feedback form. Thank you!

Join Our Newsletter

Be the first to get our free tutorials, courses, and other resources for voice app developers.