├── public
├── images
│ ├── heart.gif
│ ├── favicon.png
│ ├── TwilioQuest32.png
│ └── javascript_shield256.png
├── javascripts
│ ├── form.js
│ └── ui.js
└── stylesheets
│ └── style.css
├── views
├── error.ejs
└── index.ejs
├── package.json
├── LICENSE
├── bin
└── www
├── app.js
├── README.md
└── .gitignore
/public/images/heart.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-node/HEAD/public/images/heart.gif
--------------------------------------------------------------------------------
/public/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-node/HEAD/public/images/favicon.png
--------------------------------------------------------------------------------
/views/error.ejs:
--------------------------------------------------------------------------------
1 |
23 |
24 |
27 |
28 |
29 |

30 |
JavaScript Guild
31 |
32 | Welcome to the JavaScript Guild! Join your fellow JavaScripters
33 | and JavaScriptresses as they asynchronously dominate this
34 | Twilio quest.
35 |
36 |
37 | Gather your party and
38 | venture forth
39 |
40 |
41 |
42 |
Hello World
43 |
44 | Below, we have two simple demos that will confirm your environment
45 | has been properly configured. Please refer to the
46 | README.md in your
47 | starter app repository to see how to configure this application.
48 |
49 |
50 |
51 | - Messaging
52 | - Voice Call
53 |
54 |
60 |
61 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var createError = require('http-errors');
2 | var express = require('express');
3 | var path = require('path');
4 | var cookieParser = require('cookie-parser');
5 | var logger = require('morgan');
6 | var twilio = require('twilio');
7 |
8 | // Load configuration information from system environment variables.
9 | var TWILIO_ACCOUNT_SID = process.env.TWILIO_ACCOUNT_SID,
10 | TWILIO_AUTH_TOKEN = process.env.TWILIO_AUTH_TOKEN,
11 | TWILIO_PHONE_NUMBER = process.env.TWILIO_PHONE_NUMBER;
12 |
13 | // Create an authenticated client to access the Twilio REST API
14 | var client = twilio(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
15 |
16 | var app = express();
17 |
18 | // view engine setup
19 | app.set('views', path.join(__dirname, 'views'));
20 | app.set('view engine', 'ejs');
21 |
22 | app.use(logger('dev'));
23 | app.use(express.json());
24 | app.use(express.urlencoded({ extended: false }));
25 | app.use(cookieParser());
26 | app.use(express.static(path.join(__dirname, 'public')));
27 |
28 | // render our home page
29 | app.get('/', function(req, res, next) {
30 | res.render('index');
31 | });
32 |
33 | // handle a POST request to send a text message.
34 | // This is sent via ajax on our home page
35 | app.post('/message', function(req, res, next) {
36 | // Use the REST client to send a text message
37 | client.messages.create({
38 | to: req.body.to,
39 | from: TWILIO_PHONE_NUMBER,
40 | body: 'Good luck on your Twilio quest!'
41 | }).then(function(message) {
42 | // When we get a response from Twilio, respond to the HTTP POST request
43 | res.send('Message is inbound!');
44 | });
45 | });
46 |
47 | // handle a POST request to make an outbound call.
48 | // This is sent via ajax on our home page
49 | app.post('/call', function(req, res, next) {
50 | // Use the REST client to send a text message
51 | client.calls.create({
52 | to: req.body.to,
53 | from: TWILIO_PHONE_NUMBER,
54 | url: 'http://demo.twilio.com/docs/voice.xml'
55 | }).then(function(message) {
56 | // When we get a response from Twilio, respond to the HTTP POST request
57 | res.send('Call incoming!');
58 | });
59 | });
60 |
61 | // Create a TwiML document to provide instructions for an outbound call
62 | app.post('/hello', function(req, res, next) {
63 | // Create a TwiML generator
64 | var twiml = new twilio.twiml.VoiceResponse();
65 | // var twiml = new twilio.TwimlResponse();
66 | twiml.say('Hello there! You have successfully configured a web hook.');
67 | twiml.say('Good luck on your Twilio quest!', {
68 | voice:'woman'
69 | });
70 |
71 | // Return an XML response to this request
72 | res.set('Content-Type','text/xml');
73 | res.send(twiml.toString());
74 | });
75 |
76 | // catch 404 and forward to error handler
77 | app.use(function(req, res, next) {
78 | next(createError(404));
79 | });
80 |
81 | // error handler
82 | app.use(function(err, req, res, next) {
83 | // set locals, only providing error in development
84 | res.locals.message = err.message;
85 | res.locals.error = req.app.get('env') === 'development' ? err : {};
86 |
87 | // render the error page
88 | res.status(err.status || 500);
89 | res.render('error');
90 | });
91 |
92 | module.exports = app;
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the JavaScript Guild!
2 |
3 | As members of the JavaScript guild, you will be working through the challenges of TwilioQuest using server-side JavaScript, specifically [node.js](http://www.nodejs.org). This project is pre-configured to do some interesting Twilio stuff using node.js and the [Express](http://expressjs.com/) web framework.
4 |
5 | ## Setting Up
6 |
7 | We assume that before you begin, you will have [node.js and npm](http://www.nodejs.org) and installed on your system. Before you can run this project, you will need to set three system environment variables. These are:
8 |
9 | * `TWILIO_ACCOUNT_SID` : Your Twilio "account SID" - it's like your username for the Twilio API. This and the auth token (below) can be found [on the console](https://www.twilio.com/console).
10 | * `TWILIO_AUTH_TOKEN` : Your Twilio "auth token" - it's your password for the Twilio API. This and the account SID (above) can be found [on the console](https://www.twilio.com/console).
11 | * `TWILIO_PHONE_NUMBER` : A Twilio number that you own, that can be used for making calls and sending messages. You can find a list of phone numbers you control (and buy another one, if necessary) [in the console](https://www.twilio.com/console/phone-numbers/incoming).
12 |
13 | For Mac and Linux, environment variables can be set by opening a terminal window and typing the following three commands - replace all the characters after the `=` with values from your Twilio account:
14 |
15 | export TWILIO_ACCOUNT_SID=ACXXXXXXXXX
16 | export TWILIO_AUTH_TOKEN=XXXXXXXXX
17 | export TWILIO_PHONE_NUMBER=+16518675309
18 |
19 | To make these changes persist for every new terminal (on OS X), you can edit the file `~/.bash_profile` to contain the three commands above. This will set these environment variables for every subsequent session. Once you have edited the file to contain these commands, run `source ~/.bash_profile` in the terminal to set up these variables.
20 |
21 | On Windows, the easiest way to set permanent environment variables (as of Windows 8) is using the `setx` command. Note that there is no `=`, just the key and value separated by a space:
22 |
23 | setx TWILIO_ACCOUNT_SID 'ACXXXXXXXXX'
24 | setx TWILIO_AUTH_TOKEN 'XXXXXXXXX'
25 | setx TWILIO_PHONE_NUMBER '+16518675309'
26 |
27 | ## Running the application
28 |
29 | [Download the project source code directly](https://github.com/twilio/starter-node/archive/master.zip) or [clone the repository on GitHub](https://github.com/twilio/starter-node). Navigate to the folder with the source code on your machine in a terminal window.
30 |
31 | You will first need to install the application's dependencies. You can do this using npm, the bundled package manager for node.js:
32 |
33 | npm install
34 |
35 | Now, you should be able to launch the application. From your terminal, run `npm start`. This should launch your Express application on port 3000 - [visit that URL on your local host at http://localhost:3000](http://localhost:3000/). Enter your mobile number in the fields provided, and test both SMS text messages and phone calls being sent to the mobile number you provide.
36 |
37 |
38 |
39 | If your phone receives both a call and text message, you're good to go!
40 |
41 | ## Begin Questing!
42 | This is but your first step into a larger world. [Return to TwilioQuest](http://quest.twilio.com) to continue your adventure. Huzzah!
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
2 |
3 | # Created by https://www.gitignore.io/api/macos,node,windows,visualstudiocode
4 | # Edit at https://www.gitignore.io/?templates=macos,node,windows,visualstudiocode
5 |
6 | ### macOS ###
7 | # General
8 | .DS_Store
9 | .AppleDouble
10 | .LSOverride
11 |
12 | # Icon must end with two \r
13 | Icon
14 |
15 | # Thumbnails
16 | ._*
17 |
18 | # Files that might appear in the root of a volume
19 | .DocumentRevisions-V100
20 | .fseventsd
21 | .Spotlight-V100
22 | .TemporaryItems
23 | .Trashes
24 | .VolumeIcon.icns
25 | .com.apple.timemachine.donotpresent
26 |
27 | # Directories potentially created on remote AFP share
28 | .AppleDB
29 | .AppleDesktop
30 | Network Trash Folder
31 | Temporary Items
32 | .apdisk
33 |
34 | ### Node ###
35 | # Logs
36 | logs
37 | *.log
38 | npm-debug.log*
39 | yarn-debug.log*
40 | yarn-error.log*
41 | lerna-debug.log*
42 |
43 | # Diagnostic reports (https://nodejs.org/api/report.html)
44 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
45 |
46 | # Runtime data
47 | pids
48 | *.pid
49 | *.seed
50 | *.pid.lock
51 |
52 | # Directory for instrumented libs generated by jscoverage/JSCover
53 | lib-cov
54 |
55 | # Coverage directory used by tools like istanbul
56 | coverage
57 | *.lcov
58 |
59 | # nyc test coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # Bower dependency directory (https://bower.io/)
66 | bower_components
67 |
68 | # node-waf configuration
69 | .lock-wscript
70 |
71 | # Compiled binary addons (https://nodejs.org/api/addons.html)
72 | build/Release
73 |
74 | # Dependency directories
75 | node_modules/
76 | jspm_packages/
77 |
78 | # TypeScript v1 declaration files
79 | typings/
80 |
81 | # TypeScript cache
82 | *.tsbuildinfo
83 |
84 | # Optional npm cache directory
85 | .npm
86 |
87 | # Optional eslint cache
88 | .eslintcache
89 |
90 | # Optional REPL history
91 | .node_repl_history
92 |
93 | # Output of 'npm pack'
94 | *.tgz
95 |
96 | # Yarn Integrity file
97 | .yarn-integrity
98 |
99 | # dotenv environment variables file
100 | .env
101 | .env.test
102 |
103 | # parcel-bundler cache (https://parceljs.org/)
104 | .cache
105 |
106 | # next.js build output
107 | .next
108 |
109 | # nuxt.js build output
110 | .nuxt
111 |
112 | # react / gatsby
113 | public/
114 |
115 | # vuepress build output
116 | .vuepress/dist
117 |
118 | # Serverless directories
119 | .serverless/
120 |
121 | # FuseBox cache
122 | .fusebox/
123 |
124 | # DynamoDB Local files
125 | .dynamodb/
126 |
127 | ### VisualStudioCode ###
128 | .vscode/*
129 | # The settins file is personal and it's a team choice
130 | # to force people to check it in and use it
131 | # !.vscode/settings.json
132 | !.vscode/tasks.json
133 | !.vscode/launch.json
134 | !.vscode/extensions.json
135 |
136 | ### VisualStudioCode Patch ###
137 | # Ignore all local history of files
138 | .history
139 |
140 | ### Windows ###
141 | # Windows thumbnail cache files
142 | Thumbs.db
143 | Thumbs.db:encryptable
144 | ehthumbs.db
145 | ehthumbs_vista.db
146 |
147 | # Dump file
148 | *.stackdump
149 |
150 | # Folder config file
151 | [Dd]esktop.ini
152 |
153 | # Recycle Bin used on file shares
154 | $RECYCLE.BIN/
155 |
156 | # Windows Installer files
157 | *.cab
158 | *.msi
159 | *.msix
160 | *.msm
161 | *.msp
162 |
163 | # Windows shortcuts
164 | *.lnk
165 |
166 | # End of https://www.gitignore.io/api/macos,node,windows,visualstudiocode
167 |
168 | # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
169 | # Anything env does not get committed
170 | *.env
171 |
172 |
--------------------------------------------------------------------------------
/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | /* Eric Meyer reset */
2 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}
3 |
4 | /* Global Styles */
5 | html, body {
6 | background-color:black;
7 | }
8 |
9 | html, body, * {
10 | font-family:"Press Start 2P";
11 | font-size:18px;
12 | color:white;
13 | }
14 |
15 | form {
16 | text-align:center;
17 | }
18 |
19 | h1 {
20 | font-size: 28px;
21 | margin:10px 0;
22 | line-height: 1.3em;
23 | }
24 |
25 | h3 {
26 | font-size:18px;
27 | margin:10px 0;
28 | color:red;
29 | }
30 |
31 | pre {
32 | font-family: Monaco, monospace, sans-serif;
33 | font-size:12px;
34 | padding:10px;
35 | background-color:#232323;
36 | border:1px #fff solid;
37 | margin-bottom: 10px;
38 | }
39 |
40 | p {
41 | line-height: 1.5em;
42 | font-size:14px;
43 | margin-bottom: 10px;
44 | }
45 |
46 | a {
47 | color:orange;
48 | }
49 |
50 | b {
51 | color:yellow;
52 | font-weight:bold;
53 | }
54 |
55 | input[type=text], input[type=password], input[type=email] {
56 | background-color:black;
57 | border:5px #787878 dashed;
58 | padding:10px;
59 | }
60 |
61 | input[type=text]:focus, input[type=password]:focus, input[type=email]:focus {
62 | outline:none;
63 | }
64 |
65 | button, input[type=button], input[type=submit] {
66 | margin-top: 10px;
67 | text-align: center;
68 | border:8px solid;
69 | background-color: #000;
70 | padding:10px;
71 | color:#fff;
72 | }
73 |
74 | button:hover, input[type=button]:hover, input[type=submit]:hover {
75 | border-style:dashed;
76 | cursor:pointer;
77 | }
78 |
79 | .padding10 {
80 | padding:10px;
81 | }
82 |
83 | #content {
84 | width:900px;
85 | margin:20px auto 10px auto;
86 | }
87 |
88 | #flash {
89 | color:yellow;
90 | text-align:center;
91 | border:2px dashed;
92 | margin-bottom:20px;
93 | padding:10px;
94 | }
95 |
96 | #flash p, #flash a {
97 | color:yellow;
98 | margin:0;
99 | }
100 |
101 | #tabs {
102 | list-style:none;
103 | margin-bottom:40px;
104 | text-align: center;
105 | }
106 |
107 | #tabs li {
108 | display:inline;
109 | cursor:pointer;
110 | padding:10px;
111 | margin-right:20px;
112 | color:gray;
113 | }
114 |
115 | #tabs li.current {
116 | background-color: red;
117 | color:white;
118 | }
119 |
120 | #call-demo {
121 | display:none;
122 | }
123 |
124 | #welcome {
125 | float:left;
126 | width:300px;
127 | text-align:center;
128 | margin:0 20px 20px 0;
129 | }
130 |
131 | #welcome h1 span {
132 | color:yellow;
133 | }
134 |
135 | #footer {
136 | clear:both;
137 | width:900px;
138 | font-size:16px;
139 | text-align: center;
140 | margin:0 auto 10px auto;
141 | padding:50px 10px 10px 10px;
142 | }
143 |
144 | #footer span {
145 | color:red;
146 | }
147 |
148 | #footer p {
149 | font-size:12px;
150 | margin-top:10px;
151 | }
152 |
153 | #footer img {
154 | margin-bottom:-10px;
155 | }
--------------------------------------------------------------------------------