Exercise 1: Build out the Home Page
Goalβ
In this exercise, you'll build out the layout for the experience home page. The overall goal of the lab is to build out an interface for a single-page note-taking app that looks and feels like the other base app shell experiences that ServiceNow ships by default.
Format the home pageβ
For the first part of this exercise, you're going to bootstrap the development of the page by pulling a layout from the existing admin home page to get a head start on development. You'll do this by inserting some values in the macroponent record for the home page that comes with the app.
The macroponent record holds almost all of your UI Builder page configuration across a few JSON fields. While it's not possible to duplicate pages inside of UIB across experiences, you can copy and paste the JSON to get your page bootstrapped more quickly. The technique described in this exercise is really only necessary if you're copying a page, but I wanted to include it as a tool to add to your UIB development toolbox.
What's a macroponent anyway?β
In short, the macroponent is a metadata-defined UX Framework component that is defined in the table sys_ux_macroponent. Instead of writing a page-level component in code, you declaratively define the component's composition, data, and business logic through UI Builder, and then the system translates the macroponent metadata into HTML, CSS, and JavaScript for the client browser in the runtime.
Switch to the right application scopeβ
-
First, switch to the Killer Notes application scope by clicking the Show instance tools icon at the right-side of the header.
-
Change from Global to Killer Notes.
You can also switch scope directly within UI Builder.
Find the macroponent record for the home pageβ
-
Click the All menu.
-
In the filter, type sys_ux_macroponent.list and hit Return
-
Find the specific macroponent record by filtering the list for:
-
Sys ID | is | e70d4cb1219586107f44b97c4dc7b60a
-
-
Click into the page to bring up the macroponent record.
You should now see the mostly empty macroponent record. This is the back-end representation of the UI Builder page you'll work with. Almost everything you do with the page in UIB will be saved to this record.
Populate the structure of the pageβ
We're cheating a bit in this section, but this is a valid strategy if you find a UIB page somewhere and want to copy the page's structure in your new page. There are a couple of large JSON blobs to copy and paste in this section so rather than highlighting try to use the little copy icon at the top right of the code block.
In the real world you'd copy these JSON fields from one page to another, but in the interest of time and ease, the JSON has already been provided.
-
Paste the following JSON into the Layout model field on the macroponent:
{
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "header_container",
"styles": {
"background": "RGB(var(--now-color_brand--secondary))",
"flex": "1",
"width": "100%"
}
},
{
"element_id": "search_container",
"styles": {
"background": "rgb(var(--now-color_background--secondary))",
"height": "100%",
"width": "100%"
}
},
{
"element_id": "body_container",
"styles": {
"background": "rgb(var(--now-color_background--secondary))",
"width": "100%"
}
},
{
"element_id": "footer_container",
"styles": {
"background": "rgb(var(--now-color_background--secondary))",
"width": "100%"
}
}
],
"root": null,
"rules": null,
"styles": {
"background": "RGB(var(--now-color_brand--secondary))",
"display": "flex",
"flex-direction": "column"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
} -
In the Composition field paste the following:
[
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "header_container",
"elementLabel": "Header Container",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "container_4",
"elementLabel": "Container 4",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "container_5",
"elementLabel": "Container 5",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
{
"definition": {
"id": "4335ba6dca80378f7ba7a67cd6667bec",
"type": "MACROPONENT"
},
"elementId": "stylized_text_4",
"elementLabel": "Stylized text 4",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": null,
"propertyValues": {
"css": {
"type": "JSON_LITERAL",
"value": "* { \n color: rgb(var(--now-color--neutral-0, 255, 255, 255));\n font-family: var(--now-font-family, 'Cabin');\n font-style: normal;\n font-weight: 700;\n font-size: var(--now-global-font-size--xxl, 32px);\n margin-top: 50px;\n}"
},
"tag": {
"type": "JSON_LITERAL",
"value": "span"
},
"text": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": "Notes"
}
}
},
"slot": null,
"styles": null
}
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "stylized_text_4",
"styles": {}
}
],
"root": null,
"rules": null,
"styles": {
"display": "flex",
"flex-direction": "column",
"gap": "var(--now-static-space--sm)",
"margin": "2rem 0 0 0",
"padding-left": "3rem",
"padding-right": "1rem"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": null,
"styles": null
}
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "container_5",
"styles": {
"background": "rgb(var(--now-color--primary-3))",
"background-image": "url(\"admin-home-banner.svg\")",
"background-position": "right",
"background-repeat": "no-repeat",
"background-size": "100%",
"box-shadow": "var(--now-static-drop-shadow--md)",
"height": "100%",
"min-height": "200px",
"width": "100%"
}
}
],
"root": null,
"rules": null,
"styles": {},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": "",
"styles": null
}
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "container_4",
"styles": {
"background": "--now-color_brand--secondary",
"height": "15rem",
"max-height": "300px",
"width": "100%"
}
}
],
"root": null,
"rules": null,
"styles": {
"display": "grid",
"flex-direction": "column",
"grid-auto-columns": "1fr",
"grid-auto-rows": "1fr",
"grid-template-columns": "1fr",
"grid-template-rows": "0.1fr"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "grid"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": "",
"styles": null
},
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "search_container",
"elementLabel": "Search Container",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "container_1",
"elementLabel": "Container 1",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
{
"definition": {
"id": "1f6e0643eca7a637e36bd7833549ec9e",
"type": "MACROPONENT"
},
"elementId": "heading_1",
"elementLabel": "Heading 1",
"eventMappings": [
],
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"preset": null,
"propertyValues": {
"hasNoMargin": {
"type": "JSON_LITERAL",
"value": false
},
"label": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": "Search your notes"
}
},
"level": {
"type": "JSON_LITERAL",
"value": "3"
},
"variant": {
"type": "JSON_LITERAL",
"value": "header-primary"
},
"wontWrap": {
"type": "JSON_LITERAL",
"value": false
}
},
"slot": null,
"styles": null
}
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "heading_1",
"styles": {}
}
],
"root": null,
"rules": null,
"styles": {
"flex-direction": "column",
"flex-wrap": "nowrap",
"gap": "",
"padding": "var(--now-scalable-space--xl)",
"padding-bottom": "var(--now-scalable-space--xl)",
"padding-left": "var(--now-scalable-space--xl)",
"padding-right": "var(--now-scalable-space--xl)",
"padding-top": "var(--now-scalable-space--xl)"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": "",
"styles": null
}
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
{
"element_id": "container_1",
"styles": {
"background": "rgb(var(--now-color_background--primary))",
"border-color": "",
"border-radius": "8px",
"border-style": "id",
"border-width": "",
"box-shadow": "var(--now-static-drop-shadow--md)",
"height": "100%",
"width": ""
}
}
],
"root": null,
"rules": null,
"styles": {
"flex-direction": "column",
"margin": "-4rem 3rem 1rem 3rem"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": "",
"styles": null
},
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "body_container",
"elementLabel": "Body Container",
"eventMappings": [
],
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"overrides": {
"composition": [
],
"layout": {
"default": {
"children": null,
"items": [
],
"root": null,
"rules": null,
"styles": {
"flex-direction": "column",
"padding": "1rem",
"padding-bottom": "1rem",
"padding-left": "1rem",
"padding-right": "1rem",
"padding-top": "1rem"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"preset": null,
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"hideEmptyStateUi": {
"type": "JSON_LITERAL",
"value": true
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"slotWrapperBehavior": {
"type": "JSON_LITERAL",
"value": "fullheight"
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": null,
"styles": null
},
{
"definition": {
"id": "d356d14b6e293a3020a244b63d278d8f",
"type": "MACROPONENT"
},
"elementId": "footer_container",
"elementLabel": "Footer Container",
"eventMappings": [
],
"extensionPoints": [
],
"isHero": false,
"isHidden": {
"type": "JSON_LITERAL",
"value": null
},
"isNonDestructive": false,
"items": [
],
"overrides": {
"composition": [
],
"layout": {
"default": {
"children": null,
"isInline": null,
"items": [
],
"root": null,
"rules": null,
"styles": {
"align-items": "center",
"flex-direction": "row",
"gap": "var(--now-static-space--lg)",
"justify-content": "center",
"padding": "var(--now-static-space--lg)"
},
"templateId": "5832fd4d53c31010e6bcddeeff7b12db",
"type": "flex"
},
"version": "3.0.0"
}
},
"propertyValues": {
"ariaRegionHeadingLevel": {
"type": "JSON_LITERAL",
"value": "1"
},
"ariaRegionName": {
"type": "TRANSLATION_LITERAL",
"value": {
"code": null,
"comment": "",
"message": ""
}
},
"ariaRole": {
"type": "JSON_LITERAL",
"value": ""
},
"includeAriaHeading": {
"type": "JSON_LITERAL",
"value": false
},
"type": {
"type": "JSON_LITERAL",
"value": "section"
}
},
"slot": "",
"styles": null
}
] -
Save or Update the record.
We could have auto-populated this page as part of the lab, but sometimes it helps knowing where to go look at what is being stored in the back-end of one of our builders. Feel free to switch back to the macroponent record periodically throughout the lab to see how the macroponent changes as you make changes in UI Builder.
You can easily navigate to this record from UI Builder, also. To open the macroponent record for the page you're editing in UI Builder, click the Menu icon under the UIB logo, navigate to Developer > Open page definition.
Test the page in UI Builderβ
Now that the structure of the page is populated, let's open it in UI Builder.
-
In the All menu, go to Now Experience Framework > UI Builder (or just filter to ui b) and UIB will open in a new tab.
-
On the UIB homepage, find the Killer Notes experience and click on it.
-
You'll see there is only one page in the experience called Home default. Click into that page by clicking on the name.
-
You should see a very barebones version of the page from the JSON you pasted in the previous section.
Home default page in UI Builder
In order to generate this template, I took the admin homepage, duplicated it into a new variant, and deleted most of the contents. I then changed the wording on a couple of components, and copied the JSON from the Composition and Layout Models fields in the macroponent.