Deploying A Server For Your Timeline Enabled App With Heroku
Pins are a new and intuitive way for your users to interact with your app via the Pebble timeline. In a previous blog post I went through a complete walkthrough on how to get started with timeline. This post will focus on one single part of that process; how to deploy a server with Heroku, run jobs with Scheduler, and how to build APIs that push pins with the Express and pebble-api node modules.
Prerequisites
There are few things we’ll need to set up before we can deploy our server
- An account with Heroku
- The Heroku Toolbelt
- Node and npm installed
The Project
This time around we'll discuss how to deploy a server to push pins as part of
your app experience. We'll utilize Heroku for this
tutorial, because they make it super simple to deploy a server up to the cloud.
Our server will run Node.js with the Express
npm module to serve our HTTP
endpoints. This allows us to utilize the pebble-api
npm module which makes it super easy to create pins and push them to our users.
Why Do I Need My Own Server?
With the addition of timeline to the Pebble SDK developers are now encouraged to enhance their applications by running their own servers that bridge communication between their users' Pebble and the timeline web API.
This type of architecture allows you to do more for your users. Some of the things you can now do include:
- Push pins to users without your app running
- Push pins to all users
- Store user data (like preferences) in the cloud
Of course you aren't required to use a server to talk to the timeline web API, you can make requests directly via PebbleKit JS. A great example of this is the timeline-push-pin app. This approach allows an app to push pins to just the specific user. You can also use it to push shared pins to topics, but this will require storing the app's production API key in the JS, which we advise against.
Setup A Simple Webserver
The following commands will create a folder, create a file called server.js
,
create a file called package.json
, install the Express and pebble-api modules
and add them to list of dependencies in package.json
.
$ mkdir node
$ cd node
$ touch server.js
$ npm init # all of the default options are fine
$ npm install express pebble-api --save
In order to talk to the timeline web API, you need to obtain an API key from the
Developer Portal. Once you've obtained the
API key you need to set it as an environment variable, so the pebble-api
npm
module can use it.
$ export PEBBLE_TIMELINE_API_KEY=XXXXXXXXXXXXXXX # make sure to use your actual API key
Open server.js
in your favorite editor and paste the following:
var express = require('express'); // import the express module
var Timeline = require('pebble-api');
// create a new Timeline object with our API key passed as an environment variable
var timeline = new Timeline();
var app = express(); // create an express instance
app.set('port', (process.env.PORT || 5000)); // set the port on the instance
// push a pin to :userToken from our webservice
app.get('/senduserpin/:userToken', function(req, res) {
var userToken = req.params.userToken;
var pin = new Timeline.Pin({
id: parseInt(Math.random() * (999999 - 100000) + 100000).toString(), // random pin id
time: new Date(new Date().getTime() + 60*60*1000), // current date and time plus 1 hour
layout: new Timeline.Pin.Layout({
type: Timeline.Pin.LayoutType.GENERIC_PIN,
tinyIcon: Timeline.Pin.Icon.PIN,
title: 'Pin from Heroku!'
})
});
timeline.sendUserPin(userToken, pin, function (err, body, resp) {
if(err) {
res.status(400);
res.send(err);
} else {
res.send('Pin successfully pushed!');
}
});
});
// start the webserver
var server = app.listen(app.get('port'), function () {
console.log('Package Tracker server listening on port %s', app.get('port'));
});
When you run node server.js
this creates a super simple webserver. When a request
is made to https://localhost:5000/senduserpin/<pebble_user_token>
that will
send a pin to that user's Pebble saying "Pin from Heroku!" You can test this
locally by visiting http://localhost:5000/senduserpin/yourtoken
in your browser.
Make sure to replace "yourtoken" with your actual token in the above link!
Commit, Push, Deploy
From here we can initialize a git
repository, and commit our code so that we
push our code to Heroku.
$ git init
$ git add .
$ git commit -m 'First commit'
I would suggest adding a
.gitignore
file that ignores thenode_modules
folder. Here is a good one.
Let's create a Heroku app and connect it to our repo.
$ heroku create
Since we initalize our repo before we created our Heroku app, the Heroku Toolbelt will automatically add a git remote to Heroku's servers.
Now we just need to push our app to Heroku!
$ git push heroku master
This will push our repo to Heroku, where they'll take care of configuring the server, running our Node.js application, etc.
Before our server will work we need to set the timeline web API key environment variable on Heroku.
$ heroku config:set PEBBLE_TIMELINE_API_KEY=XXXXXXXXXXXXXXX # make sure to use your actual API key
You can check out your server by running:
$ heroku open
This will take you somewhere like https://<your_app>.herokuapp.com
. Like in
the local example, you can append /senduserpin/yourtoken
to push a pin your
Pebble.
Pushing Nested Folders to Heroku
Often you'll want to keep both your server and your Pebble app in the same folder. The best way to do this is to have two separate folders, one for the server and one for the Pebble app, with in another folder. A great example is the Timeline TV Tracker.
This poses a problem, because Heroku expects our application to be in the root
of our git repo. To resolve this problem instead of running git push heroku master
run
$ git subtree push --prefix <server folder> heroku master
You can read more about git-subtree by reading the official documentation.
Heroku Scheduler
Sometimes your server will need to run some periodic task. For example the
Timeline Package Tracker
checks to see if users have any new packages every 5 minutes. The Timeline
Package Tracker accomplishes this by using setInterval
.
Unfortunately this will not work on Heroku, because Heroku goes to sleep after
60 minutes of inactivity.
We can fix this by utilizing Heroku Scheduler
which lets us run abritrary jobs on a scheduled basis. We can create a small
JavaScript file that we can run periodically. We'll need to put this in a local
bin
directory so that Heroku knows where to find it.
$ mkdir bin
$ touch bin/pushTopicPins
In your favorite text editor put the following in pushTopicPins
.
#!/usr/bin/env node
var Timeline = require('pebble-api');
function pushTopicPins() {
// create a new Timeline object with our API key passed as an environment variable
var timeline = new Timeline();
var pin = new Timeline.Pin({
id: parseInt(Math.random() * (999999 - 100000) + 100000).toString(), // random pin id
time: new Date(), // current date and time
layout: new Timeline.Pin.Layout({
type: Timeline.Pin.LayoutType.GENERIC_PIN,
tinyIcon: Timeline.Pin.Icon.PIN,
title: 'Another pin about a topic from Heroku!'
})
});
timeline.sendSharedPin(['some_topic'], pin, function (err, body, resp) {
if(err) {
console.error(err);
}
});
}
pushTopicPins();
In order to leverage the
pebble-api
npm module you need to setPEBBLE_TIMELINE_API_KEY
with your timeline API key.
Everytime this script is run it will push a pin to every user
Add it to your git remote, push, and test it:
$ git add bin
$ git commit -m 'Add pushTopicPins job'
$ git push heroku master
$ heroku run pushTopicPins
To schedule the job we first need to add the Scheduler addon:
$ heroku addons:add scheduler:standard
Then we can schedule the job to run through the dashboard:
$ heroku addons:open scheduler
Heroku makes it easy to see all of the logs for your app in one place. This includes information about each time a job is run.
$ heroku logs
Note, Heroku is free until you exceed 750 dyno-hours per month. If you're running jobs that take a very long time you could potentially exceed that limit. For more information check out their Usage & Billing article.
Conclusion
This tutorial should help you hit the ground running when deploying your first server for timeline. I highly encourage you to try and deploy the Timeline TV Tracker and see how it all works together.
Have questions or want to share something awesome you've made for Pebble? Contact at us on twitter @pebbledev or share your project.
Overview
- Prerequisites
- The Project
- Why Do I Need My Own Server?
- Setup A Simple Webserver
- Commit, Push, Deploy
- Pushing Nested Folders to Heroku
- Heroku Scheduler
- Conclusion
Categories
- All Posts
- #makeawesomehappen
- At the Pub
- Beautiful Code
- CloudPebble
- Down the Rabbit Hole
- Freshly Baked
- Timeline