Web toolWeb tooltypeA hosted utility you use at a URL, rather than run or install. May be free or paid; source_available says whether anything behind it is inspectable.See every one →What this type is →by a community orgby a community orgoriginPublished by a community organisation, so it outlives any one maintainer.See every one →

abap2UI5 Playground

ABAP in the editor on the left and the abap2UI5 app it builds on the right, both inside one browser tab: the framework is transpiled to JavaScript at build time and the class in the editor is compiled when Run is pressed.

Trying an abap2UI5 idea normally needs a system with the framework installed, a class activated in it and a browser pointed at the handler. This page carries the framework instead: the abap2UI5 sources are transpiled to JavaScript at build time, the classes in the editor are compiled on Run in about 20 ms, an in-memory SQLite stands in for the database the framework keeps its drafts in, and the UI5 frontend runs in an iframe whose window.fetch is redirected into the parent page for the one request it makes. Two checkers read what you type: abaplint for whether the ABAP compiles, the abap2UI5 linter for whether the view the builder chain produces works on UI5 1.71. Both rule sets are editable in a tab. What it holds is a few classes rather than a package: no tables of your own, no RFC, no files, and only the ten UI5 libraries that were built in. Share puts every open file into the URL fragment, and Download for abapGit writes a zip laid out as a repository, to import with abapGit.

Facts

Last pushLicenceMIT

Where it sits

Lives in
Provides
Local developmentABAPLocal developmentcapabilityRunning the whole stack on a laptop against real bindings — the service, the UI and the routing in front of it — without deploying to see a change.Editor supportABAPEditor supportcapabilityWorking in source code with the editor helping rather than treating it as text — completion, go-to-definition, inline errors, refactoring and preview.Static analysisABAPStatic analysiscapabilityCatching problems in code before it runs: naming, obsolete statements, security findings, and compatibility with a target environment. Style linting, security scanning and cloud-readiness checks are often treated as one concern.Code formattingABAPCode formattingcapabilityMaking source match one layout — indentation, keyword case, the shape of a statement block — by rewriting it rather than by reporting on it. Distinct from [static analysis](capability:abap-static-analysis), which says what is wrong and leaves the source where it is.DocumentationABAPDocumentationcapabilityFinding the answer in what has already been written, and writing it where it has not — first-party documentation made searchable by something other than a person scrolling it, including by an agent, and a document of custom code produced from the code itself.
Add-on to
abap2UI5abap2UI5artifactOne ABAP class implementing z2ui5_if_app is the whole app: the browser loads a generic UI5 shell once, and every interaction after that is an HTTP roundtrip back into ABAP.
Requires
abap2UI5abap2UI5artifactthe framework that answers in the page: its sources are transpiled to JavaScript at build time, at a pinned commit, and the roundtrip the app makes is served by them rather than by a system@abaplint/transpiler@abaplint/transpilerartifactturning ABAP into JavaScript: the framework at build time, and the classes in the editor on every Runabaplintabaplintartifactthe checker behind the editor: it parses the real framework sources in the page so the classes are checked against them, and its error stops Runopen-abap-coreopen-abap-coreartifactthe ABAP standard library the transpiled code runs against, bundled into the page with the framework and pinned by commit; its runner is also what Run uses for the test classes beside a classabap2UI5 frontendabap2UI5 frontendartifactthe UI5 half of the app: the frontend is pinned by commit, built against OpenUI5 into the site's own dist/app/, and runs in the iframe beside the editorSQLiteSQLiteoutside the atlasthe database the ABAP runtime in the page selects from: sql.js compiled to WebAssembly, in memory, holding the framework's own tables and starting empty again on every Run

Who is behind it

abap2UI5abap2UI5OrganisationMaintains this
In the atlas: maintains 18
@abap2UI5
maintaineroblomov-devPersonContributes to this
In the atlas: maintains 4, contributes to 44
@oblomov-dev
1 contributor

Before choosing this

Conditions

PracticalFunctional boundary

A SELECT from a business table has nothing to select from: the database in the page holds the framework's own tables, and nothing can reach outside the browser, so an app that reads a system's data cannot be tried here. Only the UI5 libraries built in are available and a control from anywhere else will not load; what the transpiler cannot compile is reported in the output panel rather than run. State lives in the tab — a reload, and a press of Run, starts over on a fresh database.

What it declares

Every artifact

Type
Web tool
Origin
By a community org

As a web tool

Access
does not say
What it sends to its vendor
does not say

Connections12

abap2UI5 Playground connectionsabap2UI5 PlaygroundPROVIDES→ provides5provides stated Format — the braces in the bar, or Shift+Alt+F — is abaplint's pretty printer with layout fixes in front of it: indentation and keyword case, and the tab, the trailing space, the double space, the space before the full stop and two statements sharing a line, over every open file as one edit that Ctrl+Z takes back. It leaves a builder chain unreflowed and the behaviour of the code unchanged. abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playgroundCode formattingprovides stated The sample catalogue is one searchable page over every sample of the three abap2UI5 sample repositories, narrowed by the control a view actually builds and by the UI5 release a system runs, with the filters in the URL so a search is a link that can be sent. Every sample also has a static page of its own carrying its description, the class with an address per line, every control it builds, the release it needs and what it needs when it cannot run in the browser. abap2UI5 — Tooling, Playground: ABAP in the browser: https://abap2ui5.github.io/docs/advanced/tooling.html abap2UI5/playground — README, The sample catalogue: https://github.com/abap2ui5/playground abap2UI5/playground — README, The sample catalogue: https://github.com/abap2ui5/playgroundDocumentationprovides stated Monaco with abaplint behind it: diagnostics against the real framework sources, hover, go to definition, rename, references and quick fixes, over a panel holding the reconstructed view, the problems, the class outline, the conversation between the app and the ABAP, and the log. The View tab also turns around — change the XML, press Save, and the builder chain is written again to build it, in the layout the abap2UI5 repositories hold their chains in, with the ABAP behind an attribute you left alone kept as it was. abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playground abap2UI5/playground — README, Editing the view instead of the chain: https://github.com/abap2ui5/playgroundEditor supportprovides stated Runs an abap2UI5 app with nothing installed and no system behind it: the transpiled framework boots in the page, the classes in the editor are compiled on Run and registered with the running runtime, and Auto presses Run shortly after you stop typing. The database is an in-memory SQLite holding the framework's own tables, and the UI5 frontend in the iframe reaches the framework because `window.fetch` is replaced for that one request with a call into the parent page. abap2UI5 — Tooling, Playground: ABAP in the browser: https://abap2ui5.github.io/docs/advanced/tooling.html abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playground abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playgroundLocal developmentprovides stated Two checkers over the class in the editor, kept apart in what they block: abaplint with a small rule set against release v750, whose error stops Run because the ABAP does not compile, and the abap2UI5 linter, which reconstructs the view the builder chain produces and checks it against UI5 1.71 while the app still runs. Both configurations are live in a tab — any of abaplint's 188 rules, the ABAP release the syntax check holds you to, the UI5 floor the view is checked against — and Fix them applies abaplint's own fixes and the linter's together, as one edit per file. abap2UI5 — Tooling, Playground: ABAP in the browser: https://abap2ui5.github.io/docs/advanced/tooling.html abap2UI5/playground — README, Which problems it reports: https://github.com/abap2ui5/playground abap2UI5/playground — README, Which problems it reports: https://github.com/abap2ui5/playground abap2UI5/playground — README, Which problems it reports: https://github.com/abap2ui5/playgroundStatic analysisNEEDS→ connects to1connects to stated fetching ABAP that lives somewhere else: a `?src=` link, a shared link or a catalogue row is opened by the raw URL of its class, and the hosts it will read from are this site and GitHub's raw hosts abap2UI5/playground — README, Linking a playground: https://github.com/abap2ui5/playground abap2UI5/playground — README, The examples browser: https://github.com/abap2ui5/playgroundGitHub→ needs6needs stated turning ABAP into JavaScript: the framework at build time, and the classes in the editor on every Run abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playground abap2UI5/playground — README, What it can and cannot do: https://github.com/abap2ui5/playground@abaplint/transpilerneeds stated the framework that answers in the page: its sources are transpiled to JavaScript at build time, at a pinned commit, and the roundtrip the app makes is served by them rather than by a system abap2UI5/playground — README, What it can and cannot do: https://github.com/abap2ui5/playgroundabap2UI5needs stated the UI5 half of the app: the frontend is pinned by commit, built against OpenUI5 into the site's own `dist/app/`, and runs in the iframe beside the editor abap2UI5/playground — README, Development: https://github.com/abap2ui5/playground abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playgroundabap2UI5 frontendneeds stated the checker behind the editor: it parses the real framework sources in the page so the classes are checked against them, and its error stops Run abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playground abap2UI5/playground — README, Which problems it reports: https://github.com/abap2ui5/playgroundabaplintneeds stated the ABAP standard library the transpiled code runs against, bundled into the page with the framework and pinned by commit; its runner is also what Run uses for the test classes beside a class abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playground abap2UI5/playground — README, Development: https://github.com/abap2ui5/playground abap2UI5/playground — README, Linking a playground: https://github.com/abap2ui5/playgroundopen-abap-coreneeds stated the database the ABAP runtime in the page selects from: sql.js compiled to WebAssembly, in memory, holding the framework's own tables and starting empty again on every Run abap2UI5/playground — README, How it works: https://github.com/abap2ui5/playgroundSQLite

README

quoted from abap2UI5/playground under MIT, read
abap2UI5/playground/README.mdOn GitHub

abap2UI5 Playground

Write abap2UI5 apps in the browser. ABAP on the left, the running app on the right, and nothing in between but the browser — no server, no SAP system, no backend of any kind.

The playground: an ABAP class on the left, the app it produces on the right

First time here? The playground opens on a first lesson, with a strip of four first steps over the editor's last lines: change the code and press Run, turn on Auto, edit the view in the View tab, browse the samples. ✕ or Escape closes it for good in this browser. While the app in the editor is one of the learning path's "Start here" lessons (Basics I–VII), Lesson n of m over the file strip steps to the lesson before or after. Neither appears on a link somebody sent you, an embed or the AI pages.

How it works

The abaplint transpiler translates ABAP to JavaScript. abap2UI5 already relies on it — its CI transpiles the whole framework and runs the ABAP unit tests under Node. The playground takes that pipeline and moves the last step into the browser.

                     ┌──────────────────────── the page ────────────────────────┐
                     │                                                          │
  build time         │   Monaco + abaplint            the ABAP runtime          │
  ──────────         │   ┌─────────────────┐          ┌──────────────────┐      │
  abap2UI5 sources ──┼──▶│ registry:       │          │ abap2UI5,        │      │
  (910 files)        │   │ the real        │  Run     │ transpiled at    │      │
                     │   │ framework       │──ABAP───▶│ build time       │      │
  abap2UI5 src ──────┼──▶│ + your classes  │  → JS    │ + your classes   │      │
  downported,        │   └─────────────────┘          └────────┬─────────┘      │
  transpiled,        │                                         │ roundtrip      │
  bundled            │   ┌─────────────────────────────────────▼─────────┐      │
                     │   │ iframe: the abap2UI5 UI5 frontend             │      │
  OpenUI5 ───────────┼──▶│ window.fetch redirected to the runtime above  │      │
  built from npm     │   └───────────────────────────────────────────────┘      │
                     └──────────────────────────────────────────────────────────┘
  • Build time. The abap2UI5 sources are downported to 702-compatible syntax (abaplint --fix), transpiled, and bundled into one static module along with the open-abap standard library. The UI5 frontend is built against a pinned OpenUI5, so the site carries its own UI5 rather than linking a CDN.
  • Page load. That bundle boots the ABAP runtime, and an in-memory SQLite (sql.js, compiled to WebAssembly) takes the place of the database abap2UI5 keeps its drafts in. In parallel, abaplint parses the real framework sources so the editor can check your classes against them.
  • Editing. Monaco — the editor from VS Code — with abaplint behind it: diagnostics against the actual framework, hover, go to definition, rename, references and quick fixes. Format ({ } in the bar, and Shift+Alt+F, which does the same) is abaplint's pretty printer with its layout fixes in front of it — indentation and keyword case, and also the tab, the trailing space, the double space after a keyword, an = or a bracket (padding in front of a token is kept, as alignment), the space before the full stop and the two statements sharing a line — over every file that is open, as one edit that Ctrl+Z takes back. It never reflows a builder chain and never changes what the code does. Under the editor, a resizable panel with the view your chain builds, every problem, an outline of the class, the unit tests, the conversation between the app and the ABAP, the app's State after each roundtrip (its attributes, with what changed marked — the debugger's variables view for a program that runs a roundtrip at a time), the Console (what the app WRITEs, per roundtrip), the log, and the configuration of each checker — editable, so "why is it not warning here?" has an answer you can try rather than only read.
  • A second opinion. The abap2UI5 linter runs beside abaplint and answers a different question: abaplint says whether the ABAP compiles, the linter reconstructs the view your builder chain produces and says whether that works on UI5 1.71 — a control or property that release does not have, an icon that is in no icon font. Those compile, and at run time they render nothing and log nothing.
  • Editing the view instead of the chain. The View tab shows the XML that reconstruction produces, coloured; Edit turns it around. Change the XML — move a control, add a property, insert a Label — press Save, and the builder chain is written again to build it, in the layout the abap2UI5 repositories hold their chains in. An attribute you leave alone keeps the ABAP that produced it, so a client->_bind( … ) stays a bind rather than freezing into the string it happened to render as — and so does the code around it: change one word and one word changes, in the shape the method was written in, rather than the whole chain coming back reformatted. It is the shortest way there is to learn the builder: change the view, read the ABAP that changed with it. What it cannot rewrite — a view filled from a LOOP, a control name held in a variable — it says instead of guessing, and the ABAP editor greys out and stops taking typing for as long as the view is the one being typed into.
  • Run. Only the classes in the editor are compiled, in about 20 ms, and registered with the running runtime. Auto beside it presses Run for you, shortly after you stop typing: while it is on, Run itself is inactive and every edit reaches the app on its own. It is off to begin with, because a run is a fresh database and a reloaded app frame — which is exactly what you do not want halfway through filling in a form, and exactly what you do want while a view is taking shape.
  • Rendering. The abap2UI5 frontend runs in an iframe and talks to its backend over a plain fetch POST, so the playground replaces window.fetch for that one request with a message to the parent page, which hands it to the framework and posts the answer back. The frame and the page exchange messages and nothing else. From the framework's point of view nothing changed.

Roughly 3 MB travels to a visitor, compressed: the page bundle, the transpiled framework, the ABAP corpus and SQLite. UI5 loads its libraries on demand on top of that.

What it can and cannot do

It runs real abap2UI5. Not a subset and not a simulation: the framework in the page is the framework from the repository, at a pinned commit, and the roundtrip it answers is the one a real system answers. Modern ABAP works as written — inline declarations, VALUE #( FOR … ), COND #, string templates, table expressions.

Where it stops:

  • A few classes, not a package. The playground holds several ABAP files, named as abapGit names them, and the first one is the app - the playground starts the class it declares. What it does not have is most of what else a package brings: no message classes, no CDS.
  • Tables of your own, but nobody else's. A table is two files beside the classes: <name>.tabl.xml, the abapGit TABL definition, and optionally <name>.tabu.json, the rows it starts with — a JSON array of objects keyed by field name (either case), at most 1000. SELECT, INSERT, UPDATE and DELETE work against it. + table in the file strip adds a starter pair, zproducts with five rows. The table is created afresh with its rows at every Run, and nothing an app writes outlives the Run. A field typed by a data element needs that data element to exist in the framework corpus; a MANDT the rows leave out is the current client; a table may not reuse a name the framework or open-abap already has. ?src= still opens ABAP only; a gist carries both files, and Download for abapGit puts the table in src/ and its rows in data/, abapGit's own data layout.
  • No business tables, no RFC, no files. The database holds the framework's own tables and yours. SELECT from a business table has nothing to select from, and nothing can reach outside the browser.
  • Only what the transpiler implements. It covers a lot, and abap2UI5's whole CI depends on it, but it is not an ABAP kernel. Anything it cannot compile is reported in the output panel rather than failing silently.
  • Only the UI5 libraries that were built in. sap.m, sap.f, sap.ui.core, sap.ui.layout, sap.ui.table, sap.ui.unified, sap.tnt, sap.uxap, sap.ui.integration, sap.ui.codeeditor. A control from anywhere else will not load — see UI5_LIBRARIES in src/shell/ui5-libraries.mjs, the one list the UI5 build, the examples browser and the sample catalogue all read.
  • State lives in the tab. Reloading the page starts over, and so does pressing Run — your tables included. Your code is kept in local storage; the app's data is not.

Both halves follow your system's light or dark setting — the editor through Monaco, the app through UI5's Horizon themes. Changing it while an app is running recolours it in place rather than restarting it.

Which problems it reports

abaplint runs with a deliberately small rule set: the ones that answer would this work, not the ones that answer is this the house style. A playground that underlines a missing pragma teaches nothing.

check_syntax, parser_error, implement_methods, method_implemented_twice, global_class, begin_end_names, superclass_final, unknown_types — checked against release v750, the one abap2UI5 lints itself against. The list lives in src/editor/registry.mjs.

definitions_top is the rule that had to come off that list, and it is worth naming: abap2UI5 enables it because the framework is downported to 702 before it is transpiled, and nothing here downports what is in the editor. It was rejecting FIELD-SYMBOLS after a CREATE DATA — ABAP that compiles on every system this playground is about — and an abaplint error stops Run, so the reader was told to fix code that had nothing wrong with it.

The abap2UI5 linter runs its own rules on top, against UI5 1.71 — the floor abap2UI5 holds its own shipped apps to, and therefore the floor an example copied out of the playground has to clear. UI5 in the bar, after Auto ("Check against UI5" in the ⋯ menu on a phone), moves that floor: 1.71, 1.84, 1.96, 1.108, 1.120 or the latest this site carries — "my system runs 1.84, what will not render there?". It is the same setting as the abap2UI5 lint tab's ui5, kept between visits the same way.

The two are kept apart on purpose, in the list and in what they block: an abaplint error means the ABAP does not compile, so Run stops and says so. An abap2UI5 finding means the app runs and is wrong somewhere — and the fastest way to understand one is to look at the app it produced, so Run goes ahead.

A missing full stop is said as one. abaplint reports a statement it cannot parse as "Statement does not exist in the configured ABAP version (or a parser error)", and the commonest reason is a full stop that is not there — two lines read as one statement. Where the shape says so, the Problems row asks whether a full stop is missing and sits on the line that wants it.

Fix them appears over the list when something is repairable and says what — how many errors, warnings and hints it can repair, and which errors it leaves — abaplint's own fixes and the linter's, applied together. It goes in as one edit per file, so Ctrl+Z takes the whole rewrite back rather than unpicking it fix by fix. Nothing that has no correct answer is guessed at: an icon that does not exist stays reported rather than invented.

Both lists are only a default. The abaplint and abap2UI5 lint tabs hold the live configuration: add any of abaplint's 188 rules, change the ABAP release the syntax check holds you to, or lower the UI5 floor the view is checked against to find a control an older system would not render. Apply reports how many problems there are now, so a rule can be tried rather than argued about, and what you change is still there the next time you open the page — Reset puts it back to the curated list of the day.

Build an app by describing it

The AI Studio has a page of its own, /playground/ai/

  • the AI Studio button beside Samples, and the menu's Tools section on every page of this site. It starts on a minimal class: z2ui5_if_app implemented, main still empty. The chat runs down the left, and the stage beside it shows the running app in a window of its own, the code, or both side by side (Preview, Code, Split in the studio's bar; a phone takes them in turns, the chat first). Every run that starts the app is a card in the conversation that brings the app forward; ⛶ makes it the browser's full screen. Describe the app you want — "a table of flights with a search field" — and Claude writes it as an abap2UI5 class into the editor, presses Run, reads what the two checkers and the app said, fixes it, and runs it again until it is clean. You watch the code arrive in the editor and the app appear on the right while you talk; ask for changes until it fits, then Download for abapGit takes the class home as a repository you import with abapGit.

  • Your own key, and no server. The first message asks for an Anthropic API key. It is held in the page's memory for the visit, never stored — the playground runs ABAP from any link, and stored it would be readable by that code — and sent to api.anthropic.com and nowhere else — or, with an OpenAI-compatible server picked in the key form (OpenAI, Ollama, LM Studio), to that server, which the form names; there is still nothing behind this page. Usage is billed to that key; the chat's header counts the tokens. A key that is not tied to a workspace (the API answers "This API key is not scoped to a workspace") also needs the workspace ID (wrkspc_…, in the Console under Settings → Workspaces), which the key form takes as an optional second field.

  • The app cannot reach your key. On this page the app runs in a frame on an origin of its own (a sandbox), and talks to the page by message only: a script in an app's view — whoever wrote it, Claude included — cannot read the key form, the page or its storage. The ABAP runs in a worker that has no page and no storage to read either. The cost is that the app frame here loads UI5 from the network every time and does not work offline.

  • The model uses the playground the way you do. It has no compiler of its own: it writes files into the editor (Ctrl+Z takes them back), presses the same Run, and is told what you would see — the abaplint errors, the abap2UI5 linter's findings against UI5 1.71, the unit tests, the view the app rendered and the line a dump was raised at. Switch the chat off and the code it wrote is in the editor, ready to edit by hand; switch it on again and the model is told what changed.

  • It knows abap2UI5 from the source. Its instructions are abap2UI5's own guide to building apps, at the same commit as the framework this page runs, and it can search the sample catalogue and read a sample's code before it writes its own.

  • Files in the chat. 📎, a drop anywhere on the page or a paste adds a specification (PDF, Word), a screenshot or mockup of the screen you want, an Excel sheet whose rows become the app's data, or a text file — the same formats and limits as in the AI Pilot below, read in your browser.

  • It tries what it built. Once a run is clean, the model can type into the app's fields and press its buttons - the Pilot's eyes and hands, on the same frame - and read the toast or the message box the app answered with, so what it hands you is an app that worked once, not code that compiled.

  • Every step can be taken back, and the last message changed. A step that changed the files offers them back under its answer; ✎ on your latest message takes the exchange out and puts the text back to send again. Export writes the conversation as a markdown file, and the files stay in this browser - the welcome offers the last build back.

  • The limits are the playground's. No tables of your own, no RFC, only the UI5 libraries built in (see What it can and cannot do) — the model is told so, and fills internal tables where a real app would SELECT.

The select in the chat's header picks the model and how long it thinks: Balanced (Opus 5.5, the default), Thorough (Opus 5.5, thinking longer) or Fast (Sonnet 5.5, which answers soonest) — it applies from the next message. After every change the page runs the app by itself and hands the model the report, so no turn is spent asking for a run, and while a turn is under way the chat shows the model's short notes and counts the lines of the class it is writing. A request a safety classifier declines is answered by the fallback model the API picks rather than dropped. The SDK and the guide are a chunk of their own (~70 KB compressed), downloaded only by somebody who sends a message.

Let Claude operate an app

Still being built, and not linked from the playground either: the AI Pilot has a page of its own, /playground/pilot/. Where the AI Studio builds an app, the Pilot uses one: the app runs on the stage, the chat stands beside it, and you say what you want done — "greet Carol", "open the value help sample and pick the third colour". Claude reads the screen, types into the fields and presses the buttons, in the app on your screen: you watch the values arrive, the popup open, the message box come up. Take the controls yourself whenever you like — Claude is told what you did and carries on from there.

  • What Claude sees (the button in the bar) shows the screen the way the model reads it: the agent snapshot — fields with their values, the actions it can fire, the tables, what the app said. Nothing else: no screenshot, no CSS selector.
  • The same protocol as everywhere else. The client that turns "fill these fields, fire that event" into the request the browser would send is abap2UI5/mcp-server's own, vendored unchanged — the one the VS Code extension runs against an SAP system and cap2UI5 runs inside CAP. Its requests are sent by the app frame, so the frontend renders every answer with its own code.
  • Strict. An event that is not on the screen, a field that is not editable, a value outside a dropdown's choices are refused with what is possible, and nothing is sent.
  • Any sample. It opens on Basics II; Change app opens the samples browser, and Claude can look an app up in the catalogue and open it itself. A shared link or ?src= opens your own class: /playground/pilot/?src=<raw url> - after you said so: the app's code cannot reach your key, but the app is what Claude reads and acts on, and an app written to mislead can steer what Claude does in this chat.
  • Several apps at once. Up to four, one tab each over the stage — + App opens one beside the others, and so does Claude when a task spans two apps ("look the colour up in the value help app and greet it in the first"). They run in one runtime on one database, so opening an app keeps the others as they are; Restart starts all of them again on a fresh database.
  • Files in the chat. 📎, a drop on the chat or a paste adds files to the next message — up to five, 10 MB each: a PDF and images go to the model as they are, an Excel sheet (.xlsx) as CSV with its dates as dates, a Word document (.docx) as its text with its tables as rows, a PowerPoint deck (.pptx) as its slides' text, and text files (CSV, JSON, XML, …) as text — "enter every order in this sheet". The Office files are read in your browser; the old binary formats (.xls, .doc) are refused with what to save them as.
  • Your own key, and no server — exactly as in the AI Studio: held in memory for the visit, sent to api.anthropic.com and nowhere else, and out of reach of the apps' code — every app frame on this page, each tab's included, is on an origin of its own and talks to the page by message only.

The sample catalogue

https://abap2ui5.github.io/playground/samples/ — every abap2UI5 sample in one searchable page: the learning path of abap2UI5/samples, the UI5 demo kit ports of abap2UI5/samples-controls, and the OData/RAP/launchpad samples of abap2UI5/samples-stack.

It answers two questions the repositories' own catalogues cannot:

"which samples use sap.m.Table at all?" — not the one filed under it, but every view that actually builds one "my system runs UI5 1.84 — which of these will render on it?"

Both come out of the abap2UI5 linter, which each repository runs over its own classes and commits the answer to as catalogue-derived.json; this site joins those onto the catalogue.json beside them and builds one index at deploy time. The filters live in the URL, so a search is a link you can send: ?q=table&lib=sap.ui.table&rel=1.84.

A row is a link to that sample's page, and that is all it is: what a sample builds, what it needs, the ABAP itself, and a box that runs the sample in that page are all on the page it opens — ▶ Run it here under its title starts it. A title's (A) and (C) markers are shown as frontend action and custom control badges, which a search finds. Most samples run in your browser with nothing installed. What cannot — a stack sample, which needs a real system; a port whose library only SAPUI5 has — is listed all the same, says what it needs, and opens for reading instead: a sample you cannot find is worse than one you cannot run. Run it from its page and the playground's bar offers Back to the catalogue, in the same tab.

Every sample has a page of its own — samples/<class>/, a static document with the sample's description, the class, every control it builds, the release it needs, what it needs when it cannot run here, the sample running — press the demo box and the app mounts in the page, on its own, without the editor over it —, the whole class printed and syntax-coloured, every line of it with an address — #L42 highlights a line, #L42-L58 a passage, and Copy link hands the result over —, and the links out: the class on GitHub, SAP's own sample running in the demo kit for a port of one, the whole playground, back to the search. The catalogue itself is one URL that JavaScript fills in, which is right for searching and useless for being found: there was no address for "the abap2UI5 port of sap.m.Wizard" and so nothing a search engine could return. Now there is one for each of them, listed in sitemap.xml and reachable from the full list.

This replaced three separate GitHub Pages sites, one per sample repository.

The examples browser

Samples in the bar is the same list without leaving the editor, and it takes the screen while it is open: a full-size window over the playground, the filters down its side, the rows in as many columns as fit. Your drafts is one folded line at the top, with how many there are (it stays open or closed as you left it, and a search that matches a draft opens it); under it everything the catalogue holds — "N of M samples", the same count as the catalogue page — searched by several words in any order, over titles, summaries, class names, badges and the controls a sample builds, and narrowed by the same facets the catalogue page has: the control it uses, the library, the release your system runs, plus the repositories, "Only samples that run in this browser", "Leave out samples that need SAPUI5" and "Include samples that need a UI5 newer than 1.71". Every row says what it is, what group it belongs to, what release it needs and — where it cannot run here — what it needs instead, and links to its ABAP on GitHub and to its documentation page. A sample the page carries is listed once, as its row of abap2UI5/samples, and opens the copy the page carries; "In the page" lists only a carried sample the index does not have. A chosen entry opens through the same path a ?src= link takes — the raw URL of its class, fetched, checked and run — so it arrives with the Source link back to where it lives.

It reads the same index the catalogue page does, from this site rather than from GitHub, and nothing is fetched until the button is clicked. Where the index cannot be had, the browser quietly lists the samples in the page and your drafts alone. Everything offered is judged the way typed code is judged — a catalogued sample the transpiler cannot compile says so in the Problems list, which is the designed behaviour.

Linking a playground

Unit tests. A file named <class>.clas.testclasses.abap beside a class — the + in the file strip offers one, with a skeleton that passes — holds its local test classes, exactly as abapGit keeps them. Run runs them first, through the runner open-abap ships, and starts the app after: a failing test is listed in the Tests tab with what was expected and what was there, its row goes to the assertion, and the status line says how many failed.

Drafts. The playground keeps whatever was last in the editor on its own. Opening a sample over it never loses it: the status line says which way back there is — one Undo away when the sample went in under the same file name, and otherwise kept in Samples, under Your drafts, under the name it was saved as or as "Before the last pick" (only where the browser refuses to store it does the line fall back to comes back if you reload). For more than one piece of work, the samples browser has Your drafts at the top: name what is open, save it, and it is listed there — in this browser — to open or delete another day.

Compare and Reset to original. Code that was opened from something — a sample, a share link, ?src=, a gist, a saved draft — has an original, and ± beside Source shows your changes against it, file by file, in a diff; ⟲ puts every file back as it was opened, as one edit per file that Ctrl+Z takes back (a file you added goes to Your drafts). Where there is nothing to compare with — the last session restored, or what an AI wrote — they say so instead.

Share puts every open file in the URL fragment, deflated: a 2500-character class becomes a link of about 700 characters. Being a fragment, it never leaves the browser — it is not sent to the server and does not appear in any log. The link is copied first; the dialog that opens then has the other ways out: the block that embeds this demo in a documentation page (the loader with the class inline, or the playground framed when there are several files), the markdown fence a docs page prints an example in, and Download for abapGit — a zip laid out as a repository rather than as a bag of files: the sources and their metadata under src/, the .abapgit.xml that says so (the shape app-template carries), and a README naming the app, how to start it and the link this code came from. Import it offline with abapGit, or push it as it stands. Gist writes the open files to a secret GitHub gist with your token (held for the visit, never stored) and hands back a ?gist=<id> link; once code from a link has run in the page, it asks you to tick that you know before it takes a token. Open in Layout Editor hands the app class to the abap2UI5 layout editor, to design its view by drag and drop and export the class back: a class still exactly as it came from GitHub opens there by its address; anything else is copied to your clipboard to paste into Open ABAP class there, and rides in the link as well, for a layout editor that reads it.

Light or dark. The page follows the system until the switch in the menu behind the bar's last button says otherwise — the same menu the sample catalogue and the documentation carry, after LinkedIn and GitHub, with the project's tools and repositories under the switch. A choice is kept between visits; a choice that agrees with the system is forgotten rather than stored, so a page switched back follows the system again from then on. The button reaches the editor and the running app as well, without restarting it.

Installable. The page carries a web app manifest, so a browser that supports it offers to install the playground; opened from a home screen it runs with no network at all, on the build the last online visit left in the service worker's cache — the two documents included, and whatever UI5 modules the apps run so far have loaded. The ABAP runs in the tab either way, so there is no server to be away from.

Full screen opens the app on its own in a new tab — the whole window for the app, nothing around it: no editor, and no bar over it either. It is the same URL Share writes plus ?view=full, so the new tab is a second playground rather than a window onto this one: it compiles the code it was handed and runs it against a runtime of its own. What happens back in the first tab — another Run, an edit, closing it — leaves it alone.

?src= opens ABAP that lives somewhere else, which is what a documentation page links when it wants to show its example running rather than only printed:

?src=https://raw.githubusercontent.com/abap2UI5/samples/main/src/z2ui5_cl_smp_app_493.clas.abap

A github.com/…/blob/… page URL works as well — it is read as the raw file behind it. Several src parameters open several files; the first is the app — and the classes that app needs are looked for beside it and opened too, so a link to an app that calls another app opens both. Only siblings in the same directory, only from the hosts above, at most six files two levels deep; a name that is not there is skipped in silence, because most of them are in the framework corpus rather than in the repository. Code opened this way carries a Source link in the bar (its GitHub page — the bar's GitHub mark, at the far end, is the framework's repository), following whichever file is open — the raw URL the playground was given translated back into the page a human would want, with the repository and the history around it. Sources are limited to this site and GitHub's raw hosts — the playground fetches on behalf of whoever opened the link, and should not be a general-purpose reader for arbitrary URLs.

?embed=1 drops the brand, the examples browser, the share button and the right-hand end of the bar, leaving the editor, Run and the app — for embedding in a documentation page. An embedded playground never touches the stored draft, so it cannot overwrite what a reader has open in a normal one, and follows its reader's system theme rather than a choice made in some other tab. ?view=app drops the editor too, for a paragraph about what an app does rather than how it is written; the ABAP still compiles and runs, it is simply not on screen. ?view=full is the same view under the name Full screen opens it by. Neither shows the bar — the app and nothing else — because Run, the source and undo are all one click away in "Open in the playground" beside the frame, and a bar over a demo is this site's furniture in somebody else's page. It comes back if something goes wrong, because the status line it carries is the only channel either view has left.

Two more parameters work only in an embedded playground: ?readonly=1 takes the typing away — and Format, Undo, Redo, Fix them and the View tab's Edit with it — while Run still runs, and ?lines=12-18,25 marks those lines of the app's file and scrolls to the first (L42-L58 reads the same, the shape a sample page's line links have).

Live demos in a documentation page

embed/abap2ui5-embed.js turns an empty element into a running example:

<div class="abap2ui5-demo"
     data-src="https://raw.githubusercontent.com/.../z2ui5_cl_demo.clas.abap"></div>
<script src="https://abap2ui5.github.io/playground/embed/abap2ui5-embed.js"></script>

data-src takes one URL or several (the first is the app), data-code carries ABAP that lives only in that page, data-view="app" hides the editor, data-height sets the starting height and data-label the button text. data-readonly shows an example to read and run but not to change, data-lines="12-18,25" marks and scrolls to those lines, and data-reset shows a Reset example button under the demo once the reader has edited it, which puts the page's code back (as an edit Ctrl+Z takes back) and runs it. For a documentation framework that swaps pages without reloading, call window.abap2ui5Embed.setUp() after each navigation.

Inline code keeps the name the page gave it: the file it is put into is named after the class in it, the way abapGit names one, so data-code carries the example a manual prints under the name its reader is meant to create.

A page that draws its own button — because it wants one under a code block it already styles — asks the loader for the URL instead of writing the fragment itself:

const href = await window.abap2ui5Embed.url({ code, view: "app" });

url() takes readonly and lines as well.

That matters more than it looks: a fragment the playground cannot read is replaced by the sample the page opens on, with the status line and the Log saying so - so an encoder written by hand fails by showing the wrong code with a warning under it rather than by failing outright.

Nothing loads until the reader clicks. Each demo is a whole ABAP runtime plus an abaplint parse of nine hundred sources — a second or two of processor and a few hundred megabytes, per frame. Demos on one page share the browser cache, and after the first visit they share the playground's service worker cache as well, so the bytes are paid once and then not again; the parsing is not shared either way, and a page with ten autoloading examples would be the slowest thing in the manual. data-auto="1" overrides it where the page is about its one demo.

The app frame is served with UI5's frameOptions set to allow rather than the trusted abap2UI5 ships. trusted means "only in a frame whose top window is the same origin", and an embedded demo's top window is somebody else's manual: UI5 asks it for permission over postMessage, waits ten seconds for an answer no documentation site knows to give, and then hides everything it rendered — an app that is in the DOM, correct and invisible, under a status bar saying "running". What is unprotected is a demo compiled from code the embedding page supplied, with no session and nobody's credentials.

An embedded playground posts four kinds of message to the page that framed it — ready once it has something to show, status for each line its status bar shows, height for what an app-only demo wants to be, and edited ({ edited: true|false }, only when it changes) — and the loader turns the last into a bubbling abap2ui5-edited event on the demo's element (event.detail.edited), so a page can tell whether its example was changed. One message goes the other way: { source: "abap2ui5-embed", type: "reset" }, accepted only from the window that framed the playground, which is what data-reset's button sends. embed/ on the published site is a worked example of all of it, and is what the tests drive.

Development

npm ci
npm run build     # pins deps, builds the framework, builds UI5, assembles dist/
npm run serve     # serves dist/ on http://localhost:8080
npm test          # Playwright, against a freshly built dist/
npm run check     # build -> size budget -> tests, in the order that cannot go wrong
npm run lint      # ESLint; with typecheck and test:unit: no build, no browser
npm run typecheck # tsc over the modules that start with // @ts-check
npm run test:unit # node:test over the pure modules in tests/node/

PORT=8091 npm test moves the test server and the tests together, so two checkouts can test at once.

The first build takes a few minutes: the downport is three of them and the UI5 build one, and the two run at the same time because neither reads what the other writes. Both are cached by a hash of their inputs, so the second build is seconds.

The five steps — fetch the pins, build the framework, build UI5, build the sample catalogue, assemble the site — and what each one caches are described in docs/design/build-pipeline.md; tools/check-size.mjs is the budget for what a visitor downloads.

PG_DEBUG=1 builds the page and framework bundles unminified and with source maps; without it neither ships one.

src/runtime is the ABAP side of the page (run in a worker), src/editor is Monaco and abaplint (the registry in a worker of its own), src/shell is the page around them, src/catalogue is the sample catalogue at /samples/ (a second document with a bundle of its own), src/abap is the one class of ABAP the playground adds to the framework - the bridge into the request handler - and src/examples is ABAP served as static files so ?src= has something to point at; AGENTS.md lists every module. There are no samples here: the ones the page carries are named by class in src/editor/sample-list.mjs and come out of the pinned abap2UI5/samples at build time, so the playground holds no copy of a sample that can drift from the one upstream maintains.

Bumping abap2UI5 or OpenUI5
node tools/fetch-deps.mjs --print-latest   # what upstream has today
# edit the sha in tools/fetch-deps.mjs (or UI5_VERSION in src/shell/ui5-libraries.mjs)
npm run build && npm test

A weekly workflow (.github/workflows/upstream.yml) builds and tests against upstream HEAD without changing the pins, and opens an issue when that stops working — so a bump is a two-line commit rather than an investigation.

Deployment

.github/workflows/pages.yml builds and publishes dist/ to GitHub Pages on every push to main, after the tests pass — and nightly, which a static site would not otherwise need: the sample catalogue is built from files the three sample repositories commit, and those change when a sample is merged there, which is no reason for anything to be pushed here. .github/workflows/check.yml runs the same build and tests on every other branch and pull request.

Setup required once, by a repository admin: Settings → Pages → Source → "GitHub Actions". Until that is switched on the deploy job fails and the published page does not exist.

Where the work is written down

AGENTS.md is the short version for anyone changing the code: the layout, the commands, the CI gates, the rules and the deliberate limits. Each area's reasoning — with its measurements and what was tried and refused — is in docs/design/, and docs/design/build-traps.md holds the traps found while building it — the transpiler flag without which nothing links, the bundler option without which ABAP's own type system stops working, the caches that have to be dropped when a class is redefined. Read it before changing the build. The plan the playground was built from, phase by phase, is kept in docs/history/PLAYGROUND_PLAN.md.

License

MIT. abap2UI5, abaplint and OpenUI5 are the work of their respective authors and carry their own licenses.

MIT, read

Others providing70

Local development
  1. web-abap2UI5abap2UI5 transpiled to JavaScript and run in a browser tabfrom ABAP
  2. vite-plugin-cdsServes a Vite app through cds watch and imports .cds filesfrom CAP
  3. com.sap.cds:cds-feature-dev-dashboardBrowser dashboard for a running CAP Java service during developmentfrom CAP
  4. com.sap.cds:cds-maven-pluginMaven plugin running CDS build steps in a CAP Java projectfrom CAP
  5. @cap-js-community/commonSix CAP features in one package, from replication cache to rate limitsfrom CAP
  6. abap_trial_dockerScripts running the ABAP Developer Edition in Dockerfrom ABAP
  7. @neoimpulse/cap-js-bootstrapCLI starting several CAP services and an AppRouter locally togetherfrom CAP
  8. open-steamgateLocal ABAP server serving /IWBEP/ OData v2 without an SAP systemfrom ABAP
  9. pokrakam/abapDevSysInitABAP report setting up a new ABAP Developer Edition or trial systemfrom ABAP
  10. @sang2x/captoolsCLI of CAP development tools for Cloud Foundry workflowsfrom CAP
  11. @sap/ams-devCompiler from AMS DCL policies to DCN for local runs and testsfrom CAP
  12. @sap/cds-dkCommand line client and development toolkit for CAPfrom CAP
  13. @sap/cdsCAP Node.js runtimefrom CAP
  14. dev-approuterDev-time wrapper for the SAP Application Routerfrom CAP
Editor support
  1. abap-adt-apiJS/TS client for the ADT resources of an ABAP systemfrom ABAP
  2. abap2UI5 for VS CodeVS Code extension to preview, activate and lint abap2UI5 appsfrom ABAP
  3. vscode-tabl-ddicVS Code syntax highlighting for .tabl.ddic table definitionsfrom ABAP
  4. HammerNative macOS code editor for ABAP and CDSfrom ABAP
  5. cds-eclipse-pluginEclipse plugin for the CDS languagefrom CAP
  6. @arc-mcp/adt-lsTypeScript SDK over SAP's headless adt-ls language serverfrom ABAP
  7. abapthemesThree colour themes for ABAP source in ADT for Eclipsefrom ABAP
  8. SAP Build CodeDevelopment environment on BTP for UI5, Fiori, mobile and CAPfrom BTP/BAIP
  9. SAP Business Application StudioBrowser-based development environment with dev spacesfrom BTP/BAIP
  10. SAP Web IDE Full-StackIDE service on SAP BTP for SAPUI5, Fiori and full-stack appsfrom BTP/BAIP
  11. cds-intellijSAP CDS language support for IntelliJ IDEAfrom CAP
  12. Cloud ALM Link for ADTEclipse plugin linking ABAP transports to SAP Cloud ALM featuresfrom ABAP
  13. ABAP Call HierarchyEclipse plugin showing the call hierarchy of ABAP membersfrom ABAP
  14. abap-call-hierarchyADT backend for the ABAP Call Hierarchy Eclipse pluginfrom ABAP
  15. abap-tags-backendADT backend for the ABAP Tags Eclipse pluginfrom ABAP
  16. ABAP TagsEclipse plugin for tagging ABAP repository objectsfrom ABAP
  17. BellaEclipse plugin bringing Claude into ABAP Development Toolsfrom ABAP
  18. ABAP Syntax HighlightingVS Code syntax highlighting for .abap filesfrom ABAP
  19. abapfs_extensionsABAP objects enabling ADT updates on systems older than 7.51from ABAP
  20. ABAP remote filesystemVS Code extension editing ABAP systems over ADT as a filesystemfrom ABAP
  21. ABAP Development Tools for EclipseSAP's Eclipse plugins for ABAP development over ADTfrom ABAP
  22. ABAP Development Tools for VS CodeSAP's ABAP tools in VS Code for editing, debugging, ATC and transportsfrom ABAP
  23. @sap/cds-lspLanguage server for CDSfrom CAP
  24. cds-textmate-grammarTextMate grammar for the CDS languagefrom CAP
  25. @sap/ux-cds-odata-language-server-extensionOData annotation features for the @sap/vscode-cds extensionfrom CAP
  26. @sap/vscode-cdsCDS language support for VS Code and Business Application Studiofrom CAP
  27. vscode-ui5-language-assistantVS Code extension for SAPUI5 and OpenUI5 XML views and manifestfrom UI5
  28. @saptools/hana-lensWorkspace-wide CSN cache for querying CAP entities and columnsfrom CAP
  29. @saptools/sqltoolsSQLTools connection from a Cloud Foundry app's HANA bindingfrom BTP/BAIP
  30. zed-cds-extensionCDS language support for the Zed editorfrom CAP
  31. my-ide-actionsCollection of ABAP Development Tools IDE Actionsfrom ABAP
Static analysis
  1. @abap2ui5/linterCommand-line checker for abap2UI5 app classes and their viewsfrom ABAP
  2. abapcdsgrammarANTLR4 grammar, lexer and parser for ABAP CDSfrom ABAP
  3. @abapify/acdsParser for ABAP CDS DDL source with a typed ASTfrom ABAP
  4. abaplint-sci-clientABAP client surfacing abaplint checks in Code Inspector and ATCfrom ABAP
  5. abaplintStatic analysis for ABAP source outside a systemfrom ABAP
  6. BellaEclipse plugin bringing Claude into ABAP Development Toolsfrom ABAP
  7. abapOpenChecksOpen-source rule pack for SAP Code Inspector and ATCfrom ABAP
  8. upDOWNciUploads and downloads Code Inspector check variants as XMLfrom ABAP
  9. abaplint-Ext-for-abapGitShows abaplint results inside abapGitfrom ABAP
  10. ABAP remote filesystemVS Code extension editing ABAP systems over ADT as a filesystemfrom ABAP
  11. code pal for ABAPATC and Code Inspector checks for Clean ABAPfrom ABAP
  12. Clean-Core.ioHosted workspace redrawing custom ABAP as BPMN and grading itfrom ABAP
  13. ACESAP GUI tool for static analysis of ABAP call flow and code metricsfrom ABAP
Code formatting
  1. abapPrettyCommand-line ABAP pretty printer over ADTfrom ABAP
  2. ABAP remote filesystemVS Code extension editing ABAP systems over ADT as a filesystemfrom ABAP
Documentation
  1. @cap-js/mcp-serverMCP server for CAP development: model and docs searchfrom CAP
  2. mcp-sap-docsMCP server searching seventeen SAP documentation repositoriesfrom CAP
  3. sap-api-hub-mcpRead-only MCP server over the SAP Business Accelerator Hubfrom BTP/BAIP
  4. sap-note-search-mcpMCP server searching and fetching SAP Notes and KBAsfrom BTP/BAIP
  5. sap-roadmap-mcpMCP server over SAP Road Map Explorerfrom BTP/BAIP
  6. ui5-lib-diffHosted app listing changes between SAPUI5 or OpenUI5 versionsfrom UI5
  7. abap-docNode.js command writing PDF documentation for an ABAP packagefrom ABAP
  8. sap-ai-docs-mcpMCP server with semantic search over SAP AI Core documentationfrom BTP/BAIP
  9. sap-btp-docs-mcpMCP server with semantic search over SAP BTP documentationfrom BTP/BAIP
  10. @sap-ux/fiori-docs-embeddingsFiori documentation indexed as embeddingsfrom CAP
  11. Clean-Core.ioHosted workspace redrawing custom ABAP as BPMN and grading itfrom ABAP
  12. abapdocs-code-scannerReads the abapDoc comments of a class or interface's public methods and type definitions and returns their text at runtime.from ABAP
  13. @ui5/webcomponents-mcp-serverMCP server answering questions on UI5 Web Componentsfrom UI5
  14. vscode-ui5-api-referenceVS Code side bar view of the SAPUI5 and OpenUI5 API referencefrom UI5

Details

Sources3
GitHub APIdiscovered herechecked
github.com/abap2UI5/playgroundtree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
discovered viaGitHub API
first seen in the atlas
ecosystem and domainabap, developer-experience
Contributors1

From the repository’s contributor list, .

History in the atlas1
  1. First seen.
For your agent
Ref
artifact:abap2ui5-playground
JSON
/artifacts/abap2ui5-playground.json
MCP
Connecting an agent