build-an-app
Skill1 starsChanged 12 days agoMITView on GitHub
How to build an application WITH abap2UI5 (as opposed to changing the framework) - app class template, lifecycle, view building via z2ui5_cl_ui5_view_builder, data binding, events, popups, navigation, validation tooling. Use when writing or reviewing a z2ui5_if_app class, demo app, sample or any consumer application code.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- aazirani/flutter_agentifytheir own version, first seen Nov 15, 2026
- BuilderIO/agent-nativetheir own version, first seen Oct 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- BuilderIO/agent-native★ 7.6ksame name
- aazirani/flutter_agentify★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- abap-checkSkill
- ui5-checkSkill
- view-chain-layoutSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 84
Never feed abap_true into v raw — it serializes as X.
- Distinctive: line 103
Never write a model path as a text literal.
- Very specific: line 128
Before you finish, run the abap-check skill over what you wrote — it is the companion to this one and catches what a green lint does not: …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- GENERATED by scripts/generate-skills.mjs in abap2UI5/app-template from .claude/skills/build-an-app/SKILL.md in abap2UI5/abap2UI5 - "this repository" in the text is the framework's. Do not edit; regenerate. -->Building an abap2UI5 app
Read AGENTS.md in this repository — everything from "1. The model in one
paragraph" down is the framework's complete self-contained guide (template, lifecycle, builder verbs, binding rules,
events, popups, navigation, portability rules, validation tooling). This
skill is the trigger and the checklist; the guide is the content.
Before writing one from scratch, ask whether it exists. abap2UI5/samples
holds 150 working apps, each linted, rendered and downported to three
releases — a value help, a tree, navigation between two apps, a dynamic table
typed at runtime. Reading one beats reproducing it, and beats any snippet: the
sample is gated, a snippet is a copy somebody has to keep in step.
- With the MCP server: the
examplestool queries that catalogue (examples { query: "value help f4" }) and hands back the class to read. Its neighbourcapabilitiesanswers the other question — whether a UI5 control can be expressed at all — out of samples-controls' 622 ports. - Without it: SAMPLES.md is the same catalogue as a page.
Quick orientation while it loads:
- One ABAP class implements
z2ui5_if_app;main( client )runs once per roundtrip — dispatch withcheck_on_init( )/check_on_event( )/check_on_navigated( ). - The
check_on_navigated( )branch is part of the dispatcher, not an option.check_on_init( )is "this app instance never ran", not "the app starts": it stays false when a called app hands control back (nav_app_leave, anyz2ui5_cl_pop_*value help — those run overnav_app_calltoo) and when a bookmarked state is restored. Those roundtrips firecheck_on_navigated( )alone, and a branch that does not re-runview_display( )there leaves the previous screen standing with no error anywhere. Apps built without it work perfectly until the day someone calls them from a navigation — the linter'smissing-view-display-on-navigatedcovers the branch that exists but never displays. - …and all of it is ONE
IF/ELSEIFchain, so exactly one arm runs per roundtrip.check_on_init( )being true impliescheck_on_navigated( )is true — every path to a firstmain( )sets the flag (factory_first_start, fresh start and draft restore alike,factory_system_startup,prepare_app_stackfor call and leave). On that first roundtrip the init arm wins and the navigated arm is skipped, so the init arm seeds AND displays:IF check_on_init( ). model_init( ). view_display( ). ELSEIF check_on_navigated( ). view_display( ). ELSEIF check_on_event( ). on_event( ). ENDIF.— the guide's template. Carry the init arm only for what must happen ONCE —model_init( ), or a couple of control-state flags seeded inline; an app with nothing to seed drops it and starts the chain atcheck_on_navigated( ). An init arm that ONLY displays decides nothing (redundant-init-display), and neither doesIF check_on_init( ) OR check_on_navigated( ).. - Never split the chain. No
IF check_on_init( ). … ENDIF.block that seeds followed by anIF check_on_navigated( ).block that displays, and no lifecycleIFnested in another arm: the flags overlap (init implies navigated, a returning app can bring an event), so separate blocks run more than one arm per roundtrip, and the linter reports them asseparate-lifecycle-ifs. Only a guard block that leaves the method (… RETURN. ENDIF.) is exempt. - Ask the lifecycle with the call itself, never with
IS INITIAL. The threecheck_on_*( )methods returnabap_bool, so the branch isIF client->check_on_init( ).— a predicative call, the way the sample corpus and the documentation onz2ui5_if_clientwrite it. Compounds keep the shape (ELSEIF client->check_on_event( `LOCK` ).,IF client->check_on_navigated( ) AND mv_ready = abap_true.) — but neverIF client->check_on_init( ) OR client->check_on_navigated( )., whoseORis redundant, see the display-branch rule above.IS NOT INITIALasks a boolean whether it is EMPTY, which is what that question means for a string, and it is one more dialect an app author has to read. Only a NEGATIVE branch is spelled out, as= abap_false: the corpus has no negated predicative form. Every otherabap_boolfollows the same rule:IF mv_flag = abap_false.andDELETE lt_x WHERE flag = abap_false., neverIS INITIALon either. - PUBLIC attributes = serialized, browser-visible state. Bound data only; everything else PROTECTED.
- Build views with
z2ui5_cl_ui5_view_builder(ele/tag/a/end/stringify). The legacyz2ui5_cl_xml_viewis frozen — never use it in new code. - A boolean from an ABAP variable goes through
a( )'sbparameter:)->a( n = `editable` b = mv_edit_mode )renderstrue/false. Never feedabap_trueintovraw — it serializes asX. - The chain's layout is strict, not taste — read the
view-chain-layoutskill before writing one. It is the single source of the rules, identical in this repository and both sample repositories, and it is machine-checked (the linter'schain-house-layoutrule:npm run check:abap2ui5reports,npm run fixapplies). In short: one call per line, four spaces per level, the)rides with the arrow ()->),end( )alone in the column of theele( )it closes, a control'sa( )s one level in with theirv =aligned. Blank lines only in the single-chain shape, where a blank opens a block and there are exactly two. - Which
factory( )shape you use is decided by the chain shape, not by preference: a view split into a statement per subtree hangs the chain off thefactory( )(one statement, not two) so the variable holds themvc:View; a view written as one chain may take afactory( ).of its own. A standalonefactory( ).with the split shape is broken — the variable then holds the root and the next statement adds a second root beside themvc:View. See the skill. - Bind with
client->_bind( var )(also for display-only;_bind_editis obsolete). Row-template fields bind as`{UPPERCASE}`. Never write a model path as a text literal. - Events:
client->_event(NAME), dispatch viaCASE client->get_event( ).; client-resolved args are$-prefixed. An arg that carries data (user text, a foreign key) goes on a wire withs_ctrl-check_arg_literal = abap_true— otherwise a value starting with$or{is evaluated by the client instead of passed (guide, section 5). Changed bound data is pushed automatically —view_model_update( )is obsolete, does nothing, and gets deleted whenever you touch an app. - A per-keystroke wire (
liveChange,liveSearch,sliderChange) setss_ctrl-check_queue_last: an event fired while a roundtrip is in flight is dropped by default, so typing under a running roundtrip lost its last keystrokes and the backend sat one value behind the control. The flag keeps the LAST firing and sends it once the response has landed — one roundtrip at a time, order preserved. There is no flag for firing them all at once, and a timer tick or poll needs none:START_TIMERhas its own slot and waits out the roundtrip in flight. - Business logic is computed in ABAP, never in frontend formatters (thin frontend). UI5 1.71 is the compatibility floor — check "available since".
- The app checks its own authorizations at the top of
main. - Validate with the abap2UI5-linter
(
npm run check:abap2ui5, ornpm run check:abap2ui5:fastwithout the render gate); iterate without a SAP system via the mcp-server (deploy_app→build_backend→run_app, theninteract_appto drive the event branch andrun_unit_testsfor the class's own test double — chapter 9 of the guide lists the tooling). - Before you finish, run the
abap-checkskill over what you wrote — it is the companion to this one and catches what a green lint does not: abapGit round-trip diffs, activation errors (class_constructorvisibility,LOCAL FRIENDS), SLIN/ATC traps and runtime breakage that only shows on a real system. - The API contract is
src/02/z2ui5_if_client.intf.abapin abap2UI5/abap2UI5 — when unsure about a method or acs_eventaction, read it there; thefollow_up_actionabapdoc documents the full frontend-action catalog.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

