workspace-builder

App Engine Studio & Workspace Builder for ServiceNow

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "workspace-builder" with this command: npx skills add groeimetai/snow-flow/groeimetai-snow-flow-workspace-builder

App Engine Studio & Workspace Builder for ServiceNow

App Engine Studio (AES) enables low-code application development with custom workspaces.

AES Architecture

Application (sys_scope) ├── Tables & Forms ├── Workflows ├── Workspaces (sys_aw_workspace) │ ├── Lists │ ├── Forms │ └── Dashboards └── Portals

Key Tables

Table Purpose

sys_scope

Application scope

sys_app

Application record

sys_aw_workspace

Workspace definition

sys_ux_page

UI Builder pages

sys_ux_macroponent

Custom components

Application Development (ES5)

Create Scoped Application

// Create scoped application (ES5 ONLY!) var app = new GlideRecord("sys_scope") app.initialize()

// Basic info app.setValue("name", "IT Asset Tracker") app.setValue("scope", "x_myco_asset_track") app.setValue("short_description", "Track IT assets across the organization") app.setValue("version", "1.0.0")

// Vendor app.setValue("vendor", "My Company") app.setValue("vendor_prefix", "x_myco")

// License app.setValue("licensable", true)

app.insert()

Create Application Table

// Create table in scoped app (ES5 ONLY!) function createAppTable(scope, tableDef) { var table = new GlideRecord("sys_db_object") table.initialize()

table.setValue("name", scope + "_" + tableDef.name) table.setValue("label", tableDef.label) table.setValue("super_class", tableDef.extends || "task")

// Scope assignment table.setValue("sys_scope", getAppSysId(scope))

// Options table.setValue("is_extendable", tableDef.extendable || false) table.setValue("create_access_controls", true)

table.insert()

// Create fields if (tableDef.fields) { for (var i = 0; i < tableDef.fields.length; i++) { createField(scope + "_" + tableDef.name, tableDef.fields[i]) } }

return table.getUniqueValue() }

// Example createAppTable("x_myco_asset_track", { name: "asset_item", label: "Asset Item", extends: "cmdb_ci", fields: [ { name: "u_purchase_date", label: "Purchase Date", type: "glide_date" }, { name: "u_warranty_end", label: "Warranty End", type: "glide_date" }, { name: "u_assigned_user", label: "Assigned User", type: "reference", reference: "sys_user" }, ], })

Workspace Configuration (ES5)

Create Custom Workspace

// Create workspace (ES5 ONLY!) var workspace = new GlideRecord("sys_aw_workspace") workspace.initialize()

workspace.setValue("name", "asset_tracker_workspace") workspace.setValue("title", "Asset Tracker") workspace.setValue("description", "Workspace for IT asset management")

// Primary table workspace.setValue("primary_table", "x_myco_asset_track_asset_item")

// URL workspace.setValue("url", "asset-tracker")

// Branding workspace.setValue("icon", "laptop") workspace.setValue("color", "#2E7D32")

// App scope workspace.setValue("sys_scope", appScopeSysId)

// Features workspace.setValue("agent_assist_enabled", false) workspace.setValue("contextual_side_panel_enabled", true)

workspace.insert()

Configure Workspace Lists

// Create workspace list (ES5 ONLY!) function createWorkspaceList(workspaceSysId, listDef) { var list = new GlideRecord("sys_aw_list") list.initialize()

list.setValue("workspace", workspaceSysId) list.setValue("name", listDef.name) list.setValue("table", listDef.table)

// Filter list.setValue("filter", listDef.filter || "")

// Columns list.setValue("columns", listDef.columns.join(","))

// Sorting if (listDef.orderBy) { list.setValue("order_by", listDef.orderBy) list.setValue("order_by_desc", listDef.orderDesc || false) }

// Grouping if (listDef.groupBy) { list.setValue("group_by", listDef.groupBy) }

list.insert()

return list.getUniqueValue() }

// Example lists createWorkspaceList(workspaceSysId, { name: "My Assets", table: "x_myco_asset_track_asset_item", filter: "u_assigned_user=javascript:gs.getUserID()", columns: ["number", "name", "u_purchase_date", "u_warranty_end", "state"], })

createWorkspaceList(workspaceSysId, { name: "Expiring Warranties", table: "x_myco_asset_track_asset_item", filter: "u_warranty_endBETWEENjavascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(-30)", columns: ["number", "name", "u_assigned_user", "u_warranty_end"], orderBy: "u_warranty_end", })

UI Builder Pages (ES5)

Page Configuration

// Create UI Builder page (ES5 ONLY!) // Note: Full page creation typically done via UI Builder

var page = new GlideRecord("sys_ux_page") page.initialize()

page.setValue("name", "asset_dashboard") page.setValue("title", "Asset Dashboard") page.setValue("description", "Dashboard for asset overview")

// Page type page.setValue("page_type", "workspace")

// Workspace link page.setValue("workspace", workspaceSysId)

// Scope page.setValue("sys_scope", appScopeSysId)

page.insert()

Custom Component (Macroponent)

// Create custom macroponent definition (ES5 ONLY!) // Note: Actual components created via UI Builder

var component = new GlideRecord("sys_ux_macroponent") component.initialize()

component.setValue("name", "asset_summary_card") component.setValue("label", "Asset Summary Card") component.setValue("description", "Displays asset summary information")

// Component category component.setValue("category", "data_visualization")

// Scope component.setValue("sys_scope", appScopeSysId)

// Properties (inputs) component.setValue( "properties", JSON.stringify([ { name: "title", type: "string", label: "Card Title" }, { name: "assetTable", type: "string", label: "Asset Table" }, { name: "filter", type: "string", label: "Filter" }, ]), )

component.insert()

Data Brokers (ES5)

Create Data Broker

// Data broker for workspace data (ES5 ONLY!) // Data brokers provide data to UI Builder pages

var broker = new GlideRecord("sys_ux_data_broker") broker.initialize()

broker.setValue("name", "asset_stats") broker.setValue("label", "Asset Statistics")

// Data source type broker.setValue("type", "script")

// Script to fetch data (ES5 ONLY!) broker.setValue( "script", "(function getData(inputs) {\n" + " var result = {\n" + " total: 0,\n" + " assigned: 0,\n" + " available: 0,\n" + " expiring_warranty: 0\n" + " };\n" + " \n" + ' var ga = new GlideAggregate("x_myco_asset_track_asset_item");\n' + ' ga.addAggregate("COUNT");\n' + ' ga.groupBy("state");\n' + " ga.query();\n" + " \n" + " while (ga.next()) {\n" + ' var count = parseInt(ga.getAggregate("COUNT"), 10);\n' + " result.total += count;\n" + " \n" + ' var state = ga.getValue("state");\n' + ' if (state === "in_use") {\n' + " result.assigned = count;\n" + ' } else if (state === "available") {\n' + " result.available = count;\n" + " }\n" + " }\n" + " \n" + " // Expiring warranties\n" + ' var expiring = new GlideAggregate("x_myco_asset_track_asset_item");\n' + ' expiring.addQuery("u_warranty_end", "BETWEEN", "javascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(-30)");\n' + ' expiring.addAggregate("COUNT");\n' + " expiring.query();\n" + " \n" + " if (expiring.next()) {\n" + ' result.expiring_warranty = parseInt(expiring.getAggregate("COUNT"), 10);\n' + " }\n" + " \n" + " return result;\n" + "})(inputs);", )

broker.setValue("sys_scope", appScopeSysId)

broker.insert()

Application Deployment (ES5)

Create Update Set

// Create update set for app deployment (ES5 ONLY!) function createAppUpdateSet(appName, description) { var updateSet = new GlideRecord("sys_update_set") updateSet.initialize() updateSet.setValue("name", appName + " - " + new GlideDateTime().getDate()) updateSet.setValue("description", description) updateSet.setValue("application", getAppSysId(appName)) updateSet.setValue("state", "in progress") return updateSet.insert() }

Export Application

// Prepare app for export (ES5 ONLY!) function prepareAppExport(appScope) { // Validate all components var issues = []

// Check for missing dependencies var dependency = new GlideRecord("sys_app_dependency") dependency.addQuery("app.scope", appScope) dependency.query()

while (dependency.next()) { if (!isDependencyInstalled(dependency.getValue("dependency"))) { issues.push("Missing dependency: " + dependency.dependency.getDisplayValue()) } }

// Validate update sets var updateSet = new GlideRecord("sys_update_set") updateSet.addQuery("application.scope", appScope) updateSet.addQuery("state", "in progress") updateSet.query()

while (updateSet.next()) { issues.push("Open update set: " + updateSet.getValue("name")) }

return { ready: issues.length === 0, issues: issues, } }

MCP Tool Integration

Available Tools

Tool Purpose

snow_query_table

Query app components

snow_execute_script_with_output

Test app scripts

snow_find_artifact

Find configurations

snow_update_set_create

Create update sets

Example Workflow

// 1. Query applications await snow_query_table({ table: "sys_scope", query: "scopeSTARTSWITHx_", fields: "name,scope,version,vendor", })

// 2. Find app tables await snow_query_table({ table: "sys_db_object", query: "nameSTARTSWITHx_myco", fields: "name,label,super_class", })

// 3. Get workspace configs await snow_query_table({ table: "sys_aw_workspace", query: "sys_scope.scopeSTARTSWITHx_", fields: "name,title,primary_table,url", })

Best Practices

  • Naming Conventions - Consistent prefixes

  • Scoped Apps - Use scope isolation

  • Reusable Components - Modular design

  • Data Brokers - Efficient data fetching

  • Workspace Design - User-focused layouts

  • Testing - ATF tests for apps

  • Documentation - App documentation

  • ES5 Only - No modern JavaScript syntax

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

predictive-intelligence

No summary provided by upstream source.

Repository SourceNeeds Review
General

scheduled-jobs

No summary provided by upstream source.

Repository SourceNeeds Review
General

document-management

No summary provided by upstream source.

Repository SourceNeeds Review
General

reporting-dashboards

No summary provided by upstream source.

Repository SourceNeeds Review