SIGNAL, our customer and developer conference, was only a few days ago. In case you missed it, you can have a look at the keynotes from day one and day two and also many of the product sessions on YouTube.
Whilst there were many exciting product announcements (TwilioQuest 3 anyone?), there was one thing that got me up from my chair to yell “Hell yeah”!
Twilio Functions now can be deployed via API and this changes how many people will develop with Twilio.
Developing in a serverless environment can be challenging and raise many questions. How do you develop your serverless project locally? How do you deploy your functions to production? How do you structure your code in the first place?
Luckily, two product announcements answer all of these questions. In this article, I want to share how the new Serverless Toolkit and the new Twilio Runtime API will change the creation, development, and deployment flow of Twilio functions.
Before we get started…
To develop and deploy Twilio functions you need:
- A free Twilio account
- The installed Twilio CLI
You can use the Serverless Toolkit as a standalone tool in the form of the npm package twilio-run, however, you can also integrate it into the Twilio CLI via the Twilio Serverless plugin. The Twilio CLI covers hundreds of Twilio features and API endpoints, pair it with the Serverless plugin and you have a tool that provides all the functionality you need.
After installing the CLI, you have the twilio
command available in your environment. Ensure that you are authorized by running the following command in your terminal:
twilio login
If you need more info on how to get started with the Twilio CLI check out the Twilio video tip “Introducing the Twilio CLI!”.
After a fresh installation, the Twilio CLI is missing the serverless
commands. To add these commands, install the serverless plugin from within the Twilio CLI itself. Run the plugin:install
command:
twilio plugins:install @twilio-labs/plugin-serverless
After the plugin installation finishes, new commands like twilio serverless:deploy
and twilio serverless:start
become available right at your fingertips. 🎉
A quick note about plugin; the Twilio CLI is not only able to install plugins but it also provides the functionality to keep plugins up-to-date. The serverless plugin is still pretty new – make sure to run twilio plugins:update
now and then to receive updates.
Create a new Serverless project
To get started with a new Twilio Runtime project, it only takes one command.
twilio serverless:init your-project-name
twilio serverless:init
creates a new directory and mandatory files. It also installs all the required dependencies in one go.
twilio serverless:init serverless-tryout
✔ Creating project directory
✔ Creating project directories and files
✔ Downloading .gitignore file
✔ Installing dependencies
╭─────────────────────────────────────────────────────────────────────────────╮
│ │
│ Success! │
│ │
│ Created serverless-tryout at /your/dir │
│ │
│ Inside that directory, you can run the following command: │
│ │
│ npm start │
│ Serves all functions in the ./functions subdirectory and assets in the │
│ ./assets directory │
│ │
│ Get started by running: │
│ │
│ cd your-project-name │
│ npm start │
│ │
╰─────────────────────────────────────────────────────────────────────────────╯
Navigate into the new directory and have a look at the included files. It should look similar to the tree below.
.
├── assets
│ ├── index.html
│ ├── message.private.js
│ └── style.css
├── functions
│ ├── hello-world.js
│ ├── private-message.js
│ ├── sms
│ └ └── reply.protected.js
├── node_modules
│ ├──...
│ ├──...
│ └──...
├── .env
├── .gitignore
├── .nvmrc
├── package-lock.json
└── package.json
The new project includes config files and two main directories: assets
and functions
. The files included in these directories map to the Twilio functions and assets that will be available online after you deploy the local files. For example, the JavaScript file ./functions/hello-world.js
will be available at /hello-world
.
The filename rules them all – public vs. private vs. protected access
Some of the generated functions and assets include a protected
or private
keyword in their filename. The Serverless Toolkit evaluates access permissions using the filename and omits the keywords in the public URL after the deployment. The file /functions/sms/reply.protected.js
will result in a /sms/reply
endpoint.
The access levels for functions are:
-
public
(default) – publicly available -
protected
– only accessible by Twilio via, for examples, webhooks
And access levels for assets are:
-
public
- publicly available -
private
- only accessible inside of functions viaRuntime.getAssets()
You can have a look at all the configurations for functions and assets in the docs.
Let’s sum up the new project, it includes:
- three assets (one of them is
private
and won’t be accessible publicly) - three functions (one of them is
protected
and won’t be accessible publicly)
Now it’s time to see what all of them do and run the project locally!
A fresh Twilio Runtime right on your computer
Developing local serverless projects was always a pain. Luckily, there is now a command that emulates the Twilio Runtime on your machine and makes development much more convenient.
Run twilio serverless:start
inside of the project.
twilio serverless:start
┌────────────────────────────────────────────────────────────────────┐
│ │
│ Twilio functions available: │
│ ├── /hello-world | http://localhost:3000/hello-world │
│ ├── /private-message | http://localhost:3000/private-message │
│ └── [protected] /sms/reply | http://localhost:3000/sms/reply │
│ │
│ Twilio assets available: │
│ ├── /index.html | http://localhost:3000/index.html │
│ ├── /style.css | http://localhost:3000/style.css │
│ └── [private] /message.js | Runtime.getAssets()['/message.js'] │
│ │
└────────────────────────────────────────────────────────────────────┘
The twilio serverless:start
command spins up a local server, creates the endpoints that would be deployed on the Runtime, and also emulates the environment by providing things like the Runtime
client. Your localhost
will behave like Twilio’s infrastructure! 🎉
When you visit the local endpoints, you’ll find out that all the functions respond with some TwiML covering everyday use cases like responding text to an incoming SMS. You can now take these functions and tweak them to your needs.
For further instructions and explanations, navigate to the included asset [http://localhost:3000/index.html](http://localhost:3000/index.html)
. The example HTML page gives you more insights into the functions, assets, and the foundation for the serverless plugin – the underlying tool; twilio-run.
One last thing to mention about local development – twilio serverless:start
offers many flags that will help you with environment variables, debugging and live-reloading. It even comes with the local tunnel tool ngrok built-in. Make sure to have a look at all the options with the command twilio serverless:start --help
or read this article.
With only two commands, you were able to set up a new local serverless project that can be adjusted to specific requirements. But how do you extend the project, create new functions, and get some inspiration on how to control Twilio’s services in a serverless world?
Create new functions for other use cases
One way to add more functionality is to create additional files inside of the functions
or assets
directory. This process is somewhat manual, though. What if I told you that there was a quicker way to set up functions?
The command twilio serverless:new
helps to reduce the number of repetitive tasks and provides a way to create new functions using pre-defined templates.
twilio serverless:new
? Select a template
Hello Voice - Function to get you started with Twilio Prog. Voice
Hello Messaging - Function to get you started with Twilio Prog. Messaging
Never gonna give you up - Never gonna let you down. Plays a song to a phone call
❯ Forward Call - Forwards an incoming call to another number
Forward Message - Forwards incoming messages to another number
Forward Message to Multiple Numbers - Forwards incoming messages to a set of numbers
Forward Message to Email via SendGrid - Uses SendGrid to forward incoming messages via email
(Move up and down to reveal more choices)
After picking a template and a namespace directory, the setup process will create new files and give hints on other setup actions. For example, the template below requires the definition of a certain environment variable.
twilio serverless:new
? Select a template Forward Call - Forwards an incoming call to another number
? What should be the namespace your function(s) are placed under? private
✔ Configuring Environment Variables in .env
✔ Installing Dependencies
✔ Creating function: forward-call.js
INFO Make sure to configure MY_PHONE_NUMBER in the .env file
SUCCESS Downloaded new template into the "new-service" subdirectories
What function use cases would you like to see? All function templates are available and editable on GitHub – we’d love to hear your ideas!
After creating a new function, restart the local server by running twilio serverless:start
again. The new endpoint will be available locally. For the above function, this endpoint is /private/forward-call
.
Local development is only half of the story – how do you deploy functions to the cloud, ready to scale?
Showtime – deploy, deploy, deploy!
When you’re happy with your local functions and assets run twilio serverless:deploy
to deploy them.
twilio serverless:deploy
Deploying functions & assets to the Twilio Runtime
Account SK6b3e6df6812298f87594567895e55ede
Token kegH****************************
Service Name serverless-tryout
Environment dev
Root Directory /private/tmp/serverless-tryout
Dependencies
Env Variables MY_PHONE_NUMBER
✔ Serverless project successfully deployed
Deployment Details
Domain: serverless-tryout-6774-dev.twil.io
Service:
serverless-tryout (ZSc...)
Environment:
dev (ZEa...)
Build SID:
ZB8...
Functions:
[protected] https://foo-6774-dev.twil.io/sms/reply
https://serverless-tryout-6774-dev.twil.io/hello-world
https://serverless-tryout-6774-dev.twil.io/forward-call/forward-call
https://serverless-tryout-6774-dev.twil.io/private-message
Assets:
[private] Runtime.getAssets()['/message.js']
https://serverless-tryout-6774-dev.twil.io/index.html
https://serverless-tryout-6774-dev.twil.io/style.css
This one command deploys the code to the cloud and creates publicly available assets and function endpoints.
If you want to inspect the deployed runtime, there are two ways to do this. The first one is using the twilio serverless:list
command:
twilio serverless:list functions --service-sid=ZSc7...
Account SK6b...
Token kegH****************************
Service ZSc7...
Environment dev
Functions for environment ZEa5...
│ /sms/reply [Visibility protected]
│ /hello-world
│ /private-message
│ /forward-call/forward-call
This command accepts several configuration options so that you can inspect the exact area of your interest. If you want to see what flags are available, remember the --help
flag will be your friend.
The other way is to head to the functions API area in your Twilio console and have a look there.
A more in-depth look at the created endpoints and their new domain explicitly shows how the new Function and Assets API is structured and how it differs from the UI-only Twilio functions. Let’s have a brief look.
New power and flexibility with environments
The domain of the freshly deployed service unveils one significant improvement that comes with the new API that was not available before.
Random number
\ /
https://serverless-tryout-6774-dev.twil.io/sms/reply
\ / \ /
Service name Environment
Domain suffix
The Serverless API supports environments. When you deployed your project a few minutes ago, the CLI used a default value as the environment – dev
. Every environment is represented by its own domain. To deploy another environment, use the --environment
flag with the serverless:deploy
command.
The environment feature may not look like a big deal now, but in the future, it will be. When you run large projects with many developers working on the same serverless codebase, environments are crucial.
Thanks to environments, you can test and deploy changes in isolation to their own domain without affecting your production setup. Then, only when you’re ready to switch, you can promote one environment to another (e.g. dev
to prod
) using the command twilio serverless:activate
. Environments are a big step towards automation and the implementation of proper CI/CD workflows – both, mandatory processes when you’re running on a bigger scale.
If you want to have a look at how all the pieces of the new API come together, have a look at the reference documentation or Dominik Kundels presentation around the topic.
The automation of your Twilio setup
The new Twilio Runtime API paired with the Serverless toolkit is the missing piece to automate tasks in your existing infrastructure and even create new installations from scratch.
What if I would tell you that you can now buy numbers, create sync services, connect your communication channels via functions by running a single command? In short, do all things Twilio-related by just running a shell script. Well… I did precisely this just a few days ago, and it made me get out of my chair saying, “Hell yeah!”. Watch the space, I’ll keep you posted about how to script Twilio setups in the following tutorials. 👋
Let me know if you're as excited as me about this new API. You can reach me under the following channels.
- Email: sjudis@twilio.com
- Github: stefanjudis
- Twitter: @stefanjudis