Getting started with IBM Cloud Node.js applications, Part 1
Create a front-desk visitor log with Node.js
Developing the server-side code
Content series:
This content is part # of # in the series: Getting started with IBM Cloud Node.js applications, Part 1
This content is part of the series:Getting started with IBM Cloud Node.js applications, Part 1
Stay tuned for additional content in this series.
In this article, you learn how to use the IBM Cloud to write a Node.js application for an organization’s front desk, which needs to log visitors in and out. Along the way you will learn how to use Node.js, the Express HTTP server library, and a Cloudant database. You will learn how to do this in the highly available IBM Cloud. This is a basic introduction to Node.js programming on the IBM Cloud platform.
What you'll need to build your application
- A free IBM Cloud account.
- Basic knowledge of HTML.
- Basic knowledge of JavaScript.
Getting started
First, we create the application. Then we create the development environment.
Getting started
First, we create the application. Then we create the development environment.
Create the application
- Log on to the IBM Cloud Console. If you do not have an IBM account, create one here.
- Expand the hamburger icon and select Cloud Foundry Apps.
- Click Create resource.
- Select the category Cloud Foundry Apps. Within that category, click SDK for Node.js.
- Click SDK for Node.js.
- Enter these parameters:
App name Pick an unused value Host name Accept the default Domain mybluemix.net Region/location Choose whichever is closest to you Organization and space Leave the default - Click Create.
- Click Overview on the left sidebar.
- Click Visit App URL.
- You may have to reload until the application is created and started.
- Figure 1 shows the initial application. After you see it, do not close the tab. You will need it later.
Note: This would be your initial application. If you go to the sample application's URL you'll get a different one, a user interface we build later in the article.
Figure 1. Initial application

Create the development environment
Cloud Foundry on the IBM Cloud allows several development environments. In this article, we take the easy road and use the web development environment.
- Return to the IBM Console page for the application. If you are logged out, log back in and click the application's name in the dashboard.
- Scroll down to continuous delivery and click Enable.
- To accept the defaults click Create.
- After the tool chain is created, click Eclipse Orion Web IDE.
- Click Create new launch configuration > +.
- Click Save to create the default launch configuration. It has everything we need.
- Click Visitor-Log > app.js.
- Replace the content of the file with the code here.
- Click the play icon to apply the changes.
- Wait until you see the green circle again. It means that the application was restarted with the new code.
- Go back to the application tab and add /hello at the end of the URL. See that you get a Hello, world message.
To understand this program, we go line by line over the source code, available here.
The first line is ignored by the JavaScript interpreter as a comment. It is here because the IBM Console editor includes the Eslint utility to identify potential errors in the code. This directive tells that utility to treat the JavaScript as Node.js (server-side JavaScript) code. You can read more about the Eslint utility here.
/*Eslint-env node*/
This is the other way to write a comment in JavaScript. The rest of the line after a double slash (//) is ignored as a comment.
//------------------------------------------------------------------------------ // node.js starter application for Bluemix //------------------------------------------------------------------------------
Node.js is the runtime environment. The web server package is Express. You can read more about it here. The
way you use a package in Node.js is to use the require
function with the package name (assuming the package is declared in the
package.json file). The require
function usually returns a
function that you use to use the module.
// This application uses express as its web server // for more info, see: http://expressjs.com var express = require('express');
The cfenv
module provides Cloudy Foundry information. It is
used later to get the port number to which the web server needs to listen,
and the URL it is serving.
// cfenv provides access to your Cloud Foundry environment // for more info, see: https://www.npmjs.com/package/cfenv var cfenv = require('cfenv');
The next step is to create an HTTP server.
// create a new express server var app = express();
This is how we tell Express to serve static files from a directory. If you open the public directory in the editor, you will see the index.html file that is part of the default application (the one shown in Figure 1).
// serve the files out of ./public as our main files app.use(express.static(__dirname + '/public'));
The app.get
call specifies how to handle requests for a
particular path. The path is the first parameter. The second parameter is
a function to call when the path is requested. This function has two
parameters: a request object that includes the HTTP request, and a
response object used to send back a response. JavaScript has two syntax
options for a function literal (an anonymous function which can, for
example, be itself a function parameter). The older one, which we use
here, is function(<parameters>) {body}
.
The callback function just uses the res.send
function to send
a constant string, the traditional hello world.
The /* @callback */
comment is for Eslint. Normally, Eslint
would report that a function has an unused parameter and suggest you
remove it. However, the parameters of callback functions are set by the
calling code (here, Express). In this case, some path callbacks require
both parameters.
app.get("/hello", /* @callback */ function(req, res) { res.send("Hello, world"); });
This step gets the Cloud Foundry environment. This is how the IBM Cloud infrastructure communicates with the application. You can read more about this here.
// get the app environment from Cloud Foundry var appEnv = cfenv.getAppEnv(); // start server on the specified port and binding host app.listen(appEnv.port, '0.0.0.0', function() { // print a message when the server starts listening console.log("server starting on " + appEnv.url); });
The visitor log
The main data structure of the application is a visitor log. You can see the source code with the code that declares and manipulates it here. Replace your current app.js and click the play button to restart the application. You can see the current visitor log in https://<your app>/test/visitors. It is in JSON, so it might be clearer if you use a JSON formatter such as this one. To see the visitor log for my application instance, click here.
The visitor log is an associative array (also called hash table, or object) whose keys are visitor names. The value for each visitor name is itself an associative array, which can have two attributes:
- arrived – The last time the visitor arrived at the office. This attribute does not exist if the visitor is not currently in the office.
- history – The visitor's history, an array of associate arrays with the start and end times of previous visits. This attribute does not exist during the first visit to the office.
The default visitor log
There is a default visitor log with some sample data for debugging. It is shown in Figure 2.
Figure 2. Default visitor log

You can see the definition for this default visitor log on GitHub, lines 23-48. Most of it is a standard JavaScript object
definition, but the dates, instead of being fixed, are a fixed time before
the application was started. Date.now()
is the number of
milliseconds between now and a fixed point in time (midnight January
1st 1970 GMT). So Bill Hamm's arrival time is two hours before
this code is executed when the application starts. You can read
more about the Date object here.
"Bill Hamm": { arrived: new Date(Date.now() - 1000*3600*2) },
Reading the visitor log
When displaying the visitor log, we might want to display all of it, or we might want to display just the current visitors, those that are currently in the office. Also, it can be useful to get the names of all the visitors, all the visitors currently in the office, or all those who currently aren't, without their full information. These are the functions that implement these requirements:
To get the list of visitor names, all we need is to get the keys of the
visitors object. The function to do this is Object.keys
. Note that the function syntax here is
the new one, (parameters) => {expressions;}
. In this
particular case, there are no parameters.
var visitorNames = () => { return Object.keys(visitors); };
To get a subset (either those who are in the office or those who aren't),
use the filter
function. This function is an array method (so
you can call it on any list, such as the one returned by
visitorNames
). It gets one parameter, a function. This
function gets an item from the list as a parameter, and returns whether or
not that item should be a member of the filtered list.
The function definition is simplified. When a function literal is a single
expression, there is no need to enclose it in curly brackets
({}
) and have a return
statement. You can just
enter the expression.
var currentVisitorNames = () => { return visitorNames().filter((name) => visitors[name].arrived !== undefined); };
It is more complicated to get the list of current visitors with their
information, with the names as keys. The first step is in
currentVisitorList
. This function uses the map
function to retrieve the information for each user in the list of current
visitors. This function receives a function as a parameter, similar to
filter
. However, instead of deciding whether a value will be
in the output or not the function in map
is used to transform
the value. Those transformed values are turned into a list in the same
order as the original values. You read about this function here.
In this case, for each name we get a structure with the user information. For example, for the default data we might get something like Figure 3.
var currentVisitorNames = () => { return visitorNames().filter((name) => visitors[name].arrived !== undefined); };
Figure 3. Current visitor list

This list has the information we need, but each user is in a separate
object in a list. It makes a lot more sense to use the same format we use
in the visitors
variable, one object with each user being a
separate attribute. To do that, we use reduce
to turn the
list into a single object. If the list it receives has one item, it
returns that item. If it has two items, it runs the parameter function on
them and returns the result. If there are more, it runs the parameter
function on two of them, then on that result and another one, until there
is only a single value left. You can read
more about the function here.
var currentVisitors = () => { return currentVisitorList().reduce((a, b) => {
To create the combined object, we first need the key of the new object, the one from the list which only has a single attribute for a single user.
var bKey = Object.keys(b)[0];
We add this value to the original object, the one in which we accumulate all the users, and return it.
a[bKey] = b[bKey]; return a; }); };
Modifying the visitor log
There are two possible modifications to the visitor log. A user may be logged in when they enter the office, or logged out when they leave.
For these functions we have a get function and a set function to interact
with the visitors
variable. The purpose of these functions is
to make it easy to modify the application to use a different data storage,
for example a database, in the future.
var getVisitor = (name) => visitors[name]; var setVisitor = (name, values) => visitors[name] = values;
The log out function is relatively simple. Check whether the user has an
arrived
attribute. If the user doesn't have it, this user is
not currently in the office and cannot be logged out. Report an error. If
the arrived
attribute does exist, remove it and add the visit
that just ended to the history.
var logOut = (name) => { var oldRecord = getVisitor(name);
When a string is enclosed in back ticks (`
), it means that it
is a template literal. It can run for several lines, and you can use
the syntax ${<expression>}
to instead the
value of an expression, for example the name variable. This is the error
we return if there is no user at all:
if (oldRecord === undefined) return `Error, ${name} is unknown`;
And this is the error we return if the user exists, but is not logged in at the moment.
if (oldRecord.arrived === undefined) return `Error, ${name} is not logged in`;
The only attribute in the old record that is still relevant is
history
. We need to keep it and add a new value. However, if
this is the first visit there might be no history yet. In such a case, the
history is empty.
var history = oldRecord.history;
// If this is the first visit if (history === undefined) history = [];
The unshift
function adds a new value at the beginning of an
array. This is the behavior we want here, because the latest visits are
more likely to be relevant, so it is best if the array is sorted in
reverse chronological order. You can read more about this function here.
history.unshift({ arrived: oldRecord.arrived, left: new Date(Date.now()) });
The only attribute for a visitor who is not currently logged on is
history
.
setVisitor(name, {history: history}); return `OK, ${name} is logged out now`; };
The log in function creates a new record with the existing history and an
arrived
attribute with the current time.
var logIn = (name) => { var oldRecord = getVisitor(name); var history;
When you have multiple conditions, and you only want the first one that is true to be processed, you can use this syntax:
if <condition A>
<action A> else if <condition B> <action B> else if
<condition C> <action C> … else <default
action>
Because of the else if
statements, once a condition is
evaluated as true the action for it happens and the rest of the conditions
are skipped.
Here we need to check if there is an existing entry before we check if it
has an arrived
attribute because it is an error to check for
attributes of an undefined value.
// First time we see this person if (oldRecord === undefined) history = []; // No history // Already logged in else if (oldRecord.arrived !== undefined) return `Error, ${name} is already logged in`; // Not logged in, already exists else history = oldRecord.history; setVisitor(name, { arrived: new Date(Date.now()), history: history }); return `OK, ${name} is logged in now`; };
Testing
The code above looks like it should work, but it is best to test it before
proceeding. For testing purposes, various paths under /test return the
results of the above functions. Doing this relies on
testFunctions
, which is a table that has paths and their
associated functions. The functions in this table do not receive any
parameters, and return the information to send the user. To enable the
testing of functions that do require parameters, such as logIn
, they are
wrapped in the table within a definition that does provide the necessary
parameters. That way, the code that uses the table does not need to
specify any parameter values.
var testFunctions = [
The first few lines are simply function names for functions that do not accept parameters. There is no need to wrap them.
{path: "visitorNames", func: visitorNames}, {path: "currentVisitorNames", func: currentVisitorNames}, {path: "nonCurrentVisitorNames", func: nonCurrentVisitorNames}, {path: "currentVisitorList", func: currentVisitorList}, {path: "currentVisitors", func: currentVisitors},
The /test/visitors path does not actually show the output of a function, but a variable. However, the code that uses the table expects a function – so we wrap it in a function.
{path: "visitors", func: () => visitors},
The logIn
and logOut
functions do get a
parameter, a user name. To run the simple tests we need here, we use a
fixed user name.
{path: "logIn", func: () => logIn("Avimelech ben-Gideon")}, {path: "logOut", func: () => logOut("Avimelech ben-Gideon")} ];
This is the code that registers the handlers. It prepends
/test/
to the path and creates a function that calls the
function from the table and then sends the response to the browser.
testFunctions.map((item) => app.get( `/test/${item.path}`, /* @callback */ function(req, res) { res.send(item.func()); } ) );
To actually test the application, first go to /test/logOut to log out the non-existent Avimelech ben-Gideon account and see the error code. Then go to /test/logIn twice. The first attempt should succeed and the second one fails. Then go to /test/logOut twice to see the first attempt succeeds and the second one fails. After you do these steps, and maybe log in and out a few more times, go to /test/visitors to see the JSON data for the visitor log. The easiest way to do this is to go to a JSON formatter that accepts URLs and give it the visitor log URL. Finally, look at the other function URLs, such as /test/currentVisitorNames, to see that it shows the correct information.
Note that if you look at those paths on the sample application there might be excess information from other readers of this article.
User interface
Replace the code in your app.js with the file found here. Then go to /visitors on your application (or the sample application) to see the full visitor list. Go to /currentVisitors to see the current list. Log users in with /login and out with /logout. To see the entire user interface, go to / or /index.html.
The first difference is this instruction to the Eslint to ignore unused
parameters. This is because the /* callback */
directive
(ignore unused parameters only for this function call).
/*eslint-disable no-unused-params */
It is useful to know how long a visitor has been in the office, but a number such as 5000 seconds is hard to interpret. This function turns a time difference in milliseconds to a readable string. The input is milliseconds because that's the standard in most JavaScript functions that relate to time.
// Given a time difference in miliseconds, return a string // with the approximate value var tdiffToString = (msec) => { var sec = msec/1000;
If the number of seconds is less than 60, return a number of seconds, properly labeled. Use the trinary operator to either add an "s" for plural or not. This operator takes three parameters. If the first parameter (less than 2 seconds) is true, it returns the second parameter (an empty string). If the first parameter is false, which means we need to use the plural, the operator returns the third parameter, the plural "s."
if (sec < 60) return sec + " second" + (sec < 2 ? "" : "s");
If the number of seconds is less than 60, the function has already
returned. If the number is the between 60 and 3600 (an hour), we need to
return the number of minutes in the time interval. Note the use of Math.floor
. It is necessary because we want to avoid
reporting values like 5.23544 minutes.
if (sec < 3600) return Math.floor(sec/60) + " minute" + (sec < 60*2 ? "" : "s");
The rest of the function, for hours and days, operates the same way.
… };
This is the first function that produces HTML. The user interface displays the history (arrivals, departures, and the intervening time) in an HTML table – and this function produces the rows in that table.
// Given a history entry (arrived and left times), create a table row with // that information var histEntryToRow = (entry) => { return `<tr> <td>${entry.arrived}</td> <td>${entry.left}</td> <td>${tdiffToString(entry.left-entry.arrived)}</td> </tr>`; };
This function produces an entire table (if there is anything to produce, otherwise it just returns an empty string).
// Given a history, create a table with it var histToTable = (history) => { if (history === undefined) return ""; if (history.length === 0) return "";
People don't always want to see the history. By enclosing it in a
details
tag we hide the history until a user decides
to open it. The
style
attribute allows us to specify the background
color to make the history tables distinct from the rest of the visitor
information (which is also displayed in table form).
return `<details> <table border style="background-color: yellow"> <tr> <th> Arrived </th> <th> Left </th> <th> Time here </th> </tr> ${history.map(histEntryToRow).reduce((a, b) => a+b)} </table> </details>`; };
The next two functions, userToRow
and
usersToTable
, are very similar to the way we create the
history table. There is no point to go over them. Next,
visitorsHTML
and currentVisitorsHTML
add a
heading and create the table with the appropriate user names list. Again,
those functions are so similar that it is enough to see one of them.
var visitorsHTML = () => { return ` <h2>Current Visitor List</h2> ${usersToTable(visitorNames())} `; };
This function creates a login form. It uses an HTML form
with the GET method. This means the parameters (in this case there is only
one, user
) are going to be encoded in the URL. The
login
attribute gives the path for the handler, which you
will see later in the article.
var loginForm = () => { return `<h2>Log in a visitor</h2> <form method="get" action="login"> Visitor to log in: <input type="text" name="user"> </form>`; };
There is one substantial difference between the login form and the logout "form." There is no way to know in advance which visitor is going to be logged in. It may even be somebody completely new. However, the only visitors that can be logged out are those who are currently logged in. This lets us show a list and have the user choose from it.
var logoutForm = () => { if (currentVisitorNames().length === 0) return "No users to log out"; return ` <h2>Log out a visitor</h2> <ul> ${currentVisitorNames()
Instead of creating a form with an input field, I decided to use links. We
can do that, and simulate a GET form, because of the the way a GET form
returns its parameters. You have the usual URL
(http://<hostname>/<path>) followed by a question mark, then
<parameter>=<value>
pairs, separated by
ampersands (&
). The value might include characters that
have a special meaning in URLs (such the ampersand), so they are escaped.
This is the role of the
encodeURI
function.
.map(name => `<li> <a href="logout?user=${encodeURI(name)}">${name}</a> </li>`) .reduce((a,b) => a + b)} </ul>`; };
This function takes text, such as the HTML produced by the above functions, and turns it to a complete web page.
var embedInHTML = (str) => { return `<html><body>${str}</body></html>`; };
These two calls call the proper function to create the heading and table, embed it within a page, and respond.
app.get("/visitors", (req, res) => { res.send(embedInHTML(visitorsHTML())); }); app.get("/currentVisitors", (req, res) => { res.send(embedInHTML(currentVisitorsHTML())); });
These two calls are the form handlers. The parameters submitted to the form
using the GET method are available in req.query
. If there is
no user, send the form. If there is a user, process the command for that
user.
app.get("/login", (req, res) => { if (req.query.user === undefined) res.send(embedInHTML(loginForm())); else res.send(logIn(req.query.user)); });
app.get("/logout", (req, res) => { if (req.query.user === undefined) res.send(embedInHTML(logoutForm())); else res.send(logOut(req.query.user)); });
This app.get
call shows everything in the application. Instead
of a path there is a list of paths, which Express interprets as "this
handler applies to everything in this list."
app.get(["/index.html", "/"], (req, res) => {
app.get(["/index.html", "/"], (req, res) => { res.send(embedInHTML(` ${loginForm()} <hr /> ${logoutForm()} <hr /> ${currentVisitorsHTML()} <hr /> ${visitorsHTML()} `)); });
If we keep this call it overrides the handler we registered – so I commented it out.
/* // serve the files out of ./public as our main files app.use(express.static(__dirname + '/public')); */
Database
There is one "slight" problem with the application. Every time that it is restarted it loses the visitor log. To solve this, we store the visitor log in a Cloudant database. The visitor name is the key, and the data (history and arrival time and date) is the value.
Create the database
Follow these steps to create the database:
- In the IBM Cloud console, from the hamburger menu click Data & Analytics.
- Click Create resource and select Cloudant NoSQL DB.
- Name the service
visitor-log
and click Create. - When the service is created, click Service credentials in the left sidebar.
- Click the New credential button.
- Name the new credential
visitor-log
and click Add. - In the credential list, click View credentials. Click the copy/duplicate icon to copy the credential and paste it to a text file.
- In the left sidebar, click Manage. Then, click the LAUNCH button.
- In the left sidebar, click the Databases icon.
- Then click Create Database in the upper right.
- Name the database
visitor-log
. - Go back to the application development environment and open the file package.json.
- In the dependencies, add a line for the Cloudant package (version 1.7.x). After you finish, your file will look like the one in the link.
Use the database
To use the database, replace app.js with this code. It uses almost the same data definitions and user interface, so it won't look different. But if you restart the application, the information is not lost.
First, have a variable with your Cloudant credential. Obviously, you can't use the value in GitHub because the credential is different for each user and I'm not disclosing mine.
var cloudantCred = { << redacted >> };
Use this credential to connect to the database management system, and then specify which database you are going to use:
// Connect to the database var cloudant = require("cloudant")(cloudantCred.url); var mydb = cloudant.db.use("visitor-log");
There are two ways we can store the information in the database. One would
be to put the entire visitors
data structure in a single
database entry (called document in Cloudant). The other is to have a
separate document for each visitor name. For this introductory article, I
chose to use the first method. It is obviously less efficient, but it will work for up to 1 MB. The major advantage of this approach
is that we can use the application logic developed previously with almost
no change. We can continue to keep the visitors
data
structure as a variable.
The same Cloudant database could be used by multiple applications at the
same time. To avoid one application's interference with another, it uses a
revision system. Every document has a _rev
value with the
current revision. When you update a document, you provide the revision
you're updating. If it changed from the time you read it, the revision
is different causing the update to fail—this requires us to have a
variable to hold the current revision.
var dbRev = "";
This function updates the visitor log on the database.
var updateVisitors = () => {
The data to update always includes _id
, the key, and the
actual value. It usually also includes _rev
, the revision.
The exception is when creating a new entry.
var updateData = { "_id": "visitors", value: visitors }; if (dbRev !== "") updateData["_rev"] = dbRev;
With the update hash table ready, we can insert the latest version into the
database, using the <database>.insert
function.
mydb.insert(updateData, (err, body) => {
If the insertion is successful, the response body includes the new revision value.
if (err === undefined) dbRev = body["rev"];
These lines log database failures. The mechanism used for this is explained in later in this article.
else log += "updateVisitors: " + err + "
"; } ); };
The next few lines in the code read visitors
when the
application is started, using the <database>.get
function.
// Read the visitors data structure. mydb.get("visitors", (err, body) => {
If we get a 404 error, it means there is no visitors
data
structure yet in the database. In this case, we create one and call
updateVisitors
. This is the one case where the
database.insert
function is called without a revision.
// No visitors yet, create it. if (err !== null && err.statusCode === 404) { visitors = {"Test user": {arrived: Date.now().valueOf()}}; updateVisitors(); } else {
If there is a value, use it and keep the revision for when
updateVisitors
needs it.
visitors = body.value; dbRev = body["_rev"]; } });
The only function that directly changes visitor information after the
application starts is setVisitor
. It needs to call
updateVisitors
to save the change in the database.
var setVisitor = (name, values) => { visitors[name] = values; updateVisitors(); };
Time and date representation
There is one additional problem. Because the communication with Cloudant is text based, when writing to Cloudant Date objects are converted to their text representation, a string with the date, time, and time zone. Then, when the information is read back, they are treated as strings. This would be fine if we only wanted to display dates, but we also want the user to see how long each visit was.
To solve this problem, instead of storing a Date object in the
visitors
data structure and the database, we store the number
of milliseconds since the beginning of the epoch (an arbitrary point in
time, usually set on UNIX-derived systems to midnight on January
1, 1970, GMT). Storing milliseconds requires a few changes in the
program:
First, every place where we get the current date needs to be
Date.now().valueOf()
. The valueOf()
call turns
the date object into the number of milliseconds since the beginning of the
epoch. For example, in logout
:
history.unshift({ arrived: oldRecord.arrived, left: Date.now().valueOf() });
The functions that display date and time stamps also need to change. To
turn the time in milliseconds into a string, we create a new Date object
with the time in milliseconds in one function,
histEntryToRow
:
// Given a history entry (arrived and left times), create a table row // with that information var histEntryToRow = (entry) => { return `<tr> <td>${new Date(entry.arrived)}</td> <td>${new Date(entry.left)}</td> <td>${tdiffToString(entry.left-entry.arrived)}</td> </tr>`; // The Date need to be new, otherwise we are just // modifying the same object and all dates in // the history table are the same. };
Logging for debug purposes
While developing this application, I needed to see why database updates did not work sometimes. To do that, I created a log string and appended to it every time an update failed. This technique can also be useful in your web applications (make sure to disable it or require a secret before you have production data).
need to be new, otherwise we are just var log = ""; var updateVisitors = () => { ... mydb.insert(updateData, (err, body) => { if (err === undefined) dbRev = body["rev"]; else
When we add to the log, append a <br/>
. This string will
be retrieved by a browser, which will interpret it as HTML by default.
log += "updateVisitors: " + err + "
"; } ); };
To access the log, go to the /log path:
app.get("/log", (req, res) => { res.send(log); });
Conclusion
You are now be able to write simple Node.js web applications on the IBM Cloud and store the data in Cloudant. The main problem with this web application is that it is not visually appealing. Every change requires the entire page to be refreshed, and it is plain HTML.
In the next article in this series, I show you how to use the Bootstrap Theme to make your web applications look better, and how to use the AngularJS library to make them more responsive.