Remote smartphone control with Node.js and

Original author: Nick Anastasov
  • Transfer
  • Tutorial
It would be fun to use your smartphone as a control panel, right? In fact, it does not look very difficult. You do not even need to be able to write large applications, as there is a browser that supports opening sockets. In this short lesson, we will use Node.js and to control the presentation that is running on a computer using a phone.

There are many cool HTML5 libraries for creating presentations, but not one of them is provided for our idea. In this regard, we will use Reveal.js - the library will work with animation and respond to pressing a keyboard or touching the screen of a smartphone.

We will not develop a separate management interface. Instead, let's synchronize the open presentation on both devices. This will allow you not only to see the mobile version of the presentation, but also to understand which of the slides is currently active.


Our idea is simple - Reveal.js will pass the number of the current slide through a URL in the form of a hash (for example, ). Then we will send this hash to all other connected devices, which will scroll through the presentations automatically. In this regard, anyone can ruin everything by the elementary opening of an arbitrary slide, which will lead to turning over on all devices. In order to avoid this, we will set a password and will require its input to connect.

It’s worth mentioning that Reveal.js already has an API, and we can use it for synchronization, but the technique of changing and sending a hash is simpler, so let's use it.

Our presentation

Running example

You can run the example on your computer or deploy it with a provider like Heroku. The first option is simpler, but you need to install node.js and npm. The second involves installing the heroku toolbelt and registering with the system.
To run locally:

  1. Download the archive with the code;
  2. Make sure node.js is installed ;.
  3. Unzip the downloaded file;
  4. Open a terminal and go to the folder with the extracted files;
  5. Run npm installto install the libraries;
  6. Launch the application with the command node app.js;
  7. Open http: // localhost: 8080 and enter the password (“ kittens “ by default);
  8. Open http: // <local computer address> on the phone and enter the same phrase;
  9. Rejoice!

To run in Heroku:

  1. Download the archive with the code;
  2. Unzip it;
  3. Open a terminal and go to the folder;
  4. Create a repository and first commit;
  5. Create an application in Heroku;
  6. Run git push heroku master;
  7. Open the application at its address and enter the password “ kittens ” (default).

Read more about this process here . If you use a different provider, the last steps may vary.

The code

Stop talking, let's take a look at the code! We have only two JavaScript files - app.js for the back-end and script.js for the browser. You can run the application in Node.js 0.10+ or ​​in io.js.

In the server side, we use express and . Its task is to listen for events and send responses to them. With express.static, we display files from public folders. The file public / index.html contains the presentation itself. It is processed automatically through express.static, so there is no need to specify “/” in the address.
// This is the server-side file of our mobile remote controller app.
// It initializes and a new express instance.
// Start it by running 'node app.js' from your terminal.
// Creating an express server
var express = require('express'),
    app = express();
// This is needed if the app is run on heroku and other cloud providers:
var port = process.env.PORT || 8080;
// Initialize a new object. It is bound to 
// the express app, which allows them to coexist.
var io = require('').listen(app.listen(port));
// App Configuration
// Make the files in the public folder available to the world
app.use(express.static(__dirname + '/public'));
// This is a secret key that prevents others from opening your presentation
// and controlling it. Change it to something that only you know.
var secret = 'kittens';
// Initialize a new application
var presentation = io.on('connection', function (socket) {
    // A new client has come online. Check the secret key and 
    // emit a "granted" or "denied" message.
    socket.on('load', function(data){
        socket.emit('access', {
            access: (data.key === secret ? "granted" : "denied")
    // Clients send the 'slide-changed' message whenever they navigate to a new slide.
    socket.on('slide-changed', function(data){
        // Check the secret key again
        if(data.key === secret) {
            // Tell all connected clients to navigate to the new slide
            presentation.emit('navigate', {
                hash: data.hash
console.log('Your presentation is running on http://localhost:' + port);

And here is the JavaScript for the front-end, which listens for the hashchange event and sends a message to the server.
public / assets / js / script.js
$(function() {
    // Apply a CSS filter with our blur class (see our assets/css/styles.css)
    var blurredElements = $('.homebanner, div.reveal').addClass('blur');
    // Initialize the Reveal.js library with the default config options
    // See more here
        history: true		// Every slide will change the URL
    // Connect to the socket
    var socket = io();
    // Variable initialization
    var form = $('form.login'),
        secretTextBox = form.find('input[type=text]');
    var key = "", animationTimeout;
    // When the page is loaded it asks you for a key and sends it to the server
        key = secretTextBox.val().trim();
        // If there is a key, send it to the server-side
        // through the channel with a 'load' event.
        if(key.length) {
            socket.emit('load', {
                key: key
    // The server will either grant or deny access, depending on the secret key
    socket.on('access', function(data){
        // Check if we have "granted" access.
        // If we do, we can continue with the presentation.
        if(data.access === "granted") {
            // Unblur everything
            var ignore = false;
            $(window).on('hashchange', function(){
                // Notify other clients that we have navigated to a new slide
                // by sending the "slide-changed" message to
                    // You will learn more about "ignore" in a bit
                var hash = window.location.hash;
                socket.emit('slide-changed', {
                    hash: hash,
                    key: key
            socket.on('navigate', function(data){
                // Another device has changed its slide. Change it in this browser, too:
                window.location.hash = data.hash;
                // The "ignore" variable stops the hash change from
                // triggering our hashchange handler above and sending
                // us into a never-ending cycle.
                ignore = true;
                setInterval(function () {
                    ignore = false;
        else {
            // Wrong secret key
            // Addding the "animation" class triggers the CSS keyframe
            // animation that shakes the text input.
            secretTextBox.addClass('denied animation');
            animationTimeout = setTimeout(function(){
            }, 1000);

It's Slideshow Time!

Our smartphone remote is ready! I hope you find this useful and enjoyable.

Download Demo Code

Also popular now: