Starter repository for building abap2UI5 apps — UI5 applications written purely in ABAP. Comes with the validation gates and AI-assistant setup preconfigured, so a new app project starts with everything the abap2UI5 ecosystem has learned about developing with (and by) AI agents.
src/zcl_app_001— a working starter app (input, bound table, event) following the canonical template ofAGENTS.md, with an ABAP Unit test include (.clas.testclasses.abap) that drives it through a test double forz2ui5_if_client— first start,SAVEevent, navigated roundtrip — the shape every app test can take- abaplint — syntax/style checks with the abap2UI5 framework resolved as a dependency, no SAP system needed
- abap2UI5-linter — checks every
built view statically (unknown/deprecated/too-new controls and members,
binding mistakes, builder-tree defects, chain layout) and renders it
headless with a real
XMLView.create - CI (
.github/workflows/check.yml) running both gates on every push/PR — abaplint from this repo'spackage-lock.json, the view checks through the linter's own GitHub Action (abap2UI5/linter, SHA-pinned), which brings the UI5 runtime and the browser the render gate needs AGENTS.md— the complete app-building reference for AI assistants, plus a.claude/settings.jsonpermission allowlist so autonomous sessions run the gates without prompts.claude/skills/— the framework's four agent skills (build-an-app,view-chain-layout,abap-check,ui5-check), mirrored here so an agent in your project loads the catalogue of what a green CI does not catch without a framework checkoutnpm run doctor— an offline check of the machine and the repository: Node, both gates, a Chromium the render gate can launch, the pins, every.clas.xmlsidecar, the lint config — one line per check with the remedy.mcp.json,.devcontainer/,.vscode/extensions.json— the abap2UI5 MCP server registered for Claude Code, a dev container with everything installed on create, and the editor's extension recommendations
Four ways, one result — all of them execute template.json, so a project
started any way is the same project:
- Use this template on GitHub, then make it yours:
node scripts/rename.mjs --class zcl_my_app --package "My App" --repo my-app(below). npm create abap2ui5-app@latest my-app -- --class zcl_my_app— no GitHub account needed. Thecreate-abap2ui5-apppackage fetches the template's files frommain, applies the same substitutions and writes the directory;--package,--repoand--from <local checkout>as withrename.mjs.- VS Code: "New Project from Template" in the abap2UI5 extension.
- An MCP-capable agent: the
mcp-server's
scaffold_apptool.
- Start a project one of the four ways above (Use this template on GitHub is the first).
- Install the abap2UI5 framework in
your system via abapGit, then install this repo
the same way. The starter app needs framework 1.144.0 or newer — that
is the release the local gates lint against, pinned in
abaplint.jsonc. - Create an ICF endpoint for the framework's HTTP handler (see the
documentation) and open
<endpoint>?app_start=zcl_app_001. - Make it yours (below), then build your app following
AGENTS.md.
After Use this template the repository is still called app-template: the
name is in .abapgit.xml, the ABAP package still says abap2UI5 app, and the
app is still ZCL_APP_001. One command changes all of it:
node scripts/rename.mjs --class zcl_my_app --package "My App" --repo my-appAdd --dry to see what it would touch first. It rewrites the class in the
ABAP and the CLSNAME in its .clas.xml — renaming only one of the two
gives you an object abapGit imports under one name and ABAP activates under
another, which is the mistake this exists to prevent. (xml_consistency in
abaplint.jsonc catches it either way.)
What it renames is written down in template.json, not in the script: the
MCP server and the
VS Code extension hand out this
same template, and they read the same file — so a project started any of the
three ways is the same project.
Three decisions the script deliberately leaves to you:
- Your namespace.
abaplint.jsoncrequires^ZCL_or^ZCX_, which is the customer namespace every system has. If you develop in a registered namespace (/ACME/) or behind a company prefix (ZAB_), changeobject_namingthere first — you make this choice once and live with it for years. - The LICENSE, which still reads Copyright (c) 2026 abap2UI5. It is MIT, so you may keep it, change the holder, or replace it entirely. It is your project now.
- The ABAP package.
src/package.devc.xmlcreates one package. Whether that is$TMPor a transportable package is decided when abapGit first pulls the repository into your system, not here.
Both gates are npm devDependencies, so CI and your machine run the same versions:
npm ci # once - installs abaplint and the linter
npx playwright install chromium # once - only for the render gate
npm run check # both gates, expect 0 issues
npm run check:abap # abaplint only
npm run check:abap2ui5:fast # linter without the render gate (no browser)
npm run watch # the same, again on every save - Ctrl+C ends it
npm run watch:render # the watch with the render gate on, one warm browser across the runs
npm run test:unit # the ABAP Unit tests, run in the transpiled backend without a system
npm run fix # apply the linter's mechanical corrections
npm run check:pin # the framework release named in one place only
npm run doctor # when something above fails: what is missing, and the command that fixes itdoctor is offline and takes a second. It checks Node against .nvmrc, that
npm ci installed both gates on one minor line, that Playwright's Chromium is
where the render gate will look (npx playwright install chromium otherwise),
the framework pin (through check-pin), the linter Action pin in check.yml
against the devDependency, every .clas.xml sidecar (BOM, LF, CLSNAME,
WITH_UNIT_TESTS for a class with tests), abap2ui5lint.jsonc, and — never
failing — whether VS Code has the abap2UI5 extension, whether the pinned
framework satisfies the linter's compatibility record, when it ships one, and
whether the installed linter has --watch.
watch is the loop for Eclipse ADT users who pull with abapGit into this
checkout: save in ADT, pull, read the report — the linter re-runs on every
change under src/ (VS Code users have the extension's live check instead).
The --watch flag arrives with the @abap2ui5/linter release after 0.6.1, so
on the ^0.6.1 pinned here both watch scripts print the linter's
unknown option '--watch' until the devDependency is bumped — doctor says
whether the installed linter has it.
check:pin is the small gate around the one pin nothing else can move: the
framework release in abaplint.jsonc is a tag inside an abaplint dependency,
which Dependabot cannot read, and the same number is repeated in this README
and in AGENTS.md. It fails when the three disagree, and tells you (without
failing) when a newer framework release is out.
Settings (paths, UI5 floor, distribution, rule severities, fail level) live in
abap2ui5lint.jsonc; every rule id is documented at
abap2ui5.github.io/linter.
Prefer no project install? npx @abap2ui5/linter src --no-render runs the
static half straight from npm.
src/zcl_app_001.clas.testclasses.abap is an ABAP Unit test for the starter
app and the pattern for your own: a local ltd_client with
INTERFACES z2ui5_if_client PARTIALLY IMPLEMENTED whose attributes decide
what check_on_init( ) / check_on_navigated( ) / check_on_event( ) /
get_event( ) answer and which records the view_display( ) XML and the
message_toast_display( ) texts, and implements the four methods the view
code calls (the transpiled runtime generates no stubs for a PARTIALLY IMPLEMENTED interface, a system does). Run it on the system (ADT
Ctrl+Shift+F10) - or without one: npm run test:unit and the unit job in
check.yml run it in the transpiled abap2UI5 backend, through the
mcp-server's abap2ui5-unit
(framework at the pinned release, backend downloaded or built once and
cached). Locally abaplint compiles it against the framework and the linter
skips test includes, so npm run check stays the gate it is.
- VS Code extension
(Marketplace,
Open VSX) — F9 launches
a class in an embedded preview against a real system; the linter's findings
arrive as editor diagnostics with quick fixes while you type, plus
completion for the UI5 API and the class's own binding paths, a template
gallery for new apps, and the reconstructed XML view beside the code.
.vscode/extensions.jsonrecommends it, and the dev container installs it. - mcp-server — MCP server giving AI
agents the full loop: deploy the class, build the transpiled Node backend,
run the app headless and look at a screenshot.
.mcp.jsonregisters it for Claude Code; the VS Code extension registers it for Copilot. - Dev container — open the repository in a container (
.devcontainer/) andnpm ci, Playwright's Chromium and the three extensions are there.
- AGENTS.md — the complete app-building reference (also for humans)
- Documentation — the rendered docs site
- Samples — curated example apps (bindings, events, popups, navigation)
- samples-controls — the official UI5 demo kit rebuilt 1:1 as gate-verified abap2UI5 apps
- samples-stack — abap2UI5 alongside what your system already runs: OData, Smart Controls, RAP (with and without draft), business events, stateful sessions and locks, AMC/APC WebSockets, the MIME repository, the Fiori Launchpad. Reach for it when your app needs data or a stack the plain framework makes no assumption about