diff --git a/AGENTS.md b/AGENTS.md index 858cff1..9c2001e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,6 +12,7 @@ it depends on abap2UI5/docs or abap2UI5/playground at build time. | Path | Purpose | | --- | --- | | `src/pages/index.astro` | The home page: the text of every section, as data at the top and markup below | +| `src/pages/faq.astro` | The FAQ, grouped; the home page keeps a teaser at `#the-objections`, which is an address | | `src/pages/community.astro` | Community & Support: the open-source idea, the support ladder, what it stands on, what to give back | | `src/layouts/Page.astro` | The document: head, the Content-Security-Policy, the header with the section links, the foot | | `src/components/` | `Stats` (the headline tiles under the hero), `Icon` (inline marks) | diff --git a/src/layouts/Page.astro b/src/layouts/Page.astro index 44f6216..65b2703 100644 --- a/src/layouts/Page.astro +++ b/src/layouts/Page.astro @@ -11,7 +11,7 @@ * that scrolls sideways on a narrow screen. No script anywhere. */ import "../styles/global.css"; -interface Props { title: string; description: string; current?: "home" | "community"; subnav?: [string, string][] } +interface Props { title: string; description: string; current?: "home" | "community" | "faq"; subnav?: [string, string][] } const { title, description, current = "home", subnav } = Astro.props; const base = import.meta.env.BASE_URL; const canonical = new URL(Astro.url.pathname, Astro.site).href; @@ -33,13 +33,13 @@ export const sections: [string, string][] = [ ["what-it-costs", "Cost"], ["where-it-runs", "Where it runs"], ["ai", "AI"], - ["the-objections", "FAQ"], ["who-runs-it", "Who runs it"], ["how-to-evaluate-it-in-a-week", "Get started"], ]; const row = subnav ?? (current === "home" ? sections : []); const home = base; const community = `${base}community/`; +const faq = `${base}faq/`; // the build date, so a reader knows how old the figures on the page are const updated = new Date().toISOString().slice(0, 10); --- @@ -69,7 +69,7 @@ const updated = new Date().toISOString().slice(0, 10); abap2UI5
@@ -97,6 +97,7 @@ const updated = new Date().toISOString().slice(0, 10); Playground GitHub Slack + FAQ Community & Support Edit this page diff --git a/src/pages/faq.astro b/src/pages/faq.astro new file mode 100644 index 0000000..564b279 --- /dev/null +++ b/src/pages/faq.astro @@ -0,0 +1,71 @@ +--- +/* The FAQ - its own page: what decision makers ask, in the groups they ask + * in. The home page keeps a teaser at #the-objections, because that id is an + * address other sites link to. */ +import Page from "../layouts/Page.astro"; + +const DOCS = "https://abap2ui5.github.io/docs/"; +const GITHUB = "https://github.com/abap2UI5/abap2UI5"; +const SLACK = "https://abapgit.slack.com/join/shared_invite/zt-46tqufaht-QlrxTzlDqlx85CWbeUnOqg#/shared-invite/email"; +const MAIL = "contact@abap2UI5.org"; +const base = import.meta.env.BASE_URL; +const slug = (t: string) => t.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, ""); + +/* The FAQ, in the groups a reader asks in: risk first, then fit, team, + * landscape, and what users will say. */ +const faq = [ + ["Risk and support", [ + ["It is an open-source project. What if the maintainers stop?", `The installed version keeps running, the source is in your system in full, readable and changeable, and the apps stay plain ABAP classes. Nothing is called at runtime that is not in your system, apart from the UI5 library, which your system ships. A build renamed into your own namespace is one workflow run (Namespaces, Renaming).`], + ["Who do we call when something breaks?", `Rarely anyone, because an app is upgrade-stable: abap2UI5 uses released APIs only, passes the ABAP Cloud checks and runs the same source from NetWeaver 7.02 to S/4HANA and ABAP Cloud; the frontend is UI5 itself, tested on the oldest and the newest release. A system upgrade or a UI5 upgrade does not break it. When something does break: your developer, for the app, as for any class in the system. For the framework, write in the Slack channel or open an issue on GitHub: anyone can, at any time, no account with the project needed, and in the open is where it gets answered fastest and where everybody sees the answer. Pull requests are welcome the same way. If your organization needs more, closer cooperation, a workshop or a support arrangement, write to ${MAIL} and plan it together (Support). Security reports are acknowledged within three business days (Security).`], + ["Will an upgrade break it: the next S/4HANA release, ABAP Cloud, the next UI5?", `No. On the ABAP side abap2UI5 uses released APIs only and passes the ABAP Cloud checks, so it is cloud-ready and an S/4HANA upgrade leaves it as it is; the same source runs from NetWeaver 7.02 to ABAP Cloud, so an app moves with your landscape. On the UI5 side the frontend is UI5 itself, not a copy, and every change runs in the browser on the oldest supported release and on UI5 2.x. Releases are listed (Release Notes); what goes is announced and tracked until removal (Deprecations).`], + ["Why should we trust it over a product we pay for?", "Because you can check everything a vendor asks you to believe: the source is open, every test is public, and an app is a class in your own system that keeps running whatever happens to the project. What you do not get is an SLA in a contract; what you get is the code, and a maintainer you can reach."], + ["Is anybody actually running this in production?", `Two companies say so under Who runs it below, and every release is tested against Standard ABAP and ABAP Cloud, downported to NetWeaver 7.02 and run in the browser on the oldest and the newest supported UI5 release (verified on).`], + ]], + ["Where it fits", [ + ["When abap2UI5, and when a custom SAPUI5 app, for a complex screen?", "Ask where the complexity is. If it is in the data and the rules, which is the usual case for a cockpit, a worklist or a multi-step form, abap2UI5 is the shorter path: the logic stays in ABAP next to the data, the screen is any UI5 control, and one ABAP developer owns the whole thing. If it is in the browser itself, an editor that works offline, an animation-heavy control, a client that must keep working without SAP for minutes, a custom SAPUI5 app with its own JavaScript is the right tool. Three questions decide it: does the app need to run without a connection, does it need custom JavaScript on the client, and who will maintain it in five years."], + ["Fiori Elements covers 80 percent of our screens. What about the rest?", "That rest is what abap2UI5 is for. Keep Fiori Elements where a list report or an object page from annotations fits; take abap2UI5 where a template becomes the thing you fight: a cockpit with a chart and a custom form, a scanner screen, a tool nobody wrote a floorplan for. Both appear as tiles in the same launchpad, and the business logic behind both is the same ABAP."], + ["Our clean-core guideline names RAP. Where does this leave us?", "Side by side. abap2UI5 passes the ABAP Cloud checks and modifies nothing in the standard, so it is clean core in the technical sense, but it is not SAP's programming model. The usual outcome is a scope: standard transactional screens in RAP, the tools around them in abap2UI5, both in one launchpad."], + ]], + ["Team and skills", [ + ["Our ABAP team is small and getting older. Can we take on a new UI technology?", "You are not taking one on. The UI is one more ABAP class, written by the people who write the rest, in the tools they use today, with UI5's controls learned from running examples in hours, not weeks. No JavaScript developer to hire in a market that has few, no full-stack profile to find, no training project before the real project. And an AI assistant writes a first version of such a class whole, which is exactly where a small team gains the most."], + ["How do our developers learn it, and how long does it take?", "From running examples, not from tutorials that aged. The catalogue holds 130 learning samples and 680 control examples, each one opens in the browser and each one is maintained with the framework, so none goes stale. The quickstart takes minutes: pull, one endpoint, the first screen is up. Within hours a developer builds a first real app, and within a week the screen your team needs this quarter, with the people who will maintain it. What a developer learns is UI5's controls and their properties, in ABAP, not a new language or a new toolchain."], + ]], + ["Landscape and tooling", [ + ["Do we need BTP for this?", "No. abap2UI5 runs on the ABAP system you already have, from NetWeaver 7.02 on, with no subscription beside it. If you run the BTP ABAP Environment or S/4HANA Cloud already, it runs there too, from the same source, so the decision about BTP stays yours and is not made for you by the UI."], + ["We are in the middle of an S/4HANA move. Is this the moment?", "It is one of the better ones. An app you build on the old system today runs on S/4HANA unchanged, so nothing you build now is thrown away at go-live. Screens move one at a time, SAP GUI stays until the last one, and the same team does both. And the apps are classes in your transport landscape, so they travel with the migration like everything else."], + ["Do we need Business Application Studio, Git, npm, a deployment pipeline?", "No. The framework is installed once with abapGit, as any open-source ABAP is. An app is written in ADT or SE80, checked by ATC, transported like any class. There is no frontend build, no BSP upload, no MTA, no approuter and no cache to clear after a deployment, because there is no deployment: the system serves the screen itself."], + ]], + ["Performance and users", [ + ["Every click is a request to SAP. Is that fast enough?", `Faster than most Fiori apps, in practice: one plain HTTP request per click with the changed data only, no OData metadata, no batch, no app logic or bundle in the browser. For worklists, forms and cockpits that is the round trip a SAP GUI screen makes. It is not built for an app that holds its state offline (Performance).`], + ["Our users are fast in SAP GUI. Will they accept it?", "Users go back to SAP GUI when the Fiori app is slower than the transaction it replaced. An abap2UI5 screen makes one request per click on the same ABAP stack, so a keyboard-driven worklist stays as quick as it was. And nothing is replaced in one go: one screen at a time, the GUI stays until the last one, the logic behind both is the same code."], + ]], +]; +--- + [slug(group as string), group as string])} +> +
+
+

FAQ

+

What decision makers ask

+

The questions an IT manager, a product owner or an architecture board puts to abap2UI5, answered with the place each answer can be checked. Anything missing? Ask it in Slack or write to {MAIL}; the answer lands here.

+
+
+ +
+
+
+ {faq.map(([group, qs], g) => ( +
+

{group}

+ {qs.map(([q, a], i) =>
{q}

)} +
+ ))} +
+

→ Back to the page for decision makers, or on to Community & Support.

+
+
+
diff --git a/src/pages/index.astro b/src/pages/index.astro index 36bc3cd..546010a 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -146,35 +146,6 @@ const ai = [ ["check", "Checked before anyone looks", "The abap2UI5 linter tests every class the AI writes, and the AI fixes what it broke before a developer reviews it."], ]; -/* The FAQ, in the groups a reader asks in: risk first, then fit, team, - * landscape, and what users will say. */ -const faq = [ - ["Risk and support", [ - ["It is an open-source project. What if the maintainers stop?", `The installed version keeps running, the source is in your system in full, readable and changeable, and the apps stay plain ABAP classes. Nothing is called at runtime that is not in your system, apart from the UI5 library, which your system ships. A build renamed into your own namespace is one workflow run (Namespaces, Renaming).`], - ["Who do we call when something breaks?", `Rarely anyone, because an app is upgrade-stable: abap2UI5 uses released APIs only, passes the ABAP Cloud checks and runs the same source from NetWeaver 7.02 to S/4HANA and ABAP Cloud; the frontend is UI5 itself, tested on the oldest and the newest release. A system upgrade or a UI5 upgrade does not break it. When something does break: your developer, for the app, as for any class in the system. For the framework, write in the Slack channel or open an issue on GitHub: anyone can, at any time, no account with the project needed, and in the open is where it gets answered fastest and where everybody sees the answer. Pull requests are welcome the same way. If your organization needs more, closer cooperation, a workshop or a support arrangement, write to ${MAIL} and plan it together (Support). Security reports are acknowledged within three business days (Security).`], - ["Will an upgrade break it: the next S/4HANA release, ABAP Cloud, the next UI5?", `No. On the ABAP side abap2UI5 uses released APIs only and passes the ABAP Cloud checks, so it is cloud-ready and an S/4HANA upgrade leaves it as it is; the same source runs from NetWeaver 7.02 to ABAP Cloud, so an app moves with your landscape. On the UI5 side the frontend is UI5 itself, not a copy, and every change runs in the browser on the oldest supported release and on UI5 2.x. Releases are listed (Release Notes); what goes is announced and tracked until removal (Deprecations).`], - ["Why should we trust it over a product we pay for?", "Because you can check everything a vendor asks you to believe: the source is open, every test is public, and an app is a class in your own system that keeps running whatever happens to the project. What you do not get is an SLA in a contract; what you get is the code, and a maintainer you can reach."], - ["Is anybody actually running this in production?", `Two companies say so under Who runs it below, and every release is tested against Standard ABAP and ABAP Cloud, downported to NetWeaver 7.02 and run in the browser on the oldest and the newest supported UI5 release (verified on).`], - ]], - ["Where it fits", [ - ["When abap2UI5, and when a custom SAPUI5 app, for a complex screen?", "Ask where the complexity is. If it is in the data and the rules, which is the usual case for a cockpit, a worklist or a multi-step form, abap2UI5 is the shorter path: the logic stays in ABAP next to the data, the screen is any UI5 control, and one ABAP developer owns the whole thing. If it is in the browser itself, an editor that works offline, an animation-heavy control, a client that must keep working without SAP for minutes, a custom SAPUI5 app with its own JavaScript is the right tool. Three questions decide it: does the app need to run without a connection, does it need custom JavaScript on the client, and who will maintain it in five years."], - ["Fiori Elements covers 80 percent of our screens. What about the rest?", "That rest is what abap2UI5 is for. Keep Fiori Elements where a list report or an object page from annotations fits; take abap2UI5 where a template becomes the thing you fight: a cockpit with a chart and a custom form, a scanner screen, a tool nobody wrote a floorplan for. Both appear as tiles in the same launchpad, and the business logic behind both is the same ABAP."], - ["Our clean-core guideline names RAP. Where does this leave us?", "Side by side. abap2UI5 passes the ABAP Cloud checks and modifies nothing in the standard, so it is clean core in the technical sense, but it is not SAP's programming model. The usual outcome is a scope: standard transactional screens in RAP, the tools around them in abap2UI5, both in one launchpad."], - ]], - ["Team and skills", [ - ["Our ABAP team is small and getting older. Can we take on a new UI technology?", "You are not taking one on. The UI is one more ABAP class, written by the people who write the rest, in the tools they use today, with UI5's controls learned from running examples in hours, not weeks. No JavaScript developer to hire in a market that has few, no full-stack profile to find, no training project before the real project. And an AI assistant writes a first version of such a class whole, which is exactly where a small team gains the most."], - ["How do our developers learn it, and how long does it take?", "From running examples, not from tutorials that aged. The catalogue holds 130 learning samples and 680 control examples, each one opens in the browser and each one is maintained with the framework, so none goes stale. The quickstart takes minutes: pull, one endpoint, the first screen is up. Within hours a developer builds a first real app, and within a week the screen your team needs this quarter, with the people who will maintain it. What a developer learns is UI5's controls and their properties, in ABAP, not a new language or a new toolchain."], - ]], - ["Landscape and tooling", [ - ["Do we need BTP for this?", "No. abap2UI5 runs on the ABAP system you already have, from NetWeaver 7.02 on, with no subscription beside it. If you run the BTP ABAP Environment or S/4HANA Cloud already, it runs there too, from the same source, so the decision about BTP stays yours and is not made for you by the UI."], - ["We are in the middle of an S/4HANA move. Is this the moment?", "It is one of the better ones. An app you build on the old system today runs on S/4HANA unchanged, so nothing you build now is thrown away at go-live. Screens move one at a time, SAP GUI stays until the last one, and the same team does both. And the apps are classes in your transport landscape, so they travel with the migration like everything else."], - ["Do we need Business Application Studio, Git, npm, a deployment pipeline?", "No. The framework is installed once with abapGit, as any open-source ABAP is. An app is written in ADT or SE80, checked by ATC, transported like any class. There is no frontend build, no BSP upload, no MTA, no approuter and no cache to clear after a deployment, because there is no deployment: the system serves the screen itself."], - ]], - ["Performance and users", [ - ["Every click is a request to SAP. Is that fast enough?", `Faster than most Fiori apps, in practice: one plain HTTP request per click with the changed data only, no OData metadata, no batch, no app logic or bundle in the browser. For worklists, forms and cockpits that is the round trip a SAP GUI screen makes. It is not built for an app that holds its state offline (Performance).`], - ["Our users are fast in SAP GUI. Will they accept it?", "Users go back to SAP GUI when the Fiori app is slower than the transaction it replaced. An abap2UI5 screen makes one request per click on the same ABAP stack, so a keyboard-driven worklist stays as quick as it was. And nothing is replaced in one go: one screen at a time, the GUI stays until the last one, the logic behind both is the same code."], - ]], -]; /* Get started: one real screen, with the people who will maintain it. */ const week = [ @@ -200,10 +171,6 @@ const doors = [

UI5 apps for ABAP,
built by the team you already have

An app is a regular ABAP class, nothing more: written in ADT or SE80, checked by ATC, carried by a transport, as every ABAP developer does it today. The business logic stays in ABAP, next to the data: no JavaScript, no extra platform, no license fee. Open source since 2023, in production on the desktop and on the warehouse floor.

-
One ABAP class in the ABAP development tools, and the app it produces on a handheld: a table of sales orders with status and amount @@ -320,11 +287,29 @@ const doors = [
Every SAP operating model, from one source
+
+
+

ABAP Cloud clean core, released APIs only: abap2UI5 passes the checks

+
    +
  • SAP S/4HANA Cloud Public EditionClean core is mandatory; the same class runs, no rewrite on the way up.
  • +
  • SAP BTP ABAP EnvironmentThe standalone ABAP system on BTP: for apps beside the core, or as the side-by-side system below.
  • +
  • S/4HANA Private Cloud and on-premise, in ABAP CloudDeveloping in the ABAP Cloud language version on a RISE or on-premise system: abap2UI5 fits the clean-core tier there too.
  • +
+
+
+

Standard ABAP the classic language version, every release

+
    +
  • SAP S/4HANA Cloud Private EditionRISE with SAP, in SAP's or a hyperscaler's data centre.
  • +
  • SAP S/4HANA on-premiseIn your own data centre or at a hoster.
  • +
  • SAP ECC and NetWeaver 7.02 to 7.5xWhere RAP and a Fiori stack are out of reach, and an app written today moves to S/4HANA unchanged.
  • +
+
+
+
Two ways to deploy
    -
  • On-premiseS/4HANA, and NetWeaver 7.02 or later, in your own data centre or at a hoster.
  • -
  • Private cloudRISE with SAP, S/4HANA Cloud Private Edition.
  • -
  • Public cloudS/4HANA Cloud Public Edition and the BTP ABAP Environment. Clean core is mandatory there, and abap2UI5 passes the ABAP Cloud checks: the same app, the same class, no rewrite on the way up.
  • +
  • On-stackabap2UI5 on the system where the data and the logic live. An app calls BAPIs, function modules or RAP actions directly, as any program there does. The usual setup, one abapGit pull.
  • +
  • Side-by-sideabap2UI5 on a separate ABAP system, the BTP ABAP Environment or a hub, and the apps reach the core over RFC or HTTP. For a core kept clean of custom UI, or one UI layer in front of several systems.
Where an app appears
@@ -359,18 +344,11 @@ const doors = [
-
+

FAQ

What decision makers ask

-
- {faq.map(([group, qs], g) => ( -
-

{group}

- {qs.map(([q, a], i) =>
{q}

)} -
- ))} -
+

What if the maintainers stop, who do we call, will an upgrade break it, do we need BTP, when abap2UI5 and when a custom SAPUI5 app, will our users accept it: fifteen questions, answered on the FAQ page.

diff --git a/src/styles/global.css b/src/styles/global.css index 6908648..7cdbe65 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -144,7 +144,6 @@ code { font-family: var(--mono); font-size: .9em; } .hero h1 em { font-style: normal; color: var(--brand); } .hero .lede { margin: 22px 0 0; max-width: 720px; font-size: 19px; line-height: 1.6; color: var(--muted); } .hero .lede b { color: var(--ink); } -.hero .actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; } /* the screenshot in a window frame, tilted towards the reader */ .window { margin: 0; border-radius: 14px; overflow: hidden; @@ -160,9 +159,6 @@ code { font-family: var(--mono); font-size: .9em; } .hero { padding: 56px 0 64px; } .hero .wrap { gap: 32px; } } -@media (max-width: 480px) { - .hero .actions .btn { flex: 1 1 100%; text-align: center; } -} /* ---- the figures --------------------------------------------------------- */ .stats { margin-top: -44px; position: relative; } @@ -322,7 +318,8 @@ code { font-family: var(--mono); font-size: .9em; } .faq-group details:last-child { border-bottom: 0; } /* the objections */ -.faq { margin-top: 36px; } +.faq { margin-top: 0; } +.faq-group { scroll-margin-top: 130px; } .faq details { border-bottom: 1px solid var(--line); } .faq summary { display: flex; justify-content: space-between; gap: 20px; padding: 22px 4px; @@ -428,7 +425,7 @@ code { font-family: var(--mono); font-size: .9em; } .week.four { grid-template-columns: repeat(4, minmax(0, 1fr)); } @media (max-width: 980px) { .week.four { grid-template-columns: minmax(0, 1fr); } } .week span a { font-weight: 600; } -.about-teaser { padding: 64px 0; } +.about-teaser, .faq-teaser { padding: 64px 0; } /* the hero composite: the class and the phone, on the hero wash itself */ .composite { margin: 0; } @@ -456,9 +453,14 @@ code { font-family: var(--mono); font-size: .9em; } .models li { padding: 14px 18px; border-radius: 12px; border: 1px solid var(--line); background: var(--card); } .models li b { display: block; color: var(--ink); font-size: 15.5px; } .models li span { display: block; margin-top: 3px; font-size: 14px; line-height: 1.5; color: var(--muted); } -.models li.hot { border-color: var(--brand); background: var(--brand-soft); } -.models li.hot b { color: var(--brand); } -.models li.hot span { color: var(--ink); } +.models-group { margin-top: 14px; padding: 14px 16px 16px; border-radius: 14px; border: 1px solid var(--line); background: var(--bg-alt); } +.models-group:first-child { margin-top: 12px; } +.models-group h4 { margin: 0 0 10px; font-size: 15px; color: var(--ink); } +.models-group h4 small { display: block; margin-top: 2px; font-size: 13px; font-weight: 500; color: var(--muted); } +.models-group .models { margin-top: 0; } +.models-group.hot { border-color: var(--brand); background: var(--brand-soft); } +.models-group.hot h4 { color: var(--brand); } +.models-group.hot h4 small { color: var(--ink); } /* the foot */ .foot { padding: 36px 0 44px; background: var(--bg-alt); color: var(--muted); font-size: 14px; border-top: 1px solid var(--line); } @@ -468,7 +470,7 @@ code { font-family: var(--mono); font-size: .9em; } .foot a:hover { color: var(--brand); text-decoration: underline; } @media print { - .top, .skip, .hero .actions, .foot { display: none; } + .top, .skip, .foot { display: none; } .hero { background: none; color: #000; padding: 0 0 24px; } .hero h1, .hero .lede { color: #000; } .faq summary::after { display: none; } diff --git a/test/site.test.mjs b/test/site.test.mjs index 6751f76..d5b77a1 100644 --- a/test/site.test.mjs +++ b/test/site.test.mjs @@ -62,6 +62,15 @@ test("the community page is built, carries no script, and both pages link each o } }); +test("the FAQ page is built, carries no script, and the home page points at it", () => { + const faq = fs.readFileSync(path.join(DIST, "faq", "index.html"), "utf8"); + assert.equal([...faq.matchAll(/ on the FAQ page"); + assert.ok((faq.match(/
= 12, "the questions are on the FAQ page"); + assert.doesNotMatch(html, /class="faq"/, "no question list on the home page"); + assert.match(html, /href="\/why\/faq\/"/, "home links to the FAQ"); + assert.doesNotMatch(faq, /evaluat|problem/i); +}); + test("the canonical address is the published one", () => { assert.match(html, //); });