Build on UI5

How to build a UI5 library or extension

A reusable UI5 piece is a control library, a custom control, a UI5 CLI task or middleware, or a web component, shared on npm. What follows is how the UI5 documentation describes each and what its projects do.

Guidance, not rules. Each project's own contributing guide wins. Links read 2026-09-29

01Work with an agent

The skills written for UI5 teach an agent how to build with it, and the atlas is not part of what they read. The atlas's MCP server and its skill answer a different question, what exists, whether it is alive and where it stops, and carry no procedure for code, so the two sit side by side. It reads; it never opens an issue or a pull request. How the atlas serves agents

Skills indexed in UI5

READMEs on record for 8 of 8. None of them names the atlas.

Any MCP client: the endpoint

The atlas over streamable HTTP, stateless, answered from the bundled graph.

claude mcp add --transport http onedevatlas https://onedevatlas.dev/mcp

02How UI5 is extended

UI5 is extended through controls, libraries and the tooling's own extension kinds. A reusable piece built on them loads like any part of UI5 and can be shared on npm.

Custom control

Freestyle
Control.extend

A custom control is a subclass of sap.ui.core.Control with a metadata section (properties, aggregations, associations, events) from which UI5 generates getters, setters and other accessors, and a renderer that writes the control's HTML through the RenderManager. The Developing Controls topic says a custom control can live inside an app or component, and that for reuse across applications SAP recommends a library containing the controls.

Packages in UI5 9
jsAdapted from github.com ↗
sap.ui.define([
	"sap/ui/core/Control"
], (Control) => {
	"use strict";

	return Control.extend("ui5.walkthrough.control.ProductRating", {
		metadata : {},

		init() {},

		renderer(oRM, oControl) {}
	});
});

Control library (reuse library)

FreestyleUI5 CLI
Lib.init

A library's library.js calls sap/ui/core/Lib.init with a description of its content and returns the resulting object, which carries the library's enums registered through DataType.registerEnum. UI5 CLI documents the library project type as the key component for sharing code across projects, with sources under src/ and tests under test/ in a namespace-shaped directory structure.

Packages in UI5 9
jsAdapted from github.com ↗
sap.ui.define([
	'sap/ui/base/DataType',
	'sap/ui/core/Lib'
], function(DataType, Library) {
	"use strict";
	var oThisLibrary = Library.init({
		name: "my.lib",
		apiVersion: 2
	});
	oThisLibrary.Size = { Small: "Small", Medium: "Medium", Large: "Large" };
	DataType.registerEnum("my.lib.Size", oThisLibrary.Size);
	return oThisLibrary;
});

UI5 CLI custom task

UI5 CLI
kind: extension / type: task

A custom task extends the UI5 CLI build: its ui5.yaml declares kind: extension and type: task with the path to a module exporting an async function that receives workspace, dependencies, taskUtil, options and log. A project wires it in under builder.customTasks with beforeTask or afterTask; the page notes community tasks are often prefixed ui5-task- for npm search.

Build tools in UI5 2
yamlAdapted from ui5.github.io ↗
specVersion: "4.0"
kind: extension
type: task
metadata:
  name: render-markdown-files
task:
  path: lib/tasks/renderMarkdownFiles.js
---
# lib/tasks/renderMarkdownFiles.js
# export default async function({dependencies, log, options, taskUtil, workspace}) {
#     // [...]
# };

UI5 CLI custom server middleware

UI5 CLI
kind: extension / type: server-middleware

A custom middleware extends the UI5 CLI development server: its ui5.yaml declares type: server-middleware and a module that returns an Express-style (req, res, next) handler. A project registers it under server.customMiddleware with beforeMiddleware or afterMiddleware and optional configuration passed to the implementation.

Build tools in UI5 2
jsAdapted from ui5.github.io ↗
// ui5.yaml of the extension: kind: extension, type: server-middleware,
// middleware: { path: lib/middleware/markdownHandler.js }
export default function({log, middlewareUtil, options, resources}) {
    return async function (req, res, next) {
        // implementation
    }
}

Controller extension

FreestyleFiori elements
ControllerExtension.extend

Controller extensions add logic to an existing controller without modifying the original code; an extension declares public, final and overrideExecution for its methods and can override methods of other extensions, and both approaches are configured through manifest.json. SAP Fiori elements for OData V4 registers them under sap.ui.controllerExtensions against page controllers such as sap.fe.templates.ListReport.ListReportController, and a key after '#' targets one page instance.

jsAdapted from github.com ↗
sap.ui.define(['sap/ui/core/mvc/ControllerExtension', 'sap/ui/core/mvc/OverrideExecution'], function(ControllerExtension, OverrideExecution) {
  "use strict";
  return ControllerExtension.extend("my.extension.SampleExtension1", {
    metadata: {
      methods: {
        publicMethod: { public: true, final: false, overrideExecution: OverrideExecution.Instead },
        onMyHook: { overrideExecution: OverrideExecution.After }
      }
    }
  });
});

XML view extension points

Freestyle
core:ExtensionPoint

An application marks places in its XML views with <core:ExtensionPoint name="..."/>, optionally with default content, and an extending application supplies content for them through its manifest.json. JS views create them with ExtensionPoint.load(); the topic states that an extensible app must document which control types suit each point.

xmlAdapted from github.com ↗
<mvc:View xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc">
    <ListBox items="{/names}">
        <core:ExtensionPoint name="extension1">
            <ListItem text="{firstName}" />
        </core:ExtensionPoint>
    </ListBox>
</mvc:View>

UI5 Web Components inside UI5 apps

FreestyleWeb ComponentsUI5 CLI
ui5-tooling-modules

The OpenUI5 topic Using Web Components states that a web component with Custom Elements metadata can be required and used like a UI5 control, its properties, events and slots mapped to UI5 concepts. Its setup installs the community UI5 CLI extension ui5-tooling-modules and registers its task and middleware in every ui5*.yaml used for builds.

yamlAdapted from github.com ↗
builder:
  customTasks:
    - name: ui5-tooling-modules-task
      afterTask: replaceVersion
server:
  customMiddleware:
    - name: ui5-tooling-modules-middleware
      afterMiddleware: compression

03Tests, checks, types and releases

Each as UI5's own documentation describes it, with the pages to read. Where a source recommends something, the recommendation is its own.

Integration tests with OPA5

OPA5

OPA5 is the UI5 API for integration tests that hides asynchronicity by polling and is written in the app's own language. The topic lists its restrictions: no screen capture, no testing across pages, no remote execution, and it states end-to-end tests are not recommended with OPA.

Test starter

sap/ui/test/starter

The test starter orchestrates QUnit and OPA5 tests for applications and libraries from a testsuite.qunit.html page that loads sap/ui/test/starter/createSuite.js and a test suite module returning name, defaults and tests. It loads the frameworks asynchronously and CSP-compliantly and moves framework configuration out of test code.

jsAdapted from github.com ↗
sap.ui.define(() => {
	"use strict";

	return {
		name: "QUnit test suite for NAMESPACE",
		defaults: {},
		tests: {}
	};
});

End-to-end tests with wdi5

wdi5 (wdio-ui5-service)WebdriverIO

The OpenUI5 page The UI5 Ecosystem lists wdi5, a WebdriverIO service using UI5's test API for cross-platform end-to-end tests with OPA5-compatible selectors. It is a ui5-community project governed by a steering committee.

Static checks with UI5 linter

@ui5/linter

UI5 linter (@ui5/linter, run as ui5lint) checks JavaScript, TypeScript, XML, JSON and other project files for deprecated libraries and APIs, globals, possible CSP violations and deprecated manifest configuration, targeting readiness for UI5 2.x. It reads ui5lint.config.js/.mjs/.cjs and offers --fix for some findings.

shAdapted from github.com ↗
npm install --global @ui5/linter
ui5lint

TypeScript

@openui5/types@sapui5/types@ui5/ts-interface-generatorui5-tooling-transpile

Type definitions are published on npm as @openui5/types and @sapui5/types; ui5.github.io/typescript lists @types/openui5 (DefinitelyTyped) as deprecated and the ts-types-esm packages as legacy for versions before 1.113. Control development in TypeScript uses @ui5/ts-interface-generator to generate interfaces for the control API, shown in the SAP-samples control library sample; the OpenUI5 compatibility statement says type changes can break compilation but not runtime.

Packaging and dependencies

UI5 CLInpm

UI5 CLI consumes the framework via npm, declared in ui5.yaml under framework (name, version, libraries), manageable with ui5 use and ui5 add; the minimum consumable OpenUI5 version is 1.52.5, and OpenUI5 projects cannot depend on SAPUI5 projects. The Custom Tasks page notes community extensions are often prefixed ui5-task- to be found in the npm registry, and the ecosystem showcase names ui5-task-, ui5-middleware- and ui5-tooling- as its conventions.

yamlAdapted from ui5.github.io ↗
framework:
   name: OpenUI5
   version: 1.76.0
   libraries:
     - name: sap.ui.core
     - name: sap.m

Versioning against UI5 releases

UI5 linter

OpenUI5 versions are major.minor.patch; a new version ships monthly, standard releases are supported 6 weeks, mid-term (MTS) 9 months and long-term (LTS) 15 months. The version overview at sdk.openui5.org lists maintenance status and end-of-cloud-provisioning dates per patch; UI5 linter's README states APIs deprecated with or before 1.136 are not available in UI5 2.x.

04Using open source

Taking open source into a project, and publishing your own under an open licence, as UI5's projects and documentation describe it. Every artifact in the atlas carries the same readings, maintenance and licence among them, before it goes into a project.

Responsibility for third-party libraries

The OpenUI5 documentation states that OpenUI5 ships jQuery and datajs and can add its own security fixes to them. For any other library an application includes, it says OpenUI5 can give no statement about its security, and that the application has full responsibility for assessing a third-party library before using it and for embedding it securely.

Consuming npm packages with ui5-tooling-modules

ui5-tooling-modulesUI5 CLI

ui5-tooling-modules, a community-maintained UI5 CLI custom middleware and task in the ui5-community ecosystem showcase, lets UI5 code require npm package names as AMD-like dependencies. At build time the dependency is copied into the resources folder, and the addToNamespace option moves third-party modules into a thirdparty sub-namespace of the component. The README also describes a Seamless Web Components mode that wraps UI5 Web Components packages as UI5 controls.

jsAdapted from github.com ↗
// npm install chart.js
sap.ui.define([
  "chart.js"
], function(chartjs) {
  alert(chartjs.version);
})

Project shims and the module type in UI5 CLI

UI5 CLI

UI5 CLI's project-shim extension defines or extends the project configuration of a module, and its documentation names adding UI5 configuration to a third-party module as the most common use. The module project type is described as meant for non-UI5 resources such as third-party libraries: paths are mapped freely and resources are copied unchanged during a build.

yamlAdapted from ui5.github.io ↗
specVersion: "4.0"
kind: extension
type: project-shim
metadata:
  name: my.application.thirdparty
shims:
  configurations:
    lodash: # name as defined in package.json
      specVersion: "4.0"
      type: module # Use module type
      metadata:
        name: lodash
      resources:
        configuration:
          paths:
            /resources/my/application/thirdparty/: ""

Loader shims for non-AMD scripts

sap.ui.loader

The UI5 loader's configuration takes a shim map for modules where the normal AMD behaviour is not enough. The JSDoc in ui5loader.js names scripts that do not call define or sap.ui.define and instead export to a global name: exports names the global to read after execution, deps lists modules to load first, and amd: true temporarily disables AMD detection for that script.

jsAdapted from github.com ↗
sap.ui.loader.config({
  // provide dependency and export metadata for non-UI5 modules
  shim: {
    'sap/ui/thirdparty/blanket': {
      amd: true,
      exports: 'blanket'
    }
  }
});

Lockfiles and reproducible installs

npm

The npm documentation describes package-lock.json as generated whenever npm changes node_modules or package.json, recording the exact tree so later installs produce identical trees. npm ci requires an existing lockfile and exits with an error, rather than updating the lock, when package.json and the lockfile disagree.

Declaring a licence: SPDX, LICENSE and REUSE

REUSESPDX

The npm documentation asks for an SPDX licence identifier or SPDX expression in the license field of package.json. OpenUI5, the UI5 linter, UI5 Web Components and the UI5 docs repository each carry a LICENSES directory and a REUSE.toml, the file format of the REUSE initiative for stating copyright and licence per file. OpenUI5's REUSE.toml declares Apache-2.0 for all paths, and its THIRDPARTY.txt lists bundled subcomponents, such as UI5 Web Components in sap.f, with their own licences.

tomlAdapted from github.com ↗
version = 1
SPDX-PackageName = "OpenUI5"
SPDX-PackageDownloadLocation = "https://github.com/UI5/openui5"

[[annotations]]
path = "**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 SAP SE or an SAP affiliate company and OpenUI5 contributors"
SPDX-License-Identifier = "Apache-2.0"

Contribution terms: the DCO in OpenUI5

OpenUI5's CONTRIBUTING.md asks contributors to accept a Developer Certificate of Origin, the standard Linux Foundation text, before their first pull request; the CLA assistant bot requests it on the pull request and remembers the decision. The DCO replaced the Contributor License Agreement and Corporate CLA used earlier. SAP's organisation-wide CONTRIBUTING.md states the same DCO requirement.

Code of conduct and AI-generated contributions

The UI5 GitHub organisation's shared files adopt Contributor Covenant 2.1 as the SAP Open Source Code of Conduct. A separate guideline, linked from OpenUI5's CONTRIBUTING.md, sets conditions for AI-generated code in SAP open source projects: the tool's terms must not conflict with the project licence, similarity filtering must be on, third-party material needs permission and attribution, and employer policies apply.

05Security

What UI5's documentation and its projects state about security, with the pages to read. A project's SECURITY.md, where it has one, says how to report a vulnerability.

Where the framework's responsibility ends

The OpenUI5 security documentation describes OpenUI5 as a client-side library that cannot make the application secure on its own: authentication, session handling, authorisation and encryption are left to the server and the application. The Browser Security page lists what the application owns: output encoding in the HTML page, encoding JSON or XML sent to the client, processing that data securely, and the security of its own custom controls.

Content Security Policy

The OpenUI5 docs recommend building apps CSP-compliant and list what breaks a policy without script-src 'unsafe-inline' (inline scripts, inline event handlers, javascript: URLs) and without 'unsafe-eval' (synchronous loading, new Function, string arguments to setTimeout or setInterval). They suggest testing with Content-Security-Policy-Report-Only first. The directives table notes that controls based on UI5 Web Components, including sap.f, sap.ui.integration and sap.webc.*, still partly need style-src 'unsafe-inline'. The Get Started page replaces inline bootstrap code with ComponentSupport.

htmlAdapted from github.com ↗
<script id="sap-ui-bootstrap"
	src="resources/sap-ui-core.js"
	data-sap-ui-async="true"
	data-sap-ui-on-init="module:sap/ui/core/ComponentSupport">
</script>
<body class="sapUiBody" id="content">
	<div data-sap-ui-component data-name="sap.ui.demo.walkthrough" data-id="container" data-settings='{"id" : "walkthrough"}'></div>
</body>

Escaping in control renderers

sap.ui.core.RenderManagersap/base/security/encodeXML

For control developers, the OpenUI5 docs combine two measures against XSS: typed properties, which the core validates (a CSSSize cannot hold a script tag), and escaping of string values in the renderer. The Renderer Object page says the newer RenderManager API, declared with apiVersion: 2, hides the need for XSS protection in most cases, while the legacy string API left encoding to the caller (writeEscaped, writeAttributeEscaped, or sap/base/security/encodeXML). The docs ask for the most specific property type available.

jsAdapted from github.com ↗
var MyControlRenderer = {
    apiVersion: 2,
    render: function(oRm, oControl) {
        oRm.openStart("div", oControl).openEnd().text(oControl.getText()).close("div");
    }
};

HTML content: sap.ui.core.HTML, RichTextEditor and FormattedText

sap.ui.core.HTMLsap.m.FormattedTextsap/base/security/sanitizeHTML

The OpenUI5 docs state that controls escape the content they render, so applications pass unescaped data, with exceptions for controls built to show arbitrary HTML. sap.ui.core.HTML renders its content one to one and has sanitizeContent off by default; its JSDoc warns that user input shown there needs sanitising. RichTextEditor sanitises by default through the HTML5 sanitizer, which OpenUI5 adapted from Google's HTML4 sanitizer. sap.m.FormattedText allows only a limited set of tags and attributes and checks href values with URLListValidator.

URL allowlist with URLListValidator

sap/base/security/URLListValidator

sap/base/security/URLListValidator keeps a client-side list of allowed URLs, managed with add, clear and entries and checked with validate. The sanitizer of sap.ui.core.HTML uses it to strip URLs that are not allowed when sanitizeContent is on. The docs note that with no entries added, validate only checks that a URL is well formed, and that path entries need a leading slash.

jsAdapted from github.com ↗
// URLListValidator required from module sap/base/security/URLListValidator
URLListValidator.add("https", "sdn.sap.com");
URLListValidator.add("https", "community.sap.de", undefined, "/topics");

URLListValidator.validate("http://sdn.sap.com"); // => false (wrong protocol)
URLListValidator.validate("https://community.sap.de/anypath"); // => false (wrong path)
URLListValidator.validate("https://community.sap.de/topics"); // => true

Clickjacking and frame options

OpenUI5's frame-options configuration (allow, deny, trusted; allow is the default) places an invisible block layer over a framed page so it cannot be used, while the content stays visible. The docs distinguish it from the X-Frame-Options header, which stops the page loading, and state that the CSP frame-ancestors directive gives better control over trusted sites and is preferred over X-Frame-Options.

htmlAdapted from github.com ↗
<script id="sap-ui-bootstrap"
    data-sap-ui-frame-options="deny"
    data-sap-ui-...="...">
</script>

CSRF tokens in the OData models

sap.ui.model.odata.v4.ODataModelsap.ui.model.odata.v2.ODataModel

The OData V4 model handles an X-CSRF-Token header by itself: it sends Fetch, remembers the returned token, and on a 403 with the value required it fetches a new token with a HEAD request and repeats the request. The docs describe security token handlers for services with a fixed token or a different header name. In the OData V2 model, x-csrf-token is one of the private headers the model sets itself and that setHeaders cannot override.

UI5 linter: the CSP rule

UI5 linter

UI5 linter lists possible CSP violations among its findings. Its rule csp-unsafe-inline-script checks HTML files for inline scripts and links to the Content Security Policy topic. The rules reference has no other security rule; the remaining rules cover deprecations, globals and manifest checks.

Dependency and publishing security on npm

npm

npm audit sends a description of a project's dependencies to the registry and returns known vulnerabilities with remediations. npm's trusted publishing publishes from CI/CD over OIDC without long-lived tokens, and provenance statements, signed through Sigstore, publicly link a package to its source and build. The ui5-community ecosystem showcase's release workflow grants id-token: write for npm OIDC trusted publishing and sets NPM_CONFIG_PROVENANCE; npm also documents two-factor authentication for accounts and publishing.

Reporting vulnerabilities

The UI5 organisation's SECURITY.md is SAP's Open Source Security Policy: no public GitHub issues for vulnerabilities, reports through the SAP Trust Center or by email to secure@sap.com, with a list of details to include. OpenUI5's CONTRIBUTING.md and the UI5 linter README point to the same channels. The ui5-community ecosystem showcase uses GitHub Private Vulnerability Reporting instead, supports only the latest version of each package, and sends vulnerabilities in third-party dependencies upstream.

06Documentation the atlas can read

The atlas records only what a project's own documentation states, and quotes the sentence it rests on. What it looks for:

The stack it serves
A package is listed as an artifact only when its own documentation names the SAP stack it is built for, such as UI5. A generic library is not, however often a project installs it.
Where it runs
Runtimes and flavors are recorded where a sentence states them, and that sentence is shown beside the value. Where the documentation says nothing, the page says it does not say.
What it needs and talks to
Services it requires and systems it connects to, with the protocol, are edges drawn only from what the documentation names.
Its properties
A capability compares its artifacts on a few declared properties. A value counts only with the sentence it comes from; a property the documentation does not mention stays open.
Releases and a licence
Readings are crawled from the repository and the registry, releases and the last push among them. A README is shown whole only under a licence that permits copying; otherwise its opening and a link.

07Tutorials

Step-by-step material from SAP and the ecosystem, linked where it lives.

08Share it

Where finished UI5 work is published and found, and how it gets into the atlas.

UI5 Ecosystem Showcase: Contributing
Two paths for a UI5 CLI extension: inside the monorepo (CI and automated npm publishing via Changesets, in exchange for review and ongoing maintenance) or in your own repository; naming ui5-task-, ui5-middleware-, ui5-tooling-. ui5-community.github.io ↗
bestofui5-data
Data behind bestofui5.org; a project is added through an issue with the new-package template, the entries living in sources.json (owner, repo, type, tags). github.com ↗
Best of UI5
Community-run listing of UI5 CLI extensions, Easy-UI5 subgenerators, custom libraries and controls published as npm packages (per the OpenUI5 page The UI5 Ecosystem). bestofui5.org ↗
The UI5 Ecosystem (OpenUI5 docs)
SAP's own page listing UI5 CLI, UI5 linter, Easy-UI5, UI5-TypeScript, UI5 Web Components, wdi5 and Best of UI5. github.com ↗
ui5-community org
Hosts community UI5 libraries, custom controls and UI5 CLI middlewares and tasks; key projects wdi5, Easy UI5, bestofui5.org, the ecosystem showcase. github.com ↗
Create UI5 Web Components Project (Package)
The scaffold produces a project prepared as an npm package. ui5.github.io ↗
Add it to the atlas
Use Feedback, Add, or open a pull request against the atlas data. A repository URL is enough to start.
Credit
Maintainers and authors are linked to their work.
Corrections
Anyone can correct an entry, through Feedback or a pull request.