An Alexa Skill starter project template that uses the Serverless Framework and the Alexa Skills Kit SDK for Node.js.
This template includes the following features:
- Creates IAM Users with permissions and local profiles for development and production stages
- Automates packaging of skill into a ZIP file and deployment to AWS Lambda
- Creates an S3 bucket, enables CORS, and uploads all files and folders placed in the
deploy-s3
folder - Separate AWS Lambda and S3 deployments for development and production stages
- All skill configurations are in a separate file based on the stage and can be found in the
src/config
folderdev.skill.config.json
- development configuration; copied toskill.config.json
before deployment to development Lambdaprod.skill.config.json
- production configuration; copied toskill.config.json
before deployment to production Lambda
- NPM scripts to allow easy deployment to Lambda and/or S3 for development and production stages
- All translatable text in the
translations.json
file automatically included in S3 deployment - Content and translations can be added or changed in S3 without redeploying the Lambda function
The following are used in this template:
- Serverless Framework
- AWS
- AWS CLI
- Identity and Access Management (IAM)
- Lambda
- Simple Storage Service (S3)
- CloudFormation
- CloudWatch
- DynamoDB (optional)
You can create an Alexa skill even if you don't have an Alexa device.
Use:
-
Install Node.js
- If you are only using Node.js for Lambda development, consider installing the version of Node.js that matches the supported Lambda version which is v6.10
- Installing Node.js will also install Node Package Manager (npm)
-
Create an Amazon Web Service account
-
Create a user instead of the AWS account root user: Creating Your First IAM Admin User and Group (save the .csv file locally)
-
Install AWS CLI: Installing the AWS Command Line Interface
-
Configure AWS locally: Quick Configuration
$ aws configure AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY Default region name [None]: us-east-1 Default output format [None]: json
-
Install Serverless Framework
$ npm install -g serverless
This template has been tested with serverlesss v1.10.2
-
Install Git
-
Install a code editor. The detailed steps will show you how to use Visual Studio Code to debug your Node.js code locally.
Only 9 steps and no more than 9 minutes:
-
Clone project repository. You need to run
npm install
in both thesrc
andtest
folders. AFTER THAT all commands are run fromsrc
.$ git clone --depth=1 https://github.com/rmtuckerphx/alexa-skill-serverless-starter-template.git myskill $ cd myskill/test $ npm install $ cd ../src $ npm install
-
Configure the project
$ npm run configure
-
Create IAM Users
$ npm run iam
-
Initial deploy to AWS Lambda
$ npm run deploy:dev:sls
-
Open Amazon Developer website and AWS console website by:
$ npm run open:amz
-
Copy Lambda ARN from AWS Console for use in next step
-
Add Skill at Alexa Skills Kit website and set Lambda ARN value
-
Copy Alexa Skill ID from last step to config file(s)
-
Deploy skill to AWS Lambda & S3
$ npm run deploy:dev
The above Quick Setup is explained in more detail in this section.
The AWS Command Line Interface is used during deployment to create an S3 bucket and copy to it content such as images, audio, and translations.
Follow the AWS documentation at: Installing the AWS Command Line Interface
Install via npm:
$ npm install -g serverless
If you just want to start a new project without any commit history then use (recommended):
$ git clone --depth=1 https://github.com/rmtuckerphx/alexa-skill-serverless-starter-template.git myskill
$ cd myskill
Or you can clone this repo into a new project folder (ex: myskill).
$ git clone https://github.com/rmtuckerphx/alexa-skill-serverless-starter-template.git myskill
$ cd myskill
Navigate first to the 'test' and then to the src
folder of your skill and install packages:
$ cd test
$ npm install
$ cd ../src
$ npm install
The following files have placeholders that need to be replaced before other commands can be executed:
File | Placeholder(s) |
---|---|
src/package.json |
YOUR_NAMESPACE, YOUR_SKILL_NAME |
test/package.json |
YOUR_NAMESPACE, YOUR_SKILL_NAME |
src/translations.json |
YOUR_SKILL_NAME |
src/serverless.yml |
YOUR_NAMESPACE, YOUR_REGION |
src/config/dev.skill.config.json |
YOUR_NAMESPACE, YOUR_REGION, YOUR_ROLE_ARN |
src/config/prod.skill.config.json |
YOUR_NAMESPACE, YOUR_REGION |
The meaning of these placeholders are:
Placeholder | Description |
---|---|
YOUR_SKILL_NAME | Required. The user friendly (and translatable) name of your skill that can be used in SSML or cards. |
YOUR_NAMESPACE | Required. Your organization and skill name (ex: organization-skillname) that is used in creating the names for the service, profiles, users. |
YOUR_REGION | Required. The region to deploy the Lambda function and S3 bucket (ex: us-east-1). |
YOUR_ROLE_ARN | Optional. Used during debugging and testing so that Lambda role has trust relationship with test user. Set by npm run configure:rolearn:dev which is run by npm run deploy:dev:sls |
There are three ways you can update these placeholder values:
- Run
npm run configure
with no parameters. You will be prompted for values. (recommended) - Manually open each file and replace the placeholder value with the actual value
- Run the configure command with parameters:
$ npm run configure -- --skillName 'Fun Facts' --skillNamespace 'organization-skillname' --region 'us-east-1'
Note: Make sure to include the "--" after the word configure
.
This step is not specifically required for setting up this project, but it is a best practice to protect your AWS root user. If you have not already done so, follow the steps in Creating Your First IAM Admin User and Group and use that user.
To the Administrators (or whatever group your created) add the IAMFullAccess permission so that the next step will work properly.
$ npm run iam
Executing this command when the skillNamespace is 'organization-skillname' will:
- Create the users:
- 'organization-skillname-user-dev'
- 'organization-skillname-user-prod'
- Create access keys for each of the users
- Assign the AdministratorAccess permission to each user
- Create these local profiles with the correct access keys:
- 'organization-skillname-profile-dev'
- 'organization-skillname-profile-prod'
Executing this command, will add profiles to your local .aws/credentials
file.
To list the contents of the .aws folder, execute the command:
Linux, OS X, or Unix
$ ls ~/.aws
Windows
> dir %UserProfile%\.aws
The contents of the credentials
file will look something like this:
[organization-skillname-profile-dev]
aws_access_key_id=AKIA...
aws_secret_access_key=g0N...
[organization-skillname-profile-prod]
aws_access_key_id=AKIA...
aws_secret_access_key=d+M...
For this example, the access key and secret have been truncated.
The first deploy of the skill to AWS Lamba using the Serverless Framework creates the AWS Lambda ARN.
Development
$ npm run deploy:dev:sls
The output should look something like this:
> aws-alexa-skill@1.0.0 deploy:dev:sls E:\dev\alexa\alexa-skill-serverless-starter-template\src
> npm run copy:dev:config && serverless --stage=dev deploy
> aws-alexa-skill@1.0.0 copy:dev:config E:\dev\alexa\alexa-skill-serverless-starter-template\src
> cp ./config/dev.skill.config.json ./config/skill.config.json
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3 (5.08 MB)...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.................
Serverless: Stack update finished...
Serverless: Removing old service versions...
Service Information
service: aws-node-alexa-skill
stage: dev
region: us-east-1
api keys:
None
endpoints:
None
functions:
aws-node-alexa-skill-dev-alexa-skill: arn:aws:lambda:us-east-1:012294443141:function:aws-node-alexa-skill-dev-alexa-skill
Copy the AWS Lambda ARN value in the last line of the output. It starts with "arn:" and continues to the end of the line.
This value will be used when you manually create the Alexa Skill in the next step.
Production
Repeat by doing an inital production deploy to AWS Lambda to get the AWS Lambda ARN value.
$ npm run deploy:prod:sls
Navigate to the Alexa Skills Kit website
Follow the example shown here
At the top of the screen when creating a skill, there is a Skill ID. Copy that value to the corresponding skill configuration file:
config/dev.skill.config.json
{
"skillAppID": "REPLACE WITH dev appID",
config/prod.skill.config.json
{
"skillAppID": "REPLACE WITH prod appID",
Any files and folders in the deploy-s3
folder will be copied to an
S3 bucket. If you have audio files to use in SSML or images for Home Cards
this is the place for them.
The value of the s3.bucketName
key in the stage config file (src/config/dev.skill.config.json
or src/prod.config/skill.config.json
)
determines the name of the target bucket. The bucket name should be different for each stage and must be unique of all other buckets. That is the reason for prefixing the namespace with an organization.
For example, using these config files:
dev.skill.config.json
"s3": {
"bucketName": "organization-skillname-dev"
}
prod.skill.config.json
"s3": {
"bucketName": "organization-skillname"
}
The bucket that will be created for each of the stages will be:
Stage | Bucket Name |
---|---|
dev | organization-skillname-dev |
prod | organization-skillname |
The translations.json
file is copied to the deploy-s3
folder
before the folder is copied to the S3 bucket.
The deploy uses the contents of the src/s3-cors.json
file to set the CORS
configuration for the bucket.
To deploy both skill to AWS Lambda and content to S3:
$ npm run deploy:dev
To deploy content to S3 only: npm run deploy:dev:s3
To deploy skill to AWS Lambda only: npm run deploy:dev:sls
To deploy both skill to AWS Lambda and content to S3:
$ npm run deploy:prod
To deploy content to S3 only: npm run deploy:prod:s3
To deploy skill to AWS Lambda only: npm run deploy:prod:sls
Script | Stage | Description |
---|---|---|
configure | dev & prod | run once before deployment to replace placeholders in files |
iam | dev & prod | creates & configures IAM users for both dev and prod |
iam:dev | dev | creates & configures an IAM user for dev |
iam:prod | prod | creates & configures an IAM user for prod |
copy:trans | dev & prod | copies translations.json to the deploy-s3 folder before S3 is deployed |
copy:dev:config | dev | copies dev.skill.config.json to skill.config.json before Lambda is deployed |
copy:prod:config | prod | copies prod.skill.config.json to skill.config.json before Lambda is deployed |
deploy:dev | dev | runs all the deployment scripts including serverless deploy |
deploy:dev:sls | dev | runs serverless deploy which includes copying the correct stage config file, zipping up the skill and deploying to AWS Lambda |
postdeploy:dev:sls | dev | runs iam:trust:dev and configure:rolearn:dev so that code can be debugged and tested locally |
predeploy:dev:s3 | dev | creates the S3 bucket and sets its CORS configuration |
deploy:dev:s3 | dev | runs all scripts needed to create the S3 bucket, set CORS configuration, and copy files and folders from the deploy-s3 folder to the bucket in S3 |
deploy:prod | prod | runs all the deployment scripts including serverless deploy |
deploy:prod:sls | prod | runs serverless deploy which includes copying the correct stage config file, zipping up the skill and deploying to AWS Lambda |
predeploy:prod:s3 | prod | creates the S3 bucket and sets its CORS configuration |
deploy:prod:s3 | prod | runs all scripts needed to create the S3 bucket, set CORS configuration, and copy files and folders from the deploy-s3 folder to the bucket in S3 |
iam:trust:dev | dev | establishes a trust relationship between the dev user and the dev Lambda role for local debugging and testing |
configure:rolearn:dev | dev | sets the roleArn property in dev.skill.config.json |
open:amz | n/a | Opens in the web browser both the Amazon developer and AWS websites |
test | dev | runs unit and e2e tests using Mocha |
test:unit | dev | runs unit tests using Mocha |
test:e2e | dev | runs e2e tests using Mocha |
The test/requests
folder contains .json
files for different requests for your skills. You can use the Skill Developer Console to test your skill and then capture and save those requests here.
The naming convention that I use is the handler function name is the name of the file. Although you could have multiple files per handler to test different scenarios.
These requests can be used for both debugging and end-to-end testing.
If using Visual Studio Code, you are all setup for debugging.
The .vscode\launch.json
file points to the /test/debug/main.js
file. To change the request file that will be passed to the skill locally (event
variable)
and therefore to the handler method that will be called, change the /test/debug/main.js
file (line 5).
Put request json files in the test/requests
folder.
From the DEBUG dropdown in Visual Studio Code, select Launch Program
The purpose of end-to-end testing is to test the skill at the Lambda request and response level with code going against live instances of S3, DynamoDB, and other services.
Mocha and Chai are used for this type of testing. Consult their documentation for details.
Execute the tests using npm run test:e2e
All .js
files in the test/e2e
folder will be executed.
Put request json files in the test/requests
folder.
To debug e2e tests, from the DEBUG dropdown in Visual Studio Code, select Run Mocha - e2e tests
The purpose of unit tests is to test code independently of other code.
Mocha and Chai are used for this type of testing. Consult their documentation for details.
Execute the tests using npm run test:unit
All .js
files in the test/unit
folder will be executed.
To debug unit tests, from the DEBUG dropdown in Visual Studio Code, select Run Mocha - unit tests