
Ui5 Best Practices
- 86 installs
- 32 repo stars
- Updated August 4, 2026
- ui5/plugins-coding-agents
ui5-best-practices is an agent skill that applies official SAP UI5 coding standards for async modules, binding, i18n, CSP, TypeScript events, linter MCP tools, CAP, and form layouts.
About
ui5-best-practices is a Frontend Development agent skill that enforces SAP UI5 standards drawn from official guidelines for solo builders and small teams shipping Fiori-style or CAP-integrated apps. Invoke it while writing or refactoring UI5 code so modules load asynchronously, bindings use OData types, translations flow through i18n, and Content Security Policy stays free of inline scripts. It also steers TypeScript handler typing on modern UI5 releases and points agents toward MCP helpers for API reference lookup and ui5 linter runs. CAP integration notes and local cds watch workflows keep full-stack SAP projects consistent. The form layout rule is explicit: avoid SimpleForm and use Form with ColumnLayout. Use this skill whenever an AI coder might otherwise fall back to legacy global patterns or deprecated controls.
- Never global sap.m access—declare dependencies via sap.ui.define, ES6 imports, or core:require
- Data binding with OData types, i18n management, and CSP compliance (no inline scripts)
- TypeScript event types for UI5 >= 1.115.0 (e.g. Button$PressEvent)
- MCP tooling: get_api_reference and run_ui5_linter
- Form rule: never SimpleForm—always Form with ColumnLayout; includes CAP integration and cds watch patterns
Ui5 Best Practices by the numbers
- 86 all-time installs (skills.sh)
- +16 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,094 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ui5/plugins-coding-agents --skill ui5-best-practicesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 86 |
|---|---|
| repo stars | ★ 32 |
| Last updated | August 4, 2026 |
| Repository | ui5/plugins-coding-agents ↗ |
What it does
Keep SAP UI5 apps aligned with official async loading, binding, i18n, CSP, TypeScript events, linter MCP tools, CAP patterns, and form layout rules.
Who is it for?
Best when you're building or maintaining SAP UI5 / Fiori apps with agent assistance and need standards enforced on every edit.
Skip if: Non-UI5 React or Vue frontends, or greenfield projects with no SAP UI5 dependency.
When should I use this skill?
Use when writing UI5 applications to ensure modern, maintainable code following SAP standards (async loading, binding, i18n, CSP, TypeScript, MCP linter, CAP, forms).
What you get
New and revised UI5 code follows SAP-documented patterns—async dependencies, typed events, linter-clean structure, and ColumnLayout forms ready for CAP-backed apps.
- UI5 code aligned to SAP module-loading and binding rules
- Form layouts using Form + ColumnLayout
- Linter-ready UI5 changes with CSP-safe script boundaries
By the numbers
- UI5 TypeScript event types documented for UI5 >= 1.115.0
- Explicit never-SimpleForm / always ColumnLayout Form rule
Files
UI5 Best Practices and Coding Standards
Overview
This skill enforces UI5 development standards derived from official SAP guidelines. It covers the four critical areas: coding guidelines, tooling integration, CAP integration, and form creation rules.
---
1. Module Loading - CRITICAL
Never Use Global Access
NEVER access UI5 framework objects globally (e.g., sap.m.Button). Always declare dependencies explicitly for asynchronous loading.
JavaScript
// ❌ WRONG - Global access
var oButton = new sap.m.Button();
// ✅ CORRECT - Explicit dependency
sap.ui.define(["sap/m/Button"], function(Button) {
var oButton = new Button();
});
// ✅ CORRECT - Dynamic loading with sap.ui.require
sap.ui.require(["sap/m/MessageBox"], function(MessageBox) {
MessageBox.show("Hello");
});TypeScript
// ❌ WRONG - Global namespace
const button: sap.m.Button;
// ✅ CORRECT - Import module
import Button from "sap/m/Button";
const button: Button;XML Views
<!-- ✅ Controls are auto-loaded by tag -->
<m:Button text="Click Me"/>
<!-- ✅ For formatters/types, use core:require -->
<ObjectListItem
core:require="{
Currency: 'sap/ui/model/type/Currency'
}"
number="{
parts: ['invoice>Price', 'view>/currency'],
type: 'Currency'
}"/>Why: Ensures proper async loading, improves performance in production builds.
Reference: UI5 documentation page "Require Modules in XML View and Fragment"
---
2. Component Initialization
Use sap/ui/core/ComponentSupport for declarative initialization of the initial (root) component:
<!-- index.html -->
<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-on-init="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-resource-roots='{ "my.app": "./" }'>
</script>
<body class="sapUiBody">
<div data-sap-ui-component
data-name="my.app"
data-id="container">
</div>
</body>Reference: UI5 documentation page "Declarative API for Initial Components"
Note: Nested components should be managed via component usages (declared in the manifest.json of the containing component)
---
3. Data Binding Best Practices
Always Use Built-in Data Types
ALWAYS use data binding in views to connect UI controls to data or i18n models.
Priority order: 1. OData types (sap/ui/model/odata/type/*) - Preferred 2. Simple types (sap/ui/model/type/*) - Only when no OData equivalent 3. Custom types - For special two-way binding scenarios or complex validation 4. Custom formatters - Only for unique business logic (one-way binding)
<!-- ❌ WRONG - Custom formatter for standard formatting -->
<Text text="{path: 'price', formatter: '.formatCurrency'}"/>
<!-- ✅ CORRECT - Use OData type with format options -->
<Text text="{
path: 'price',
type: 'sap.ui.model.odata.type.Decimal',
formatOptions: {
style: 'currency',
currencyCode: 'EUR'
}
}"/>
<!-- ✅ CORRECT - Use grouping for thousands separator -->
<Text text="{
path: 'quantity',
type: 'sap.ui.model.odata.type.Decimal',
formatOptions: {
groupingEnabled: true
}
}"/>Common OData Types:
sap.ui.model.odata.type.Decimal- Numbers with decimalssap.ui.model.odata.type.String- Text with length constraintssap.ui.model.odata.type.DateTime- Date and time
Common Simple Types (use only when no OData equivalent):
sap.ui.model.type.DateInterval- Date rangessap.ui.model.type.FileSize- File size formatting
Example: For number formatting with thousands separator, prefer sap.ui.model.odata.type.Decimal with formatOptions: {groupingEnabled: true} over sap.ui.model.type.Integer or a custom formatter.
When to Use Custom Types
Custom types are needed for special two-way binding scenarios where built-in types don't provide the required validation or conversion logic.
Example: Custom Type for Email Validation with Two-Way Binding
// controller/EmailType.js
sap.ui.define(["sap/ui/model/SimpleType"], function(SimpleType) {
return SimpleType.extend("my.app.type.EmailType", {
formatValue: function(oValue) {
return oValue;
},
parseValue: function(oValue) {
return oValue;
},
validateValue: function(oValue) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (oValue && !emailRegex.test(oValue)) {
throw new sap.ui.model.ValidateException("Invalid email format");
}
}
});
});Usage in View:
<!-- ❌ WRONG - Formatter doesn't work for two-way binding validation -->
<Input value="{path: 'email', formatter: '.validateEmail'}"/>
<!-- ✅ CORRECT - Custom type enables two-way binding with validation -->
<Input
core:require="{EmailType: 'my/app/type/EmailType'}"
value="{
path: 'email',
type: 'EmailType'
}"/>Why Custom Types:
- ✅ Two-way binding support (formatValue + parseValue + validateValue)
- ✅ Real-time validation as user types
- ✅ Model updates immediately on valid input
- ❌ Custom formatters only work for one-way (display) binding
Data Binding in Views
ALWAYS use data binding to connect controls to models:
<!-- Property binding -->
<Input value="{/customer/name}"/>
<!-- Aggregation binding -->
<List items="{/products}">
<StandardListItem title="{name}" description="{price}"/>
</List>
<!-- Expression binding -->
<Text text="{= ${quantity} * ${price} }" visible="{= ${stock} > 0 }"/>---
4. Internationalization (i18n)
Translation Workflow Guidelines
When modifying .properties files, follow the appropriate workflow based on your project type:
For development and testing:
- Update
i18n.properties(base file) only - Changes will be reflected immediately for development
Production translation workflows:
- SAP S/4HANA apps: NEVER manually edit localized files (
i18n_de.properties,i18n_fr.properties, etc.) - Translation is handled through SAP's internal translation process
- Apps using SAP Translation Hub or Translation Export/Import (TEW): DO NOT touch localized files
- Translations are generated automatically from the base file
- Manually translated apps only: Apply changes to all locale files to maintain consistency
Why: Professional translation workflows generate localized files from the base i18n.properties file. Manual edits to localized files will be overwritten during the translation process.
---
5. Security - Content Security Policy
Never Use Inline Scripts or Styles
NEVER use inline scripts or inline styles in HTML. They violate the recommended CSP settings for UI5 applications.
<!-- ❌ WRONG - Violates CSP -->
<script>
alert("Hello");
</script>
<style>
.error { color: red; }
</style>
<div style="color: red;">Styled text</div>
<!-- ✅ CORRECT - External files -->
<script src="controller/Main.controller.js"></script>
<link rel="stylesheet" href="css/style.css">
<!-- ✅ CORRECT - CSS classes -->
<div class="errorText">Styled text</div>Requirements:
- All application logic must reside in dedicated JS or TS files
- All styling must reside in dedicated CSS files
- Inline
<script>tags violate CSP - Inline
<style>tags violate CSP - Inline
styleattributes violate CSP
Reference: UI5 documentation page "Content Security Policy"
---
6. TypeScript Event Handling (UI5 >= 1.115.0)
Use Control-Specific Event Types
For UI5 1.115.0 and above, import and use the specific event type from the control's module.
Pattern: <ControlName>$<EventName>Event (notice the "Event" suffix)
// ✅ CORRECT - Import specific event type
import { Button$PressEvent } from "sap/m/Button";
import { Table$RowSelectionChangeEvent } from "sap/ui/table/Table";
import Controller from "sap/ui/core/mvc/Controller";
export default class MainController extends Controller {
public onPress(event: Button$PressEvent): void {
const button = event.getSource(); // Correctly typed as Button
// ...
}
public onRowSelectionChange(event: Table$RowSelectionChangeEvent): void {
// Correctly typed: getParameter is known and return value inferred
const selectedContext = event.getParameter("rowContext");
// ...
}
}Fallback for Older Versions
UI5 < 1.115.0: Control-specific event types are NOT available. Use the generic Event type:
import Event from "sap/ui/base/Event";
import Controller from "sap/ui/core/mvc/Controller";
export default class MainController extends Controller {
public onPress(event: Event): void {
// Generic Event type for UI5 < 1.115.0
// ...
}
}Benefits: Static type checking and autocompletion for event parameters without manual casting.
---
7. MCP Tooling Integration
API Lookup
ALWAYS use the get_api_reference tool to get information on UI5 controls and APIs. This provides direct access to the official UI5 API Reference for the UI5 version in use.
Usage: get_api_reference with project path
Returns: Official API documentation for controls, classes, and namespacesCode Validation
ALWAYS use the run_ui5_linter tool to identify issues. It detects deprecated APIs, accessibility issues, and other potential bugs.
Usage: run_ui5_linter with project path
Returns: List of issues with severity levelsCode Fixes
To apply fixes suggested by the linter: 1. ALWAYS confirm with the user first 2. Use the fix parameter of the run_ui5_linter tool 3. The tool automatically corrects some identified issues 4. Manually fix remaining issues using the context information provided
Local Server Behavior
When interacting with the UI5 CLI's development server:
CRITICAL: The server does NOT serve a default index file.
# ❌ WRONG - Will not work
http://localhost:8080/
# ✅ CORRECT - Must reference files by full path
http://localhost:8080/index.htmlCode Quality Checks
After making code changes, ALWAYS run the project's linter if available:
npm run lint # Standard
npm run eslint # Alternative
eslint . # Direct ESLint call
npm run ui5-lint # UI5 Linter if configured
ui5lint . # UI5 Linter if available as CLI toolWhy: Linters catch common issues before committing:
- Missing imports or type errors
- Formatting inconsistencies
- Deprecated API usage
- Code style violations
Fix all linting errors before committing.
---
8. CAP Integration
When creating a UI5 project within a CAP (Cloud Application Programming Model) project:
Project Location
ALWAYS create UI5 projects within the app/ directory of the CAP project root.
cap-project/
├── app/ # ← UI5 apps go here
│ └── my-ui5-app/
├── srv/ # CAP services
├── db/ # Database models
└── package.jsonService Information
Get service information:
- If CDS tools are available: Use them to get definitions, services, and endpoints
- If no CDS tools: Run these commands:
cds compile '*' # Get definitions
cds compile '*' --to serviceinfo # Get services and endpointsService Integration
When creating the UI5 project, ALWAYS provide:
- Absolute OData V4 service URL
- Target entity set
Plugin Installation
ALWAYS run in CAP project root:
npm i -D cds-plugin-ui5This plugin automatically handles serving the UI5 applications.
Running the Server
# ❌ WRONG - Never run separate UI5 server
cd app/my-ui5-app
ui5 serve # Don't do this!
npm start # Don't do this!
# ✅ CORRECT - Run from CAP project root
cds watch # Serves both backend and UI5 apps
# or
cds run # Alternative commandWhy: Single command serves both backend services and all UI5 applications from the same origin (http://localhost:4004).
Data Connection
NEVER configure ui5-middleware-simpleproxy in ui5.yaml:
# ❌ WRONG - No proxy needed
server:
customMiddleware:
- name: ui5-middleware-simpleproxy # Don't add this!Why: cds watch ensures UI and service are served from the same origin, making a proxy unnecessary.
Accessing the App
Check the CAP launch page (typically http://localhost:4004) for:
- List of available services
- Links to UI5 applications
---
9. Form Creation Rules
Never Use SimpleForm (Unless Explicitly Requested)
<!-- ❌ AVOID - SimpleForm -->
<form:SimpleForm>
<Label text="Name"/>
<Input value="{name}"/>
</form:SimpleForm>
<!-- ✅ CORRECT - Use Form with ColumnLayout -->
<form:Form editable="true">
<form:layout>
<form:ColumnLayout
columnsM="2"
columnsL="3"
columnsXL="4"/>
</form:layout>
<form:formContainers>
<form:FormContainer title="Personal Data">
<form:formElements>
<form:FormElement label="Name">
<form:fields>
<Input value="{name}"/>
</form:fields>
</form:FormElement>
</form:formElements>
</form:FormContainer>
</form:formContainers>
</form:Form>Default Column Configuration
ALWAYS use these defaults unless requested differently:
- M-size: 2 columns
- L-size: 3 columns
- XL-size: 4 columns
---
Documentation References
For additional information, consult these UI5 documentation pages:
- "Require Modules in XML View and Fragment"
- "Declarative API for Initial Components"
- "Content Security Policy"
- Official UI5 API Reference (use
get_api_referencetool)
---
Related skills
How it compares
SAP-specific frontend standards skill—not a generic JavaScript style guide or a deployed MCP server by itself.
FAQ
Who is ui5-best-practices for?
Developers (and small SAP teams) using coding agents to write UI5 applications, especially with OData, i18n, TypeScript, and CAP.
When should I use ui5-best-practices?
During Build frontend work whenever you create views, controllers, components, forms, or CAP-integrated UI5 features—or before asking the agent to run ui5 linter fixes.
Is ui5-best-practices safe to install?
The skill describes MCP linter and API reference tooling; verify repo and tool permissions on the Security Audits panel on this Prism page before enabling network or shell access.