--- sidebar_label: 'Overview' sidebar_position: 1 --- # Frontend plugins ## What is a frontend plugin? Frontend plugins can be used to add new features, modify existing functionality, or integrate with third-party services. They can be developed by the application's own developers or by third-party developers. ## How do plugins work? A plugin is a piece of code executed upon page load, serving to inject additional functionality into the ordering frontend. Typically, the init-function registers one or more of the following: - **Block component** - A component that can be used to inject a custom piece of HTML on a page - **Page component** - A component that creates a new page with custom HTML - **Transform component** - A component that can be used to modify lists or other types of repeating data, for example to inject a new link in the pop-out navigation - **Event handlers** - A plugin can listen to events emitted by the Future Ordering UI, which are triggered by user actions. These events can then be used to perform various actions ## What can I do with a plugin? While plugins have the capability to perform a wide range of functions as they are essentially imported scripts, it is important to follow the [guidelines](#plugin-guidelines) on what plugins should and should not do. Example of what a plugin can do: - Display custom HTML on an existing page - Create a new page and display HTML - Show a modal dialog when the user logs in - Navigate to a page - Receive an event when the user's current order is updated and show information based on that - Send tracking data to another system - Use CSS variables from the theme to style custom HTML to blend in with the rest of the Future Ordering UI - Retrieve an access token for the currently logged-in user to use when calling other APIs ## Build your first plugin Building a plugin is straightforward. Here's an example of a plugin init-function that logs 'Hello world' in the console. ```javascript export default async context => { console.log('Hello world'); }; ``` Here is an example of a more useful plugin. It registers a block component at the bottom of the start page, displaying a div with the text "Hello world". ```javascript export default async context => { context.componentLoader.registerBlockComponent({ location: 'start-bottom', loadContent: async ctx => { const { shadow } = ctx; const container = document.createElement('div'); container.innerText = 'Hello world'; shadow.appendChild(container); }, }); }; ``` Plugins can be written in javascript or in typescript and transpiled to javascript. All typescript definitions are provided using the [Plugin types NPM package](https://www.npmjs.com/package/@futureordering/fo-web-plugin-types). ## Documentation For more in depth information about the different kinds of plugins and related concepts, please refer to the following links: - [Block component](./components/plugins-block-component) - [Page component](./components/plugins-page-component) - [Transform component](./components/plugins-transform-component) - [Plugin events](./plugins-events) - [Component styling](./components/plugins-component-styling) - [User tokens](./plugins-user-tokens) - [Using the Frontend Plugin API to upload new versions of plugins](./plugins-update-using-apis) - [Kiosk plugins](./plugins-kiosk) - [Services](./services/services-overview) ## Getting started ### Typescript Using the boilerplate project with typescript is the easiest way to get started developing a plugin. 1. Clone [plugin boilerplate project on github](https://github.com/Future-Ordering/frontend-plugin-boilerplate). ``` git clone https://github.com/Future-Ordering/frontend-plugin-boilerplate cd frontend-plugin-boilerplate ``` 2. Follow the instructions provided in the GitHub project on how to install and start the development server. 3. To view the plugin, see [Testing out a plugin in the Future Ordering UI](#testing-out-a-plugin-in-the-future-ordering-ui) below. 4. See examples directory in boilerplate project for inspiration ### Javascript 1. Write code in a text editor of your choice. For example, create myplugin/1.0.0/myplugin.js using the following command: ``` mkdir -p myplugin/1.0.0 touch myplugin/1.0.0/myplugin.js ``` 2. Enter the following code: ```javascript export default async context => { console.log('Hello world'); }; ``` 3. Easiest and most convenient way to develop a plugin is to serve it from localhost. Starts a web server on localhost (files served must have cors enabled) Using [Node.js](https://nodejs.org/) to serve plugins from current directory ``` npx serve --cors . ``` 4. To run the plugin, see [Testing out a plugin in the Future Ordering UI](#testing-out-a-plugin-in-the-future-ordering-ui) below ### Testing out a plugin in the Future Ordering UI This feature enables loading a plugin from your local computer for testing purposes. Your plugin will not be visible to anyone else. We recommend using Google Chrome. You may need to enable the flag for allowing insecure localhost in your browser. To do so, navigate to: chrome://flags/#allow-insecure-localhost and restart your browser. 1. Navigate to \{Future Ordering UI}/plugins - Set plugin host (from examples above, use http://localhost:3000) - Add plugin, set name, version and optional config (from example above use name "myplugin" and version "1.0.0") ![Page configurator](./assets/plugins/plugin-configurator.png) 2. Plugin must be served from the following URL format _\{name}/\{version}/\{name}.js_, for example if the plugin host is "http://localhost:3000", the name is "myplugin", and the version is "1.0.0", then the full url would be http://localhost:3000/myplugin/1.0.0/myplugin.js. Only localhost and local IP address ranges are allowed for security reasons. 3. Press the "Back to site" button. Plugin should now be active Note: see "bundling" below for important information about how to bundle your plugin. ## Using HTTPS Some browsers do not permit loading files over HTTP while on a site served over HTTPS. In such instances, a self-signed certificate must be generated and used. We recommend using a tool called mkcert, which will create and install an HTTPS certificate. After you install mkcert, generate a certificate for HTTPS: mkcert -install localhost The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" When using the [boilerplate project](https://github.com/Future-Ordering/frontend-plugin-boilerplate), the dev-server can simply be started by running the command: npm run dev-https If instead using plain javascript, start serve with the following command: npx serve --cors --ssl-cert localhost.pem --ssl-key localhost-key.pem . Please note that the plugin host needs to be changed to use HTTPS instead of HTTP. Set the plugin host to __https://localhost:3000__. See [Testing out a plugin in the Future Ordering UI](#testing-out-a-plugin-in-the-future-ordering-ui) ## Bundling Each plugin must be bundled to a _single file_, only a single javascript code file can be uploaded (see publish plugin below). Use format __esm__ when bundling to preserve import/export format. ## Plugin manifest Each plugin must have a manifest file that describes metadata about the plugin. Create a file named `manifest.json` that should contain the following properties: - `version`: Example: "1.0.0" - `description`: Description of the plugin. - `parameters`: Description of parameters in the configuration. Each parameter is rendered as inputs to be easily entered when configuring the plugin. [More info about plugin manifest](./plugins-manifest.md) ## Upload a plugin 1. Ensure the plugin is bundled into a single javascript file along with the plugin manifest. 2. Navigate to Future Ordering Navigator at https://\{tenantId}.navigator.futureordering.com/. (Replace \{tenantId} with your actual tenant ID.). 3. Access the "Frontend Plugin Uploader" app. 4. Click on the "Upload Plugin" button, then either drag and drop the files or click to upload them. ## Publish plugin 1. Navigate to Future Ordering Navigator at https://\{tenantId}.navigator.futureordering.com/. (Replace \{tenantId} with your actual tenant ID.). 2. Access the app "Frontend Plugin Configurator". 3. Click on the "Configure plugin" button 4. Enter details - Choose the newly uploaded plugin from the dropdown menu. - Enter specific plugin configuration, if available (configured in manifest.json). - Specify channels if the plugin is only available in specific channels. - Specify countries if the plugin is only available in specific countries. - Specify consent levels if the plugin requires user approval for certain content levels in the cookie dialog. - Specify app tracking if the plugin requires user to allow tracking in the app. - Configure allowed data URLs if the plugin loads data from other domains. ## Plugin guidelines - Plugin should only modify the code inside of the plugin. It is NOT recommended to access HTML elements outside of the plugin container. HTML outside of the plugin's scope does not provide any guarantees for staying as is and can change at any time. - Plugin should not rely on reading of the URL, cookies, session/local storage. URLs of the Future Ordering UI, cookies, variables in storage can change at any time. Instead, the plugin should use classes and methods provided on the context object to figure out what context the user is in. - A plugin should always clean up after itself. This includes stopping intervals, loops, and other code that will continue executing if not stopped. ## Browser support Full plugin functionality requires a modern browser. However, a limited subset of plugin features can also be made to work in older browsers. For more details, see [plugins in old browsers](./plugins-old-browsers.md).