diff --git a/ajax_comments.module b/ajax_comments.module
index 5de3605..c8bbf5a 100644
--- a/ajax_comments.module
+++ b/ajax_comments.module
@@ -4,6 +4,9 @@
  * @file
  * AJAX comments module file.
  */
+define('AJAX_COMMENTS_COMMENT_CREATED', 1);
+define('AJAX_COMMENTS_COMMENT_UPDATED', 2);
+define('AJAX_COMMENTS_COMMENT_DELETED', 3);
 
 /**
  * Implements hook_init().
@@ -207,25 +210,105 @@ function ajax_comments_edit_cancel($node, $comment) {
 }
 
 /**
+ * Derived from comment_get_thread(), removed pager support
+ * (when updating comments via AJAX, we don't care)
+ * and added the ability to only get comments for a certain
+ * thread when comments are threaded.
+ */
+function ajax_comments_get_thread($comment, $mode) {
+  $query = db_select('comment', 'c');
+  $query->addField('c', 'cid');
+  $query->condition('c.nid', $comment->nid);
+
+  if (!user_access('administer comments')) {
+    $query->condition('c.status', COMMENT_PUBLISHED);
+  }
+  if ($mode === COMMENT_MODE_FLAT) {
+    $query->orderBy('c.cid', 'ASC');
+  }
+  else {
+    // See comment above. Analysis reveals that this doesn't cost too
+    // much. It scales much much better than having the whole comment
+    // structure.
+    $query->addExpression('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'torder');
+    $query->orderBy('torder', 'ASC');
+
+    // only get comments for this comment's thread
+    if (isset($comment->thread)) {
+      $query->condition('c.thread', db_like(substr($comment->thread, 0, -1)) . '%', 'LIKE');
+    }
+  }
+
+  $cids = $query->execute()->fetchCol();
+
+  return $cids;
+}
+
+/**
  * Builds the comment.
  */
+function ajax_comments_create_ajax_response($action, $node, $comment) {
+  $commands = array();
+
+  switch ($action) {
+    case AJAX_COMMENTS_COMMENT_CREATED:
+      $notify_text = variable_get('ajax_comments_notify', '') ? theme('ajax_comments_notify_text') : '';
+      $comment_build = comment_view($comment, $node);
+      // Brand new comment
+      if (!$comment->pid) {
+        // Append comment to root comment wrapper
+        $comment_output = drupal_render($comment_build);
+        $commands[] = ajax_command_append('#comment-wrapper', $notify_text . $comment_output);
+      }
+      // Replying to comment
+      else {
+        // Append comment to parent wrapper
+        $comment_output = drupal_render($comment_build);
+        $commands[] = ajax_command_append('#comment-wrapper-' . $comment->pid, $notify_text . $comment_output);
+      }
+      break;
+
+    case AJAX_COMMENTS_COMMENT_UPDATED:
+      $notify_text = variable_get('ajax_comments_notify', '') ? theme('ajax_comments_notify_text') : '';
+      $mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED);
+      if ($cids = ajax_comments_get_thread($comment, $mode)) {
+        $comments = comment_load_multiple($cids);
+        comment_prepare_thread($comments);
+        $comment_build = comment_view_multiple($comments, $node);
+        $comment_output = drupal_render($comment_build);
+        $commands[] = ajax_command_replace('#comment-wrapper-' . $comment->cid, $notify_text . $comment_output);
+      }
+      break;
+
+    case AJAX_COMMENTS_COMMENT_DELETED:
+      $notify_text = variable_get('ajax_comments_notify', '') ? theme('ajax_comments_notify_text', array('type' => 'delete')) : '';
+      if ($notify_text) {
+        $commands[] = ajax_command_replace('#comment-wrapper-' . $comment->cid, $notify_text);
+      }
+      else {
+        $commands[] = ajax_command_remove('#comment-wrapper-' . $comment->cid);
+      }
+      break;
+  }
+
+  return $commands;
+}
+
 function ajax_comments_submit_js($form, &$form_state) {
   // Return the actual form if it contains errors.
   if (form_get_errors()) {
     return $form;
   }
 
+  $comment = $form_state['comment'];
+  $node = $form['#node'];
+
   // This is to remove the "Your comment has been posted" status message that
   // will appear upon refresh. This seems dirty but it means we don't have to
   // rewrite the whole comment_form_submit(). Please chime in if you think this
   // is dumb.
   ajax_comments_remove_status($_SESSION);
 
-  $comment = $form_state['comment'];
-  $node = $form['#node'];
-  $notify_text = variable_get('ajax_comments_notify', '') ? theme('ajax_comments_notify_text') : '';
-
-  $comment_build = comment_view($comment, $node);
 
   if (variable_get('comment_preview_' . $node->type)) {
     $commands[] = ajax_command_remove('.comment-preview');
@@ -235,45 +318,33 @@ function ajax_comments_submit_js($form, &$form_state) {
   // Don't display as a preview as this is being submitted.
   unset($comment_build['comment_body']['#object']->in_preview);
 
-  // Are we editing a comment.
-  if (isset($form['cid']['#value'])) {
-    // Remove wrapper because the form we replace exists inside the wrapper.
-    unset($comment_build['#prefix']);
-    unset($comment_build['#suffix']);
+  // Figure out what action we're performing
+  $action = isset($form['cid']['#value']) ? AJAX_COMMENTS_COMMENT_UPDATED : AJAX_COMMENTS_COMMENT_CREATED;
 
-    // Trim surrounding whitespace so ajax.js doesn't wrap us in a new div.
-    $comment_output = trim(drupal_render($comment_build));
-    $commands[] = ajax_command_replace('#' . $form['#id'], $comment_output);
-  }
-  // Or are we replying to another comment.
-  elseif (isset($form_state['values']['pid'])) {
-    // Append comment to parent wrapper.
-    $comment_output = drupal_render($comment_build);
-    $commands[] = ajax_command_append('#comment-wrapper-' . $comment->pid, $notify_text . $comment_output);
+  // Generate AJAX commands to actually update the comment content
+  $commands = ajax_comments_create_ajax_response($action, $node, $comment);
 
-    // Delete the form.
-    $commands[] = ajax_command_invoke('#' . $form['#id'], 'remove');
-  }
-  // Or is this a brand new comment?
-  else {
-    // Append comment to root comment wrapper.
-    $comment_output = drupal_render($comment_build);
-    $commands[] = ajax_command_append('#comment-wrapper-nid-' . $node->nid, $notify_text . $comment_output);
-
-    // If we have a default form, update it with a new one.
-    if (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW) {
-      $node = $form['#node'];
-
-      $new_form_state = array();
-      $new_form_state['build_info']['args'][] = (object) array('nid' => $node->nid);
-      // Don't pull from cache.
-      $new_form_state['input'] = array();
-      $new_form_build = drupal_build_form($form['#form_id'], $new_form_state);
-      $new_form_output = drupal_render($new_form_build);
-
-      $commands[] = ajax_command_replace('#' . $form['#id'], $new_form_output);
+  // Now, remove/replace comment forms
+  if ($action == AJAX_COMMENTS_COMMENT_CREATED) {
+    if (!$comment->pid) {
+      // If we have a default form, update it with a new one
+      if (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW) {
+        $node = $form['#node'];
+
+        $new_form_state = array();
+        $new_form_state['build_info']['args'][] = (object) array('nid' => $node->nid);
+        $new_form_state['input'] = array(); // don't pull from cache
+        $new_form_build = drupal_build_form($form['#form_id'], $new_form_state);
+        $new_form_output = drupal_render($new_form_build);
+
+        $commands[] = ajax_command_replace('#' . $form['#id'], $new_form_output);
+      }
+      // Otherwise, delete it
+      else {
+        $commands[] = ajax_command_remove('#' . $form['#id']);
+      }
     }
-    // Otherwise, delete it.
+    // Reply to a comment
     else {
       $commands[] = ajax_command_remove('#' . $form['#id']);
     }
@@ -290,14 +361,7 @@ function ajax_comments_delete_js($form, &$form_state) {
 
   ajax_comments_remove_status($_SESSION);
 
-  $notify_text = variable_get('ajax_comments_notify', '') ? theme('ajax_comments_notify_text', array('type' => 'delete')) : '';
-
-  if ($notify_text) {
-    $commands[] = ajax_command_replace('#comment-wrapper-' . $comment->cid, $notify_text);
-  }
-  else {
-    $commands[] = ajax_command_remove('#comment-wrapper-' . $comment->cid);
-  }
+  $commands = ajax_comments_create_ajax_response(AJAX_COMMENTS_COMMENT_DELETED, NULL, $comment);
 
   return array('#type' => 'ajax', '#commands' => $commands);
 }
diff --git a/ajax_comments_nodejs/ajax_comments_nodejs.info b/ajax_comments_nodejs/ajax_comments_nodejs.info
old mode 100644
new mode 100755
index 092284a..a1169e4
--- a/ajax_comments_nodejs/ajax_comments_nodejs.info
+++ b/ajax_comments_nodejs/ajax_comments_nodejs.info
@@ -3,4 +3,4 @@ description = Integrates Nodejs with Ajax Comments
 core = 7.x
 dependencies[] = comment
 dependencies[] = nodejs
-
+dependencies[] = ajax_comments
diff --git a/ajax_comments_nodejs/ajax_comments_nodejs.module b/ajax_comments_nodejs/ajax_comments_nodejs.module
old mode 100644
new mode 100755
index 7f83b7b..529a791
--- a/ajax_comments_nodejs/ajax_comments_nodejs.module
+++ b/ajax_comments_nodejs/ajax_comments_nodejs.module
@@ -1,6 +1,109 @@
 <?php
 
 /**
- * @file
- *  Right now this is a stub. Please use this to commit patches.
+ * Implementation of hook_menu()
  */
+function ajax_comments_nodejs_menu() {
+  $items['ajax_comments_nodejs/%/%'] = array(
+    'page callback' => 'ajax_comments_nodejs_view_comment',
+    'page arguments' => array(1, 2),
+    'access arguments' => array('access comments'),
+    'delivery callback' => 'ajax_deliver',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_nodejs_handlers_info().
+ */
+function ajax_comments_nodejs_nodejs_handlers_info() {
+  return array(
+    drupal_get_path('module', 'ajax_comments_nodejs') . '/ajax_comments_nodejs.js',
+  );
+}
+
+/**
+ * Implements hook_page_alter().
+ */
+function ajax_comments_nodejs_page_alter(&$page) {
+  $node = menu_get_object();
+
+  if ($node && ($node->type == 'article' || $node->type == 'forum')) {
+    nodejs_send_content_channel_token('ajax_comments_' . $node->nid);
+  }
+}
+
+/**
+ * Implements hook_comment_insert().
+ */
+function ajax_comments_nodejs_comment_insert($comment) {
+  $message = (object) array(
+    'channel' => 'ajax_comments_' . $comment->nid,
+    'broadcast' => FALSE,
+    'cid' => $comment->cid,
+    'callback' => 'ajaxCommentsInsert',
+  );
+
+  nodejs_send_content_channel_message($message);
+}
+
+/**
+ * Implements hook_comment_update().
+ */
+function ajax_comments_nodejs_comment_update($comment) {;
+  $message = (object) array(
+    'channel' => 'ajax_comments_' . $comment->nid,
+    'broadcast' => FALSE,
+    'cid' => $comment->cid,
+    'callback' => 'ajaxCommentsUpdate',
+  );
+
+  nodejs_send_content_channel_message($message);
+}
+
+/**
+ * Implements hook_comment_delete().
+ */
+function ajax_comments_nodejs_comment_delete($comment) {
+  if (!($node = node_load($comment->nid))) {
+    return MENU_NOT_FOUND;
+  }
+
+  $commands = ajax_comments_create_ajax_response(AJAX_COMMENTS_COMMENT_DELETED, $node, $comment);
+
+  $message = (object) array(
+    'channel' => 'ajax_comments_' . $comment->nid,
+    'broadcast' => FALSE,
+    'commands' => $commands,
+    'callback' => 'ajaxCommentsDelete',
+  );
+
+  nodejs_send_content_channel_message($message);
+}
+
+/**
+ *  Callback for comment request from client.
+ */
+function ajax_comments_nodejs_view_comment($action, $cid) {
+  if (!($comment = comment_load($cid))) {
+    return MENU_NOT_FOUND;
+  }
+
+  if (!($node = node_load($comment->nid))) {
+    return MENU_NOT_FOUND;
+  }
+
+  if ($action == 'insert') {
+    $commands = ajax_comments_create_ajax_response(AJAX_COMMENTS_COMMENT_CREATED, $node, $comment);
+  }
+  else if ($action == 'update') {
+    $commands = ajax_comments_create_ajax_response(AJAX_COMMENTS_COMMENT_UPDATED, $node, $comment);
+  }
+  else {
+    return MENU_NOT_FOUND;
+  }
+
+  return array('#type' => 'ajax', '#commands' => $commands);
+}