diff --git a/form_example/form_example.info.yml b/form_example/form_example.info.yml
new file mode 100644
index 0000000..2232340
--- /dev/null
+++ b/form_example/form_example.info.yml
@@ -0,0 +1,5 @@
+name: Form example
+type: module
+description: 'Demonstrates hook_form() and related features'
+package: Example modules
+core: 8.x
diff --git a/form_example/form_example.local_actions.yml b/form_example/form_example.local_actions.yml
new file mode 100644
index 0000000..96e1436
--- /dev/null
+++ b/form_example/form_example.local_actions.yml
@@ -0,0 +1,7 @@
+form_example.tutorial_1_tab:
+  route_name: form.example
+  tab_root_id: form.example_tutorials_tab
+form_example.tutorial_2_tab:
+  route_name: form.example
+  tab_root_id: form.example_tutorials_tab
+  title: ''
diff --git a/form_example/form_example.module b/form_example/form_example.module
new file mode 100644
index 0000000..c294890
--- /dev/null
+++ b/form_example/form_example.module
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Examples demonstrating the Drupal Form API.
+ */
+
+/**
+ * @defgroup form_example Example: Form API
+ * @ingroup examples
+ * @{
+ * Examples demonstrating the Drupal Form API.
+ *
+ * The Form Example module is a part of the Examples for Developers Project
+ * and provides various Drupal Form API Examples. You can download and
+ * experiment with this code at the
+ * @link http://drupal.org/project/examples Examples for Developers project page. @endlink
+ */
+
+/**
+ * Implements hook_menu().
+ *
+ * Here we set up the URLs (menu entries) for the
+ * form examples. Note that most of the menu items
+ * have page callbacks and page arguments set, with
+ * page arguments set to be functions in external files.
+ */
+function form_example_menu() {
+  $items = array();
+  $items['examples/form_example'] = array(
+    'title' => 'Form Example',
+    'route_name' => 'form_example',
+    'access callback' => TRUE,
+    'expanded' => TRUE,
+  );
+  $items['examples/form_example/tutorial'] = array(
+    'title' => 'Form Tutorial',
+    // 'page callback' => 'drupal_get_form',
+    'route_name' => array('form_example_tutorial_1'),
+    'access callback' => TRUE,
+    'description' => 'A set of ten tutorials',
+    // 'file' => 'form_example_tutorial.inc',
+    // 'type' => MENU_NORMAL_ITEM,
+  );
+  $items['examples/form_example/tutorial/1'] = array(
+    'title' => '#1',
+    // 'page callback' => 'drupal_get_form',
+    'route_name' => array('form_example_tutorial_1'),
+    'access callback' => TRUE,
+    'description' => 'Tutorial 1: Simplest form',
+    // 'type' => MENU_DEFAULT_LOCAL_TASK,
+    // 'file' => 'form_example_tutorial.inc',
+  );
+  return $items;
+}
diff --git a/form_example/form_example.routing.yml b/form_example/form_example.routing.yml
new file mode 100644
index 0000000..002e89a
--- /dev/null
+++ b/form_example/form_example.routing.yml
@@ -0,0 +1,21 @@
+form.example:
+  path: 'examples/form_example'
+  defaults:
+    _content: '\Drupal\form_example\Controller\FormExampleController::description'
+    _title: 'Form Example'
+  requirements:
+    _access: 'TRUE'
+form.example_tutorial_1:
+  path: 'examples/form_example/tutorial'
+  defaults:
+    _form: '\Drupal\form_example\Forms\FormExampleForm'
+  requirements:
+    _access: 'TRUE'
+form_example_2:
+  path: 'examples/form_example/tutorial/2'
+  defaults:
+    _form: '\Drupal\form_example\Forms\FormExampleForm1'
+  requirements:
+    _access: 'TRUE'
+
+
diff --git a/form_example/lib/Drupal/form_example/Controller/FormExampleController.php b/form_example/lib/Drupal/form_example/Controller/FormExampleController.php
new file mode 100644
index 0000000..1824fba
--- /dev/null
+++ b/form_example/lib/Drupal/form_example/Controller/FormExampleController.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\page_example\Controller\FormExampleController.
+ */
+
+namespace Drupal\form_example\Controller;
+
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+
+/**
+ * Controller routines for filter routes.
+ */
+class FormExampleController {
+
+  /**
+   * Text for our general info page.
+   *
+   * Our router maps this method to the path 'examples/form_example'.
+   */
+  function description() {
+    $build = array(
+      '#markup' => t('<p>The form example module provides a tutorial, extensible multistep example, an element example, and a #states example</p>')
+    );
+
+    return $build;
+  }
+}
diff --git a/form_example/lib/Drupal/form_example/Forms/FormExampleForm.php b/form_example/lib/Drupal/form_example/Forms/FormExampleForm.php
new file mode 100644
index 0000000..8e26801
--- /dev/null
+++ b/form_example/lib/Drupal/form_example/Forms/FormExampleForm.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\form_example\Form\FormExampleForm
+ */
+namespace Drupal\form_example\Forms;
+
+use Drupal\Core\Form\FormInterface;
+use Drupal\Core\Form\FormBase;
+
+/**
+ * Form with examples.
+ */
+class FormExampleForm extends FormBase implements FormInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'form_example';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+
+     $form['form_example'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Form Example'),
+      '#group' => '',
+      '#required' => TRUE,
+    );
+     $form['form_example'] = array(
+      '#type' => 'label',
+      '#title' => t('Form Example'),
+      '#required' => TRUE,
+    );
+     $form['form_example'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Name'),
+      '#default_value' => 'This is a simple text field.',
+      '#required' => false,
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {}
+}
diff --git a/form_example/lib/Drupal/form_example/Tests/FormExampleTestCase.php b/form_example/lib/Drupal/form_example/Tests/FormExampleTestCase.php
new file mode 100644
index 0000000..8760714
--- /dev/null
+++ b/form_example/lib/Drupal/form_example/Tests/FormExampleTestCase.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @file
+ * Test case for testing the cron example module.
+ */
+
+/**
+ * @addtogroup cron_example
+ * @{
+ */
+namespace Drupal\form_example\Tests;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * form_example test class
+ */
+class FormExampleTestCase extends WebTestBase {
+  public static $modules = array('form_example');
+  protected $web_user;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Cron example functionality',
+      'description' => 'Test the functionality of the Cron Example.',
+      'group' => 'Examples',
+    );
+  }
+
+  /**
+   * Enable modules and create user with specific permissions.
+   */
+  function setUp() {
+    parent::setUp();
+    // Create user. Search content permission granted for the search block to
+    // be shown.
+    $this->web_user = $this->drupalCreateUser(array('administer site configuration'));
+    $this->drupalLogin($this->web_user);
+  }
+
+  /**
+   * Login user, create an example node, and test block functionality through
+   * the admin and user interfaces.
+   */
+  function testFormExampleBasic() {
+    // Pretend that cron has never been run (even though simpletest seems to
+    // run it once...)
+    variable_set('form_example_next_execution', 0);
+    $this->drupalGet('examples/form_example');
+
+    // Initial run should cause form_example_cron() to fire.
+    $post = array();
+    $this->drupalPostForm('examples/form_example', $post, t('Run cron now'));
+    $this->assertText(t('form_example executed at'));
+
+    // Forcing should also cause form_example_cron() to fire.
+    $post['form_reset'] = TRUE;
+    $this->drupalPostForm(NULL, $post, t('Run cron now'));
+    $this->assertText(t('form_example executed at'));
+
+    // But if followed immediately and not forced, it should not fire.
+    $post['form_reset'] = FALSE;
+    $this->drupalPostForm(NULL, $post, t('Run cron now'));
+    $this->assertNoText(t('form_example executed at'));
+
+
+    $this->assertText(t('There are currently 0 items in queue 1 and 0 items in queue 2'));
+    $post = array(
+      'num_items' => 5,
+      'queue' => 'form_example_queue_1',
+    );
+    $this->drupalPostForm(NULL, $post, t('Add jobs to queue'));
+    $this->assertText('There are currently 5 items in queue 1 and 0 items in queue 2');
+    $post = array(
+      'num_items' => 100,
+      'queue' => 'form_example_queue_2',
+    );
+    $this->drupalPostForm(NULL, $post, t('Add jobs to queue'));
+    $this->assertText('There are currently 5 items in queue 1 and 100 items in queue 2');
+
+    $post = array();
+    $this->drupalPostForm('examples/form_example', $post, t('Run cron now'));
+    $this->assertPattern('/Queue 1 worker processed item with sequence 5 /');
+    $this->assertPattern('/Queue 2 worker processed item with sequence 100 /');
+  }
+}
+
+/**
+ * @} End of "addtogroup form_example".
+ */
