diff --git a/src/node/examples/route_guide.proto b/src/node/examples/route_guide.proto
index b648a0589182ce026264332b0ef04cedd518377b..4c7be175e4c600437ecfd60fb9b322fb3afaf601 100644
--- a/src/node/examples/route_guide.proto
+++ b/src/node/examples/route_guide.proto
@@ -117,4 +117,4 @@ message RouteSummary {
 
   // The duration of the traversal in seconds.
   optional int32 elapsed_time = 4;
-}
\ No newline at end of file
+}
diff --git a/src/node/examples/route_guide_server.js b/src/node/examples/route_guide_server.js
index 3df90e91738f916836371949aeba99d52bcf0830..b21190d62e47169e874954f084eaae75f159cac0 100644
--- a/src/node/examples/route_guide_server.js
+++ b/src/node/examples/route_guide_server.js
@@ -35,19 +35,42 @@ var Server = grpc.buildServer([examples.RouteGuide.service]);
 
 var COORD_FACTOR = 1e7;
 
+/**
+ * For simplicity, a point is a record type that looks like
+ * {latitude: number, longitude: number}, and a feature is a record type that
+ * looks like {name: string, location: point}. feature objects with name==='' are
+ * points with no feature.
+ */
+
+/**
+ * List of feature objects at points that have been requested so far.
+ */
 var feature_list = [];
 
+/**
+ * Return a random "word" (alphabetic character sequence) of the given length.
+ * @param {number} length The length of the word to create
+ * @return {string} An alphabetic string with the given length.
+ */
 function randomWord(length) {
   var alphabet = 'abcdefghijklmnopqrstuvwxyz';
   var word = '';
   for (var i = 0; i < length; i++) {
+    // Add a random character from the alphabet to the word
     word += alphabet[_.random(0, alphabet.length - 1)];
   }
   return word;
 }
 
+/**
+ * Get a feature object at the given point, or creates one if it does not exist.
+ * @param {point} point The point to check
+ * @return {feature} The feature object at the point. Note that an empty name
+ *     indicates no feature
+ */
 function checkFeature(point) {
   var feature;
+  // Check if there is already a feature object for the given point
   for (var i = 0; i < feature_list.length; i++) {
     feature = feature_list[i];
     if (feature.point.latitude === point.latitude &&
@@ -55,6 +78,7 @@ function checkFeature(point) {
       return feature;
     }
   }
+  // If not, create a new one with 50% chance of indicating "no feature present"
   var name;
   if (_.random(0,1) === 0) {
     name = '';
@@ -65,14 +89,27 @@ function checkFeature(point) {
     name: name,
     location: point
   };
+  // Add the feature object to the list and return it
   feature_list.push(feature);
   return feature;
 }
 
+/**
+ * getFeature request handler. Gets a request with a point, and responds with a
+ * feature object indicating whether there is a feature at that point.
+ * @param {EventEmitter} call Call object for the handler to process
+ * @param {function(Error, feature)} callback Response callback
+ */
 function getFeature(call, callback) {
   callback(null, checkFeature(call.request));
 }
 
+/**
+ * listFeatures request handler. Gets a request with two points, and responds
+ * with a stream of all features in the bounding box defined by those points.
+ * @param {Writable} call Writable stream for responses with an additional
+ *     request property for the request value.
+ */
 function listFeatures(call) {
   var lo = call.request.lo;
   var hi = call.request.hi;
@@ -80,7 +117,11 @@ function listFeatures(call) {
   var right = _.max(lo.longitude, hi.longitude);
   var top = _.max(lo.latitude, hi.latitude);
   var bottom = _.max(lo.latitude, hi.latitude);
+  // For each feature, check if it is in the given bounding box
   _.each(feature_list, function(feature) {
+    if (feature.name === '') {
+      return;
+    }
     if (feature.location.longitude >= left &&
         feature.location.longitude <= right &&
         feature.location.latitude >= bottom &&
@@ -117,17 +158,28 @@ function getDistance(start, end) {
   return R * c;
 }
 
+/**
+ * recordRoute handler. Gets a stream of points, and responds with statistics
+ * about the "trip": number of points, number of known features visited, total
+ * distance traveled, and total time spent.
+ * @param {Readable} call The request point stream.
+ * @param {function(Error, routeSummary)} callback The callback to pass the
+ *     response to
+ */
 function recordRoute(call, callback) {
   var point_count = 0;
   var feature_count = 0;
   var distance = 0;
   var previous = null;
+  // Start a timer
   var start_time = process.hrtime();
   call.on('data', function(point) {
     point_count += 1;
-    if (checkFeature(point) !== '') {
+    if (checkFeature(point).name !== '') {
       feature_count += 1;
     }
+    /* For each point after the first, add the incremental distance from the
+     * previous point to the total distance value */
     if (previous != null) {
       distance += getDistance(previous, point);
     }
@@ -137,7 +189,9 @@ function recordRoute(call, callback) {
     callback(null, {
       point_count: point_count,
       feature_count: feature_count,
+      // Cast the distance to an integer
       distance: distance|0,
+      // End the timer
       elapsed_time: process.hrtime(start_time)[0]
     });
   });
@@ -145,13 +199,25 @@ function recordRoute(call, callback) {
 
 var route_notes = {};
 
+/**
+ * Turn the point into a dictionary key.
+ * @param {point} point The point to use
+ * @return {string} The key for an object
+ */
 function pointKey(point) {
   return point.latitude + ' ' + point.longitude;
 }
 
-function routeChat(call, callback) {
+/**
+ * routeChat handler. Receives a stream of message/location pairs, and responds
+ * with a stream of all previous messages at each of those locations.
+ * @param {Duplex} call The stream for incoming and outgoing messages
+ */
+function routeChat(call) {
   call.on('data', function(note) {
     var key = pointKey(note.location);
+    /* For each note sent, respond with all previous notes that correspond to
+     * the same point */
     if (route_notes.hasOwnProperty(key)) {
       _.each(route_notes[key], function(note) {
         call.write(note);
@@ -159,6 +225,7 @@ function routeChat(call, callback) {
     } else {
       route_notes[key] = [];
     }
+    // Then add the new note to the list
     route_notes[key].push(note);
   });
   call.on('end', function() {
@@ -166,6 +233,11 @@ function routeChat(call, callback) {
   });
 }
 
+/**
+ * Get a new server with the handler functions in this file bound to the methods
+ * it serves.
+ * @return {Server} The new server object
+ */
 function getServer() {
   return new Server({
     'examples.RouteGuide' : {
@@ -178,6 +250,7 @@ function getServer() {
 }
 
 if (require.main === module) {
+  // If this is run as a script, start a server on an unused port
   var routeServer = getServer();
   routeServer.bind('0.0.0.0:0');
   routeServer.listen();