title: Socket.io chat app on heroku with node.js
body: <p>Messing about with Node.js and a bit nonplussed that I can't get something this simple working.  This code works fine on my local server, but the chat doesn't work on Heroku.  If I enter something, nothing happens.  I've checked the Heroku logs and they look fine.</p>
  
  <p><strong>package.json</strong></p>
  
  <pre><code>{
       "name": "mukhin_chat",
       "description": "example chat application with socket.io",
       "version": "0.0.1",
       "dependencies": {
          "express": "2.4.6",
          "socket.io": "0.8.4"
       },
      "engines": {
      "node": "0.8.x",
      "npm": "1.1.x"
    }
  }
  </code></pre>
  
  <p><strong>app.js</strong></p>
  
  <pre><code>// Variable port setting for heroku
  
  var port = process.env.PORT || 3000;
  
  var app = require('express').createServer()
  var io = require('socket.io').listen(app);
  
  app.listen(port);
  
  // Heroku setting for long polling - assuming io is the Socket.IO server object
  io.configure(function () { 
    io.set("transports", ["xhr-polling"]); 
    io.set("polling duration", 10); 
  });
  
  // routing
  app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
  });
  
  // usernames which are currently connected to the chat
  var usernames = {};
  
  io.sockets.on('connection', function (socket) {
  
      // when the client emits 'sendchat', this listens and executes
      socket.on('sendchat', function (data) {
          // we tell the client to execute 'updatechat' with 2 parameters
          io.sockets.emit('updatechat', socket.username, data);
      });
  
      // when the client emits 'adduser', this listens and executes
      socket.on('adduser', function(username){
          // we store the username in the socket session for this client
          socket.username = username;
          // add the client's username to the global list
          usernames[username] = username;
          // echo to client they've connected
          socket.emit('updatechat', 'SERVER', 'you have connected');
          // echo globally (all clients) that a person has connected
          socket.broadcast.emit('updatechat', 'SERVER', username + ' has connected');
          // update the list of users in chat, client-side
          io.sockets.emit('updateusers', usernames);
      });
  
      // when the user disconnects.. perform this
      socket.on('disconnect', function(){
          // remove the username from global usernames list
          delete usernames[socket.username];
          // update list of users in chat, client-side
          io.sockets.emit('updateusers', usernames);
          // echo globally that this client has left
          socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
      });
  });
  </code></pre>
  
  <p><strong>index.html</strong></p>
  
  <pre><code>&lt;script src="/socket.io/socket.io.js"&gt;&lt;/script&gt;
  &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script&gt;
      var socket = io.connect('http://localhost:8080');
  
      // on connection to server, ask for user's name with an anonymous callback
      socket.on('connect', function(){
          // call the server-side function 'adduser' and send one parameter (value of prompt)
          socket.emit('adduser', prompt("What's your name?"));
      });
  
      // listener, whenever the server emits 'updatechat', this updates the chat body
      socket.on('updatechat', function (username, data) {
          $('#conversation').append('&lt;b&gt;'+username + ':&lt;/b&gt; ' + data + '&lt;br&gt;');
      });
  
      // listener, whenever the server emits 'updateusers', this updates the username list
      socket.on('updateusers', function(data) {
          $('#users').empty();
          $.each(data, function(key, value) {
              $('#users').append('&lt;div&gt;' + key + '&lt;/div&gt;');
          });
      });
  
      // on load of page
      $(function(){
          // when the client clicks SEND
          $('#datasend').click( function() {
              var message = $('#data').val();
              $('#data').val('');
              // tell server to execute 'sendchat' and send along one parameter
              socket.emit('sendchat', message);
          });
  
          // when the client hits ENTER on their keyboard
          $('#data').keypress(function(e) {
              if(e.which == 13) {
                  $(this).blur();
                  $('#datasend').focus().click();
              }
          });
      });
  
  &lt;/script&gt;
  &lt;div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;"&gt;
      &lt;b&gt;USERS&lt;/b&gt;
      &lt;div id="users"&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;"&gt;
      &lt;div id="conversation"&gt;&lt;/div&gt;
      &lt;input id="data" style="width:200px;" /&gt;
      &lt;input type="button" id="datasend" value="send" /&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p><strong>Procfile</strong></p>
  
  <pre><code>web: node app.js
  </code></pre>
  
  <p><strong>Logs</strong></p>
  
  <pre><code>2012-08-15T01:24:03+00:00 heroku[web.1]: State changed from up to starting
  2012-08-15T01:24:03+00:00 heroku[slugc]: Slug compilation finished
  2012-08-15T01:24:05+00:00 heroku[web.1]: Starting process with command `node app.js`
  2012-08-15T01:24:05+00:00 heroku[web.1]: Stopping all processes with SIGTERM
  2012-08-15T01:24:07+00:00 heroku[web.1]: Process exited with status 1
  2012-08-15T01:24:08+00:00 app[web.1]:    info  - socket.io started
  2012-08-15T01:24:09+00:00 heroku[web.1]: State changed from starting to up
  2012-08-15T01:24:21+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/ dyno=web.1 queue=0 wait=0ms service=23ms status=200 bytes=1774
  2012-08-15T01:24:21+00:00 app[web.1]:    debug - served static /socket.io.js
  2012-08-15T01:24:21+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/socket.io/socket.io.js dyno=web.1 queue=0 wait=0ms service=15ms status=200 bytes=95997
  2012-08-15T01:24:23+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/favicon.ico dyno=web.1 queue=0 wait=0ms service=3ms status=404 bytes=34
  2012-08-15T01:24:45+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/ dyno=web.1 queue=0 wait=0ms service=7ms status=200 bytes=1774
  2012-08-15T01:24:45+00:00 app[web.1]:    debug - served static /socket.io.js
  2012-08-15T01:24:45+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/socket.io/socket.io.js dyno=web.1 queue=0 wait=0ms service=18ms status=200 bytes=95997
  2012-08-15T01:24:50+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/ dyno=web.1 queue=0 wait=0ms service=6ms status=304 bytes=0
  2012-08-15T01:24:51+00:00 app[web.1]:    debug - served static /socket.io.js
  2012-08-15T01:24:51+00:00 heroku[router]: GET still-bastion-7144.herokuapp.com/socket.io/socket.io.js dyno=web.1 queue=0 wait=0ms service=14ms status=200 bytes=95997
  </code></pre>