A Lowdefy app is written as YAML files, which are combined together using the _ref
operator when the app is built, into a configuration object that describes the entire app. This object has different sections that describes different parts of the app.
The root schema for a Lowdefy app is:
lowdefy: string
: Required - The Lowdefy version number the app uses. This is required and cannot be a reference to another file.name: string
: A name for the application.licence: string
: A SPDX licence ID. You can use this to indicate the project's licence if you are licencing your project under a specific software licence. If you wish to indicate to others that you do not grant the right to use your project, you can optionally useUNLICENSED
for this field. How you share your Lowdefy config is up to you.cli: object
: An object with configuration for the CLI.config: object
: An object with app configuration like the home page pageId.global: object
: A data object that can be accessed anywhere in the app using the_global
operator.connections: object[]
: An array ofconnection
objects.types: object
: An object to customize and add block types.menus: object[]
: An array of menu objects.pages: object[]
: An array of page objects.
Config
The config object has the following properties:
homePageId: string
: The pageId of the page that should be loaded when a user loads the app without a pageId in the url route. This is the page that is loaded when you navigate toyourdomain.com
.
Global
Any data that you wish to use in your app can be stored in the global object, and accessed using the _global
operator. This is a good place to store data or configuration that is used throughout the app, for example the url of a logo or configuration of a page, since then these are only written once, and can be updated easily.
The global object can also be modified using the SetGlobal
action.
Menus
Menu objects are an object with links to pages. The are used by blocks like PageSiderMenu
to render the links in the menu. If no menus are provided, a default menu is created, with links to all of the defined pages, and with their pageIds as menu item titles.
Blocks like like PageSiderMenu
use the menu with id: default
by default. This means that if you create a menu object with id: default
, this will be used unless another menu is configured.
More than one menu can be configured in an app. As an example, this can be used when two logically different sections in the app need different menus.
If OpenID Connect authentication and role based authentication is configured, pages that the user is restricted from seeing are filtered from the menu object.
The schema for a menu object is:
id: string
: Required - A identifier for the menu. If it isdefault
, it will be used as default by pages.links: object[]
: An array ofMenuLink
orMenuGroup
objects that form the links in the menu.MenuGroups
can be two levels deep.
The schema for a MenuLink
is:
id: string
: Required - A identifier for the link unique to the menu.type: string
: Required - The type should beMenuLink
.pageId: string
: The id of the page to link to. Used as the title if no title is provided.url: string
: An external url to link to.properties: object
: The properties of the menu link. These are:title: string
: The title to display for the link.icon: string | object
: The name of an Ant Design Icon or properties of an Icon block to use as the icon for the link. The icon is only shown if the link is at the top level of the menu (not in a menu group).
The schema for a MenuGroup
is:
id: string
: Required - A identifier for the group unique to the menu.type: string
: Required - The type should beMenuGroup
.properties: object
: The properties of the menu group. These are:title: string
: The title to display for the group.icon: string | object
: The name of an Ant Design Icon or properties of an Icon block to use as the icon for the group. The icon is only shown if the group is at the top level of the menu (not in a menu group).
links: object[]
: An array ofMenuLink
orMenuGroup
objects that are should be grouped together in the group.
Menus example:
lowdefy: LOWDEFY_VERSION
menus:
- id: default
links:
- id: page1
type: MenuLink
pageId: page1
properties:
title: Page 1
icon: FileOutlined
- id: top-group
properties:
title: Group
icon: GroupOutlined
links:
- id: page2
type: MenuLink
pageId: page2 # pageId will be used as link title
- id: external
type: MenuLink
url: https://external.com
properties:
title: External site
- id: nested-group
type: MenuGroup
properties:
title: Nested Group
links:
- id: page3
type: MenuLink
pageId: page3
properties:
title: Page 3
- id: page-1-and-3
links:
- id: page1
type: MenuLink
pageId: page1
properties:
title: Page 1
icon: FileOutlined
- id: page3
type: MenuLink
pageId: page3
properties:
title: Page 3
icon: ControlOutlined
Pages
Pages in a Lowdefy app are actually just blocks, the building blocks of a Lowdefy app, with a few extra restrictions and features.
Each page should have an id
that is unique among all pages in the app. Each page is served with the pageId
as the url route. That is, if you create a page with id page1
, it will be served at domain.com/page1
.
Page blocks should be of category context
, in order to create a context for the page. This means they always have the context initialization events like onInit
to initialize the page.
If properties.title
is set on a page block, the title will be set as the page title (This is the title displayed on the tabs in your browser).
References and templates
References are used to split the configuration of an app into logically distinct files, and to reuse configuration in the app. References can be used almost anywhere in the configuration, as long as the configuration remains valid YAML.
References are made using the _ref
operator. If the referenced file has a .yaml
or .json
extension, the contents of the file will be parsed, else the file content is included as a string (this is useful for .md
or .html
files). As an example of splitting an app into logically distinct files, references can be used to write each page as a separate file:
lowdefy.yaml
lowdefy: LOWDEFY_VERSION
pages:
_ref: pages/page1.yaml # Path to the referenced file. Always from the root of the project.
_ref: pages/page1.yaml
The _ref
operator can take an argument called vars
. This can be any data, and is passed down to later be accessed with the _var
operator. By using vars, the referenced file can become a template, using the given variables. For example, a standard page template might be used for multiple pages in an app:
pages/page1.yaml
_ref:
path: templates/text_page.yaml
vars:
id: page1
title: Page 1
content: |
Page content text.
templates/text_page.yaml
id:
_var: id
type: PageHeaderMenu
properties:
title:
_var: title
blocks:
- id: content_card
type: Card
blocks:
- id: title
type: Title
properties:
content:
_var: title
- id: content
type: Markdown
properties:
content:
_var: content
Templating can be taken further by referencing Nunjucks template files. If a file ends with the .njk
file extension, the file will first be hydrated as a Nunjucks template, using the vars
as template variables. If the file ends with .yaml.njk
or .json.njk
, the output of the template will then be parsed. Nunjucks templates are useful since the template file does not need to be valid yaml before it is hydrated, and features like for-loops and if-statements can be used.
Templating is used extensively to create the Lowdefy docs (these docs are a Lowdefy app). You can look at how they are used here.
JSON instead of YAML
Since you can reference JSON files, you can build your app using JSON instead of YAML files. The lowdefy.yaml
file needs to be a YAML file, but all other configuration can be in referenced JSON files. It also makes sense to use JSON instead of YAML if you are generating configuration using code.
Lowdefy versions and version updates
Lowdefy is versioned using semantic versioning, with a three part version number, with the form major.minor.patch
. Lowdefy is in the early stages of development and under active development, with new versions published on a regular basis.
To update the version of your app, change the lowdefy
version field in the lowdefy.yaml
file, and redeploy the app. You might also need to make some changes to your app configuration to be compatible with the new version.
Patch updates only contain fixes, and you should be safe to update to a patched version without any changes to your app. Since we are actively developing new features, most releases will be minor version updates, and patches won't be made to older versions.
Minor version changes include new features. At this stage, since the project is still in early development, they might also have minor breaking changes to individual blocks, actions, operators or connections. Please check the changelog to see if any configuration changes are needed before updating.
Major version updates may include major breaking changes or architecture changes. You might need to make more changes to your configuration to be compatible with the new version. We don't intend to release major versions regularly, and try to minimize breaking changes.
As the project grows, we will release a long term support (LTS) version, that will continue to receive patches, but won't have any breaking changes.