diff --git a/Build/Resources/Public/Less/Component/module.less b/Build/Resources/Public/Less/Component/module.less
new file mode 100644
index 0000000000000000000000000000000000000000..cbbe71d916f958ee64470b5726fe840f5724d175
--- /dev/null
+++ b/Build/Resources/Public/Less/Component/module.less
@@ -0,0 +1,88 @@
+//
+// ModuleTemplate
+// ======
+// General component for backend modules.
+//
+
+
+//
+// Variables
+//
+@module-bg: #fff;
+
+@module-docheader-bg: #eee;
+@module-docheader-border: #c3c3c3;
+@module-docheader-zindex: 300;
+@module-docheader-height: 65px;
+@module-docheader-padding-vertical: 0;
+@module-docheader-padding-horizontal: 24px;
+@module-docheader-padding: @module-docheader-padding-vertical @module-docheader-padding-horizontal;
+
+@module-docheader-bar-height: 26px;
+@module-docheader-bar-margin-vertical: 4px;
+@module-docheader-bar-margin-horizontal: 0;
+@module-docheader-bar-margin: @module-docheader-bar-margin-vertical @module-docheader-bar-margin-horizontal;
+
+@module-body-padding-vertical: 24px;
+@module-body-padding-horizontal: 24px;
+@module-body-padding: @module-body-padding-vertical @module-body-padding-horizontal;
+
+
+//
+// Template
+//
+.module {
+	height: 100%;
+	width: 100%;
+	background-color: @module-bg;
+	form {
+		margin: 0;
+	}
+}
+
+
+//
+// Docheader
+//
+.module-docheader {
+	.clearfix;
+	position: fixed;
+	width: 100%;
+	top: 0;
+	left: 0;
+	height: @module-docheader-height;
+	z-index: @module-docheader-zindex;
+	background-color: @module-docheader-bg;
+	border-bottom: 1px solid @module-docheader-border;
+	padding: @module-docheader-padding;
+}
+.module-docheader-bar {
+	.clearfix;
+	height: @module-docheader-bar-height;
+	margin: @module-docheader-bar-margin;
+	line-height: @module-docheader-bar-height;
+	label {
+		margin-top: 0;
+		margin-bottom: 0;
+	}
+	.form-group {
+		margin: 0;
+	}
+}
+.module-docheader-bar-column-left {
+	float: left;
+}
+.module-docheader-bar-column-right {
+	float: right;
+}
+
+
+//
+// Body
+//
+.module-body {
+	padding: @module-body-padding;
+}
+.module-docheader + .module-body {
+	padding-top: @module-docheader-height + @module-body-padding-vertical;
+}
diff --git a/Build/Resources/Public/Less/TYPO3/_element_buttons.less b/Build/Resources/Public/Less/TYPO3/_element_buttons.less
index 6a339682c575cbf13f49a0c526fadef00fc6397d..20eea7dfea2c43581f1b9cfa9f1c900e71654223 100644
--- a/Build/Resources/Public/Less/TYPO3/_element_buttons.less
+++ b/Build/Resources/Public/Less/TYPO3/_element_buttons.less
@@ -1,10 +1,8 @@
 //
 // Button
 //
-.btn {
-	.t3-icon {
-		margin: 0;
-	}
+.btn-sm {
+	min-height: floor(2px + (@padding-small-vertical * 2) + (@font-size-small * @line-height-small));
 }
 
 //
diff --git a/Build/Resources/Public/Less/_minimal.less b/Build/Resources/Public/Less/_minimal.less
index 8e1564a6e71b68d0ee5ff615731abf929b2db2f5..789aeada41af1a51033c4ea5d36a0768c8366156 100644
--- a/Build/Resources/Public/Less/_minimal.less
+++ b/Build/Resources/Public/Less/_minimal.less
@@ -74,6 +74,7 @@
 @import "Component/callout.less";
 @import "Component/icon.less";
 @import "Component/diff.less";
+@import "Component/module.less";
 
 //
 // Bootstrap Utility classes
diff --git a/typo3/sysext/backend/Classes/Module/AbstractModule.php b/typo3/sysext/backend/Classes/Module/AbstractModule.php
new file mode 100644
index 0000000000000000000000000000000000000000..901f3e9255ef198f59eb0b2f2d2d976b3832fe5c
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Module/AbstractModule.php
@@ -0,0 +1,81 @@
+<?php
+namespace TYPO3\CMS\Backend\Module;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Template\ModuleTemplate;
+use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * A backend module. This class may be used by extension backend modules
+ * to implement own actions and controllers. It initializes the module
+ * template and comes with a simple dispatcher method.
+ *
+ * @internal Experimental for now
+ */
+class AbstractModule {
+
+	/**
+	 * ModuleTemplate object
+	 *
+	 * @var ModuleTemplate
+	 */
+	protected $moduleTemplate;
+
+	/**
+	 * IconFactory object
+	 *
+	 * @var IconFactory
+	 */
+	protected $iconFactory;
+
+	/**
+	 * Constructor Method
+	 */
+	public function __construct() {
+		$this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
+		$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+	}
+
+	/**
+	 * PSR Request Object
+	 *
+	 * @var ServerRequestInterface
+	 */
+	protected $request;
+
+	/**
+	 * Central Request Dispatcher
+	 *
+	 * @param ServerRequestInterface $request PSR7 Request Object
+	 * @param ResponseInterface $response PSR7 Response Object
+	 *
+	 * @return ResponseInterface
+	 *
+	 * @throws \InvalidArgumentException In case an action is not callable
+	 */
+	public function processRequest(ServerRequestInterface $request, ResponseInterface $response) {
+		$methodName = $request->getQueryParams()['action'] ?: 'index';
+		if (!is_callable([$this, $methodName])) {
+			throw new \InvalidArgumentException(
+				'The method "' . $methodName . '" is not callable within "' . get_class($this) . '".',
+				1442736343
+			);
+		}
+		return $this->{$methodName}($request, $response);
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/AbstractControl.php b/typo3/sysext/backend/Classes/Template/Components/AbstractControl.php
new file mode 100644
index 0000000000000000000000000000000000000000..d7eedf4cc9b69ad0c2705e07e4c614b94127276f
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/AbstractControl.php
@@ -0,0 +1,135 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Control used by various components
+ */
+class AbstractControl {
+
+	/**
+	 * HTML tag attribute for class
+	 *
+	 * @var string
+	 */
+	protected $classes = '';
+
+	/**
+	 * HTML tag attribute for title
+	 *
+	 * @var string
+	 */
+	protected $title = '';
+
+	/**
+	 * HTML tag attributes for data-*
+	 * Use key => value pairs
+	 *
+	 * @var array
+	 */
+	protected $dataAttributes = [];
+
+	/**
+	 * HTML tag attribute onClick
+	 * Outdated, use sparingly
+	 *
+	 * @var string
+	 */
+	protected $onClick = '';
+
+	/**
+	 * Get classes
+	 *
+	 * @return string
+	 */
+	public function getClasses() {
+		return $this->classes;
+	}
+
+	/**
+	 * Get Title
+	 *
+	 * @return string
+	 */
+	public function getTitle() {
+		return $this->title;
+	}
+
+	/**
+	 * Get Data attributes
+	 *
+	 * @return array
+	 */
+	public function getDataAttributes() {
+		return $this->dataAttributes;
+	}
+
+	/**
+	 * Get Onclick Attribute
+	 *
+	 * @return string
+	 */
+	public function getOnClick() {
+		return $this->onClick;
+	}
+
+	/**
+	 * Set classes
+	 *
+	 * @param string $classes HTML class attribute to set
+	 *
+	 * @return $this
+	 */
+	public function setClasses($classes) {
+		$this->classes = $classes;
+		return $this;
+	}
+
+	/**
+	 * Set title attribute
+	 *
+	 * @param string $title HTML title attribute to set
+	 *
+	 * @return $this
+	 */
+	public function setTitle($title) {
+		$this->title = $title;
+		return $this;
+	}
+
+	/**
+	 * Set Data attributes
+	 *
+	 * @param array $dataAttributes HTML data attributes to set
+	 *
+	 * @return $this
+	 */
+	public function setDataAttributes(array $dataAttributes) {
+		$this->dataAttributes = $dataAttributes;
+		return $this;
+	}
+
+	/**
+	 * Set OnClick
+	 *
+	 * @param string $onClick HTML onClick attribute to set
+	 *
+	 * @return $this
+	 */
+	public function setOnClick($onClick) {
+		$this->onClick = $onClick;
+		return $this;
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/ButtonBar.php b/typo3/sysext/backend/Classes/Template/Components/ButtonBar.php
new file mode 100644
index 0000000000000000000000000000000000000000..57be284675984a589ea37ab917231aa7bbc4d115
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/ButtonBar.php
@@ -0,0 +1,137 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Buttons\ButtonInterface;
+use TYPO3\CMS\Backend\Template\Components\Buttons\FullyRenderedButton;
+use TYPO3\CMS\Backend\Template\Components\Buttons\InputButton;
+use TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton;
+use TYPO3\CMS\Backend\Template\Components\Buttons\SplitButton;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Bar holding the buttons
+ */
+class ButtonBar {
+
+	/**
+	 * Identifier for the left button bar
+	 */
+	const BUTTON_POSITION_LEFT = 'left';
+
+	/**
+	 * Identifier for the right button bar
+	 */
+	const BUTTON_POSITION_RIGHT = 'right';
+
+	/**
+	 * Internal array of all registered buttons
+	 *
+	 * @var array
+	 */
+	protected $buttons = [];
+
+	/**
+	 * Add button
+	 *
+	 * @param ButtonInterface $button The Button Object to add
+	 * @param string $buttonPosition Position of the button (left/right)
+	 * @param int $buttonGroup Buttongroup of the button
+	 *
+	 * @throws \InvalidArgumentException In case a button is not valid
+	 *
+	 * @return $this
+	 */
+	public function addButton(
+		ButtonInterface $button,
+		$buttonPosition = self::BUTTON_POSITION_LEFT,
+		$buttonGroup = 1
+	) {
+		if (!$button->isValid($button)) {
+			throw new \InvalidArgumentException('Button "' . $button->getType() . '" is not valid', 1441706370);
+		}
+		// We make the button immutable here
+		$this->buttons[$buttonPosition][$buttonGroup][] = clone $button;
+		return $this;
+	}
+
+	/**
+	 * Creates a new button of the given type
+	 *
+	 * @param string $button ButtonClass to invoke. Must implement ButtonInterface
+	 *
+	 * @throws \InvalidArgumentException In case a ButtonClass does not implement
+	 * ButtonInterface
+	 *
+	 * @return ButtonInterface
+	 */
+	public function makeButton($button) {
+		if (!in_array(ButtonInterface::class, class_implements($button), TRUE)) {
+			throw new \InvalidArgumentException('A Button must implement ButtonInterface', 1441706378);
+		}
+		return GeneralUtility::makeInstance($button);
+	}
+
+	/**
+	 * Creates a new InputButton
+	 *
+	 * @return InputButton
+	 */
+	public function makeInputButton() {
+		return GeneralUtility::makeInstance(InputButton::class);
+	}
+
+	/**
+	 * Creates a new SplitButton
+	 *
+	 * @return SplitButton
+	 */
+	public function makeSplitButton() {
+		return GeneralUtility::makeInstance(SplitButton::class);
+	}
+
+	/**
+	 * Creates a new LinkButton
+	 *
+	 * @return LinkButton
+	 */
+	public function makeLinkButton() {
+		return GeneralUtility::makeInstance(LinkButton::class);
+	}
+
+	/**
+	 * Creates a new FullyRenderedButton
+	 *
+	 * @return FullyRenderedButton
+	 */
+	public function makeFullyRenderedButton() {
+		return GeneralUtility::makeInstance(FullyRenderedButton::class);
+	}
+
+	/**
+	 * Returns an associative array of all buttons in the form of
+	 * ButtonPosition > ButtonGroup > Button
+	 *
+	 * @return array
+	 */
+	public function getButtons() {
+		// here we need to call the sorting methods and stuff.
+		foreach ($this->buttons as  $position => $_) {
+			ksort($this->buttons[$position]);
+		}
+		// @todo do we want to provide a hook here?
+		return $this->buttons;
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/AbstractButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/AbstractButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..e5d8bdb32e671dc69e42ae272843512df99714dc
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/AbstractButton.php
@@ -0,0 +1,100 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\AbstractControl;
+use TYPO3\CMS\Core\Imaging\Icon;
+
+/**
+ * AbstractButton
+ */
+class AbstractButton extends AbstractControl implements ButtonInterface {
+
+	/**
+	 * Icon object
+	 *
+	 * @var Icon
+	 */
+	protected $icon;
+
+	/**
+	 * ButtonType
+	 *
+	 * @var string
+	 */
+	protected $type;
+
+	/**
+	 * Get icon
+	 *
+	 * @return Icon
+	 */
+	public function getIcon() {
+		return $this->icon;
+	}
+
+	/**
+	 * Get type
+	 *
+	 * @return string
+	 */
+	public function getType() {
+		return get_class($this);
+	}
+
+	/**
+	 * Set icon
+	 *
+	 * @param Icon $icon Icon object for the button
+	 *
+	 * @return $this
+	 */
+	public function setIcon(Icon $icon) {
+		$this->icon = $icon;
+		return $this;
+	}
+
+	/**
+	 * Implementation from ButtonInterface
+	 * This object is an abstract, so no implementation is necessary
+	 *
+	 * @return bool
+	 */
+	public function isValid() {
+		return FALSE;
+	}
+
+	/**
+	 * Implementation from ButtonInterface
+	 * This object is an abstract, so no implementation is necessary
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return '';
+	}
+
+	/**
+	 * Implementation from ButtonInterface
+	 * This object is an abstract, so no implementation is necessary
+	 *
+	 * @return string
+	 */
+	public function render() {
+		return '';
+	}
+
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/ButtonInterface.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/ButtonInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..df1f83bad5a066c69d3cbf3c58e48302a7b0003d
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/ButtonInterface.php
@@ -0,0 +1,49 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Interface for buttons
+ */
+interface ButtonInterface {
+
+	/**
+	 * Validates all set parameters of a button.
+	 *
+	 * @return bool
+	 */
+	public function isValid();
+
+	/**
+	 * Returns the fully qualified class name of the button as a string
+	 *
+	 * @return string
+	 */
+	public function getType();
+
+	/**
+	 * RenderMethod of a button if accessed as string from fluid
+	 *
+	 * @return string
+	 */
+	public function __toString();
+
+	/**
+	 * Renders the markup for the button
+	 *
+	 * @return string
+	 */
+	public function render();
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/FullyRenderedButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/FullyRenderedButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..6af32e61447b1051f8f56b69bdc054d9a5a6043d
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/FullyRenderedButton.php
@@ -0,0 +1,106 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * FullyRenderedButton
+ *
+ * This button type is an intermediate solution for buttons that are rendered
+ * by methods from TYPO3 itself, like the CSH buttons or Bookmark buttons.
+ *
+ * There should be no need to use them, so do yourself a favour and don't.
+ *
+ * EXAMPLE USAGE TO ADD A BUTTON TO THE FIRST BUTTON GROUP IN THE LEFT BAR:
+ *
+ * $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
+ * $myButton = $buttonBar->makeFullyRenderedButton()
+ *      ->setHtmlSource('<span class="i-should-not-be-using-this>Foo</span>');
+ * $buttonBar->addButton($myButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
+ */
+class FullyRenderedButton implements ButtonInterface {
+
+	/**
+	 * The full HTML source of the rendered button.
+	 * This source will be passed through to the frontend as is,
+	 * so keep htmlspecialchars() in mind
+	 *
+	 * @var string
+	 */
+	protected $htmlSource = '';
+
+	/**
+	 * Gets the HTML Source of the button
+	 *
+	 * @return string
+	 */
+	public function getHtmlSource() {
+		return $this->htmlSource;
+	}
+
+	/**
+	 * Sets the HTML Source of the button and returns itself
+	 *
+	 * @param string $htmlSource HTML sourcecode of the button
+	 *
+	 * @return FullyRenderedButton
+	 */
+	public function setHtmlSource($htmlSource) {
+		$this->htmlSource = $htmlSource;
+		return $this;
+	}
+
+	/**
+	 * Gets the type of the button
+	 *
+	 * @return string
+	 */
+	public function getType() {
+		return get_class($this);
+	}
+
+	/**
+	 * Validator for a FullyRenderedButton
+	 *
+	 * @return bool
+	 */
+	public function isValid() {
+		if (
+			trim($this->getHtmlSource()) !== ''
+			&& $this->getType() === FullyRenderedButton::class
+		) {
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Renders the button
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return $this->render();
+	}
+
+	/**
+	 * Renders the button
+	 *
+	 * @return string
+	 */
+	public function render() {
+		return '<span class="btn btn-sm btn-default">' . $this->getHtmlSource() . '</span>';
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/InputButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/InputButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..70038435a21184cb2ae5e83ff93cad79d380b083
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/InputButton.php
@@ -0,0 +1,141 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * InputButton
+ *
+ * This button type renders a HTML tag <button> and takes the HTML attributes
+ * name and value as additional attributes to those defined in AbstractButton.
+ *
+ * Since we no longer want to have any <input type="submit" /> in the TYPO3 core
+ * you should use this button type to send forms
+ *
+ * EXAMPLE USAGE TO ADD A BUTTON TO THE FIRST BUTTON GROUP IN THE LEFT BAR:
+ *
+ * $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
+ * $saveButton = $buttonBar->makeInputButton()
+ *      ->setName('save')
+ *      ->setValue('1')
+ *      ->setIcon($this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL))
+ *      ->setTitle('Save');
+ * $buttonBar->addButton($saveButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
+ */
+class InputButton extends AbstractButton implements ButtonInterface {
+
+	/**
+	 * Name Attribute of the button
+	 *
+	 * @var string
+	 */
+	protected $name = '';
+
+	/**
+	 * Value attribute of the button
+	 *
+	 * @var string
+	 */
+	protected $value = '';
+
+	/**
+	 * Get name
+	 *
+	 * @return string
+	 */
+	public function getName() {
+		return $this->name;
+	}
+
+	/**
+	 * Set name
+	 *
+	 * @param string $name Name attribute
+	 *
+	 * @return InputButton
+	 */
+	public function setName($name) {
+		$this->name = $name;
+		return $this;
+	}
+
+	/**
+	 * Get value
+	 *
+	 * @return string
+	 */
+	public function getValue() {
+		return $this->value;
+	}
+
+	/**
+	 * Set value
+	 *
+	 * @param string $value Value attribute
+	 *
+	 * @return InputButton
+	 */
+	public function setValue($value) {
+		$this->value = $value;
+		return $this;
+	}
+
+	/**
+	 * Validates the current button
+	 *
+	 * @return bool
+	 */
+	public function isValid() {
+		if (
+			trim($this->getName()) !== ''
+			&& trim($this->getValue()) !== ''
+			&& trim($this->getTitle()) !== ''
+			&& $this->getType() === InputButton::class
+			&& $this->getIcon() !== NULL
+		) {
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Renders the markup of the button
+	 *
+	 * @return string
+	 */
+	public function render() {
+		$content = '
+		<button name="' .
+			htmlspecialchars($this->getName()) .
+			'" class="' .
+			htmlspecialchars($this->getClasses()) .
+			'" value="' .
+			htmlspecialchars($this->getValue()) .
+			'" title="' .
+			htmlspecialchars($this->getTitle()) .
+			'">' . $this->getIcon()->__toString() .
+			'</button>
+		';
+		return $content;
+	}
+
+	/**
+	 * Magic method so Fluid can access a button via {button}
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return $this->render();
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/LinkButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/LinkButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..aead71088e7907fcceaf51561cb5c3509e1e7063
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/LinkButton.php
@@ -0,0 +1,114 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * LinkButton
+ *
+ * This button type renders a regular anchor tag with TYPO3s way to render a
+ * button control.
+ *
+ * EXAMPLE USAGE TO ADD A BUTTON TO THE FIRST BUTTON GROUP IN THE LEFT BAR:
+ *
+ * $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
+ * $saveButton = $buttonBar->makeLinkButton()
+ *      ->setHref('#')
+ *      ->setDataAttributes([
+ *          'foo' => 'bar'
+ *      ])
+ *      ->setIcon($this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL))
+ *      ->setTitle('Save');
+ * $buttonBar->addButton($saveButton, ButtonBar::BUTTON_POSITION_LEFT, 1);
+ */
+class LinkButton extends AbstractButton implements ButtonInterface {
+
+	/**
+	 * HREF attribute of the link
+	 *
+	 * @var string
+	 */
+	protected $href = '';
+
+	/**
+	 * Get href
+	 *
+	 * @return string
+	 */
+	public function getHref() {
+		return $this->href;
+	}
+
+	/**
+	 * Set href
+	 *
+	 * @param string $href HREF attribute
+	 *
+	 * @return LinkButton
+	 */
+	public function setHref($href) {
+		$this->href = $href;
+		return $this;
+	}
+
+	/**
+	 * Validates the current button
+	 *
+	 * @return bool
+	 */
+	public function isValid() {
+		if (
+			trim($this->getHref()) !== ''
+			&& trim($this->getTitle()) !== ''
+			&& $this->getType() === LinkButton::class
+			&& $this->getIcon() !== NULL
+		) {
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Renders the markup for the button
+	 *
+	 * @return string
+	 */
+	public function render() {
+		if ($this->onClick !== '') {
+			$onClick = 'onclick="' . htmlspecialchars($this->onClick) . '"';
+		} else {
+			$onClick = '';
+		}
+		return '<a href="' .
+		htmlspecialchars($this->getHref()) .
+		'" class="btn btn-sm btn-default ' .
+		htmlspecialchars($this->getClasses()) .
+		'" ' .
+		$onClick .
+		' title="' .
+		htmlspecialchars($this->getTitle()) .
+		'">' .
+		$this->getIcon()->__toString() .
+		'</a>';
+	}
+
+	/**
+	 * Magic method so Fluid can access a button via {button}
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return $this->render();
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/SplitButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/SplitButton.php
new file mode 100644
index 0000000000000000000000000000000000000000..881e1314b772e65353f57c176de61987c44e2b4b
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/SplitButton.php
@@ -0,0 +1,172 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * SplitButton
+ *
+ * This button type renders a bootstrap split button.
+ * It takes multiple button objects as parameters
+ *
+ * EXAMPLE USAGE TO ADD A SPLIT BUTTON TO THE FIRST BUTTON GROUP IN THE LEFT BAR:
+ *
+ * $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
+ *
+ * $saveButton = $buttonBar->makeInputButton()
+ *      ->setName('save')
+ *      ->setValue('1')
+ *      ->setIcon($this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL))
+ *      ->setTitle('Save');
+ *
+ * $saveAndCloseButton = $buttonBar->makeInputButton()
+ *      ->setName('save_and_close')
+ *      ->setValue('1')
+ *      ->setTitle('Save and close')
+ *      ->setIcon($this->iconFactory->getIcon('actions-document-save-close', Icon::SIZE_SMALL));
+ *
+ * $saveAndShowPageButton = $buttonBar->makeInputButton()
+ *      ->setName('save_and_show')
+ *      ->setValue('1')
+ *      ->setTitle('Save and show')
+ *      ->setIcon($this->iconFactory->getIcon('actions-document-save-view', Icon::SIZE_SMALL));
+ *
+ * $splitButtonElement = $buttonBar->makeSplitButton()
+ *      ->addItem($saveButton, TRUE)
+ *      ->addItem($saveAndCloseButton)
+ *      ->addItem($saveAndShowPageButton);
+ */
+class SplitButton extends AbstractButton implements ButtonInterface {
+
+	/**
+	 * Internal var that determines whether the split button has received any primary
+	 * actions yet
+	 *
+	 * @var bool
+	 */
+	protected $containsPrimaryAction = FALSE;
+
+	/**
+	 * Internal array of items in the split button
+	 *
+	 * @var array
+	 */
+	protected $items = [];
+
+	/**
+	 * Adds an instance of any button to the split button
+	 *
+	 * @param AbstractButton $item ButtonObject to add
+	 * @param bool $primaryAction Is the button the primary action?
+	 *
+	 * @throws \InvalidArgumentException In case a button is not valid
+	 *
+	 * @return $this
+	 */
+	public function addItem(AbstractButton $item, $primaryAction = FALSE) {
+		if (!$item->isValid($item)) {
+			throw new \InvalidArgumentException(
+				'Only valid items may be assigned to a split Button. "' .
+				$item->getType() .
+				'" did not pass validation', 1441706330
+			);
+		}
+		if ($primaryAction && $this->containsPrimaryAction) {
+			throw new \InvalidArgumentException('A splitButton may only contain one primary action', 1441706340);
+		}
+		if ($primaryAction) {
+			$this->containsPrimaryAction = TRUE;
+			$this->items['primary'] = clone $item;
+		} else {
+			$this->items['options'][] = clone $item;
+		}
+		return $this;
+	}
+
+	/**
+	 * Returns the current button
+	 *
+	 * @return array
+	 */
+	public function getButton() {
+		if (!isset($this->items['primary']) && isset($this->items['options'])) {
+			$primaryAction = array_shift($this->items['options']);
+			$this->items['primary'] = $primaryAction;
+		}
+		return $this->items;
+	}
+
+	/**
+	 * Validates the current button
+	 *
+	 *
+	 * @return bool
+	 */
+	public function isValid() {
+		$subject = $this->getButton();
+		if (
+			isset($subject['primary'])
+			&& ($subject['primary'] instanceof AbstractButton)
+			&& isset($subject['options'])
+		) {
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Renders the HTML markup of the button
+	 *
+	 * @return string
+	 */
+	public function render() {
+		$items = $this->getButton();
+		$content = '
+		<div class="btn-group">
+			<button
+				type="submit"
+				value="' . htmlspecialchars($items['primary']->getValue()) . '"
+				class="btn btn-sm btn-default ' . htmlspecialchars($items['primary']->getClasses()) . '"
+			>
+				' . $items['primary']->getIcon()->render() . '
+				' . htmlspecialchars($items['primary']->getTitle()) . '
+			</button>
+			<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+				<span class="caret"></span>
+				<span class="sr-only">Toggle Dropdown</span>
+			</button>
+			<ul class="dropdown-menu">';
+		foreach ($items['options'] as $option) {
+			$content .= '
+				<li>
+					<a href="#">' . $option->getIcon()->render() . ' ' . htmlspecialchars($option->getTitle()) . '</a>
+				</li>
+			';
+		}
+		$content .= '
+			</ul>
+		</div>
+		';
+		return $content;
+	}
+
+	/**
+	 * Magic method so Fluid can access a button via {button}
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return $this->render();
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/DocHeaderComponent.php b/typo3/sysext/backend/Classes/Template/Components/DocHeaderComponent.php
new file mode 100644
index 0000000000000000000000000000000000000000..bf0e5eeb292bad4ab9bf7506c2d2502f88bc229f
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/DocHeaderComponent.php
@@ -0,0 +1,96 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * DocHeader component class
+ */
+class DocHeaderComponent {
+
+	/**
+	 * MenuRegistry Object
+	 *
+	 * @var MenuRegistry
+	 */
+	protected $menuRegistry;
+
+	/**
+	 * Meta information
+	 *
+	 * @var MetaInformation
+	 */
+	protected $metaInformation;
+
+	/**
+	 * Registry Container for Buttons
+	 *
+	 * @var ButtonBar
+	 */
+	protected $buttonBar;
+
+	/**
+	 * Sets up buttonBar and MenuRegistry
+	 */
+	public function __construct() {
+		$this->buttonBar = GeneralUtility::makeInstance(ButtonBar::class);
+		$this->menuRegistry = GeneralUtility::makeInstance(MenuRegistry::class);
+		$this->metaInformation = GeneralUtility::makeInstance(MetaInformation::class);
+	}
+
+	/**
+	 * Set page information
+	 *
+	 * @param array $metaInformation Record array
+	 *
+	 * @return void
+	 */
+	public function setMetaInformation(array $metaInformation) {
+		$this->metaInformation->setRecordArray($metaInformation);
+	}
+
+	/**
+	 * Get moduleMenuRegistry
+	 *
+	 * @return MenuRegistry
+	 */
+	public function getMenuRegistry() {
+		return $this->menuRegistry;
+	}
+
+	/**
+	 * Get ButtonBar
+	 *
+	 * @return ButtonBar
+	 */
+	public function getButtonBar() {
+		return $this->buttonBar;
+	}
+
+	/**
+	 * Returns the abstract content of the docHeader as an array
+	 *
+	 * @return array
+	 */
+	public function docHeaderContent() {
+		return [
+			'buttons' => $this->buttonBar->getButtons(),
+			'menus' => $this->menuRegistry->getMenus(),
+			'metaInformation' => $this->metaInformation
+		];
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Menu/Menu.php b/typo3/sysext/backend/Classes/Template/Components/Menu/Menu.php
new file mode 100644
index 0000000000000000000000000000000000000000..7dd6bbcc1f07a24244d04625e363678c6840bb28
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Menu/Menu.php
@@ -0,0 +1,135 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Menu;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Menu
+ */
+class Menu {
+
+	/**
+	 * Menu Identifier
+	 *
+	 * @var string
+	 */
+	protected $identifier = '';
+
+	/**
+	 * Label of the Menu (useful for Selectbox menus)
+	 *
+	 * @var string
+	 */
+	protected $label = '';
+
+	/**
+	 * Container for menuitems
+	 *
+	 * @var array
+	 */
+	protected $menuItems = [];
+
+	/**
+	 * Get the label
+	 *
+	 * @return string
+	 */
+	public function getLabel() {
+		return $this->label;
+	}
+
+	/**
+	 * Set label
+	 *
+	 * @param string $label LabelText for the menu (accepts LLL syntax)
+	 *
+	 * @return Menu
+	 */
+	public function setLabel($label) {
+		$this->label = $label;
+		return $this;
+	}
+
+	/**
+	 * Set identifier
+	 *
+	 * @param string $identifier Menu Identifier
+	 *
+	 * @return Menu
+	 */
+	public function setIdentifier($identifier) {
+		$this->identifier = $identifier;
+		return $this;
+	}
+
+	/**
+	 * Adds a new menuItem
+	 *
+	 * @param MenuItem $menuItem The menuItem to add to the menu
+	 *
+	 * @throws \InvalidArgumentException In case a menuItem is not valid
+	 *
+	 * @return void
+	 */
+	public function addMenuItem(MenuItem $menuItem) {
+		if (!$menuItem->isValid($menuItem)) {
+			throw new \InvalidArgumentException('MenuItem "' . $menuItem->getTitle() . '" is not valid', 1442236317);
+		}
+		// @todo implement sorting of menu items
+		// @todo maybe even things like spacers/sections?
+		$this->menuItems[] = clone $menuItem;
+	}
+
+	/**
+	 * Get menu items
+	 *
+	 * @return array
+	 */
+	public function getMenuItems() {
+		return $this->menuItems;
+	}
+
+	/**
+	 * Get identifier
+	 *
+	 * @return string
+	 */
+	public function getIdentifier() {
+		return $this->identifier;
+	}
+
+	/**
+	 * MenuItem Factory Method
+	 *
+	 * @return MenuItem
+	 */
+	public function makeMenuItem() {
+		$menuItem = GeneralUtility::makeInstance(MenuItem::class);
+		return $menuItem;
+	}
+
+	/**
+	 * Validation function
+	 *
+	 * @param Menu $menu The menu to validate
+	 *
+	 * @return bool
+	 */
+	public function isValid(Menu $menu) {
+		return (trim($menu->getIdentifier()) !== '');
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/Menu/MenuItem.php b/typo3/sysext/backend/Classes/Template/Components/Menu/MenuItem.php
new file mode 100644
index 0000000000000000000000000000000000000000..6960ef22d6d4c3afea84b3b88470bad8c63d9df8
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/Menu/MenuItem.php
@@ -0,0 +1,97 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components\Menu;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\AbstractControl;
+
+/**
+ * MenuItem
+ */
+class MenuItem extends AbstractControl {
+
+	/**
+	 * Sets the href of the menuItem
+	 *
+	 * @var string
+	 */
+	protected $href = '';
+
+	/**
+	 * Sets the active state of the menuItem
+	 *
+	 * @var bool
+	 */
+	protected $active = FALSE;
+
+	/**
+	 * Set href
+	 *
+	 * @param string $href Href of the MenuItem
+	 *
+	 * @return MenuItem
+	 */
+	public function setHref($href) {
+		$this->href = $href;
+		return $this;
+	}
+
+	/**
+	 * Set active
+	 *
+	 * @param bool $active Defines whether a menuItem is active
+	 *
+	 * @return MenuItem
+	 */
+	public function setActive($active) {
+		$this->active = $active;
+		return $this;
+	}
+
+	/**
+	 * Get href
+	 *
+	 * @return string
+	 */
+	public function getHref() {
+		return $this->href;
+	}
+
+	/**
+	 * Check if is active
+	 *
+	 * @return bool
+	 */
+	public function isActive() {
+		return $this->active;
+	}
+
+	/**
+	 * Validation
+	 *
+	 * @param MenuItem $menuItem The menuItem to validate
+	 *
+	 * @return bool
+	 */
+	public function isValid(MenuItem $menuItem) {
+		if (
+			$menuItem->getHref() !== ''
+			&& $menuItem->getTitle() !== ''
+		) {
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/MenuRegistry.php b/typo3/sysext/backend/Classes/Template/Components/MenuRegistry.php
new file mode 100644
index 0000000000000000000000000000000000000000..ded6f9eff618c172d15ef1332e79eb9f46b731fe
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/MenuRegistry.php
@@ -0,0 +1,79 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Menu\Menu;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * MenuRegistry
+ */
+class MenuRegistry {
+
+	/**
+	 * Internal array that stores all registered menus
+	 *
+	 * @var array
+	 */
+	protected $menus = [];
+
+	/**
+	 * Adds a menu to the registry
+	 *
+	 * @param Menu $menu Menu object to add to the menuRegistry
+	 *
+	 * @throws \InvalidArgumentException In case a menu is not valid
+	 *
+	 * @return void
+	 */
+	public function addMenu(Menu $menu) {
+		if (!$menu->isValid($menu)) {
+			throw new \InvalidArgumentException('Menu "' . $menu->getIdentifier() . '" is not valid', 1442236362);
+		}
+		$this->menus[$menu->getIdentifier()] = clone $menu;
+	}
+
+	/**
+	 * Returns all menus in an abstract array
+	 *
+	 * @return array
+	 */
+	public function getMenus() {
+		// @todo do we want to provide a hook here?
+		/**
+		 * For Code Completion
+		 *
+		 * @var int $key
+		 * @var Menu $menu
+		 */
+		foreach ($this->menus as $key => $menu) {
+			if (empty($menu->getMenuItems())) {
+				unset($this->menus[$key]);
+			}
+		}
+		return $this->menus;
+	}
+
+	/**
+	 * MenuFactory method
+	 *
+	 * @return Menu
+	 */
+	public function makeMenu() {
+		$menu = GeneralUtility::makeInstance(Menu::class);
+		return $menu;
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/Components/MetaInformation.php b/typo3/sysext/backend/Classes/Template/Components/MetaInformation.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae349eee2cc228e0578d11531587306c5ca8597a
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/Components/MetaInformation.php
@@ -0,0 +1,133 @@
+<?php
+namespace TYPO3\CMS\Backend\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\ModuleTemplate;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\Utility\IconUtility;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Core\Imaging\IconFactory;
+
+/**
+ * MetaInformation
+ */
+class MetaInformation {
+
+	/**
+	 * The recordArray.
+	 * Typically this is a page record
+	 *
+	 * @var array
+	 */
+	protected $recordArray = [];
+
+	/**
+	 * Set the RecordArray
+	 *
+	 * @param array $recordArray RecordArray
+	 *
+	 * @return void
+	 */
+	public function setRecordArray(array $recordArray) {
+		$this->recordArray = $recordArray;
+	}
+
+	/**
+	 * Generate the page path for docHeader
+	 *
+	 * @return string The page path
+	 */
+	public function getPath() {
+		$pageRecord = $this->recordArray;
+		// Is this a real page
+		if (is_array($pageRecord) && $pageRecord['uid']) {
+			$title = substr($pageRecord['_thePathFull'], 0, -1);
+			// Remove current page title
+			$pos = strrpos($title, $pageRecord['title']);
+			if ($pos !== FALSE) {
+				$title = substr($title, 0, $pos);
+			}
+		} else {
+			$title = '';
+		}
+		// Setting the path of the page
+		// crop the title to title limit (or 50, if not defined)
+		$beUser = $this->getBackendUser();
+		$cropLength = empty($beUser->uc['titleLen']) ? 50 : $beUser->uc['titleLen'];
+		$croppedTitle = GeneralUtility::fixed_lgd_cs($title, - $cropLength);
+		if ($croppedTitle !== $title) {
+			$pagePath = '<abbr title="' . htmlspecialchars($title) . '">' . htmlspecialchars($croppedTitle) . '</abbr>';
+		} else {
+			$pagePath = htmlspecialchars($title);
+		}
+		return $pagePath;
+	}
+
+	/**
+	 * Setting page icon with clickMenu + uid for docheader
+	 *
+	 * @return string Page info
+	 */
+	public function getRecordInformation() {
+		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+		$pageRecord = $this->recordArray;
+		// Add icon with clickMenu, etc:
+		// If there IS a real page
+		if (is_array($pageRecord) && $pageRecord['uid']) {
+			$altText = BackendUtility::getRecordIconAltText($pageRecord, 'pages');
+			$iconImg = IconUtility::getSpriteIconForRecord('pages', $pageRecord, array('title' => $altText));
+			// Make Icon:
+			$theIcon = ModuleTemplate::wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
+			$uid = $pageRecord['uid'];
+			$title = BackendUtility::getRecordTitle('pages', $pageRecord);
+		} else {
+			// On root-level of page tree
+			// Make Icon
+			$iconImg = '<span title="' .
+				htmlspecialchars($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) .
+				'">' .
+				$iconFactory->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render() . '</span>';
+			if ($this->getBackendUser()->isAdmin()) {
+				$theIcon = ModuleTemplate::wrapClickMenuOnIcon($iconImg, 'pages', 0);
+			} else {
+				$theIcon = $iconImg;
+			}
+			$uid = '0';
+			$title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
+		}
+		// Setting icon with clickMenu + uid
+		return $theIcon . '<strong>' . htmlspecialchars($title) . '&nbsp;[' . $uid . ']</strong>';
+	}
+
+	/**
+	 * Get LanguageService Object
+	 *
+	 * @return LanguageService
+	 */
+	protected function getLanguageService() {
+		return $GLOBALS['LANG'];
+	}
+
+	/**
+	 * Get the Backend User Object
+	 *
+	 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+	 */
+	protected function getBackendUser() {
+		return $GLOBALS['BE_USER'];
+	}
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Classes/Template/ModuleTemplate.php b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1157e5948d4e5db544d94ea928bc84b8a5b5043
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php
@@ -0,0 +1,771 @@
+<?php
+namespace TYPO3\CMS\Backend\Template;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Page\PageRenderer;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\Exception\InvalidTemplateResourceException;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Version\View\VersionView;
+
+/**
+ * A class taking care of the "outer" HTML of a module, especially
+ * the doc header and other related parts.
+ *
+ * @internal This API is not yet carved in stone and may be adapted later.
+ */
+class ModuleTemplate {
+
+	/**
+	 * Error Icon Constant
+	 *
+	 * @internal
+	 */
+	const STATUS_ICON_ERROR = 3;
+
+	/**
+	 * Warning Icon Constant
+	 *
+	 * @internal
+	 */
+	const STATUS_ICON_WARNING = 2;
+
+	/**
+	 * Notification Icon Constant
+	 *
+	 * @internal
+	 */
+	const STATUS_ICON_NOTIFICATION = 1;
+
+	/**
+	 * OK Icon Constant
+	 *
+	 * @internal
+	 */
+	const STATUS_ICON_OK = -1;
+
+	/**
+	 * DocHeaderComponent
+	 *
+	 * @var DocHeaderComponent
+	 */
+	protected $docHeaderComponent;
+
+	/**
+	 * Javascript Code Array
+	 * Used for inline JS
+	 *
+	 * @var array
+	 */
+	protected $javascriptCodeArray = [];
+
+	/**
+	 * Expose the pageRenderer
+	 *
+	 * @var PageRenderer
+	 */
+	protected $pageRenderer;
+
+	/**
+	 * TemplateRootPath
+	 *
+	 * @var string
+	 */
+	protected $templateRootPath = 'EXT:backend/Resources/Private/Templates';
+
+	/**
+	 * PartialRootPath
+	 *
+	 * @var string
+	 */
+	protected $partialRootPath = 'EXT:backend/Resources/Private/Partials';
+
+	/**
+	 * LayoutRootPath
+	 *
+	 * @var string
+	 */
+	protected $layoutRootPath = 'EXT:backend/Resources/Private/Layouts';
+
+	/**
+	 * Template name
+	 *
+	 * @var string
+	 */
+	protected $templateFile = 'Module.html';
+
+	/**
+	 * Fluid Standalone View
+	 *
+	 * @var StandaloneView
+	 */
+	protected $view;
+
+	/**
+	 * Content String
+	 *
+	 * @var string
+	 */
+	protected $content = '';
+
+	/**
+	 * Defines whether a section has been opened before
+	 *
+	 * @var int
+	 */
+	protected $sectionFlag = 0;
+
+	/**
+	 * IconFactory Member
+	 *
+	 * @var IconFactory
+	 */
+	protected $iconFactory;
+
+	/**
+	 * Module ID
+	 *
+	 * @var string
+	 */
+	protected $moduleId = '';
+
+	/**
+	 * Module Name
+	 *
+	 * @var string
+	 */
+	protected $moduleName = '';
+
+	/**
+	 * Get template root path
+	 *
+	 * @return string
+	 */
+	public function getTemplateRootPath() {
+		return $this->templateRootPath;
+	}
+
+	/**
+	 * Set content
+	 *
+	 * @param string $content Content of the module
+	 *
+	 * @return void
+	 */
+	public function setContent($content) {
+		$this->view->assign('content', $content);
+	}
+
+	/**
+	 * Class constructor
+	 * Sets up view and property objects
+	 *
+	 * @throws InvalidTemplateResourceException In case a template is invalid
+	 */
+	public function __construct() {
+		$this->view = GeneralUtility::makeInstance(StandaloneView::class);
+		$this->view->setPartialRootPaths([$this->partialRootPath]);
+		$this->view->setTemplateRootPaths([$this->templateRootPath]);
+		$this->view->setLayoutRootPaths([$this->layoutRootPath]);
+		$this->view->setTemplate($this->templateFile);
+		$this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
+		$this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class);
+		$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+	}
+
+	/**
+	 * Loads all necessary Javascript Files
+	 *
+	 * @return void
+	 */
+	protected function loadJavaScripts() {
+		$this->pageRenderer->loadJquery();
+		$this->pageRenderer->loadRequireJsModule('bootstrap');
+		$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
+	}
+
+	/**
+	 * Loads all necessary stylesheets
+	 *
+	 * @return void
+	 */
+	protected function loadStylesheets() {
+		if ($GLOBALS['TBE_STYLES']['stylesheet']) {
+			$this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheet']);
+		}
+		if ($GLOBALS['TBE_STYLES']['stylesheet2']) {
+			$this->pageRenderer->addCssFile($GLOBALS['TBE_STYLES']['stylesheet2']);
+		}
+	}
+
+	/**
+	 * Sets mandatory parameters for the view (pageRenderer)
+	 *
+	 * @return void
+	 */
+	protected function setupPage() {
+		// Yes, hardcoded on purpose
+		$this->pageRenderer->setCharSet('utf-8');
+		$this->pageRenderer->setLanguage('default');
+	}
+
+	/**
+	 * Wrapper function for adding JS inline blocks
+	 *
+	 * @return void
+	 */
+	protected function setJavaScriptCodeArray() {
+		foreach ($this->javascriptCodeArray as $name => $code) {
+			$this->pageRenderer->addJsInlineCode($name, $code, FALSE);
+		}
+	}
+
+	/**
+	 * Adds JS inline blocks of code to the internal registry
+	 *
+	 * @param string $name Javascript code block name
+	 * @param string $code Inline Javascript
+	 *
+	 * @return void
+	 */
+	public function addJavaScriptCode($name = '', $code = '') {
+		$this->javascriptCodeArray[$name] = $code;
+	}
+
+	/**
+	 * Get the DocHeader
+	 *
+	 * @return DocHeaderComponent
+	 */
+	public function getDocHeaderComponent() {
+		return $this->docHeaderComponent;
+	}
+
+	/**
+	 * Returns the fully rendered view
+	 *
+	 * @return string
+	 */
+	public function renderContent() {
+		$this->setupPage();
+		$this->loadJavaScripts();
+		$this->setJavaScriptCodeArray();
+		$this->loadStylesheets();
+
+		$this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent());
+		if ($this->moduleId) {
+			$this->view->assign('moduleId', $this->moduleId);
+		}
+		if ($this->moduleName) {
+			$this->view->assign('moduleName', $this->moduleName);
+		}
+
+		$renderedPage = $this->pageRenderer->render(PageRenderer::PART_HEADER);
+		$renderedPage .= $this->view->render();
+		$renderedPage .= $this->pageRenderer->render(PageRenderer::PART_FOOTER);
+
+		return $renderedPage;
+	}
+
+	/**
+	 * Get PageRenderer
+	 *
+	 * @return PageRenderer
+	 */
+	public function getPageRenderer() {
+		return $this->pageRenderer;
+	}
+
+	/**
+	 * Set form tag
+	 *
+	 * @param string $formTag Form tag to add
+	 *
+	 * @return void
+	 */
+	public function setForm($formTag = '') {
+		$this->view->assign('formTag', $formTag);
+	}
+
+	/**
+	 * Sets the ModuleId
+	 *
+	 * @param string $moduleId ID of the module
+	 *
+	 * @return void
+	 */
+	public function setModuleId($moduleId) {
+		$this->moduleId = $moduleId;
+		$this->registerModuleMenu($moduleId);
+	}
+
+	/**
+	 * Sets the ModuleName
+	 *
+	 * @param string $moduleName Name of the module
+	 *
+	 * @return void
+	 */
+	public function setModuleName($moduleName) {
+		$this->moduleName = $moduleName;
+	}
+
+	/**
+	 * Generates the Menu for things like Web->Info
+	 *
+	 * @param $moduleMenuIdentifier
+	 */
+	public function registerModuleMenu($moduleMenuIdentifier) {
+		if (isset($GLOBALS['TBE_MODULES_EXT'][$moduleMenuIdentifier])) {
+			$menuEntries =
+				$GLOBALS['TBE_MODULES_EXT'][$moduleMenuIdentifier]['MOD_MENU']['function'];
+			$menu = $this->getDocHeaderComponent()->getMenuRegistry()->makeMenu()->setIdentifier('MOD_FUNC');
+			foreach ($menuEntries as $menuEntry) {
+				$menuItem = $menu->makeMenuItem()
+					->setTitle($menuEntry['title'])
+					->setHref('#');
+				$menu->addMenuItem($menuItem);
+			}
+			$this->docHeaderComponent->getMenuRegistry()->addMenu($menu);
+		}
+	}
+
+
+
+	/*******************************************
+	 * THE FOLLOWING METHODS ARE SUBJECT TO BE DEPRECATED / DROPPED!
+	 *
+	 * These methods have been copied over from DocumentTemplate and enables
+	 * core modules to drop the dependency to DocumentTemplate altogether without
+	 * rewriting these modules now.
+	 * The methods below are marked as internal and will be removed
+	 * one-by-one with further refactoring of modules.
+	 *
+	 * Do not use these methods within own extensions if possible or
+	 * be prepared to change this later again.
+	 *******************************************/
+
+	/**
+	 * Makes click menu link (context sensitive menu)
+	 * Returns $str (possibly an <|img> tag/icon) wrapped in a link which will
+	 * activate the context sensitive menu for the record ($table/$uid) or
+	 * file ($table = file)
+	 * The link will load the top frame with the parameter "&item" which is
+	 * the table,uid and listFr arguments imploded
+	 * by "|": rawurlencode($table.'|'.$uid.'|'.$listFr)
+	 *
+	 * @param string $content String to be wrapped in link, typ. image tag.
+	 * @param string $table Table name/File path. If the icon is for a database
+	 * record, enter the tablename from $GLOBALS['TCA']. If a file then enter
+	 * the absolute filepath
+	 * @param int $uid If icon is for database record this is the UID for the
+	 * record from $table
+	 * @param bool $listFr Tells the top frame script that the link is coming
+	 * from a "list" frame which means a frame from within the backend content frame.
+	 * @param string $addParams Additional GET parameters for the link to the
+	 * ClickMenu AJAX request
+	 * @param string $enDisItems Enable / Disable click menu items.
+	 * Example: "+new,view" will display ONLY these two items (and any spacers
+	 * in between), "new,view" will display all BUT these two items.
+	 * @param bool $returnTagParameters If set, will return only the onclick
+	 * JavaScript, not the whole link.
+	 *
+	 * @return string The link-wrapped input string.
+	 * @internal
+	 */
+	public function wrapClickMenuOnIcon(
+		$content,
+		$table,
+		$uid = 0,
+		$listFr = TRUE,
+		$addParams = '',
+		$enDisItems = '',
+		$returnTagParameters = FALSE
+	) {
+		$tagParameters = array(
+			'class'           => 't3-js-clickmenutrigger',
+			'data-table'      => $table,
+			'data-uid'        => (int)$uid !== 0 ? (int)$uid : '',
+			'data-listframe'  => $listFr,
+			'data-iteminfo'   => str_replace('+', '%2B', $enDisItems),
+			'data-parameters' => $addParams,
+		);
+
+		if ($returnTagParameters) {
+			return $tagParameters;
+		}
+		return '<a href="#" ' . GeneralUtility::implodeAttributes($tagParameters, TRUE) . '>' . $content . '</a>';
+	}
+
+	/**
+	 * Includes a javascript library that exists in the core /typo3/ directory
+	 *
+	 * @param string $lib Library name. Call it with the full path like
+	 * "sysext/core/Resources/Public/JavaScript/QueryGenerator.js" to load it
+	 *
+	 * @return void
+	 * @internal
+	 */
+	public function loadJavascriptLib($lib) {
+		// @todo: maybe we can remove this one as well
+		$this->pageRenderer->addJsFile($lib);
+	}
+
+	/**
+	 * Returns a linked shortcut-icon which will call the shortcut frame and set a
+	 * shortcut there back to the calling page/module
+	 *
+	 * @param string $gvList Is the list of GET variables to store (if any)
+	 * @param string $setList Is the list of SET[] variables to store
+	 * (if any) - SET[] variables a stored in $GLOBALS["SOBE"]->MOD_SETTINGS
+	 * for backend modules
+	 * @param string $modName Module name string
+	 * @param string|int $motherModName Is used to enter the "parent module
+	 * name" if the module is a submodule under eg. Web>* or File>*. You
+	 * can also set this value to 1 in which case the currentLoadedModule
+	 * is sent to the shortcut script (so - not a fixed value!) - that is used
+	 * in file_edit and wizard_rte modules where those are really running as
+	 * a part of another module.
+	 *
+	 * @return string HTML content
+	 * @todo Make this thing return a button object
+	 * @internal
+	 */
+	public function makeShortcutIcon($gvList, $setList, $modName, $motherModName = '') {
+		$storeUrl = $this->makeShortcutUrl($gvList, $setList);
+		$pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
+		// Fallback for alt_mod. We still pass in the old xMOD... stuff,
+		// but TBE_MODULES only knows about "record_edit".
+		// We still need to pass the xMOD name to createShortcut below,
+		// since this is used for icons.
+		$moduleName = $modName === 'xMOD_alt_doc.php' ? 'record_edit' : $modName;
+		// Add the module identifier automatically if typo3/index.php is used:
+		if (GeneralUtility::_GET('M') !== NULL && isset($GLOBALS['TBE_MODULES']['_PATHS'][$moduleName])) {
+			$storeUrl = '&M=' . $moduleName . $storeUrl;
+		}
+		if ((int)$motherModName === 1) {
+			$motherModule = 'top.currentModuleLoaded';
+		} elseif ($motherModName) {
+			$motherModule = GeneralUtility::quoteJSvalue($motherModName);
+		} else {
+			$motherModule = '\'\'';
+		}
+		$confirmationText = GeneralUtility::quoteJSvalue(
+			$this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark')
+		);
+
+		$shortcutUrl = $pathInfo['path'] . '?' . $storeUrl;
+		$shortcutExist = BackendUtility::shortcutExists($shortcutUrl);
+
+		if ($shortcutExist) {
+			return '<a class="active" title="">' .
+			$this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render() . '</a>';
+		}
+
+		$url = GeneralUtility::quoteJSvalue(rawurlencode($shortcutUrl));
+		$onClick = 'top.TYPO3.ShortcutMenu.createShortcut(' . GeneralUtility::quoteJSvalue(rawurlencode($modName)) .
+			', ' . $url . ', ' . $confirmationText . ', ' . $motherModule . ', this);return false;';
+
+		return '<a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' .
+		$this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.makeBookmark', TRUE) . '">' .
+		$this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render() . '</a>';
+	}
+
+	/**
+	 * MAKE url for storing
+	 * Internal func
+	 *
+	 * @param string $gvList Is the list of GET variables to store (if any)
+	 * @param string $setList Is the list of SET[] variables to store (if any)
+	 * - SET[] variables a stored in $GLOBALS["SOBE"]->MOD_SETTINGS for backend
+	 * modules
+	 *
+	 * @return string
+	 * @internal
+	 */
+	public function makeShortcutUrl($gvList, $setList) {
+		$getParams = GeneralUtility::_GET();
+		$storeArray = array_merge(
+			GeneralUtility::compileSelectedGetVarsFromArray($gvList, $getParams),
+			array('SET' => GeneralUtility::compileSelectedGetVarsFromArray($setList, (array)$GLOBALS['SOBE']->MOD_SETTINGS))
+		);
+		return GeneralUtility::implodeArrayForUrl('', $storeArray);
+	}
+
+	/**
+	 * Returns a URL with a command to TYPO3 Core Engine (tce_db.php)
+	 * See description of the API elsewhere.
+	 *
+	 * @param string $params Is a set of GET params to send to tce_db.php.
+	 * Example: "&cmd[tt_content][123][move]=456" or
+	 * "&data[tt_content][123][hidden]=1&data[tt_content][123][title]=Hello%20World
+	 * @param string|int $redirectUrl Redirect URL, default is to use
+	 * GeneralUtility::getIndpEnv('REQUEST_URI'), -1 means to generate
+	 * an URL for JavaScript using T3_THIS_LOCATION
+	 *
+	 * @return string URL to BackendUtility::getModuleUrl('tce_db') + parameters
+	 * @internal
+	 */
+	public function issueCommand($params, $redirectUrl = '') {
+		$urlParameters = [
+			'prErr' => 1,
+			'uPT' => 1,
+			'vC' => $this->getBackendUserAuthentication()->veriCode()
+		];
+		$url = BackendUtility::getModuleUrl('tce_db', $urlParameters) . $params . '&redirect=';
+		if ((int)$redirectUrl === -1) {
+			$url = GeneralUtility::quoteJSvalue($url) . '+T3_THIS_LOCATION';
+		} else {
+			$url .= rawurlencode($redirectUrl ?: GeneralUtility::getIndpEnv('REQUEST_URI'));
+		}
+		return $url;
+	}
+
+	/**
+	 * Creates the version selector for the page id inputted.
+	 * Requires the core version management extension, "version" to be loaded.
+	 *
+	 * @param int $id Page id to create selector for.
+	 * @param bool $noAction If set, there will be no button for swapping page.
+	 *
+	 * @return string
+	 * @internal
+	 */
+	public function getVersionSelector($id, $noAction = FALSE) {
+		if (
+			ExtensionManagementUtility::isLoaded('version') &&
+			!ExtensionManagementUtility::isLoaded('workspaces')
+		) {
+			/**
+			 * For Code Completion
+			 *
+			 * @var $versionGuiObj VersionView
+			 */
+			$versionGuiObj = GeneralUtility::makeInstance(VersionView::class);
+			return $versionGuiObj->getVersionSelector($id, $noAction);
+		}
+		return '';
+	}
+
+	/**
+	 * Begins an output section and sets header and content
+	 *
+	 * @param string $label The header
+	 * @param string $text The HTML-content
+	 * @param bool $noStrToUpper A flag that will prevent the header from
+	 * being converted to uppercase
+	 * @param bool $sH Defines the type of header (if set, "<h3>" rather
+	 * than the default "h4")
+	 * @param int $type The number of an icon to show with the header
+	 * (see the icon-function). -1,1,2,3
+	 * @param bool $allowHtmlInHeader If set, HTML tags are allowed in
+	 * $label (otherwise this value is by default htmlspecialchars()'ed)
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function section($label, $text, $noStrToUpper = FALSE, $sH = FALSE, $type = 0, $allowHtmlInHeader = FALSE) {
+		$str = '';
+		// Setting header
+		if ($label) {
+			if (!$allowHtmlInHeader) {
+				$label = htmlspecialchars($label);
+			}
+			$str .= $this->sectionHeader($this->icons($type) . $label, $sH, $noStrToUpper ? '' : ' class="uppercase"');
+		}
+		// Setting content
+		$str .= '
+
+	<!-- Section content -->
+' . $text;
+		return $this->sectionBegin() . $str;
+	}
+
+	/**
+	 * Inserts a divider image
+	 * Ends a section (if open) before inserting the image
+	 *
+	 * @param int $dist The margin-top/-bottom of the <hr> ruler.
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function divider($dist) {
+		$dist = (int)$dist;
+		$str = '
+
+	<!-- DIVIDER -->
+	<hr style="margin-top: ' . $dist . 'px; margin-bottom: ' . $dist . 'px;" />
+';
+		return $this->sectionEnd() . $str;
+	}
+
+	/**
+	 * Returns a blank <div>-section with a height
+	 *
+	 * @param int $dist Padding-top for the div-section
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function spacer($dist) {
+		if ($dist > 0) {
+			return '
+
+	<!-- Spacer element -->
+	<div style="padding-top: ' . (int)$dist . 'px;"></div>
+';
+		}
+		return '';
+	}
+
+	/**
+	 * Make a section header.
+	 * Begins a section if not already open.
+	 *
+	 * @param string $label The label between the <h3> or <h4> tags. (Allows HTML)
+	 * @param bool $sH If set, <h3> is used, otherwise <h4>
+	 * @param string $addAttribute Additional attributes to h-tag, eg. ' class=""'
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function sectionHeader($label, $sH = FALSE, $addAttribute = '') {
+		$tag = $sH ? 'h2' : 'h3';
+		if ($addAttribute && $addAttribute[0] !== ' ') {
+			$addAttribute = ' ' . $addAttribute;
+		}
+		$str = '
+
+	<!-- Section header -->
+	<' . $tag . $addAttribute . '>' . $label . '</' . $tag . '>
+';
+		return $this->sectionBegin() . $str;
+	}
+
+	/**
+	 * Begins an output section.
+	 * Returns the <div>-begin tag AND sets the ->sectionFlag TRUE
+	 * (if the ->sectionFlag is not already set!)
+	 * You can call this function even if a section is already begun
+	 * since the function will only return something if the sectionFlag
+	 * is not already set!
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function sectionBegin() {
+		if (!$this->sectionFlag) {
+			$this->sectionFlag = 1;
+			$str = '
+
+	<!-- ***********************
+	      Begin output section.
+	     *********************** -->
+	<div>
+';
+			return $str;
+		}
+		return '';
+	}
+
+	/**
+	 * Ends and output section
+	 * Returns the </div>-end tag AND clears the ->sectionFlag
+	 * (but does so only IF the sectionFlag is set - that is a section is 'open')
+	 * See sectionBegin() also.
+	 *
+	 * @return string HTML content
+	 * @internal
+	 */
+	public function sectionEnd() {
+		if ($this->sectionFlag) {
+			$this->sectionFlag = 0;
+			return '
+	</div>
+	<!-- *********************
+	      End output section.
+	     ********************* -->
+';
+		}
+		return '';
+	}
+
+
+
+	/**
+	 * Returns the BE USER Object
+	 *
+	 * @return BackendUserAuthentication
+	 */
+	protected function getBackendUserAuthentication() {
+		return $GLOBALS['BE_USER'];
+	}
+
+	/**
+	 * Returns the LanguageService
+	 *
+	 * @return LanguageService
+	 */
+	protected function getLanguageService() {
+		return $GLOBALS['LANG'];
+	}
+
+	/**
+	 * Returns an image-tag with an 18x16 icon of the following types:
+	 *
+	 * $type:
+	 * -1:»   OK icon (Check-mark)
+	 * 1:»   Notice (Speach-bubble)
+	 * 2:»   Warning (Yellow triangle)
+	 * 3:»   Fatal error (Red stop sign)
+	 *
+	 * @param int $type See description
+	 *
+	 * @return string HTML image tag (if applicable)
+	 * @internal
+	 */
+	public function icons($type) {
+		$icon = '';
+		switch ($type) {
+			case self::STATUS_ICON_ERROR:
+				$icon = 'status-dialog-error';
+				break;
+			case self::STATUS_ICON_WARNING:
+				$icon = 'status-dialog-warning';
+				break;
+			case self::STATUS_ICON_NOTIFICATION:
+				$icon = 'status-dialog-notification';
+				break;
+			case self::STATUS_ICON_OK:
+				$icon = 'status-dialog-ok';
+				break;
+			default:
+				// Do nothing
+		}
+		if ($icon != '') {
+			return $this->iconFactory->getIcon($icon, Icon::SIZE_SMALL)->render();
+		}
+		return '';
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Partials/ButtonBar.html b/typo3/sysext/backend/Resources/Private/Partials/ButtonBar.html
new file mode 100644
index 0000000000000000000000000000000000000000..f1b5b7195421abf07b277a718f089ded126ca9fc
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Partials/ButtonBar.html
@@ -0,0 +1,9 @@
+<div class="btn-toolbar" role="toolbar" aria-label="">
+	<f:for each="{buttons}" as="buttonGroup">
+		<div class="btn-group" role="group" aria-label="">
+			<f:for each="{buttonGroup}" as="button">
+				{button}
+			</f:for>
+		</div>
+	</f:for>
+</div>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Partials/DocHeader.html b/typo3/sysext/backend/Resources/Private/Partials/DocHeader.html
new file mode 100644
index 0000000000000000000000000000000000000000..b6dd7d015e75cce8a02c7963209f70b1396f1da6
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Partials/DocHeader.html
@@ -0,0 +1,25 @@
+<div class="module-docheader">
+	<div class="module-docheader-bar">
+		<div class="module-docheader-bar-column-left">
+			<div class="form-inline">
+				<f:for each="{docHeader.menus}" as="menu">
+					<div class="form-group form-group-sm">
+						<f:render partial="Menus/SelectBoxJumpMenu" arguments="{menu:menu}" />
+					</div>
+				</f:for>
+			</div>
+		</div>
+		<div class="module-docheader-bar-column-right">
+			<span class="typo3-docheader-pagePath"><f:translate key="LLL:EXT:lang/locallang_core.xlf:labels.path" />: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw></span> <f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw>
+		</div>
+
+	</div>
+	<div class="module-docheader-bar">
+		<div class="module-docheader-bar-column-left">
+			<f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.left}" />
+		</div>
+		<div class="module-docheader-bar-column-right">
+			<f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}" />
+		</div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Partials/Menus/SelectBoxJumpMenu.html b/typo3/sysext/backend/Resources/Private/Partials/Menus/SelectBoxJumpMenu.html
new file mode 100644
index 0000000000000000000000000000000000000000..c6c7e7d673e32a1f2051414c5582ffbb0a5087d3
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Partials/Menus/SelectBoxJumpMenu.html
@@ -0,0 +1,5 @@
+{menu.label} <select class="form-control t3-js-jumpMenuBox" name="{menu.identifier}" onchange="if(this.options[this.selectedIndex].value){window.location.href=(this.options[this.selectedIndex].value);}">
+	<f:for each="{menu.menuItems}" as="menuItem">
+		<option value="{menuItem.href}" {f:if(condition: '{menuItem.active}', then: ' selected="selected"')}>{menuItem.title}</option>
+	</f:for>
+</select>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Templates/Module.html b/typo3/sysext/backend/Resources/Private/Templates/Module.html
new file mode 100644
index 0000000000000000000000000000000000000000..bb3fe1cc166d69cca3ecc203f80a3ea5eca72439
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Templates/Module.html
@@ -0,0 +1,16 @@
+<div class="module" data-module-id="{moduleId}" data-module-name="{moduleName}">
+	<f:if condition="{formTag}">
+		<f:then>
+			<f:format.raw>{formTag}</f:format.raw>
+		</f:then>
+	</f:if>
+	<f:render partial="DocHeader" arguments="{docHeader:docHeader}" />
+	<div class="module-body">
+		<f:format.raw>{content}</f:format.raw>
+	</div>
+	<f:if condition="{formTag}">
+		<f:then>
+			</form>
+		</f:then>
+	</f:if>
+</div>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Templates/blank.html b/typo3/sysext/backend/Resources/Private/Templates/blank.html
new file mode 100644
index 0000000000000000000000000000000000000000..b1ae1ad5620cf347c64cdd62dc57883dfd8d3a06
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Templates/blank.html
@@ -0,0 +1,3 @@
+<!-- ###FULLDOC### begin -->
+###CONTENT###
+<!-- ###FULLDOC### end -->
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/Button/FullyRenderedButtonTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/FullyRenderedButtonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1309cab948c0df57371695d20c8399c5b0f7fb21
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/FullyRenderedButtonTest.php
@@ -0,0 +1,50 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Buttons\FullyRenderedButton;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case for FullyRenderedButton
+ */
+class FullyRenderedButtonTest extends UnitTestCase {
+
+	/**
+	 * Try to valide an empty button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidBlankCallExpectFalse() {
+		$button = new FullyRenderedButton();
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Tests a valid HTML Button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidHtmlSourceGivenExpectTrue() {
+		$button = new FullyRenderedButton();
+		$button->setHtmlSource('<span>Husel</span>');
+		$isValid = $button->isValid();
+		$this->assertTrue($isValid);
+	}
+
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/Button/InputButtonTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/InputButtonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5046ee9180f47fc23c3feb11e0e8d93f45bad2d9
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/InputButtonTest.php
@@ -0,0 +1,106 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Buttons\InputButton;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case for InputButton
+ */
+class InputButtonTest extends UnitTestCase {
+
+	/**
+	 * Try to validate an empty button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidBlankCallExpectFalse() {
+		$button = new InputButton();
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the Icon
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedIconExpectFalse() {
+		$button = new InputButton();
+		$button->setName('husel')->setValue('1')->setTitle('huhu');
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the title
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedTitleExpectFalse() {
+		$button = new InputButton();
+		$icon = new Icon();
+		$button->setName('husel')->setValue('1')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the name
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedNameExpectFalse() {
+		$button = new InputButton();
+		$icon = new Icon();
+		$button->setTitle('husel')->setValue('1')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the Value
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedValueExpectFalse() {
+		$button = new InputButton();
+		$icon = new Icon();
+		$button->setTitle('husel')->setName('husel')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Set a 100% valid button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidAllValuesSetExpectTrue() {
+		$button = new InputButton();
+		$icon = new Icon();
+		$button->setTitle('husel')->setName('husel')->setIcon($icon)->setValue('1');
+		$isValid = $button->isValid();
+		$this->assertTrue($isValid);
+	}
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/Button/LinkButtonTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/LinkButtonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bbdefc280aa05ad46b855fdf30fbaf1d4f037edb
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/LinkButtonTest.php
@@ -0,0 +1,92 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case for LinkButton
+ */
+class LinkButtonTest extends UnitTestCase {
+
+	/**
+	 * Try validating an empty button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidBlankCallExpectFalse() {
+		$button = new LinkButton();
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the Icon
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedIconExpectFalse() {
+		$button = new LinkButton();
+		$button->setHref('#')->setTitle('huhu');
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit the title
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedTitleExpectFalse() {
+		$button = new LinkButton();
+		$icon = new Icon();
+		$button->setHref('husel')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Omit Href
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidOmittedHrefExpectFalse() {
+		$button = new LinkButton();
+		$icon = new Icon();
+		$button->setTitle('husel')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Send a valid button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidAllValuesSetExpectTrue() {
+		$button = new LinkButton();
+		$icon = new Icon();
+		$button->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$isValid = $button->isValid();
+		$this->assertTrue($isValid);
+	}
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/Button/SplitButtonTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/SplitButtonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..78f19d4a3f11c42d3e3c65ab43b8a04be70bdbc3
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/Button/SplitButtonTest.php
@@ -0,0 +1,126 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components\Buttons;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton;
+use TYPO3\CMS\Backend\Template\Components\Buttons\SplitButton;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Class BackendModuleRequestHandlerTest
+ */
+class SplitButtonTest extends UnitTestCase {
+
+	/**
+	 * Try to validate an empty button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidBlankCallExpectFalse() {
+		$button = new SplitButton();
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Try adding an invalid button to a splitButton
+	 *
+	 * @test
+	 * @expectedException \InvalidArgumentException
+	 * @expectedExceptionCode 1441706330
+	 * @return void
+	 */
+	public function isButtonValidInvalidButtonGivenExpectFalse() {
+		$button = new SplitButton();
+
+		$primaryAction = new LinkButton();
+		$button->addItem($primaryAction);
+
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Try to add multiple primary actions
+	 *
+	 * @test
+	 * @expectedException \InvalidArgumentException
+	 * @expectedExceptionCode 1441706340
+	 * @return void
+	 */
+	public function isButtonValidBrokenSetupMultiplePrimaryActionsGivenExpectFalse() {
+		$button = new SplitButton();
+
+		$primaryAction = new LinkButton();
+		$icon = new Icon();
+		$primaryAction->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$button->addItem($primaryAction, TRUE);
+
+		$anotherPrimaryAction = new LinkButton();
+		$anotherPrimaryAction->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$button->addItem($anotherPrimaryAction, TRUE);
+
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Try to add an invalid button as second parameter
+	 *
+	 * @test
+	 * @expectedException \InvalidArgumentException
+	 * @expectedExceptionCode 1441706330
+	 * @return void
+	 */
+	public function isButtonValidBrokenSetupInvalidButtonAsSecondParametersGivenExpectFalse() {
+		$button = new SplitButton();
+
+		$primaryAction = new LinkButton();
+		$icon = new Icon();
+		$primaryAction->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$button->addItem($primaryAction, TRUE);
+
+		$anotherPrimaryAction = new LinkButton();
+		$anotherPrimaryAction->setTitle('husel')->setHref('husel');
+		$button->addItem($anotherPrimaryAction, TRUE);
+
+		$isValid = $button->isValid();
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Send in a valid button
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isButtonValidValidSetupExpectTrue() {
+		$button = new SplitButton();
+
+		$primaryAction = new LinkButton();
+		$icon = new Icon();
+		$primaryAction->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$button->addItem($primaryAction, TRUE);
+
+		$anotherAction = new LinkButton();
+		$anotherAction->setTitle('husel')->setHref('husel')->setIcon($icon);
+		$button->addItem($anotherAction);
+
+		$isValid = $button->isValid();
+		$this->assertTrue($isValid);
+	}
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/Menu/MenuItemTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/Menu/MenuItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..180b173fc9994b2ebda4eeb4193b51d7f56587a8
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/Menu/MenuItemTest.php
@@ -0,0 +1,77 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components\Menu;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Menu\MenuItem;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case for MenuItem
+ */
+class MenuItemTest extends UnitTestCase {
+
+	/**
+	 * Try a blank menu Item
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuItemValidBlankCallExpectFalse() {
+		$menuItem = new MenuItem();
+		$isValid = $menuItem->isValid($menuItem);
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Try omitting the title and a Href
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuItemValidOmittedHrefAndRouteExpectFalse() {
+		$menuItem = new MenuItem();
+		$menuItem->setTitle('huhu');
+		$isValid = $menuItem->isValid($menuItem);
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Try omitting the title
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuItemValidOmittedTitleExpectFalse() {
+		$menuItem = new MenuItem();
+		$menuItem->setHref('husel');
+		$isValid = $menuItem->isValid($menuItem);
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Set a valid title and href
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuItemValidSetValidHrefAndTitleExpectTrue() {
+		$menuItem = new MenuItem();
+		$menuItem->setTitle('husel')->setHref('husel');
+		$isValid = $menuItem->isValid($menuItem);
+		$this->assertTrue($isValid);
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/Template/Components/MenuTest.php b/typo3/sysext/backend/Tests/Unit/Template/Components/MenuTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4c4f779fab1648d822bdc233c0da693c5eb6384
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Template/Components/MenuTest.php
@@ -0,0 +1,94 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Template\Components;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Template\Components\Menu\Menu;
+use TYPO3\CMS\Backend\Template\Components\MenuRegistry;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case for Menu
+ */
+class MenuTest extends UnitTestCase {
+
+	/**
+	 * Try setting an empty menu
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuValidBlankCallExpectFalse() {
+		$menu = new Menu();
+		$isValid = $menu->isValid($menu);
+		$this->assertFalse($isValid);
+	}
+
+	/**
+	 * Set a valid menu
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function isMenuValidValidMenuWithDefaultsExpectTrue() {
+		$menu = new Menu();
+		$menu->setIdentifier('husel');
+		$isValid = $menu->isValid($menu);
+		$this->assertTrue($isValid);
+	}
+
+	/**
+	 * Set a valid menu
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function makeMenuAllGoodExpectTrue() {
+		$menuRegistry = new MenuRegistry();
+		$result = $menuRegistry->makeMenu()->setLabel('MenuLabel')->setIdentifier('MenuIdent');
+		$expected = new Menu();
+		$expected->setIdentifier('MenuIdent');
+		$expected->setLabel('MenuLabel');
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * Tests if empty menus get removed from the stack
+	 *
+	 * @test
+	 * @return void
+	 */
+	public function getMenusremovedEmptyMenusExpectsEquals() {
+		$menuRegistry = new MenuRegistry();
+
+		$menu1 = $menuRegistry->makeMenu();
+		$menu1->setIdentifier('husel');
+		$menu1->setLabel('Label of an empty Menu');
+		$menuRegistry->addMenu($menu1);
+
+		$menu2 = $menuRegistry->makeMenu()->setIdentifier('Foo');
+		$item = $menu2->makeMenuItem()->setHref('#')->setTitle('Husel');
+		$menu2->addMenuItem($item);
+
+		$menuRegistry->addMenu($menu2);
+
+		$result = $menuRegistry->getMenus();
+		$expected = [
+			'Foo' => $menu2
+		];
+
+		$this->assertEquals($expected, $result);
+	}
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-69814-ModuleTemplateAPI.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-69814-ModuleTemplateAPI.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7950c2749fe49726877af294e80aff17a36a431e
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-69814-ModuleTemplateAPI.rst
@@ -0,0 +1,98 @@
+==================
+ModuleTemplate API
+==================
+
+Challenge
+=========
+
+
+Currently all DocHeaders are implemented on their own.
+
+This means we have about 80 DocHeaders which are equal but not the same.
+
+The main challenge is to provide extension developers with all tools they need to build decent backend modules while maintaining control of the docHeader itself.
+
+Solution
+========
+
+We will provide a replacement for DocumentTemplate which provides an easy-to-use API which is on the other hand flexible enough to tackle all tasks we currently think of.
+
+At the same time we will remove the amount of duplicate marker based templates.
+
+The API uses the Fluent-API approach and has been built to supply maximum IDE code completion support.
+
+Parts of a docHeader Currently a typical docHeader is split up into the following sections:
+
+* Top Bar
+
+  * Context Sensitive Help Icon
+  * Select Menu(s)
+  * Path
+  * RecordInformation incl. Clickmenu
+
+* Bottom Bar
+
+  * Left Button Bar
+  * Right Button Bar
+
+API Components
+==============
+
+Buttons
+-------
+
+**InputButton**
+    Used to generate a <button> element.
+
+**LinkButton**
+    Used to generate links
+
+**SplitButton**
+    A mixed component accepting multiple button objects and renders them into a condensed form.
+
+**FullyRenderedButton**
+    Displays arbitrary HTML code and we highly recommend to use these.
+
+Menus
+-----
+
+Creating menus is pretty simple.
+Ask the ``DocHeaderComponent`` for the ``MenuRegistry`` and ask the ``MenuRegistry`` to create a ``Menu`` for you.
+
+The ``Menu`` in return can create ``MenuItems`` for you.
+
+A ``Menu`` can have several **Types** which are represented by their respective Fluid Partials in EXT:backend/Resources/Private/Partials/Menu/.
+
+
+Examples of usages
+==================
+
+**Adding a button**
+
+.. code-block:: php
+
+    $openInNewWindowButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()
+        ->makeLinkButton()
+        ->setHref('#')
+        ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.openInNewWindow', TRUE))
+        ->setIcon($this->iconFactory->getIcon('actions-window-open', Icon::SIZE_SMALL))
+        ->setOnClick($aOnClick);
+
+    $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()
+        ->addButton($openInNewWindowButton, ButtonBar::BUTTON_POSITION_RIGHT);
+
+**Adding a menu with menu items**
+
+.. code-block:: php
+
+    $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getModuleMenuRegistry()->makeMenu()
+        ->setIdentifier('_langSelector')
+        ->setLabel($this->getLanguageService()->sL('LLL:EXT:lang/locallang_general.xlf:LGL.language', TRUE));
+    $menuItem = $languageMenu->makeMenuItem()
+        ->setTitle($lang['title'] . $newTranslation)
+        ->setHref($href);
+    if((int)$lang['uid'] === $currentLanguage) {
+        $menuItem->setActive(TRUE);
+    }
+    $languageMenu->addMenuItem($menuItem);
+    $this->moduleTemplate->getDocHeaderComponent()->getModuleMenuRegistry()->addMenu($languageMenu);
\ No newline at end of file
diff --git a/typo3/sysext/t3skin/Resources/Public/Css/backend.css b/typo3/sysext/t3skin/Resources/Public/Css/backend.css
index dadfc6207d6ccf5577f8426cf420f18b3113fa53..395b550eeeab3e0e2e72305f3f111dfbfdb0066f 100644
--- a/typo3/sysext/t3skin/Resources/Public/Css/backend.css
+++ b/typo3/sysext/t3skin/Resources/Public/Css/backend.css
@@ -7854,6 +7854,81 @@ button.close {
   background-color: #ebfce3;
   text-decoration: none;
 }
+.module {
+  height: 100%;
+  width: 100%;
+  background-color: #ffffff;
+}
+.module form {
+  margin: 0;
+}
+.module-docheader {
+  position: fixed;
+  width: 100%;
+  top: 0;
+  left: 0;
+  height: 65px;
+  z-index: 300;
+  background-color: #eeeeee;
+  border-bottom: 1px solid #c3c3c3;
+  padding: 0 24px;
+}
+.module-docheader:before,
+.module-docheader:after {
+  content: " ";
+  display: table;
+}
+.module-docheader:after {
+  clear: both;
+}
+.module-docheader:before,
+.module-docheader:after {
+  content: " ";
+  display: table;
+}
+.module-docheader:after {
+  clear: both;
+}
+.module-docheader-bar {
+  height: 26px;
+  margin: 4px 0;
+  line-height: 26px;
+}
+.module-docheader-bar:before,
+.module-docheader-bar:after {
+  content: " ";
+  display: table;
+}
+.module-docheader-bar:after {
+  clear: both;
+}
+.module-docheader-bar:before,
+.module-docheader-bar:after {
+  content: " ";
+  display: table;
+}
+.module-docheader-bar:after {
+  clear: both;
+}
+.module-docheader-bar label {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.module-docheader-bar .form-group {
+  margin: 0;
+}
+.module-docheader-bar-column-left {
+  float: left;
+}
+.module-docheader-bar-column-right {
+  float: right;
+}
+.module-body {
+  padding: 24px 24px;
+}
+.module-docheader + .module-body {
+  padding-top: 89px;
+}
 .clearfix:before,
 .clearfix:after,
 .dl-horizontal dd:before,
@@ -11461,8 +11536,9 @@ a.badge-danger:hover,
 a.badge-danger:focus {
   background-color: #a32e2e;
 }
-.btn .t3-icon {
-  margin: 0;
+.btn-sm,
+.btn-group-sm > .btn {
+  min-height: 26px;
 }
 .btn-group {
   font-size: 0;