diff --git a/examples.module b/examples.module
index 8f732da..3dd05da 100644
--- a/examples.module
+++ b/examples.module
@@ -55,6 +55,7 @@ function examples_toolbar() {
     'pager_example' => 'pager_example.page',
     'phpunit_example' => 'phpunit_example_description',
     'plugin_type_example' => 'plugin_type_example.description',
+    'render_example' => 'render_example.description',
     'simpletest_example' => 'simpletest_example_description',
     'stream_wrapper_example' => 'stream_wrapper_example.description',
     'testing_example' => 'testing_example.description',
diff --git a/render_example/css/render_example.css b/render_example/css/render_example.css
new file mode 100644
index 0000000..3f79120
--- /dev/null
+++ b/render_example/css/render_example.css
@@ -0,0 +1,15 @@
+.render_example--array {
+  border-bottom: 2px solid #000;
+  margin-top: 10px;
+  padding-left: 5px;
+  padding-top: 5px;
+}
+
+.render_example--code {
+  background: #f1f1f1;
+  border: 1px solid #000;
+  display: block;
+  max-height: 300px;
+  overflow: scroll;
+  padding: 10px;
+}
diff --git a/render_example/render_example.info.yml b/render_example/render_example.info.yml
new file mode 100644
index 0000000..79238fa
--- /dev/null
+++ b/render_example/render_example.info.yml
@@ -0,0 +1,7 @@
+name: Render example
+type: module
+description: Provides examples demonstrating Drupal's Render API.
+package: Example modules
+core: 8.x
+dependencies:
+  - examples:examples
diff --git a/render_example/render_example.libraries.yml b/render_example/render_example.libraries.yml
new file mode 100644
index 0000000..d45506d
--- /dev/null
+++ b/render_example/render_example.libraries.yml
@@ -0,0 +1,9 @@
+# Define a new asset library which includes the CSS used to style the page
+# at examples/render_example/arrays. See how asset libraries are attached to
+# render arrays by reading the example code in
+# Drupal\render_example\Controller\RenderExampleController::arrays().
+render-example-css:
+  version: 1.x
+  css:
+    theme:
+      css/render_example.css: {}
diff --git a/render_example/render_example.module b/render_example/render_example.module
new file mode 100644
index 0000000..8b0f692
--- /dev/null
+++ b/render_example/render_example.module
@@ -0,0 +1,234 @@
+<?php
+
+/**
+ * @file
+ * Demonstrates using Drupal's Render API.
+ */
+
+/**
+ * @defgroup render_example Example: Render API
+ * @ingroup examples
+ * @{
+ * The  @link https://www.drupal.org/docs/8/api/render-api Render API @endlink
+ * consists of two parts: one, structured arrays that provide data, and hints
+ * about how that data should be rendered, and two, a rendering pipeline that
+ * can be used to render these arrays into various output formats. This example
+ * module looks at how to define content using render arrays, as well as how to
+ * use alter hooks to manipulate render arrays created by other modules.
+ *
+ * For more on the rendering pipeline see @link
+ * https://www.drupal.org/docs/8/api/render-api/the-drupal-8-render-pipeline The
+ * Drupal 8 Render Pipeline @endlink.
+ *
+ * In order to ensure that a theme can completely customize the markup output
+ * by Drupal, module developers should avoid directly writing HTML markup for
+ * pages, blocks, and other user-visible output in their modules, and should
+ * instead return structured "render arrays". Checkout the example code in
+ * \Drupal\render_example\Controller\RenderExampleController::arrays() for an
+ * explanation of how to define new renderable arrays. The output from that
+ * code can be viewed at examples/render_example/arrays.
+ *
+ * One of the primary benefits of using arrays to define content instead of
+ * strings of HTML is that arrays are easier to manipulate. There are dozens of
+ * hooks, and other ways to gain access to and manipulate existing render arrays
+ * during the rendering process both from within a module, and via a theme. As
+ * a rule of thumb the process of rendering an array into HTML is delayed for as
+ * long as possible. In most cases it's not until the variable containing the
+ * content to be rendered is printed out in a Twig template file that it is
+ * finally rendered.
+ *
+ * For examples of altering render arrays checkout the code in
+ * render_example_preprocess_page() and render_example_preprocess_block(). There
+ * is a form at examples/render_example/altering that can be used to turn these
+ * features on and off if you would like to see the results of the array
+ * altering code on your site.
+ *
+ * This module contains code that can display the render array used to build
+ * each page, and/or block, as you navigate through a site as a way to show some
+ * examples of real render arrays being used. This functionality requires that
+ * the @link https://www.drupal.org/project/devel Devel module @endlink be
+ * installed in order to work.
+ *
+ * Modules can also provide new render element types. A powerful way to
+ * encapsulate complex display logic into a reusable widget. This can help to
+ * cut down on code repetition, and allow other module developers to build off
+ * of your work. See an example of a new render element definition by looking at
+ * \Drupal\render_example\Element\Marquee.
+ *
+ * Forms are generated using a superset of the Render API. You can see examples
+ * of how the Render API is used when creating forms in the fapi_example module.
+ *
+ * @see theme_render
+ * @see \Drupal\Core\Render\RendererInterface::render()
+ * @see \Drupal\Core\Template\TwigExtension::renderVar()
+ */
+
+use Drupal\Core\Render\Element;
+
+/**
+ * Implements hook_theme().
+ */
+function render_example_theme() {
+  return [
+    // These theme hooks are both used by examples in
+    // \Drupal\render_example\Controller\RenderExampleController::arrays().
+    'render_example_add_div' => ['render element' => 'element'],
+    'render_array' => ['render element' => 'element'],
+    // This is used in combination with \Drupal\render_example\Element\Marquee
+    // to define a new custom render element type that allows for the use of
+    // '#type' => 'marquee' elements in a render array.
+    'render_example_marquee' => [
+      'variables' => [
+        'content' => '',
+        'attributes' => array(),
+      ],
+    ],
+  ];
+}
+
+/**
+ * Example '#post_render' callback function.
+ *
+ * Post render callbacks are triggered after an element has been rendered to
+ * HTML and can act upon the final rendered string.
+ *
+ * This function is made use of by one of the examples in
+ * Drupal\render_example\Controller\RenderExampleController::arrays().
+ *
+ * @param string $markup
+ *   The rendered element.
+ * @param array $element
+ *   The element which was rendered (for reference)
+ *
+ * @return string
+ *   Markup altered as necessary. In this case we add a little postscript to it.
+ *
+ * @see \Drupal\render_example\Controller\RenderExampleController::arrays()
+ */
+function render_example_add_prefix($markup, $element) {
+  $markup = $markup . '<div style="color:blue">This markup was added after rendering by a #post_render callback.</div>';
+  return $markup;
+}
+
+/**
+ * Example '#pre_render' function.
+ *
+ * Pre render callbacks are triggered prior to rendering an element to HTML and
+ * are given the chance to manipulate the renderable array. Any changes they
+ * make will be reflected in the final rendered HTML.
+ *
+ * This function is made use of by one of the examples in
+ * Drupal\render_example\Controller\RenderExampleController::arrays().
+ *
+ * @param array $element
+ *   The element which will be rendered.
+ *
+ * @return array
+ *   The altered element. In this case we add a #prefix to it.
+ *
+ * @see \Drupal\render_example\Controller\RenderExampleController::arrays()
+ */
+function render_example_add_suffix($element) {
+  $element['#suffix'] = '<div style="color:red">' . t('This #suffix was added by a #pre_render callback.') . '</div>';
+  return $element;
+}
+
+/**
+ * Implements hook_preprocess_page().
+ *
+ * Demonstrates using a preprocess function to alter the renderable array that
+ * represents the page currently being viewed.
+ */
+function render_example_preprocess_page(&$variables) {
+  $config = \Drupal::config('render_example.settings');
+
+  // Preprocess hooks are invoked by the theme layer, and are used to give
+  // modules a chance to manipulate the variables that are going to be made
+  // available to a specific template file. Since content is still defined as
+  // renderable arrays at this point you can do quite a bit to manipulate the
+  // eventual output by altering these arrays.
+  //
+  // The $page variable in this case contains the complete content of the page
+  // including all regions, and the blocks placed within each region.
+  //
+  // The actual process of converting a renderable array to HTML is started when
+  // this variable is printed out within a Twig template. Drupal's Twig
+  // extension provides a wrapper around the Twig code that prints out variables
+  // which checks to see if the variable being printed is a renderable array and
+  // passes it through \Drupal\Core\Render\RendererInterface::render() before
+  // printing it to the screen.
+  $page = &$variables['page'];
+
+  if (\Drupal::routeMatch()->getRouteName() == 'render_example.altering') {
+
+  }
+
+  // Move the breadcrumbs into the content area.
+  if ($config->get('render_example.move_breadcrumbs') && !empty($page['breadcrumb']) && !empty($page['content'])) {
+    $page['content']['breadcrumb'] = $page['breadcrumb'];
+    unset($page['breadcrumb']);
+    $page['content']['breadcrumb']['#weight'] = -99999;
+
+    // Force the content to be re-sorted.
+    $page['content']['#sorted'] = FALSE;
+  }
+
+  // Re-sort the contents of the sidebar in reverse order.
+  if ($config->get('render_example.reverse_sidebar') && !empty($page['sidebar_first'])) {
+    $page['sidebar_first'] = array_reverse($page['sidebar_first']);
+    foreach (Element::children($page['sidebar_first']) as $element) {
+      // Reverse the weights if they exist.
+      if (!empty($page['sidebar_first'][$element]['#weight'])) {
+        $page['sidebar_first'][$element]['#weight'] *= -1;
+      }
+    }
+    // This forces the sidebar to be re-sorted.
+    $page['sidebar_first']['#sorted'] = FALSE;
+  }
+
+  // Show the render array used to build the current page.
+  // This relies on the Devel module's variable dumper service.
+  // https://wwww.drupal.org/project/devel
+  if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('render_example.show_page')) {
+    $page['content']['page_render_array'] = array(
+      '#type' => 'markup',
+      '#prefix' => '<h2>' . t('The page render array') . '</h2>',
+      // The devel.dumper service is provided by the devel module and makes for
+      // and easier to read var_dump(). Especially if the companion Kint module
+      // is enabled.
+      'dump' => \Drupal::service('devel.dumper')->exportAsRenderable($page, '$page'),
+      '#weight' => -99999,
+    );
+
+    $page['content']['#sorted'] = FALSE;
+  }
+}
+
+/**
+ * Implements hook_preprocess_block().
+ */
+function render_example_preprocess_block(&$variables){
+  $config = \Drupal::config('render_example.settings');
+
+  // This example shows how you can manipulate an existing renderable array. In
+  // this case by adding #prefix and #suffix properties to the block in order to
+  // wrap a <div> around it.
+  if ($config->get('render_example.prefix')) {
+    $variables['content']['#prefix'] = '<div class="block-prefix"><p>' . t('Prefixed') . '</p>';
+    $variables['content']['#suffix'] = '<span class="block-suffix">' . t('Block suffix') . '</span></div>';
+  }
+
+  // Show the render array used to build each block if the Devel module is
+  // installed and the feature is enabled.
+  if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('render_example.show_block')) {
+    $variables['content']['block_render_array'] = array(
+      '#type' => 'markup',
+      '#prefix' => '<h2>' . t('The block render array for @block_id.', array('@block_id' => $variables['plugin_id'])) . '</h2>',
+      'dump' => \Drupal::service('devel.dumper')->exportAsRenderable($variables, $variables['plugin_id']),
+    );
+  }
+}
+
+/**
+ * @} End of "defgroup render_example".
+ */
diff --git a/render_example/render_example.routing.yml b/render_example/render_example.routing.yml
new file mode 100644
index 0000000..fff4a60
--- /dev/null
+++ b/render_example/render_example.routing.yml
@@ -0,0 +1,21 @@
+render_example.description:
+  path: 'examples/render_example'
+  defaults:
+    _controller: '\Drupal\render_example\Controller\RenderExampleController::description'
+  requirements:
+    _access: 'access content'
+
+render_example.altering:
+  path: 'examples/render_example/altering'
+  defaults:
+    _form: '\Drupal\render_example\Form\RenderExampleDemoForm'
+    _title: 'Alter pages and blocks'
+  requirements:
+    _access: 'access content'
+
+render_example.arrays:
+  path: 'examples/render_example/arrays'
+  defaults:
+    _controller: '\Drupal\render_example\Controller\RenderExampleController::arrays'
+  requirements:
+    _access: 'access content'
diff --git a/render_example/src/Controller/RenderExampleController.php b/render_example/src/Controller/RenderExampleController.php
new file mode 100644
index 0000000..c2e4652
--- /dev/null
+++ b/render_example/src/Controller/RenderExampleController.php
@@ -0,0 +1,474 @@
+<?php
+
+namespace Drupal\render_example\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\examples\Utility\DescriptionTemplateTrait;
+use Drupal\Core\Link;
+use Drupal\Core\Render\Element;
+use Drupal\Core\Url;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Component\Utility\Variable;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Provides module description page and examples of building render arrays.
+ *
+ * Controllers that respond to a route should always return their content as
+ * a renderable array. See the arrays() method below as an example.
+ *
+ * @ingroup render_example
+ */
+class RenderExampleController extends ControllerBase {
+  use DescriptionTemplateTrait;
+
+
+  /**
+   * Current user.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $currentUser;
+
+  /**
+   * Constructs a new BlockController instance.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   */
+  public function __construct(AccountInterface $current_user) {
+    $this->currentUser = $current_user;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('current_user')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getModuleName() {
+    return 'render_example';
+  }
+
+  /**
+   * Examples of defining content using renderable arrays.
+   *
+   * Methods on a controller that are the target of a route should return a
+   * renderable array which contains any content to display for that route.
+   */
+  public function arrays() {
+    // The core structure of the Render API is the render array, which is a
+    // hierarchical associative array containing data to be rendered and
+    // properties describing how the data should be rendered. Whenever a module
+    // needs to output content it should do so be defining that content as a
+    // renderable array. Below we'll look at some common examples of how render
+    // arrays can be used to define content.
+    $build = array();
+
+    // Renderable arrays have two kinds of key/value pairs: properties and
+    // children. Properties have keys starting with '#' and their values
+    // influence how the array will be translated to a string. Children are all
+    // elements whose keys do not start with a '#'. Their values should be
+    // renderable arrays themselves.
+    //
+    // This example defines a new element, 'simple', that contains two
+    // properties; '#markup' and '#description'. This is the quickest way to
+    // output a string of HTML.
+    $build['simple'] = [
+      '#markup' => '<p>' . $this->t('This page contains examples of various content elements described using render arrays. Read the code and comments in \Drupal\render_example\Controller\RenderExampleController::arrays() for more information.') . '</p>',
+      '#description' => $this->t('Example of using #markup'),
+    ];
+
+    // Additional properties can be used to further define the content. In this
+    // case '#prefix' and '#suffix' are being used to provide strings to add
+    // before, and after, the main content. This is useful because now the tag
+    // being used to wrap the block of content can be easily changed without
+    // having to worry about the content. Or, the tag can easily be left out
+    // during rendering if for example the content is being output as JSON.
+    //
+    // There is a set of common properties that can be used for all elements in
+    // a render array. These are defined by
+    // \Drupal\Core\Render\Element\RenderElement. Most elements also have
+    // additional element type specific properties.
+    //
+    // Figuring out what additional properties are available requires first
+    // determining what sort of render element you're dealing with. Look for the
+    // presence of one of these properties to start:
+    // - #markup, or #plain_text: These are the simplest render arrays, and are
+    //   used to display simple strings of text. In addition to the common set
+    //   of properties available for all elements #markup elements can use the
+    //   #allowed_tags property, an array of additional tags to allow when the
+    //   HTML string is run through \Drupal\Component\Utility\Xss::filterAdmin()
+    //   to strip out possible XSS vectors.
+    // - #theme: The presence of #theme indicates that the array contains data
+    //   to be themed by a particular theme hook. The available properties will
+    //   depend on the specific theme hook. See the example below for more about
+    //   determining what properties to use.
+    // - #type: The presence of #type indicates that the array contains data and
+    //   options for a particular type of "render element" (for example, 'form',
+    //   'textfield', 'submit', for HTML form element types; 'table', for a
+    //   table with rows, columns, and headers). The additional properties will
+    //   depend on the render element type, and are documented on the class that
+    //   defines the element type.
+    //
+    $build['simple_extras'] = [
+      '#description' => $this->t('Example of using #prefix and #suffix'),
+      // Note the addition of '#type' => 'markup' in this example compared to
+      // the one above. Because #markup is such a commonly used element type you
+      // can exclude the '#type' => 'markup' line and it will be assumed
+      // automatically if the '#markup' property is present.
+      '#type' => 'markup',
+      '#markup' => '<p>' . $this->t('This one adds a prefix and suffix, which put a blockqoute tag around the item.') . '</p>',
+      '#prefix' => '<blockquote>',
+      '#suffix' => '</blockquote>',
+    ];
+
+    // In addition to #markup, you can also use #plain_text to output, you
+    // guessed it, strings of plain text. This indicates that the array contains
+    // text which should be escaped before it is displayed.
+    $build['simple_text'] = [
+      '#plain_text' => '<em>This is escaped</em>',
+      '#description' => $this->t('Example of using #plain_text'),
+    ];
+
+    // Using the '#theme' property for an element specifies that the array
+    // contains data to be themed by a particular theme hook. Essentially using
+    // a Twig template to generate the HTML for an element. Modules define theme
+    // hooks by implementing hook_theme(), which specifies the input "variables"
+    // used to provide data and options; if a hook_theme() implementation
+    // specifies variable 'separator', then in a render array, you would provide
+    // this data using the '#separator' property.
+    //
+    // @see hook_theme()
+    $build['theme_element'] = [
+      // The '#theme' property can be set to any valid theme hook. For more
+      // information about theme hooks, and to discover available theme hooks
+      // that you can use when creating render arrays see the documentation for
+      // hook_theme().
+      //
+      // Many of the most commonly used theme hooks are defined in
+      // drupal_common_theme().
+      '#theme' => 'item_list',
+      '#title' => $this->t('Example of using #theme'),
+      // The #items property is specific to the 'item_list' theme hook, and
+      // corresponds to the variable {{ items }} in the item-list.twig.html
+      // template file.
+      '#items' => [
+        'value' => $this->t('This is some more text that we need in the list'),
+        'attributes' => ['class' => ['item_list__item']],
+      ],
+    ];
+
+    // Using the '#type' property for an element specifies that the array
+    // contains data and options for a particular type of "render element".
+    // Render element types can be thought of as prepackaged render arrays that
+    // provide default values for a set of properties as well as code that
+    // will perform additional processing on the array before it is rendered.
+    //
+    // As an example take a look at the code in
+    // \Drupal\Core\Render\Element\Table::getInfo(). Notice that it is defining
+    // values for #theme, and #process? These values will be merged with
+    // whatever properties you define in your code.
+    //
+    // In addition, most render element types have type specific properties. A
+    // table for example has #header, and #rows properties. The easiest way to
+    // determine what element type specific properties exist is to read the
+    // documentation for the class that defines the element type. Don't forget
+    // that it will also inherit properties used by any class it is extending.
+    //
+    // There are two types of render element types:
+    // - Generic elements: Generic render element types encapsulate logic for
+    //   generating HTML and attaching relevant CSS and JavaScript to the page.
+    //   These include things like link, table, and drop button elements.
+    // - Form elements: Most of the render element types provided by core
+    //   represent the various widgets you might use on a form. Text fields,
+    //   password fields, and file upload buttons for example. These elements
+    //   are intended to be used in conjunction with a form controller class
+    //   and have additional properties such as `#required`, and
+    //   `#element_validate`, related to their use as part of a form. For more
+    //   on form elements check out the fapi_example module.
+    $build['table'] = [
+      // The value used for #type is the ID of the plugin that implements the
+      // element type you want to use. This can be inferred from the annotation
+      // for the element.
+      // You can also find a list of element types provided by Drupal core here
+      // https://api.drupal.org/api/drupal/elements.
+      '#type' => 'table',
+      '#caption' => $this->t('Our favorite colors.'),
+      '#header' => [$this->t('Name'), $this->t('Favorite color')],
+      '#rows' => [
+        [$this->t('Amber'), $this->t('teal')],
+        [$this->t('Addi'), $this->t('green')],
+        [$this->t('Blake'), $this->t('#063')],
+        [$this->t('Enid'), $this->t('indigo')],
+        [$this->t('Joe'), $this->t('green')],
+      ],
+      '#description' => $this->t('Example of using #type.'),
+    ];
+
+    // Render arrays can be nested any level deep. This allows you to group
+    // like things together. A great example of this is the $page array used in
+    // conjunction with the page.html.twig template. The top level contains all
+    // the regions, each of which contain the blocks placed in that region,
+    // which in turn contain their own content. In fact, when this array is
+    // ultimately displayed on a page it will be as part of the $page array.
+    $build['nested_example'] = [
+      '#description' => $this->t('Example of nesting elements'),
+      '#markup' => '<p>' . $this->t('Render arrays can contain any number of nested elements. During rendering, the innermost elements are rendered first, and their output is incorporated into the parent element.') . '</p>',
+      'nested_child_element' => [
+        // An un-ordered list of links.
+        // See /core/modules/system/templates/item-list.html.twig.
+        '#theme' => 'item_list',
+        '#title' => $this->t('Links'),
+        '#list_type' => 'ol',
+        '#items' => [
+          Link::fromTextAndUrl($this->t('Drupal'), Url::fromUri('https://www.drupal.org')),
+          Link::fromTextAndUrl($this->t('Not Drupal'), Url::fromUri('https://wordpress.org/')),
+        ],
+      ],
+    ];
+
+    // Example of adding a link using the #link element type.
+    $build['nested_example']['another_nested_child'] = [
+      // See \Drupal\Core\Render\Element\Link.
+      '#type' => 'link',
+      '#title' => $this->t('A link to example.com'),
+      '#url' => Url::fromUri('https://example.com'),
+    ];
+
+    // The #theme_wrappers property can be used to provide an array of theme
+    // hooks which provide the envelope or "wrapper" of a set of child elements.
+    // The theme function finds its element children (the sub-arrays) already
+    // rendered in '#children'.
+    $build['theme_wrappers demonstration'] = [
+      '#description' => $this->t('Example of using #theme_wrappers'),
+      'child1' => ['#markup' => $this->t('Markup for child1')],
+      'child2' => ['#markup' => $this->t('Markup for child2')],
+      '#theme_wrappers' => [
+        'render_example_add_div',
+      ],
+    ];
+
+    // Use the #access property to control who can see what content. If an
+    // element in an render array has its #access property set to FALSE it will
+    // be removed from the array before rendering. And thus not visible.
+    $build['access_example'] = [
+      '#description' => $this->t('Example of using #access to control visibility'),
+      '#markup' => $this->t('This text is only visible to authenticated users.'),
+      '#access' => $this->currentUser->isAuthenticated(),
+    ];
+
+    // Some properties define callbacks, which are callable functions or methods
+    // that are triggered at specific points during the rendering pipeline.
+    $build['pre_render and post_render'] = [
+      '#description' => $this->t('Example of using #pre_render and #post_render'),
+      '#markup' => '<div style="color:green">' . t('markup for pre_render and post_render example') . '</div>',
+      // #pre_render callbacks are triggered early in the rendering process,
+      // they get access to the element in the array where the callback is
+      // named, and all of its children. They can be used to do things like
+      // conditionally alter the value of a property prior to the array being
+      // rendered to HTML.
+      '#pre_render' => ['render_example_add_suffix'],
+      // #post_render callbacks are triggered after the array has been rendered
+      // and can operate on the rendered HTML. They also have access to the
+      // original array for context.
+      '#post_render' => ['render_example_add_prefix'],
+    ];
+
+    // Properties that contain callbacks can also reference methods on a class
+    // in addition to functions. See
+    // \Drupal\render_example\Controller\RenderExampleController::preRender()
+    $build['#pre_render'] = [static::class . '::preRender'];
+
+    // Caching is an important part of the Render API, converting an array to a
+    // string of HTML can be an expensive process, and therefore whenever
+    // possible the Render API will cache the results of rendering an array in
+    // order to improve performance.
+    //
+    // When defining a render array you should use the #cache property to define
+    // the cachability of an element.
+    $build['cache_demonstration'] = [
+      '#description' => $this->t('#cache demonstration'),
+      // This string contains information that is specific to the user who is
+      // currently viewing the page. We can cache it, and re-use the string any
+      // time the same user views the page again. However, if the user changes,
+      // or if the user changes their name, we need to expire the cached data
+      // and rebuild it so that it is accurate.
+      '#markup' => $this->t('Hello @name, welcome to the #cache example.', ['@name' => $this->currentUser->getAccountName()]),
+      // The #cache property is used to provide metadata about the element being
+      // cached, and the conditions under which it should be expired. This can
+      // be time based, or context based. You can read more about caching
+      // render arrays here
+      // https://www.drupal.org/docs/8/api/render-api/cacheability-of-render-arrays
+      '#cache' => [
+        // The "current user" is used above, which depends on the request, so
+        // we tell Drupal to vary by the 'user' cache context.
+        'contexts' => [
+          'user',
+        ],
+      ],
+    ];
+
+    // A #lazy_builder callback can be used to build a highly dynamic section of
+    // a render array from scratch. This, combined with the use of placeholders,
+    // allows the renderer to cache some, but not all, portions of a render
+    // array. Without #lazy_builders, if any element in the render tree is
+    // uncacheable the whole tree would need to be re-rendered every time.
+    //
+    // The general rendering flow is as follows:
+    // - Check for cached version of output from previous rendering, if it
+    //   exists replace any placeholders in the rendered output with their
+    //   dynamic content as generated by the #lazy_builder callback, and return
+    //   the resulting HTML.
+    // - If no cached version exists render the array to HTML, when an element
+    //   that can be placeholdered is encountered insert a placeholder, cache
+    //   the HTML after rendering for next time, replace the placeholders with
+    //   their dynamic content, and return the resulting HTML.
+    //
+    // This is especially noticeable when used in conjunction with modules like
+    // Big Pipe which do rendering of a page in multiple passes vs. the default
+    // single flush renderer.
+    //
+    // See \Drupal\block\BlockViewBuilder::viewMultiple() for an example from
+    // core.
+    $build['lazy_builder'] = [
+      // Set the value of the #lazy_builder property to an array, the first key
+      // of the array is the method, service, or function, to call in oder to
+      // generate the dynamic data. The second argument is an array of any
+      // arguments to pass to the callback. Arguments can be only primitive
+      // types (string, bool, int, float, NULL).
+      '#lazy_builder' => [
+        static::class . '::lazyBuilder',
+        [$this->currentUser->id(), 'Y-m-d'],
+      ],
+      // #lazy_builder callbacks can be used in conjunction with
+      // #create_placeholder to tell the renderer that instead of simply calling
+      // the #lazy_builder code right away, to instead insert a placeholder and
+      // delay execution of the #lazy_builder code until it's needed.
+      //
+      // This is somewhat analogous to the way Drupal uses the PSR-4 autoloading
+      // standard to "lazy" load PHP files that contain the definition of a
+      // class only if, and when, that class is used.
+      //
+      // To force a element to use a placeholder set #create_placeholder to
+      // TRUE.
+      //
+      // Alternatively you could include #cache metadata (see above) and allow
+      // the Render API to use that metadata to automatically determine based on
+      // the existence of high-cardinality cache contexts in the subtree whether
+      // or not the element should use a placeholder.
+      '#create_placeholder' => TRUE,
+    ];
+
+    // CSS and JavaScript libraries can be attached to elements in a renderable
+    // array. This way, if the element ends up being rendered and displayed you
+    // know for sure the CSS/JavaScript will also be included. But, if the for
+    // some reason the element isn't ever rendered then Drupal can skip the
+    // unnecessary extra files.
+    //
+    // Learn more about attaching CSS and JavaScript libraries with the
+    // #attached property here:
+    // https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21theme.api.php/group/theme_render/#sec_attached
+    $build['#attached'] = [
+      'library' => [
+        'render_example/render-example-css',
+      ],
+    ];
+
+    // Example of the marquee element type defined by
+    // \Drupal\render_example\Element\Marquee.
+    $build['marquee'] = [
+      '#description' => $this->t('Example custom element type'),
+      '#type' => 'markup',
+      'marquee_element' => [
+        '#type' => 'marquee',
+        '#content' => $this->t('Hello world!'),
+      ],
+    ];
+
+    return $build;
+  }
+
+  /**
+   * A #pre_render callback, expand array to include additional example info.
+   *
+   * This method is called during the process of rendering the array generated
+   * by \Drupal\render_example\Controller\RenderExampleController::arrays().
+   *
+   * This also demonstrates how a #pre_render callback could be used to expand
+   * a relatively simple array into multiple individual renderable elements
+   * based on application logic.
+   *
+   * @param array $element
+   *   Pre render methods (and functions) get a single argument that is the
+   *   render API array representing the element where the #pre_render property
+   *   was defined, and all of it's children.
+   *
+   * @return array $element
+   *   Pre render methods (and functions) should return the modified render
+   *   array.
+   */
+  public static function preRender($element) {
+    // For each first level child element lets add some additional helpful
+    // output. \Drupal\Core\Render\Element::children() is a utility method that
+    // allows you to quickly identify all children of a render array. That is
+    // those key/value pairs whose key does not start with a '#'.
+    foreach (Element::children($element) as $key) {
+      $child = $element[$key];
+      unset($element[$key]);
+      $element[$key] = [
+        // The value from the #description property will be used as a title
+        // for this element in the final output.
+        'description' => [
+          '#markup' => $child['#description'],
+        ],
+        // Move the original element to 'rendered'. The rendering process is
+        // recursive so this will still be located, and rendered to HTML.
+        'rendered' => $child,
+        // Export the element definition as a string of text so we can display
+        // the array that was used to create the rendered output just below the
+        // output.
+        'unrendered' => [
+          '#markup' => htmlentities(Variable::export($child)),
+        ],
+        '#theme' => 'render_array',
+      ];
+    }
+
+    // Return our modified version of the original $element.
+    return $element;
+  }
+
+  /**
+   * Example #lazy_builder callback.
+   *
+   * Demonstrates the use of a #lazy_builder callback to build out a render
+   * array that can be substituted into the parent array wherever the cacheable
+   * placeholder exists.
+   *
+   * This method is called during the process of rendering the array generated
+   * by \Drupal\render_example\Controller\RenderExampleController::arrays().
+   *
+   * @param string $date_format
+   *   Date format to use with \Drupal\Core\Datetime\DateFormatter::format().
+   *
+   * @return array
+   *   A renderable array with content to replace the #lazy_builder placeholder.
+   */
+  public static function lazyBuilder($date_format) {
+    $build = [
+      'lazy_builder_time' => [
+        '#markup' => '<p>' . \Drupal::translation()->translate('The current time is @time', ['@time' => \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', $date_format)]) . '</p>',
+      ],
+    ];
+
+    return $build;
+  }
+
+}
diff --git a/render_example/src/Element/Marquee.php b/render_example/src/Element/Marquee.php
new file mode 100644
index 0000000..13f5ad0
--- /dev/null
+++ b/render_example/src/Element/Marquee.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace Drupal\render_example\Element;
+
+use Drupal\Core\Render\Element\RenderElement;
+
+/**
+ * Provides a marquee render element.
+ *
+ * New render element types are defined as plugins. They live in the
+ * Drupal\{module_name}\Element namespace and implement
+ * \Drupal\Core\Render\Element\ElementInterface. They are annotated with either
+ * \Drupal\Core\Render\Annotation\RenderElement or
+ * \Drupal\Core\Render\Annotation\FormElement. And extend either the
+ * \Drupal\Core\Render\Element\RenderElement, or
+ * \Drupal\Core\Render\Element\FormElement base classes.
+ *
+ * In the annotation below we define the string "marquee" as the ID for this
+ * plugin. That will also be the value used for the '#type' property in a render
+ * array. For example:
+ *
+ * @code
+ * $build['awesome'] = [
+ *   '#type' => 'marquee',
+ *   '#content' => 'Whoa cools, a marquee!',
+ * ];
+ * @endcode
+ *
+ * View an example of this custom element in use in
+ * \Drupal\render_example\Controller\RenderExampleController::arrays().
+ *
+ * @see plugin_api
+ * @see render_example_theme()
+ *
+ * @RenderElement("marquee")
+ */
+class Marquee extends RenderElement {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInfo() {
+    $class = get_class($this);
+
+    // Returns an array of default properties that will be merged with any
+    // properties defined in a render array when using this element type.
+    // You can use any standard render array property here, and you can also
+    // custom properties that are specific to your new element type.
+    return [
+      // See render_example_theme() where this new theme hook is declared.
+      '#theme' => 'render_example_marquee',
+      // Define a default #pre_render method. We will use this to handle
+      // additional processing for the custom attributes we add below.
+      '#pre_render' => array(
+        array($class, 'preRenderMarquee'),
+      ),
+      // This is a custom property for our element type. We set it to blank by
+      // default. The expectation is that a user will add the content that they
+      // would like to see inside the marquee tag. This custom property is
+      // accounted for in the associated template file.
+      '#content' => '',
+      '#attributes' => [
+        'direction' => 'left',
+        'loop' => -1,
+        'scrollamount' => 'random',
+      ],
+    ];
+  }
+
+  /**
+   * Pre-render callback; Process custom attribute options.
+   *
+   * @param array $element
+   *   The renderable array representing the element with '#type' => 'marquee'
+   *   property set.
+   *
+   * @return array mixed
+   *   The passed in element with changes made to attributes depending on
+   *   context.
+   */
+  public static function preRenderMarquee($element) {
+    // Normal attributes for a <marquee> tag do not include a 'random' option
+    // for scroll amount. Our marquee element type does though. So we use this
+    // #pre_render callback to check if the element was defined with the value
+    // 'random' for the scrollamount attribute, and if so replace the string
+    // with a random number.
+    if ($element['#attributes']['scrollamount'] == 'random') {
+      $element['#attributes']['scrollamount'] = abs(rand(1, 50));
+    }
+    return $element;
+  }
+
+}
diff --git a/render_example/src/Form/RenderExampleDemoForm.php b/render_example/src/Form/RenderExampleDemoForm.php
new file mode 100644
index 0000000..1460a4c
--- /dev/null
+++ b/render_example/src/Form/RenderExampleDemoForm.php
@@ -0,0 +1,286 @@
+<?php
+
+namespace Drupal\render_example\Form;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides the form for toggling module features on and off.
+ *
+ * @ingroup render_example
+ */
+class RenderExampleDemoForm extends ConfigFormBase {
+
+  /**
+   * Module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'render_example_demo_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
+    parent::__construct($config_factory);
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory'),
+      $container->get('module_handler')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('render_example.settings');
+
+    $form['description'] = [
+      '#markup' => $this->t('This example shows what render arrays look like in the building of a page. It will not work unless the user running it has the "access devel information" privilege. It shows both the actual arrays used to build a page or block, and examples of altering the page late in its lifecycle.'),
+    ];
+
+    $form['show_arrays'] = [
+      '#type' => 'fieldset',
+      '#title' => $this->t('Show render arrays'),
+      'render_example_show_block' => [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Show block render arrays'),
+        '#default_value' => $config->get('render_example.show_block'),
+        // Only enable this option if the Devel module is enabled.
+        '#access' => $this->moduleHandler->moduleExists('devel'),
+      ],
+      'render_example_show_page' => [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Show page render arrays'),
+        '#default_value' => $config->get('render_example.show_page'),
+        // Only enable this option if the Devel module is enabled.
+        '#access' => $this->moduleHandler->moduleExists('devel'),
+      ],
+      'render_example_devel' => [
+        '#markup' => $this->t('Install the Devel module (https://www.drupal.org/project/devel) to enable additional demonstration features.'),
+        // Only display this if the Devel module is not already installed.
+        '#access' => !$this->moduleHandler->moduleExists('devel'),
+      ],
+    ];
+
+    $form['page_fiddling'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Make changes on all pages via hook_preprocess_page()'),
+      '#description' => $this->t('Theses changes are all made via the function render_example_preprocess_page()'),
+      'render_example_move_breadcrumbs' => [
+        '#title' => t('Move the breadcrumbs to the top of the content area'),
+        '#description' => t('Uses hook_preprocess_page() to move the breadcrumbs into another region.'),
+        '#type' => 'checkbox',
+        '#default_value' => $config->get('render_example.move_breadcrumbs'),
+      ],
+      'render_example_reverse_sidebar' => [
+        '#title' => t('Reverse ordering of sidebar_first elements (if it exists)'),
+        '#description' => t('Uses hook_preprocess_page() to reverse the ordering of items in sidebar_first'),
+        '#type' => 'checkbox',
+        '#default_value' => $config->get('render_example.reverse_sidebar'),
+      ],
+      'render_example_prefix' => [
+        '#title' => t('Use #prefix and #suffix to wrap a div around every block'),
+        '#description' => t('Uses hook_block_view_alter() to wrap all blocks with a div using #prefix and #suffix'),
+        '#type' => 'checkbox',
+        '#default_value' => $config->get('render_example.prefix'),
+      ],
+    ];
+
+    $form['tabledrag'] = [
+      '#type' => 'table',
+      '#id' => 'draggable-table',
+      '#caption' => $this->t('Our favorite colors.'),
+      '#header' => [
+        $this->t('Name'),
+        $this->t('Favorite color'),
+        $this->t('Weight'),
+      ],
+      // #tabledrag and be used on #table elements in the context of a form.
+      // When enabled, the table will be rendered with a drag & drop interface
+      // that can be used to re-order elements within the table. Any changes you
+      // make to the order will be made available to your validation and submit
+      // handlers via values in $form_state->getValues().
+      //
+      // The #tabledrag property contains an array of options passed to the
+      // drupal_attach_tabledrag() function. These options are used to generate
+      // the necessary JavaScript settings to configure the tableDrag behavior
+      // for this table.
+      //
+      // For more in-depth documentation of the options below see
+      // drupal_attach_tabledrag().
+      '#tabledrag' => [
+        [
+          // The HTML ID of the table to make draggable. See #id above.
+          'table_id' => 'draggable-table',
+          // The action to be done on the form item. Either 'match' 'depth', or
+          // 'order'.
+          'action' => 'order',
+          // String describing where the "action" option should be performed.
+          // Either 'parent', 'sibling', 'group', or 'self'.
+          'relationship' => 'sibling',
+          // Class name applied on all related form elements for this action.
+          // See below.
+          'group' => 'table-order-weight',
+        ],
+      ],
+      // Rather than defining the values to insert into the table using the
+      // #rows property you can define each row as a sub element of the table
+      // render array. And each column in the row as a sub element of the row
+      // array.
+      [
+        // Apply the 'draggable' class to each row in the table that you want to
+        // be made draggable.
+        '#attributes' => ['class' => ['draggable']],
+        // The first two columsn are render arrays that display a string of
+        // text.
+        'name' => ['#plain_text' => $this->t('Amber')],
+        'color' => ['#plain_text' => $this->t('teal')],
+        // The third column is a #weight form field.
+        'weight' => [
+          '#type' => 'weight',
+          '#title_display' => 'invisible',
+          // Set the default value to whatever the current weight, or order, of
+          // the element that this row represents is.
+          '#default_value' => 1,
+          // Set a class on each field that represents the value to manipulate
+          // when the table is reordered. The name of this class should match
+          // the value used for the 'group' argument in the #tabledrag property
+          // above.
+          '#attributes' => ['class' => ['table-order-weight']],
+        ],
+      ],
+      // The rest of this array is additional rows so there is some data in the
+      // table to drag around.
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Addi')],
+        'color' => ['#plain_text' => $this->t('green')],
+        'weight' => [
+          '#type' => 'weight',
+          '#title_display' => 'invisible',
+          '#default_value' => 2,
+          '#attributes' => ['class' => ['table-order-weight']],
+        ],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Blake')],
+        'color' => ['#plain_text' => $this->t('#063')],
+        'weight' => [
+          '#type' => 'weight',
+          '#title_display' => 'invisible',
+          '#default_value' => 3,
+          '#attributes' => ['class' => ['table-order-weight']],
+        ],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Enid')],
+        'color' => ['#plain_text' => $this->t('indigo')],
+        'weight' => [
+          '#type' => 'weight',
+          '#title_display' => 'invisible',
+          '#default_value' => 4,
+          '#attributes' => ['class' => ['table-order-weight']],
+        ],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Joe')],
+        'color' => ['#plain_text' => $this->t('green')],
+        'weight' => [
+          '#type' => 'weight',
+          '#title_display' => 'invisible',
+          '#default_value' => 5,
+          '#attributes' => ['class' => ['table-order-weight']],
+        ],
+      ],
+    ];
+
+    $form['tableselect'] = [
+      '#type' => 'table',
+      '#caption' => $this->t('Our favorite colors.'),
+      '#header' => [
+        $this->t('Name'),
+        $this->t('Favorite color'),
+      ],
+      '#tableselect' => TRUE,
+      // Rather than defining the values to insert into the table using the
+      // #rows property you can define each row as a sub element of the table
+      // render array. And each column in the row as a sub element of the row
+      // array.
+      [
+        'name' => ['#plain_text' => $this->t('Amber')],
+        'color' => ['#plain_text' => $this->t('teal')],
+      ],
+      // The rest of this array is additional rows so there is some data in the
+      // table.
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Addi')],
+        'color' => ['#plain_text' => $this->t('green')],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Blake')],
+        'color' => ['#plain_text' => $this->t('#063')],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Enid')],
+        'color' => ['#plain_text' => $this->t('indigo')],
+      ],
+      [
+        '#attributes' => ['class' => ['draggable']],
+        'name' => ['#plain_text' => $this->t('Joe')],
+        'color' => ['#plain_text' => $this->t('green')],
+      ],
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['render_example.settings'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+
+    $config = $this->config('render_example.settings');
+    $config->set('render_example.show_block', $values['render_example_show_block'])->save();
+    $config->set('render_example.show_page', $values['render_example_show_page'])->save();
+    $config->set('render_example.note_about_render_arrays', $values['render_example_note_about_render_arrays'])->save();
+    $config->set('render_example.move_breadcrumbs', $values['render_example_move_breadcrumbs'])->save();
+    $config->set('render_example.reverse_sidebar', $values['render_example_reverse_sidebar'])->save();
+    $config->set('render_example.prefix', $values['render_example_prefix'])->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/render_example/src/Tests/RenderExampleTest.php b/render_example/src/Tests/RenderExampleTest.php
new file mode 100644
index 0000000..94f7029
--- /dev/null
+++ b/render_example/src/Tests/RenderExampleTest.php
@@ -0,0 +1,136 @@
+<?php
+
+namespace Drupal\render_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Test the render example functionality.
+ *
+ * @group render_example
+ * @group examples
+ */
+class RenderExampleTest extends WebTestBase {
+
+  // @TODO: I'm not sure at all we need 'node'. Currently we need it because
+  // We create a new user with the 'Access content' permission.
+  public static $modules = array('devel', 'render_example', 'node');
+
+
+  /**
+   * Assert that all of the xpaths in the array have results.
+   *
+   * @param $xpath_array
+   *   An array of xpaths, each of which must return something.
+   */
+  protected function assertRenderResults($xpath_array) {
+    foreach ($xpath_array as $xpath) {
+      $result = $this->xpath($xpath);
+      $this->assertTrue(!empty($result), format_string('Found xpath %xpath', array('%xpath' => $xpath)));
+    }
+  }
+
+  /**
+   * Asserts that the string value of the result is the same as the passed text.
+   *
+   * @param $xpath_array
+   *   Array of keyed arrays of tests to be made. Each child array consists of
+   *   $xpath => $expected_text
+   */
+  protected function assertRenderedText($xpath_array) {
+    foreach ($xpath_array as $xpath => $text) {
+      $result = $this->xpath($xpath);
+      $this->assertTrue((string) $result[0][0] == $text, format_string('%ary selects text %text', array(
+        '%ary' => $xpath,
+        '%text' => $text
+      )));
+    }
+  }
+
+  /**
+   * Login user, create an example node, and test blog functionality through the admin and user interfaces.
+   */
+  public function testRenderExampleBasic() {
+    // Create a user that can access devel information and log in.
+    $web_user = $this->drupalCreateUser(array(
+      'access devel information',
+      'access content'
+    ));
+    $this->drupalLogin($web_user);
+
+    // Turn on the block render array display and make sure it shows up.
+    $edit = array(
+      'render_example_show_block' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+    $xpath_array = array(
+      "//div[@id='sidebar-first']//fieldset[starts-with(@id, 'edit-render-example-block-fieldset')]",
+      '//*[@id="content"]//fieldset[contains(@id,"edit-render-example-block-fieldset")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+
+    // Turn off block render array display and turn on the page render array
+    // display.
+    $edit = array(
+      'render_example_show_page' => TRUE,
+      'render_example_show_block' => FALSE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+    $xpath_array = array(
+      '//*[@id="content"]//fieldset[starts-with(@id,"edit-render-example-page-fieldset")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Add note about render arrays to the top of sidebar_first.
+    $edit = array(
+      'render_example_note_about_render_arrays' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="sidebar-first"]//ol//li[starts-with(.,"Render arrays are everywhere")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Move the navigation menu to the top of the content area.
+    $edit = array(
+      'render_example_move_navigation_menu' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="content"]//h2[starts-with(.,"Navigation")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Skip a test for reversing order of sidebar_first as I think it would
+    // be too fragile.
+
+    // Test the addition of #prefix and #suffix
+    $edit = array(
+      'render_example_prefix' => TRUE,
+    );
+    $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+    $xpath_array = array(
+      '//*[@id="sidebar-first"]//*[contains(@class, "block-prefix")]/span[contains(@class, "block-suffix")]',
+    );
+    $this->assertRenderResults($xpath_array);
+
+    // Test some rendering facets of the various render examples
+    $this->drupalGet('examples/render_example/arrays');
+    $content = $this->xpath('//*[@class="render-array"][1]');
+
+    $xpath_array = array(
+      '//div[@class="rendered"][starts-with(.,"Some basic text in a #markup")]' => 'Some basic text in a #markup (shows basic markup and how it is rendered)',
+      '//div[@class="rendered"][starts-with(.,"This is some text that should be put to")]' => 'This is some text that should be put together | This is some more text that we need | ',
+      '//div[@class="rendered"][starts-with(.,"The current time was")]' => 'The current time was  when this was cached. Updated every  seconds',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"(prefix)This one")]' => '(prefix)This one adds a prefix and suffix, which put a div around the item(suffix)',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"markup for pre_")]' => 'markup for pre_render and post_render example',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"This markup was added")]' => 'This markup was added after rendering by a #post_render',
+      '//div[@class="rendered"]/div[text()][starts-with(.,"This #suffix")]' => 'This #suffix was added by a #pre_render',
+    );
+    $this->assertRenderedText($xpath_array);
+  }
+
+}
diff --git a/render_example/templates/description.html.twig b/render_example/templates/description.html.twig
new file mode 100644
index 0000000..a40d8c0
--- /dev/null
+++ b/render_example/templates/description.html.twig
@@ -0,0 +1,21 @@
+{#
+
+Description text for the Render API Example.
+
+#}
+
+{% set arrays_url = path('render_example.arrays') %}
+{% set alter_url = path('render_example.altering') %}
+
+{% trans %}
+<h2>What are render arrays?</h2>
+
+<p>Add some text here that gives an overview of the render API system? ......................................</p>
+
+<h2>Examples</h2>
+
+<ul>
+  <li><a href="{{ arrays_url }}">Demonstration of render array usage.</a></li>
+  <li><a href="{{ alter_url }}">Using alter hooks to modify existing render arrays.</a></li>
+</ul>
+{% endtrans %}
\ No newline at end of file
diff --git a/render_example/templates/render-array.html.twig b/render_example/templates/render-array.html.twig
new file mode 100644
index 0000000..09008c2
--- /dev/null
+++ b/render_example/templates/render-array.html.twig
@@ -0,0 +1,25 @@
+{#
+/**
+ * @file
+ * Default theme implementation for render_array_help.
+ *
+ * Themes the render array help portion (from the demonstration page).
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ * - element['rendered'] : rendered element
+ * - element['unrendered'] : unrendered element
+ * - element['description'] : the description of this example
+ *
+ * @ingroup themeable
+ */
+#}
+<div class="render_example--array">
+  <h2>{{ element['description'] }}</h2>
+  <h3>Rendered Element</h3>
+  <div class="render_example--rendered">
+    {{ element['rendered'] }}
+  </div>
+  <h3>Unrendered Element</h3>
+  <pre><code class="render_example--code">{{ element['unrendered'] }}</code></pre>
+</div>
diff --git a/render_example/templates/render-example-add-div.html.twig b/render_example/templates/render-example-add-div.html.twig
new file mode 100644
index 0000000..c1d107d
--- /dev/null
+++ b/render_example/templates/render-example-add-div.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation for render_example_add_div.
+ *
+ * Wraps a div around the already-rendered #children.
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ *
+ * @ingroup themeable
+ */
+#}
+<div class="render-example-wrapper-div">
+  {{ element['#children'] }}
+</div>
diff --git a/render_example/templates/render-example-marquee.html.twig b/render_example/templates/render-example-marquee.html.twig
new file mode 100644
index 0000000..11f046e
--- /dev/null
+++ b/render_example/templates/render-example-marquee.html.twig
@@ -0,0 +1,14 @@
+{#
+/**
+ * @file
+ * Default theme implementation for the marquee render element.
+ *
+ * Available variables:
+ * - attributes: Attributes for the marguee tag.
+ * - content: The text to display within the marquee tag.
+ *
+ * @ingroup themeable
+ * @ingroup render_example
+ */
+#}
+<marquee{{ attributes }}>{{ content }}</marquee>
