├── .env.example
├── .eslintignore
├── .eslintrc.yml
├── .github
├── dependabot.yml
└── workflows
│ └── node.js.yml
├── .gitignore
├── LICENSE
├── README.md
├── app.js
├── name_generator.js
├── package-lock.json
├── package.json
├── public
├── chat
│ ├── index.css
│ ├── index.html
│ └── index.js
├── config-check.js
├── index.css
├── index.html
├── notify
│ ├── facebook_messenger.html
│ ├── index.html
│ ├── notify.css
│ └── notify.js
└── sync
│ ├── index.css
│ ├── index.html
│ └── index.js
├── src
├── config.js
├── notification_handler.js
├── router.js
├── sync_service_details.js
└── token_generator.js
└── test
├── config.test.js
└── token_generator.test.js
/.env.example:
--------------------------------------------------------------------------------
1 | # Required for all uses
2 | TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3 | TWILIO_API_KEY=SKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
4 | TWILIO_API_SECRET=YYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5 |
6 | # Required for Chat
7 | TWILIO_CHAT_SERVICE_SID=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8 |
9 | # Required for Notify
10 | TWILIO_NOTIFICATION_SERVICE_SID=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 |
12 | # Optional for Sync. By default, the app uses the 'default' instance on your account.
13 | TWILIO_SYNC_SERVICE_SID=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 |
15 | NODE_ENV=production
16 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | public/**/*.js
2 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | extends: google
2 | parserOptions:
3 | ecmaVersion: 6
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 | ignore:
9 | - dependency-name: y18n
10 | versions:
11 | - 4.0.2
12 | - dependency-name: twilio
13 | versions:
14 | - 3.51.0
15 | - dependency-name: lodash
16 | versions:
17 | - 4.17.20
18 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Node.js CI
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | paths-ignore:
10 | - '**.md'
11 | pull_request:
12 | branches: [ master ]
13 | paths-ignore:
14 | - '**.md'
15 |
16 | jobs:
17 | build:
18 | runs-on: ${{ matrix.os }}
19 | strategy:
20 | matrix:
21 | os: [ubuntu-latest, macos-latest]
22 | node-version: [14]
23 |
24 | steps:
25 | - uses: actions/checkout@v2
26 | - name: Use Node.js ${{ matrix.node-version }}
27 | uses: actions/setup-node@v2
28 | with:
29 | node-version: ${{ matrix.node-version }}
30 | cache: 'npm'
31 |
32 | - name: Create env file
33 | run: cp .env.example .env
34 |
35 | - name: Install Dependencies
36 | run: npm install
37 | - run: npm run build --if-present
38 | - run: npm test
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | .DS_Store
3 | .idea
4 | node_modules
5 | npm-debug.log*
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Twilio Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Twilio SDK Starter Application for Node.js
6 | [](https://github.com/TwilioDevEd/sdk-starter-node/actions/workflows/node.js.yml)
7 |
8 | This sample project demonstrates how to use Twilio APIs in a Node.js web
9 | application. Once the app is up and running, check out [the home page](http://localhost:3000)
10 | to see which demos you can run. You'll find examples for [Chat](https://www.twilio.com/chat),
11 | [Sync](https://www.twilio.com/sync), and [Notify](https://www.twilio.com/notify).
12 |
13 | Let's get started!
14 |
15 | ## Configure the sample application
16 |
17 | To run the application, you'll need to gather your Twilio account credentials and configure them
18 | in a file named `.env`. To create this file from an example template, do the following in your
19 | Terminal.
20 |
21 | ```bash
22 | cp .env.example .env
23 | ```
24 |
25 | Open `.env` in your favorite text editor and configure the following values.
26 |
27 | ### Configure account information
28 |
29 | Every sample in the demo requires some basic credentials from your Twilio account. Configure these first.
30 |
31 | | Config Value | Description |
32 | | :------------- |:------------- |
33 | `TWILIO_ACCOUNT_SID` | Your primary Twilio account identifier - find this [in the console here](https://www.twilio.com/console).
34 | `TWILIO_API_KEY` | Used to authenticate - [generate one here](https://www.twilio.com/console/dev-tools/api-keys).
35 | `TWILIO_API_SECRET` | Used to authenticate - [just like the above, you'll get one here](https://www.twilio.com/console/dev-tools/api-keys).
36 |
37 | #### A Note on API Keys
38 |
39 | When you generate an API key pair at the URLs above, your API Secret will only be shown once -
40 | make sure to save this information in a secure location, or possibly your `~/.bash_profile`.
41 |
42 | ### Configure product-specific settings
43 |
44 | Depending on which demos you'd like to run, you may need to configure a few more values in your `.env` file.
45 |
46 | ### Configuring Twilio Sync
47 |
48 | Twilio Sync works out of the box, using default settings per account. Once you have your API keys configured, execute `npm install; npm run start` and [open a browser](http://localhost:3000/sync)!
49 |
50 | ### Configuring Twilio Chat
51 |
52 | In addition to the above, you'll need to [generate a Chat Service](https://www.twilio.com/console/chat/services) in the Twilio Console. Put the result in your `.env` file.
53 |
54 | | Config Value | Where to get one. |
55 | | :------------- |:------------- |
56 | `TWILIO_CHAT_SERVICE_SID` | Chat | [Generate one in the Twilio Chat console](https://www.twilio.com/console/chat/services)
57 |
58 | ### Configuring Twilio Notify
59 |
60 | You will need to create a Notify Service and add at least one credential on the [Mobile Push Credential screen](https://www.twilio.com/console/notify/credentials) (such as Apple Push Notification Service or Firebase Cloud Messaging for Android) to send notifications using Notify.
61 |
62 | | Config Value | Where to get one. |
63 | | :------------- |:------------- |
64 | `TWILIO_NOTIFICATION_SERVICE_SID` | Generate one in the [Notify Console](https://www.twilio.com/console/notify/services) and put this in your `.env` file.
65 | A Push Credential | Generate one with Apple or Google and [configure it as a Notify credential](https://www.twilio.com/console/notify/credentials).
66 |
67 | Once you've done that, run the application and [open a browser](localhost:3000/notify)!
68 |
69 | ## Run the sample application
70 |
71 | Now that the application is configured, we need to install our dependencies from npm.
72 |
73 | ```bash
74 | npm install
75 | ```
76 |
77 | Now we should be all set! Run the application using the `node` command.
78 |
79 | ```bash
80 | npm start
81 | ```
82 |
83 | Your application should now be running at [http://localhost:3000/](http://localhost:3000/).
84 |
85 | 
86 |
87 | Check your config values, and follow the links to the demo applications!
88 |
89 | ## Running the SDK Starter Kit with ngrok
90 |
91 | If you are going to connect to this SDK Starter Kit with a mobile app (and you should try it out!), your phone won't be able to access localhost directly. You'll need to create a publicly accessible URL using a tool like [ngrok](https://ngrok.com/) to send HTTP/HTTPS traffic to a server running on your localhost. Use HTTPS to make web connections that retrieve a Twilio access token.
92 |
93 | ```bash
94 | ngrok http 3000
95 | ```
96 |
97 | ## Meta
98 |
99 | * No warranty expressed or implied. Software is as is. Diggity.
100 | * [MIT License](http://www.opensource.org/licenses/mit-license.html)
101 | * Lovingly crafted by Twilio Developer Education.
102 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 |
3 | // Node/Express
4 | const express = require('express');
5 | const http = require('http');
6 | const path = require('path');
7 | const bodyParser = require('body-parser');
8 |
9 | const router = require('./src/router');
10 | const syncServiceDetails = require('./src/sync_service_details');
11 |
12 | // Create Express webapp
13 | const app = express();
14 | app.use(express.static(path.join(__dirname, 'public')));
15 |
16 | // Add body parser for Notify device registration
17 | app.use(bodyParser.urlencoded({extended: true}));
18 | app.use(bodyParser.json());
19 |
20 | app.use(router);
21 |
22 | // production error handler
23 | // no stacktraces leaked to user
24 | app.use(function(err, req, res, next) {
25 | console.trace(err);
26 | res.status(err.status || 500);
27 | res.send({
28 | message: err.message,
29 | error: {},
30 | });
31 | });
32 |
33 | // Get Sync Service Details for lazy creation of default service if needed
34 | syncServiceDetails();
35 |
36 | // Create http server and run it
37 | const server = http.createServer(app);
38 | const port = process.env.PORT || 3000;
39 | server.listen(port, function() {
40 | console.log('Express server running on *:' + port);
41 | });
42 |
43 | module.exports = app;
44 |
--------------------------------------------------------------------------------
/name_generator.js:
--------------------------------------------------------------------------------
1 | const ADJECTIVES = [
2 | 'Awesome', 'Bold', 'Creative', 'Dapper', 'Eccentric', 'Fiesty', 'Golden',
3 | 'Holy', 'Ignominious', 'Jolly', 'Kindly', 'Lucky', 'Mushy', 'Natural',
4 | 'Oaken', 'Precise', 'Quiet', 'Rowdy', 'Sunny', 'Tall',
5 | 'Unique', 'Vivid', 'Wonderful', 'Xtra', 'Yawning', 'Zesty',
6 | ];
7 |
8 | const FIRST_NAMES = [
9 | 'Anna', 'Bobby', 'Cameron', 'Danny', 'Emmett', 'Frida', 'Gracie', 'Hannah',
10 | 'Isaac', 'Jenova', 'Kendra', 'Lando', 'Mufasa', 'Nate', 'Owen', 'Penny',
11 | 'Quincy', 'Roddy', 'Samantha', 'Tammy', 'Ulysses', 'Victoria', 'Wendy',
12 | 'Xander', 'Yolanda', 'Zelda',
13 | ];
14 |
15 | const LAST_NAMES = [
16 | 'Anchorage', 'Berlin', 'Cucamonga', 'Davenport', 'Essex', 'Fresno',
17 | 'Gunsight', 'Hanover', 'Indianapolis', 'Jamestown', 'Kane', 'Liberty',
18 | 'Minneapolis', 'Nevis', 'Oakland', 'Portland', 'Quantico', 'Raleigh',
19 | 'SaintPaul', 'Tulsa', 'Utica', 'Vail', 'Warsaw', 'XiaoJin', 'Yale',
20 | 'Zimmerman',
21 | ];
22 |
23 | const rand = (arr) => arr[Math.floor(Math.random() * arr.length)];
24 |
25 | module.exports = () => rand(ADJECTIVES) + rand(FIRST_NAMES) + rand(LAST_NAMES);
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdk-starter-node",
3 | "version": "1.0.0",
4 | "description": "Starter Server Application for Node.js",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "node app.js",
8 | "test": "NODE_ENV=test && jest"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/TwilioDevEd/sdk-starter-node.git"
13 | },
14 | "author": "Twilio Developer Education",
15 | "license": "MIT",
16 | "bugs": {
17 | "url": "https://github.com/TwilioDevEd/sdk-starter-node/issues"
18 | },
19 | "homepage": "https://github.com/TwilioDevEd/sdk-starter-node#readme",
20 | "dependencies": {
21 | "body-parser": "^1.19.0",
22 | "camelcase": "^6.2.0",
23 | "dotenv": "^10.0.0",
24 | "express": "^4.17.1",
25 | "extend": "^3.0.2",
26 | "pug": "^3.0.2",
27 | "twilio": "^3.66.0"
28 | },
29 | "devDependencies": {
30 | "jest": "^27.0.6",
31 | "jest-extended": "^0.11.5",
32 | "jsonwebtoken": "^8.5.1"
33 | },
34 | "jest": {
35 | "setupFilesAfterEnv": [
36 | "jest-extended"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/public/chat/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing:border-box;
3 | }
4 |
5 | html, body {
6 | padding:0;
7 | margin:0;
8 | height:100%;
9 | width:100%;
10 | color:#dedede;
11 | background-color: #849091;
12 | font-family: 'Helvetica Neue', Helvetica, sans-serif;
13 | }
14 |
15 | header {
16 | width:100%;
17 | position:absolute;
18 | text-align:center;
19 | bottom:20px;
20 | }
21 |
22 | header a, header a:visited {
23 | font-size:18px;
24 | color:#dedede;
25 | text-decoration:none;
26 | }
27 |
28 | header a:hover {
29 | text-decoration:underline;
30 | }
31 |
32 | section {
33 | height:70%;
34 | background-color:#2B2B2A;
35 | }
36 |
37 | section input {
38 | display:block;
39 | height:52px;
40 | width:800px;
41 | margin:10px auto;
42 | outline:none;
43 | background-color:transparent;
44 | border:none;
45 | border-bottom:1px solid #2B2B2A;
46 | padding:0;
47 | font-size:42px;
48 | color:#eee;
49 | }
50 |
51 | #messages {
52 | background-color:#232323;
53 | padding:10px;
54 | height:100%;
55 | width:800px;
56 | margin:0 auto;
57 | overflow-y:auto;
58 | }
59 |
60 | #messages p {
61 | margin:5px 0;
62 | padding:0;
63 | }
64 |
65 | .info {
66 | margin:5px 0;
67 | font-style:italic;
68 | }
69 |
70 | .message-container {
71 | margin:5px 0;
72 | color:#fff;
73 | }
74 |
75 | .message-container .username {
76 | display:inline-block;
77 | margin-right:5px;
78 | font-weight:bold;
79 | color:#849091;
80 | }
81 |
82 | .me, .username.me {
83 | font-weight:bold;
84 | color:cyan;
85 | }
86 |
87 | .message-container .username.me {
88 | display:inline-block;
89 | margin-right:5px;
90 | }
--------------------------------------------------------------------------------
/public/chat/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |