Skip to content
An abstraction layer on top of the Twilio API to make automating customer service interactions much easier! Designed for use with Node.js and Express
Branch: master
Clone or download
Latest commit e112a81 Jul 14, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples first example in readme Nov 20, 2018
src fix typo in TwilioController Jul 6, 2019
tests fix typo in TwilioController Jul 6, 2019
.gitignore rm DS_Store Nov 22, 2018
.npmignore edit npmignore Dec 1, 2018
CONTRIBUTING.md Update CONTRIBUTING.md Feb 22, 2019
LICENSE.md add license Nov 30, 2018
README.md Update README.md Jul 8, 2019
jest.config.js move tests to own dir Dec 1, 2018
package-lock.json manually update lodash Jul 14, 2019
package.json tick version Jul 14, 2019
tsconfig.json fixing build Nov 9, 2018
webpack.config.js add source map to config Dec 1, 2018

README.md

Twilly 📱💬

Writing the back end of an SMS web application with Twilio should be easy, and Twilly was created to greatly simplify the process of writing such applications.

Twilly is a Node.js library that can be used with TypeScript or JavaScript and integrates with Express.js. It works in conjunction with the Twilio API to allow you to defined complex SMS interactions for your users with ease.

The design of the library's exposed interface was built with one goal in mind, make interactions as easy to design as they are with tools like FlowXO or Twilio Studio but allow the interactions to be defined with code (in this case, JavaScript) instead of a GUI.


Contents

  1. Installation and Setup
  2. Quick Start
  3. Documentation
  4. License
  5. Contributing
  6. Bugs or Feature Suggestions
  7. Feature Pipeline

Installation and Setup

Twilly is published on npm. To add Twilly to your Node.js Express application, run

npm i -s twilly

You will download a precompiled version of Twilly so there is no need to add TypeScript or Twilly's settings to your build config.

You will need to have an account with Twilio in order to use Twilly, if there is demand to allow other APIs to be compatible then I am open to adding more. For now, you will need to create a messaging service with Twilio using their dashboard. You will also need to set your inbound message url to the path of your application you use the twilly function.

I recommend you download the package ngrok (or another library like it) while developing with Twilly.


Quick Start

The most simple interaction a user can have with an SMS application is where whenever the user sends a message, the application replies with "Hello world!". Twilly allows us to code this application in just a few lines.

First you need to install the required dependencies,

const bp = require('body-parser');
const express = require('express');

and let's set up our Express application,

const app = express();

app.use(bp.urlencoded({ extended: false, limit: '2mb' }));
app.use(bp.json({ limit: '5mb' }));

// Twilio requires your site have a GET to your index return an HTML response
app.get('/', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end('<html><body>Hello world!</body></html>');
});

Now let's start defining your SMS app. Twilly separates the different type of interactions into linear sequences of actions called Flows. A Flow is a linear collection of actions your app can take after receiving a message.

The application we want to build just has one Flow, the user sends a message and the application replies with "Hello world!". So let's import the Flow and Reply objects from Twilly.

const { Flow, Reply } = require('twilly');

The Flow any user who hasn't already started any application enters is called the "root" Flow. Every other Flow is a "child" of this Flow, and later on, we will see how to initiate Flows within each other using the Trigger object.

Now let's set up the root Flow for this interaction,

const root = new Flow();

root.addAction('reply', () => new Reply('Hello world!'));

The add action method on the Flow object appends a new action to the end of the Flow. The first argument is the name of the action, and can be used later to retrieve metadata about the action in later actions.

The last thing we need to do is add the twilly function to the Express app. This is done below:

const { twilly } = require('twilly');

app.use('/twilly', twilly({
  accountSid: TWILIO_ACCOUNT_SID,
  authToken: TWILIO_AUTH_TOKEN,
  messagingServiceSid: TWILIO_MESSAGE_SERVICE_ID,
  root,
}));

You can see the entire twilly app in working form in examples/quickstart.js.


Documentation

You can view the documentation of Twilly's exposed objects and API here.


License

Twilly is available free of charge under the MIT license. See LICENSE.md for details.


Contributing

See CONTRIBUTING.md for information on contribution guidlines and community standards.


Bugs or Feature Suggestions

To report any bugs or suggest any features or improvements, please open an issue here.


Feature Pipeline

Below is a list of the features I plan on adding to twilly in the future. I am always open to suggested features and contributions from other developers who want to make twilly better!

Trigger Flows outside of the twilly() function

As pointed out in Issue #3 it would be nice to be able to trigger flows from other places in your Node application outside of the twilly function. This seems like a common use case and seems feasible though I have not actually tried implementing. PRs are welcome if anyone is interested as well.

Filtering Actions

Right now there is no way to "filter" (or skip) Actions in a Flow. Either an Action is performed or the entire interaction ends. The next release I plan on doing is adding an ability to filter actions so that interactions can continue even if a particular action is not performed.

I am open to suggestions about implementation, but right now I am planning on adding a 3rd optional argument to Flow.addAction which is a function of the Flow and user contexts and returns a Boolean which indicates if the Action should execute. For Flow.addActions this would be an optional filter key in each of the plain objects. Each Action's contexts would have a filtered key which would be false if an Action is performed or true if no Action was performed and the Flow skipped to the next Action.

You can’t perform that action at this time.