diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index dba31c99a1679f19bfa8590bb94bead9107f6053..ecce16fbb67c2b1cd7230bbf7e43a545e0eaa8f4 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -129,6 +129,16 @@ return array(
     'OCP\\DB\\QueryBuilder\\IParameter' => $baseDir . '/lib/public/DB/QueryBuilder/IParameter.php',
     'OCP\\DB\\QueryBuilder\\IQueryBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IQueryBuilder.php',
     'OCP\\DB\\QueryBuilder\\IQueryFunction' => $baseDir . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
+    'OCP\\Dashboard\\Exceptions\\DashboardAppNotAvailableException' => $baseDir . '/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php',
+    'OCP\\Dashboard\\IDashboardManager' => $baseDir . '/lib/public/Dashboard/IDashboardManager.php',
+    'OCP\\Dashboard\\IDashboardWidget' => $baseDir . '/lib/public/Dashboard/IDashboardWidget.php',
+    'OCP\\Dashboard\\Model\\IWidgetConfig' => $baseDir . '/lib/public/Dashboard/Model/IWidgetConfig.php',
+    'OCP\\Dashboard\\Model\\IWidgetRequest' => $baseDir . '/lib/public/Dashboard/Model/IWidgetRequest.php',
+    'OCP\\Dashboard\\Model\\WidgetSetting' => $baseDir . '/lib/public/Dashboard/Model/WidgetSetting.php',
+    'OCP\\Dashboard\\Model\\WidgetSetup' => $baseDir . '/lib/public/Dashboard/Model/WidgetSetup.php',
+    'OCP\\Dashboard\\Model\\WidgetTemplate' => $baseDir . '/lib/public/Dashboard/Model/WidgetTemplate.php',
+    'OCP\\Dashboard\\Service\\IEventsService' => $baseDir . '/lib/public/Dashboard/Service/IEventsService.php',
+    'OCP\\Dashboard\\Service\\IWidgetsService' => $baseDir . '/lib/public/Dashboard/Service/IWidgetsService.php',
     'OCP\\Defaults' => $baseDir . '/lib/public/Defaults.php',
     'OCP\\Diagnostics\\IEvent' => $baseDir . '/lib/public/Diagnostics/IEvent.php',
     'OCP\\Diagnostics\\IEventLogger' => $baseDir . '/lib/public/Diagnostics/IEventLogger.php',
@@ -672,6 +682,7 @@ return array(
     'OC\\DB\\SQLiteMigrator' => $baseDir . '/lib/private/DB/SQLiteMigrator.php',
     'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php',
     'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php',
+    'OC\\Dashboard\\DashboardManager' => $baseDir . '/lib/private/Dashboard/DashboardManager.php',
     'OC\\DatabaseException' => $baseDir . '/lib/private/DatabaseException.php',
     'OC\\DatabaseSetupException' => $baseDir . '/lib/private/DatabaseSetupException.php',
     'OC\\DateTimeFormatter' => $baseDir . '/lib/private/DateTimeFormatter.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 927f14ff72830eb8d834106417b57104ddc40730..8cfbc4c3e3a57e2a23e99ff8503fd98beec0ddc9 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -159,6 +159,16 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OCP\\DB\\QueryBuilder\\IParameter' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IParameter.php',
         'OCP\\DB\\QueryBuilder\\IQueryBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IQueryBuilder.php',
         'OCP\\DB\\QueryBuilder\\IQueryFunction' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
+        'OCP\\Dashboard\\Exceptions\\DashboardAppNotAvailableException' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php',
+        'OCP\\Dashboard\\IDashboardManager' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IDashboardManager.php',
+        'OCP\\Dashboard\\IDashboardWidget' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IDashboardWidget.php',
+        'OCP\\Dashboard\\Model\\IWidgetConfig' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/IWidgetConfig.php',
+        'OCP\\Dashboard\\Model\\IWidgetRequest' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/IWidgetRequest.php',
+        'OCP\\Dashboard\\Model\\WidgetSetting' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetSetting.php',
+        'OCP\\Dashboard\\Model\\WidgetSetup' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetSetup.php',
+        'OCP\\Dashboard\\Model\\WidgetTemplate' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetTemplate.php',
+        'OCP\\Dashboard\\Service\\IEventsService' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Service/IEventsService.php',
+        'OCP\\Dashboard\\Service\\IWidgetsService' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Service/IWidgetsService.php',
         'OCP\\Defaults' => __DIR__ . '/../../..' . '/lib/public/Defaults.php',
         'OCP\\Diagnostics\\IEvent' => __DIR__ . '/../../..' . '/lib/public/Diagnostics/IEvent.php',
         'OCP\\Diagnostics\\IEventLogger' => __DIR__ . '/../../..' . '/lib/public/Diagnostics/IEventLogger.php',
@@ -702,6 +712,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
         'OC\\DB\\SQLiteMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteMigrator.php',
         'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php',
         'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php',
+        'OC\\Dashboard\\DashboardManager' => __DIR__ . '/../../..' . '/lib/private/Dashboard/DashboardManager.php',
         'OC\\DatabaseException' => __DIR__ . '/../../..' . '/lib/private/DatabaseException.php',
         'OC\\DatabaseSetupException' => __DIR__ . '/../../..' . '/lib/private/DatabaseSetupException.php',
         'OC\\DateTimeFormatter' => __DIR__ . '/../../..' . '/lib/private/DateTimeFormatter.php',
diff --git a/lib/private/Dashboard/DashboardManager.php b/lib/private/Dashboard/DashboardManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..712d56641fae98012cbd6b857f5188777a2dcff9
--- /dev/null
+++ b/lib/private/Dashboard/DashboardManager.php
@@ -0,0 +1,148 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard app
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OC\Dashboard;
+
+
+use OCP\Dashboard\Exceptions\DashboardAppNotAvailableException;
+use OCP\Dashboard\IDashboardManager;
+use OCP\Dashboard\Model\IWidgetConfig;
+use OCP\Dashboard\Service\IEventsService;
+use OCP\Dashboard\Service\IWidgetsService;
+
+
+/**
+ * Class DashboardManager
+ *
+ * @package OC\Dashboard
+ */
+class DashboardManager implements IDashboardManager {
+
+
+	/** @var IWidgetsService */
+	private $widgetsService;
+
+	/** @var IEventsService */
+	private $eventsService;
+
+
+	/**
+	 * @param IEventsService $eventsService
+	 */
+	public function registerEventsService(IEventsService $eventsService) {
+		$this->eventsService = $eventsService;
+	}
+
+
+	/**
+	 * @param IWidgetsService $widgetsService
+	 */
+	public function registerWidgetsService(IWidgetsService $widgetsService) {
+		$this->widgetsService = $widgetsService;
+	}
+
+
+	/**
+	 * @param string $widgetId
+	 * @param string $userId
+	 *
+	 * @return IWidgetConfig
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function getWidgetConfig(string $widgetId, string $userId): IWidgetConfig {
+		return $this->getWidgetsService()->getWidgetConfig($widgetId, $userId);
+	}
+
+
+	/**
+	 * @param string $widgetId
+	 * @param array $users
+	 * @param array $payload
+	 * @param string $uniqueId
+	 *
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createUsersEvent(string $widgetId, array $users, array $payload, string $uniqueId = '') {
+		$this->getEventsService()->createUsersEvent($widgetId, $users, $payload, $uniqueId);
+	}
+
+
+	/**
+	 * @param string $widgetId
+	 * @param array $groups
+	 * @param array $payload
+	 * @param string $uniqueId
+	 *
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createGroupsEvent(string $widgetId, array $groups, array $payload, string $uniqueId = '') {
+		$this->getEventsService()->createGroupsEvent($widgetId, $groups, $payload, $uniqueId);
+	}
+
+
+	/**
+	 * @param string $widgetId
+	 * @param array $payload
+	 * @param string $uniqueId
+	 *
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createGlobalEvent(string $widgetId, array $payload, string $uniqueId = '') {
+		$this->getEventsService()->createGlobalEvent($widgetId, $payload, $uniqueId);
+	}
+
+
+	/**
+	 * @return IWidgetsService
+	 * @throws DashboardAppNotAvailableException
+	 */
+	private function getWidgetsService() {
+		if ($this->widgetsService === null) {
+			throw new DashboardAppNotAvailableException('No IWidgetsService registered');
+		}
+
+		return $this->widgetsService;
+	}
+
+
+	/**
+	 * @return IEventsService
+	 * @throws DashboardAppNotAvailableException
+	 */
+	private function getEventsService() {
+		if ($this->eventsService === null) {
+			throw new DashboardAppNotAvailableException('No IEventsService registered');
+		}
+
+		return $this->eventsService;
+	}
+
+}
+
diff --git a/lib/private/Server.php b/lib/private/Server.php
index c79f16567d8afc3f5d97296469d25ac1cc26aa76..5ea1b697391f8a4b073adad1d9a80abc45eb5a48 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -119,6 +119,7 @@ use OC\Tagging\TagMapper;
 use OC\Template\IconsCacher;
 use OC\Template\JSCombiner;
 use OC\Template\SCSSCacher;
+use OC\Dashboard\DashboardManager;
 use OCA\Theming\ImageManager;
 use OCA\Theming\ThemingDefaults;
 
@@ -126,6 +127,7 @@ use OCP\App\IAppManager;
 use OCP\AppFramework\Utility\ITimeFactory;
 use OCP\Collaboration\AutoComplete\IManager;
 use OCP\Contacts\ContactsMenu\IContactsStore;
+use OCP\Dashboard\IDashboardManager;
 use OCP\Defaults;
 use OCA\Theming\Util;
 use OCP\Federation\ICloudFederationFactory;
@@ -1172,6 +1174,8 @@ class Server extends ServerContainer implements IServerContainer {
 		});
 		$this->registerAlias(IContactsStore::class, ContactsStore::class);
 
+		$this->registerAlias(IDashboardManager::class, Dashboard\DashboardManager::class);
+
 		$this->connectDispatcher();
 	}
 
diff --git a/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php b/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..4c3013000e831ad1b8bb6be379cb5f5c0f91b787
--- /dev/null
+++ b/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php
@@ -0,0 +1,41 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard app
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Exceptions;
+
+/**
+ * @since 15.0.0
+ *
+ * Class DashboardAppNotAvailableException
+ *
+ * @package OCP\Dashboard\Exceptions
+ */
+class DashboardAppNotAvailableException extends \Exception {
+}
+
diff --git a/lib/public/Dashboard/IDashboardManager.php b/lib/public/Dashboard/IDashboardManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..ede47c4baaf958e8e53d8a819de35b82bfbd2080
--- /dev/null
+++ b/lib/public/Dashboard/IDashboardManager.php
@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCP\Dashboard;
+
+
+use OCP\Dashboard\Exceptions\DashboardAppNotAvailableException;
+use OCP\Dashboard\Model\IWidgetConfig;
+use OCP\Dashboard\Service\IEventsService;
+use OCP\Dashboard\Service\IWidgetsService;
+
+/**
+ * Interface IDashboardManager
+ *
+ * IDashboardManager should be used to manage widget from the backend.
+ * The call can be done from any Service.
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard
+ */
+interface IDashboardManager {
+
+
+	/**
+	 * Register a IWidgetsService.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param IWidgetsService $widgetsService
+	 */
+	public function registerWidgetsService(IWidgetsService $widgetsService);
+
+
+	/**
+	 * Register a IEventsService.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param IEventsService $eventsService
+	 */
+	public function registerEventsService(IEventsService $eventsService);
+
+
+	/**
+	 * returns the OCP\Dashboard\Model\IWidgetConfig for a widgetId and userId.
+	 *
+	 * @see IWidgetConfig
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param string $userId
+	 *
+	 * @throws DashboardAppNotAvailableException
+	 * @return IWidgetConfig
+	 */
+	public function getWidgetConfig(string $widgetId, string $userId): IWidgetConfig;
+
+
+	/**
+	 * Create push notifications for users.
+	 * $payload is an array that will be send to the Javascript method
+	 * called on push.
+	 * $uniqueId needs to be used if you send the push to multiples users
+	 * and multiples groups so that one user does not have duplicate
+	 * notifications.
+	 *
+	 * Push notifications are created in database and broadcast to user
+	 * that are running dashboard.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $users
+	 * @param array $payload
+	 * @param string $uniqueId
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createUsersEvent(string $widgetId, array $users, array $payload, string $uniqueId = '');
+
+
+	/**
+	 * Create push notifications for groups. (ie. createUsersEvent())
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $groups
+	 * @param array $payload
+	 * @param string $uniqueId
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createGroupsEvent(string $widgetId, array $groups, array $payload, string $uniqueId = '');
+
+
+	/**
+	 * Create push notifications for everyone. (ie. createUsersEvent())
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $payload
+	 * @param string $uniqueId
+	 * @throws DashboardAppNotAvailableException
+	 */
+	public function createGlobalEvent(string $widgetId, array $payload, string $uniqueId = '');
+
+}
+
diff --git a/lib/public/Dashboard/IDashboardWidget.php b/lib/public/Dashboard/IDashboardWidget.php
new file mode 100644
index 0000000000000000000000000000000000000000..bbbdf86da8f6b1cbab688174b8309b6e2e871270
--- /dev/null
+++ b/lib/public/Dashboard/IDashboardWidget.php
@@ -0,0 +1,147 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCP\Dashboard;
+
+
+use OCP\Dashboard\Model\WidgetSetup;
+use OCP\Dashboard\Model\WidgetTemplate;
+use OCP\Dashboard\Model\IWidgetConfig;
+use OCP\Dashboard\Model\IWidgetRequest;
+
+/**
+ * Interface IDashboardWidget
+ *
+ * This interface is used to create a widget: the widget must implement this
+ * interface and be defined in appinfo/info.xml:
+ *
+ *    <dashboard>
+ *      <widget>OCA\YourApp\YourWidget</widget>
+ *  </dashboard>
+ *
+ * Multiple widget can be defined in the same appinfo/info.xml.
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard
+ */
+interface IDashboardWidget {
+
+	/**
+	 * Should returns the (unique) Id of the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getId(): string;
+
+
+	/**
+	 * Should returns the [display] name of the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getName(): string;
+
+
+	/**
+	 * Should returns some text describing the widget.
+	 * This description is displayed in the listing of the available widgets.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getDescription(): string;
+
+
+	/**
+	 * Must generate and return a WidgetTemplate that define important stuff
+	 * about the Widget: icon, content, css or javascript.
+	 *
+	 * @see WidgetTemplate
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function getWidgetTemplate(): WidgetTemplate;
+
+
+	/**
+	 * Must create and return a WidgetSetup containing the general setup of
+	 * the widget
+	 *
+	 * @see WidgetSetup
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return WidgetSetup
+	 */
+	public function getWidgetSetup(): WidgetSetup;
+
+
+	/**
+	 * This method is called when a widget is loaded on the dashboard.
+	 * A widget is 'loaded on the dashboard' when one of these conditions
+	 * occurs:
+	 *
+	 * - the user is adding the widget on his dashboard,
+	 * - the user already added the widget on his dashboard and he is opening
+	 *   the dashboard app.
+	 *
+	 * @see IWidgetConfig
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param IWidgetConfig $settings
+	 */
+	public function loadWidget(IWidgetConfig $settings);
+
+
+	/**
+	 * This method s executed when the widget call the net.requestWidget()
+	 * from the Javascript API.
+	 *
+	 * This is used by the frontend to communicate with the backend.
+	 *
+	 * @see IWidgetRequest
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param IWidgetRequest $request
+	 */
+	public function requestWidget(IWidgetRequest $request);
+
+}
+
diff --git a/lib/public/Dashboard/Model/IWidgetConfig.php b/lib/public/Dashboard/Model/IWidgetConfig.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ae4cad50a9a6bf8d7a527f942777141ab635dfb
--- /dev/null
+++ b/lib/public/Dashboard/Model/IWidgetConfig.php
@@ -0,0 +1,129 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Model;
+
+
+use OCP\Dashboard\IDashboardWidget;
+
+/**
+ * Interface IWidgetConfig
+ *
+ * This object contains the configuration of a widget for a userId
+ *
+ * @see IDashboardWidget::loadWidget
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Model
+ */
+interface IWidgetConfig {
+
+
+	/**
+	 * Returns the userId
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getUserId(): string;
+
+
+	/**
+	 * Returns the widgetId
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getWidgetId(): string;
+
+
+	/**
+	 * Returns the current position and the current size of the widget as
+	 * displayed on the user's dashboard
+	 *
+	 * The returned value is an array:
+	 * [
+	 *   'x'      => (int) position on the X axis,
+	 *   'y'      => (int) position on the Y axis,
+	 *   'width'  => (int) width of the widget,
+	 *   'height' => (int) height of the widget
+	 * ]
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getPosition(): array;
+
+
+	/**
+	 * Returns an array with the settings defined by the user for the widget.
+	 * The returned value is an array, with setting used as keys:
+	 *
+	 * [
+	 *   'setting1'  => 'any value',
+	 *   'setting2'  => 'other value'
+	 * ]
+	 *
+	 * Each setting that can be edited by a user should be defined in a
+	 * WidgetSetting.
+	 *
+	 * @see WidgetSetting
+	 *
+	 * Those WidgetSetting are in the WidgetTemplate defined during the setup
+	 * of the widget in the IDashboardWidget.
+	 *
+	 * @see IDashboardWidget::getWidgetTemplate
+	 * @see WidgetTemplate
+	 *
+	 * When using this framework, the settings interface is generated by the
+	 * Dashboard app.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getSettings(): array;
+
+
+	/**
+	 * Returns if the widget is enabled/displayed in this user's dashboard.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return bool
+	 */
+	public function isEnabled(): bool;
+
+
+}
+
diff --git a/lib/public/Dashboard/Model/IWidgetRequest.php b/lib/public/Dashboard/Model/IWidgetRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3a3658b30b243567c6130fdafc9db0ff5d780a04
--- /dev/null
+++ b/lib/public/Dashboard/Model/IWidgetRequest.php
@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Model;
+
+
+use OCP\Dashboard\IDashboardWidget;
+
+
+/**
+ * Interface IWidgetRequest
+ *
+ * WidgetRequest are created by the Dashboard App and used to communicate from
+ * the frontend to the backend.
+ * The object is send to the WidgetClass using IDashboardWidget::requestWidget
+ *
+ * @see IDashboardWidget::requestWidget
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Model
+ */
+interface IWidgetRequest {
+
+	/**
+	 * Get the widgetId.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getWidgetId(): string;
+
+
+	/**
+	 * Get the WidgetClass.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return IDashboardWidget
+	 */
+	public function getWidget(): IDashboardWidget;
+
+
+	/**
+	 * Get the 'request' string sent by the request from the front-end with
+	 * the format:
+	 *
+	 *  net.requestWidget(
+	 *    {
+	 *     widget: widgetId,
+	 *     request: request,
+	 *     value: value
+	 *    },
+	 *    callback);
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getRequest(): string;
+
+
+	/**
+	 * Get the 'value' string sent by the request from the front-end.
+	 *
+	 * @see getRequest
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getValue(): string;
+
+
+	/**
+	 * Returns the result.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getResult(): array;
+
+
+	/**
+	 * add a result (as string)
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $key
+	 * @param string $result
+	 *
+	 * @return $this
+	 */
+	public function addResult(string $key, string $result): IWidgetRequest;
+
+	/**
+	 * add a result (as array)
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $key
+	 * @param array $result
+	 *
+	 * @return $this
+	 */
+	public function addResultArray(string $key, array $result): IWidgetRequest;
+
+}
+
diff --git a/lib/public/Dashboard/Model/WidgetSetting.php b/lib/public/Dashboard/Model/WidgetSetting.php
new file mode 100644
index 0000000000000000000000000000000000000000..616771f7bca3fa6b870adb09dde4cfd5644314f9
--- /dev/null
+++ b/lib/public/Dashboard/Model/WidgetSetting.php
@@ -0,0 +1,242 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Model;
+
+
+use JsonSerializable;
+
+
+/**
+ * Interface WidgetSetting
+ *
+ * Each setting that can be edited by a user should be defined in a
+ * WidgetSetting.
+ *
+ * When using this framework, the settings interface is generated by the
+ * Dashboard app.
+ *
+ * Each WidgetSetting must be generated and declared in the WidgetTemplate
+ * during the setup of the widget in the IDashboardWidget using addSetting().
+ *
+ * @see IDashboardWidget::getWidgetTemplate
+ * @see WidgetTemplate::addSetting
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Model
+ */
+final class WidgetSetting implements JsonSerializable {
+
+
+	const TYPE_INPUT = 'input';
+	const TYPE_CHECKBOX = 'checkbox';
+
+
+	/** @var string */
+	private $name = '';
+
+	/** @var string */
+	private $title = '';
+
+	/** @var string */
+	private $type = '';
+
+	/** @var string */
+	private $placeholder = '';
+
+	/** @var string */
+	private $default = '';
+
+
+	/**
+	 * WidgetSetting constructor.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $type
+	 */
+	public function __construct(string $type = '') {
+		$this->type = $type;
+	}
+
+
+	/**
+	 * Set the name of the setting (full string, no space)
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $name
+	 *
+	 * @return WidgetSetting
+	 */
+	public function setName(string $name): WidgetSetting {
+		$this->name = $name;
+
+		return $this;
+	}
+
+	/**
+	 * Get the name of the setting
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getName(): string {
+		return $this->name;
+	}
+
+
+	/**
+	 * Set the title/display name of the setting.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $title
+	 *
+	 * @return WidgetSetting
+	 */
+	public function setTitle(string $title): WidgetSetting {
+		$this->title = $title;
+
+		return $this;
+	}
+
+	/**
+	 * Get the title of the setting
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getTitle(): string {
+		return $this->title;
+	}
+
+
+	/**
+	 * Set the type of the setting (input, checkbox, ...)
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $type
+	 *
+	 * @return WidgetSetting
+	 */
+	public function setType(string $type): WidgetSetting {
+		$this->type = $type;
+
+		return $this;
+	}
+
+	/**
+	 * Get the type of the setting.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getType(): string {
+		return $this->type;
+	}
+
+
+	/**
+	 * Set the placeholder (in case of type=input)
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $text
+	 *
+	 * @return WidgetSetting
+	 */
+	public function setPlaceholder(string $text): WidgetSetting {
+		$this->placeholder = $text;
+
+		return $this;
+	}
+
+	/**
+	 * Get the placeholder.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getPlaceholder(): string {
+		return $this->placeholder;
+	}
+
+
+	/**
+	 * Set the default value of the setting.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $value
+	 *
+	 * @return WidgetSetting
+	 */
+	public function setDefault(string $value): WidgetSetting {
+		$this->default = $value;
+
+		return $this;
+	}
+
+	/**
+	 * Get the default value.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getDefault(): string {
+		return $this->default;
+	}
+
+
+	/**
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function jsonSerialize() {
+		return [
+			'name' => $this->getName(),
+			'title' => $this->getTitle(),
+			'type' => $this->getTitle(),
+			'default' => $this->getDefault(),
+			'placeholder' => $this->getPlaceholder()
+		];
+	}
+
+
+}
+
diff --git a/lib/public/Dashboard/Model/WidgetSetup.php b/lib/public/Dashboard/Model/WidgetSetup.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f0881a3a17b9aca4780b8ff8b8eb36753854922
--- /dev/null
+++ b/lib/public/Dashboard/Model/WidgetSetup.php
@@ -0,0 +1,271 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Model;
+
+
+use JsonSerializable;
+
+
+/**
+ * Interface WidgetSetup
+ *
+ * A widget must create an WidgetSetup object and returns it in the
+ * IDashboardWidget::getWidgetSetup method.
+ *
+ * @see IDashboardWidget::getWidgetSetup
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Model
+ */
+final class WidgetSetup implements JsonSerializable {
+
+
+	const SIZE_TYPE_MIN = 'min';
+	const SIZE_TYPE_MAX = 'max';
+	const SIZE_TYPE_DEFAULT = 'default';
+
+
+	/** @var array */
+	private $sizes = [];
+
+	/** @var array */
+	private $menus = [];
+
+	/** @var array */
+	private $jobs = [];
+
+	/** @var string */
+	private $push = '';
+
+	/** @var array */
+	private $settings = [];
+
+
+	/**
+	 * Get the defined size for a specific type (min, max, default)
+	 * Returns an array:
+	 * [
+	 *   'width' => width,
+	 *   'height' => height
+	 * ]
+	 *
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $type
+	 *
+	 * @return array
+	 */
+	public function getSize(string $type): array {
+		if (array_key_exists($type, $this->sizes)) {
+			return $this->sizes[$type];
+		}
+
+		return [];
+	}
+
+	/**
+	 * Returns all sizes defined for the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getSizes(): array {
+		return $this->sizes;
+	}
+
+	/**
+	 * Add a new size to the setup.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $type
+	 * @param int $width
+	 * @param int $height
+	 *
+	 * @return WidgetSetup
+	 */
+	public function addSize(string $type, int $width, int $height): WidgetSetup {
+		$this->sizes[$type] = [
+			'width' => $width,
+			'height' => $height
+		];
+
+		return $this;
+	}
+
+	/**
+	 * Returns menu entries.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getMenuEntries(): array {
+		return $this->menus;
+	}
+
+	/**
+	 * Add a menu entry to the widget.
+	 * $function is the Javascript function to be called when clicking the
+	 *           menu entry.
+	 * $icon is the css class of the icon.
+	 * $text is the display name of the menu entry.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $function
+	 * @param string $icon
+	 * @param string $text
+	 *
+	 * @return WidgetSetup
+	 */
+	public function addMenuEntry(string $function, string $icon, string $text): WidgetSetup {
+		$this->menus[] = [
+			'function' => $function,
+			'icon' => $icon,
+			'text' => $text
+		];
+
+		return $this;
+	}
+
+
+	/**
+	 * Add a delayed job to the widget.
+	 *
+	 * $function is the Javascript function to be called.
+	 * $delay is the time in seconds between each call.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $function
+	 * @param int $delay
+	 *
+	 * @return WidgetSetup
+	 */
+	public function addDelayedJob(string $function, int $delay): WidgetSetup {
+		$this->jobs[] = [
+			'function' => $function,
+			'delay' => $delay
+		];
+
+		return $this;
+	}
+
+	/**
+	 * Get delayed jobs.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getDelayedJobs(): array {
+		return $this->jobs;
+	}
+
+
+	/**
+	 * Get the push function, called when an event is send to the front-end
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getPush(): string {
+		return $this->push;
+	}
+
+	/**
+	 * Set the Javascript function to be called when an event is pushed to the
+	 * frontend.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $function
+	 *
+	 * @return WidgetSetup
+	 */
+	public function setPush(string $function): WidgetSetup {
+		$this->push = $function;
+
+		return $this;
+	}
+
+
+	/**
+	 * Returns the default settings for a widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getDefaultSettings(): array {
+		return $this->settings;
+	}
+
+	/**
+	 * Set the default settings for a widget.
+	 * This method is used by the Dashboard app, using the settings created
+	 * using WidgetSetting
+	 *
+	 * @see WidgetSetting
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param array $settings
+	 *
+	 * @return WidgetSetup
+	 */
+	public function setDefaultSettings(array $settings): WidgetSetup {
+		$this->settings = $settings;
+
+		return $this;
+	}
+
+
+	/**
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function jsonSerialize() {
+		return [
+			'size' => $this->getSizes(),
+			'menu' => $this->getMenuEntries(),
+			'jobs' => $this->getDelayedJobs(),
+			'push' => $this->getPush(),
+			'settings' => $this->getDefaultSettings()
+		];
+	}
+}
+
diff --git a/lib/public/Dashboard/Model/WidgetTemplate.php b/lib/public/Dashboard/Model/WidgetTemplate.php
new file mode 100644
index 0000000000000000000000000000000000000000..485d629853955e679c686b9fa575f1bd4187dd37
--- /dev/null
+++ b/lib/public/Dashboard/Model/WidgetTemplate.php
@@ -0,0 +1,319 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Dashboard\Model;
+
+
+use JsonSerializable;
+
+
+/**
+ * Interface WidgetTemplate
+ *
+ * A widget must create an WidgetTemplate object and returns it in the
+ * IDashboardWidget::getWidgetTemplate method.
+ *
+ * @see IDashboardWidget::getWidgetTemplate
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Model
+ */
+final class WidgetTemplate implements JsonSerializable {
+
+
+	/** @var string */
+	private $icon = '';
+
+	/** @var array */
+	private $css = [];
+
+	/** @var array */
+	private $js = [];
+
+	/** @var string */
+	private $content = '';
+
+	/** @var string */
+	private $function = '';
+
+	/** @var WidgetSetting[] */
+	private $settings = [];
+
+
+	/**
+	 * Get the icon class of the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getIcon(): string {
+		return $this->icon;
+	}
+
+	/**
+	 * Set the icon class of the widget.
+	 * This class must be defined in one of the CSS file used by the widget.
+	 *
+	 * @see addCss
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $icon
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setIcon(string $icon): WidgetTemplate {
+		$this->icon = $icon;
+
+		return $this;
+	}
+
+	/**
+	 * Get CSS files to be included when displaying a widget
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getCss(): array {
+		return $this->css;
+	}
+
+	/**
+	 * path and name of CSS files
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param array $css
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setCss(array $css): WidgetTemplate {
+		$this->css = $css;
+
+		return $this;
+	}
+
+	/**
+	 * Add a CSS file to be included when displaying a widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $css
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function addCss(string $css): WidgetTemplate {
+		$this->css[] = $css;
+
+		return $this;
+	}
+
+	/**
+	 * Get JS files to be included when loading a widget
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function getJs(): array {
+		return $this->js;
+	}
+
+	/**
+	 * Set an array of JS files to be included when loading a widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param array $js
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setJs(array $js): WidgetTemplate {
+		$this->js = $js;
+
+		return $this;
+	}
+
+	/**
+	 * Add a JS file to be included when loading a widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $js
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function addJs(string $js): WidgetTemplate {
+		$this->js[] = $js;
+
+		return $this;
+	}
+
+	/**
+	 * Get the HTML file that contains the content of the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getContent(): string {
+		return $this->content;
+	}
+
+	/**
+	 * Set the HTML file that contains the content of the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $content
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setContent(string $content): WidgetTemplate {
+		$this->content = $content;
+
+		return $this;
+	}
+
+	/**
+	 * Get the JS function to be called when loading the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return string
+	 */
+	public function getInitFunction(): string {
+		return $this->function;
+	}
+
+	/**
+	 * JavaScript function to be called when loading the widget on the
+	 * dashboard
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $function
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setInitFunction(string $function): WidgetTemplate {
+		$this->function = $function;
+
+		return $this;
+	}
+
+	/**
+	 * Get all WidgetSetting defined for the widget.
+	 *
+	 * @see WidgetSetting
+	 *
+	 * @since 15.0.0
+	 *
+	 * @return WidgetSetting[]
+	 */
+	public function getSettings(): array {
+		return $this->settings;
+	}
+
+	/**
+	 * Define all WidgetSetting for the widget.
+	 *
+	 * @since 15.0.0
+	 *
+	 * @see WidgetSetting
+	 *
+	 * @param WidgetSetting[] $settings
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function setSettings(array $settings): WidgetTemplate {
+		$this->settings = $settings;
+
+		return $this;
+	}
+
+	/**
+	 * Add a WidgetSetting.
+	 *
+	 * @see WidgetSetting
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param WidgetSetting $setting
+	 *
+	 * @return WidgetTemplate
+	 */
+	public function addSetting(WidgetSetting $setting): WidgetTemplate {
+		$this->settings[] = $setting;
+
+		return $this;
+	}
+
+	/**
+	 * Get a WidgetSetting by its name
+	 *
+	 * @see WidgetSetting::setName
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $key
+	 *
+	 * @return WidgetSetting
+	 */
+	public function getSetting(string $key): WidgetSetting {
+		if (!array_key_exists($key, $this->settings)) {
+			return null;
+		}
+
+		return $this->settings[$key];
+	}
+
+
+	/**
+	 * @since 15.0.0
+	 *
+	 * @return array
+	 */
+	public function jsonSerialize() {
+		return [
+			'icon' => $this->getIcon(),
+			'css' => $this->getCss(),
+			'js' => $this->getJs(),
+			'content' => $this->getContent(),
+			'function' => $this->getInitFunction(),
+			'settings' => $this->getSettings()
+		];
+	}
+
+
+}
+
diff --git a/lib/public/Dashboard/Service/IEventsService.php b/lib/public/Dashboard/Service/IEventsService.php
new file mode 100644
index 0000000000000000000000000000000000000000..4262e235fd58aac5969b2437eaa11ac31f2fb5f8
--- /dev/null
+++ b/lib/public/Dashboard/Service/IEventsService.php
@@ -0,0 +1,94 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCP\Dashboard\Service;
+
+
+use OCP\Dashboard\IDashboardManager;
+
+/**
+ * Interface IEventsService
+ *
+ * The Service is provided by the Dashboard app. The method in this interface
+ * are used by the IDashboardManager when creating push event.
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Service
+ */
+interface IEventsService {
+
+
+	/**
+	 * Create an event for a widget and an array of users.
+	 *
+	 * @see IDashboardManager::createUsersEvent
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $users
+	 * @param array $payload
+	 * @param string $uniqueId
+	 */
+	public function createUsersEvent(string $widgetId, array $users, array $payload, string $uniqueId);
+
+
+	/**
+	 * Create an event for a widget and an array of groups.
+	 *
+	 * @see IDashboardManager::createGroupsEvent
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $groups
+	 * @param array $payload
+	 * @param string $uniqueId
+	 */
+	public function createGroupsEvent(string $widgetId, array $groups, array $payload, string $uniqueId);
+
+
+	/**
+	 * Create a global event for all users that use a specific widget.
+	 *
+	 * @see IDashboardManager::createGlobalEvent
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param array $payload
+	 * @param string $uniqueId
+	 */
+	public function createGlobalEvent(string $widgetId, array $payload, string $uniqueId);
+
+
+}
+
diff --git a/lib/public/Dashboard/Service/IWidgetsService.php b/lib/public/Dashboard/Service/IWidgetsService.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9a4482b4fc75dd1ae3e904981371f29ab4c824f
--- /dev/null
+++ b/lib/public/Dashboard/Service/IWidgetsService.php
@@ -0,0 +1,62 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Dashboard App
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCP\Dashboard\Service;
+
+
+use OCP\Dashboard\Model\IWidgetConfig;
+
+/**
+ * Interface IWidgetsService
+ *
+ * The Service is provided by the Dashboard app. The method in this interface
+ * are used by the IDashboardManager when a widget needs to access the current
+ * configuration of a widget for a user.
+ *
+ * @since 15.0.0
+ *
+ * @package OCP\Dashboard\Service
+ */
+interface IWidgetsService {
+
+	/**
+	 * Returns the IWidgetConfig for a widgetId and userId
+	 *
+	 * @since 15.0.0
+	 *
+	 * @param string $widgetId
+	 * @param string $userId
+	 *
+	 * @return IWidgetConfig
+	 */
+	public function getWidgetConfig(string $widgetId, string $userId): IWidgetConfig;
+
+}
+
diff --git a/resources/app-info-shipped.xsd b/resources/app-info-shipped.xsd
index a9a93dc7d1888d1d9642b8a79ce742ceeed3d21d..ae3aaee0996721f6fc7d791414c3e8091ab7da8d 100644
--- a/resources/app-info-shipped.xsd
+++ b/resources/app-info-shipped.xsd
@@ -53,6 +53,8 @@
                             maxOccurs="1"/>
                 <xs:element name="activity" type="activity" minOccurs="0"
                             maxOccurs="1"/>
+                <xs:element name="dashboard" type="dashboard"
+                            minOccurs="0" maxOccurs="1"/>
                 <xs:element name="navigations" type="navigations" minOccurs="0"
                             maxOccurs="1"/>
                 <xs:element name="contactsmenu" type="contactsmenu" minOccurs="0"
@@ -655,6 +657,13 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="dashboard">
+        <xs:sequence>
+            <xs:element name="widget" type="php-class" minOccurs="1"
+                        maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
     <xs:simpleType name="php-class">
         <xs:restriction base="xs:string">
             <xs:pattern
diff --git a/resources/app-info.xsd b/resources/app-info.xsd
index c3520e23ef12a7e01bb94bf6f7469780ec4dfcad..5c2ab89e213f7a1e4b8134e1ce3114d71f50f35e 100644
--- a/resources/app-info.xsd
+++ b/resources/app-info.xsd
@@ -51,6 +51,8 @@
                             maxOccurs="1"/>
                 <xs:element name="activity" type="activity" minOccurs="0"
                             maxOccurs="1"/>
+                <xs:element name="dashboard" type="dashboard"
+                            minOccurs="0" maxOccurs="1"/>
                 <xs:element name="navigations" type="navigations" minOccurs="0"
                             maxOccurs="1"/>
                 <xs:element name="contactsmenu" type="contactsmenu" minOccurs="0"
@@ -644,6 +646,13 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="dashboard">
+        <xs:sequence>
+            <xs:element name="widget" type="php-class" minOccurs="1"
+                        maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
     <xs:simpleType name="php-class">
         <xs:restriction base="xs:string">
             <xs:pattern