diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 9895b1f..8574d04 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -653,7 +653,7 @@ function comment_node_view(EntityInterface $node, EntityDisplay $display, $view_
       }
     }
 
-    $node->content['links']['comment'] = array(
+    $node->links['comment'] = array(
       '#theme' => 'links__node__comment',
       '#links' => $links,
       '#attributes' => array('class' => array('links', 'inline')),
@@ -664,7 +664,7 @@ function comment_node_view(EntityInterface $node, EntityDisplay $display, $view_
     // appended to other nodes shown on the page, for example a node_reference
     // displayed in 'full' view mode within another node.
     if ($node->comment && $view_mode == 'full' && node_is_page($node) && empty($node->in_preview)) {
-      $node->content['comments'] = comment_node_page_additions($node);
+      $node->comments = comment_node_page_additions($node);
     }
   }
 }
@@ -1529,6 +1529,13 @@ function comment_preview(Comment $comment) {
 }
 
 /**
+ * Implements hook_preprocess_HOOK() for node.html.twig.
+ */
+function comment_preprocess_node(&$variables) {
+  $variables['comments'] = $variables['node']->comments;
+}
+
+/**
  * Implements hook_preprocess_HOOK() for block.html.twig.
  */
 function comment_preprocess_block(&$variables) {
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
index 18c879f..66f0798 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
@@ -132,9 +132,9 @@ function testMultilingualDisplaySettings() {
 
     // Check if node body is showed.
     $this->drupalGet("node/$node->nid");
-    $body = $this->xpath('//article[@id=:id]//div[@class=:class]/descendant::p', array(
-      ':id' => 'node-' . $node->nid,
-      ':class' => 'content',
+    $body = $this->xpath('//article[@class=:node-class]//div[@class=:content-class]/descendant::p', array(
+      ':node-class' => 'node-.' . $node->nid,
+      ':content-class' => 'content',
     ));
     $this->assertEqual(current($body), $node->body['en'][0]['value'], 'Node body found.');
   }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index d41d960..d1d33e3 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1112,6 +1112,7 @@ function template_preprocess_node(&$variables) {
   $variables['teaser'] = $variables['view_mode'] == 'teaser';
   $variables['node'] = $variables['elements']['#node'];
   $node = $variables['node'];
+  $variables['nid'] = $node->nid;
 
   $variables['date'] = format_date($node->created);
   // @todo Change 'name' to 'author' and also convert to a render array pending
@@ -1122,7 +1123,8 @@ function template_preprocess_node(&$variables) {
   ));
 
   $uri = $node->uri();
-  $variables['node_url']  = url($uri['path'], $uri['options']);
+  $variables['url']  = url($uri['path'], $uri['options']);
+  // @todo $variables['title']['label'] after http://drupal.org/node/2004966.
   $variables['label'] = check_plain($node->label());
   $variables['page'] = $variables['view_mode'] == 'full' && node_is_page($node);
 
@@ -1138,21 +1140,27 @@ function template_preprocess_node(&$variables) {
   // Display post information only on certain node types.
   if (variable_get('node_submitted_' . $node->type, TRUE)) {
     $variables['display_submitted'] = TRUE;
+    // @todo remove submitted once http://drupal.org/node/1927584 is resolved.
     $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));
     if (theme_get_setting('features.node_user_picture')) {
       // To change user picture settings (e.g. image style), edit the 'compact'
       // view mode on the User entity. Note that the 'compact' view mode might
       // not be configured, so remember to always check the theme setting first.
-      $variables['user_picture'] = user_view($node->account, 'compact');
+      $variables['author'] = user_view($node->account, 'compact');
     }
     else {
-      $variables['user_picture'] = array();
+      $variables['author'] = array();
     }
   }
   else {
     $variables['display_submitted'] = FALSE;
+    // @todo remove submitted once http://drupal.org/node/1927584 is resolved.
     $variables['submitted'] = '';
-    $variables['user_picture'] = '';
+    $variables['author'] = '';
+  }
+
+  if (!empty($node->links)) {
+    $variables['links'] = $node->links;
   }
 
   // Add article ARIA role.
@@ -1181,6 +1189,7 @@ function template_preprocess_node(&$variables) {
   $variables['theme_hook_suggestions'][] = 'node__' . $node->type;
   $variables['theme_hook_suggestions'][] = 'node__' . $node->nid;
 
+  // @todo these should be attributes on content instead.
   $variables['content_attributes']['class'][] = 'content';
 }
 
diff --git a/core/modules/node/templates/node.html.twig b/core/modules/node/templates/node.html.twig
index d28b880..7268fbe 100644
--- a/core/modules/node/templates/node.html.twig
+++ b/core/modules/node/templates/node.html.twig
@@ -6,6 +6,7 @@
  * Available variables:
  * - node: Full node entity.
  *   - type: The type of the node, for example, "page" or "article".
+ *   - nid: The node ID of the node.
  *   - uid: The user ID of the node author.
  *   - created: Formatted creation date. Preprocess functions can reformat it by
  *     calling format_date() with the desired parameters on
@@ -26,7 +27,7 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {% hide(content.field_example) %} to temporarily suppress the printing
  *   of a given element.
- * - user_picture: The node author's picture from user-picture.html.twig.
+ * - author: The node author, using the 'compact' view mode.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
@@ -75,38 +76,31 @@
  * @see template_preprocess()
  * @see template_preprocess_node()
  *
- * @todo Remove the id attribute (or make it a class), because if that gets
- *   rendered twice on a page this is invalid CSS for example: two lists
- *   in different view modes.
- *
  * @ingroup themeable
  */
 #}
-<article id="node-{{ node.nid }}" class="{{ attributes.class }} clearfix"{{ attributes }}>
+<article {{ attributes }}>
 
   {{ title_prefix }}
   {% if not page %}
     <h2{{ title_attributes }}>
-      <a href="{{ node_url }}" rel="bookmark">{{ label }}</a>
+      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
     </h2>
   {% endif %}
   {{ title_suffix }}
 
   {% if display_submitted %}
     <footer>
-      {{ user_picture }}
-      <p class="submitted">{{ submitted }}</p>
+      {{ author }}
+      <p class="node__submitted">{{ submitted }}</p>
     </footer>
   {% endif %}
 
   <div{{ content_attributes }}>
-    {# We hide the comments and links now so that we can render them later. #}
-    {% hide(content.comments) %}
-    {% hide(content.links) %}
     {{ content }}
   </div>
 
-  {{ content.links }}
-  {{ content.comments }}
+  {{ links }}
+  {{ comments }}
 
 </article>
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index aaea6bb..3e71a43 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -499,7 +499,7 @@ function rdf_preprocess_node(&$variables) {
   // URI of the resource described within the HTML element, while the @typeof
   // attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so
   // on.)
-  $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
+  $variables['attributes']['about'] = empty($variables['url']) ? NULL: $variables['url'];
   $variables['attributes']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
 
   // Adds RDFa markup to the title of the node. Because the RDFa markup is
@@ -516,7 +516,7 @@ function rdf_preprocess_node(&$variables) {
       '#tag' => 'meta',
       '#attributes' => array(
         'content' => $variables['label'],
-        'about' => $variables['node_url'],
+        'about' => $variables['url'],
       ),
     );
     if (!empty($variables['node']->rdf_mapping['title']['predicates'])) {
@@ -563,7 +563,7 @@ function rdf_preprocess_node(&$variables) {
       $element = array(
         '#tag' => 'meta',
         '#attributes' => array(
-          'about' => $variables['node_url'],
+          'about' => $variables['url'],
           'property' => $variables['node']->rdf_mapping['comment_count']['predicates'],
           'content' => $variables['node']->comment_count,
           'datatype' => $variables['node']->rdf_mapping['comment_count']['datatype'],
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index 68a4a93..843602e 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -6,6 +6,7 @@
  * Available variables:
  * - node: Full node entity.
  *   - type: The type of the node, for example, "page" or "article".
+ *   - nid: The node ID of the node.
  *   - uid: The user ID of the node author.
  *   - created: Formatted creation date. Preprocess functions can reformat it by
  *     calling format_date() with the desired parameters on
@@ -26,12 +27,12 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {% hide(content.field_example) %} to temporarily suppress the printing
  *   of a given element.
- * - user_picture: The node author's picture from user-picture.html.twig.
+ * - author: The node author, using the 'compact' view mode.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
  * - name: Themed username of node author output from theme_username().
- * - node_url: Direct URL of the current node.
+ * - url: Direct URL of the current node.
  * - display_submitted: Whether submission information should be displayed.
  * - submitted: Submission information created from name and date during
  *   template_preprocess_node().
@@ -78,38 +79,35 @@
  * @ingroup themeable
  */
 #}
-<article id="node-{{ node.nid }}" class="{{ attributes.class}} clearfix"{{ attributes }} role="article">
+<article class="node__{{ nid }} {{ attributes.class}} clearfix"{{ attributes }} role="article">
 
   <header>
     {{ title_prefix }}
     {% if not page %}
       <h2{{ title_attributes }}>
-        <a href="{{ node_url }}">{{ label }}</a>
+        <a href="{{ url }}">{{ label }}</a>
       </h2>
     {% endif %}
     {{ title_suffix }}
 
     {% if display_submitted %}
       <div class="meta submitted">
-        {{ user_picture }}
+        {{ author }}
         {{ submitted }}
       </div>
     {% endif %}
   </header>
 
   <div class="content clearfix"{{ content_attributes }}>
-    {# We hide the comments and links now so that we can render them later. #}
-    {% hide(content.comments) %}
-    {% hide(content.links) %}
     {{ content }}
   </div>
 
   {% if content.links %}
     <footer class="link-wrapper">
-      {{ content.links }}
+      {{ links }}
     </footer>
   {% endif %}
 
-  {{ content.comments }}
+  {{ comments }}
 
 </article>
