From 3e40d6db1667081a914f78031d3f902bcd8e220e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 06:41:47 +0000 Subject: [PATCH 01/44] Rewrite the page for a reader who gives it three minutes Half the length, proof before the pitch, the downsides next to the upsides: what a decision maker checks first, in the order they check it. - Order: use cases, who runs it, where it fits and where it does not, governance, cost, platform, AI, FAQ, get started. Add-ons dropped (a developer topic, linked), No strings folded into Cost, the week and the ways in merged into one closing block. - Who runs it: "In production" and "Partner" tags instead of ABAP release numbers, the figures a reader can check (since December 2022, 25+ contributors, release 1.148 in October 2026) with their source; the five references a manager recognizes first, the other fifteen folded. - Comparison: three rows where abap2UI5 is not ahead (standard transactional apps, offline and real-time, support), a "Where something else fits better" box next to the reasons, and no superlative headings. - Support, as SUPPORT.md states it: community, best effort, no support contract on offer today; the FAQ and the cost sheet say so. - Cost: a five-line sheet (three zeros, developer time, partner services) beside the price card; the calculator folds under a summary; the giving-back note moves to a short strip before the foot. - Hero: the grid-table example in the current theme instead of the grey walkthrough; the primary action opens the example apps, not the playground sandbox. - Platform in manager terms: no ICF, sy-uname or user exit in the text. - Mobile: the section links stay as a scrolling row under the header; a comparison row becomes a card with the column name on every cell. - Footer: build date and the contact address. - Tests: the visible text stays under 2,600 words, the comparison keeps its even rows and the support wording, every carries data-th. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014YZFmDmGbnnhTHeXMxMCrJ --- AGENTS.md | 23 +- README.md | 7 +- public/walkthrough-preview.webp | Bin 22254 -> 0 bytes src/components/CostCalculator.astro | 19 +- src/components/Stats.astro | 13 +- src/layouts/Page.astro | 20 +- src/pages/index.astro | 469 ++++++++++++++-------------- src/styles/global.css | 99 ++++-- test/site.test.mjs | 22 +- 9 files changed, 363 insertions(+), 309 deletions(-) delete mode 100644 public/walkthrough-preview.webp diff --git a/AGENTS.md b/AGENTS.md index c6bd3f8..53f9e41 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,9 @@ # AGENTS.md abap2UI5 for decision makers: one static page that presents abap2UI5 to IT -management and product owners - what it can build, why it beats every other -UI5 solution on SAP (commercial ones included), what it costs - published at https://abap2ui5.github.io/test-docs/ by GitHub Pages. A +management and product owners - what it can build, who runs it, where it is +the shorter path to a UI5 app on SAP and where it is not, what it costs - +published at https://abap2ui5.github.io/test-docs/ by GitHub Pages. A standalone site — its own repository, build and deployment — and nothing in it depends on abap2UI5/docs or abap2UI5/playground at build time. @@ -12,10 +13,10 @@ it depends on abap2UI5/docs or abap2UI5/playground at build time. | --- | --- | | `src/pages/index.astro` | The page: the text of every section, as data at the top and markup below | | `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), `CostCalculator` (the sheet, after the manual's), `Icon` (inline marks) | +| `src/components/` | `Stats` (the headline tiles under the hero), `CostCalculator` (the sheet, folded under What it costs), `Icon` (inline marks) | | `public/calc.js` | The cost calculator in the browser - the page's one script; the calculator reads correctly without it | | `src/styles/global.css` | The one stylesheet; light and dark follow the system | -| `public/` | Font (Inter, self-hosted), logo, icons, the screenshot | +| `public/` | Font (Inter, self-hosted), logo, icons, `apps/` (one screenshot per example app; the hero shows one of them) | | `test/site.test.mjs` | `node:test` over the built `dist/index.html` | | `.github/workflows/pages.yml` | Build + test on every PR; deploy on main | @@ -43,6 +44,20 @@ npm run check # build + test, what CI runs the font and the images are in `public/`. - **Written for managers.** No technical counts (tests, specs, gates) and no "evaluate" or "problem" in the visible text - `test/site.test.mjs` checks the latter. + Figures a reader can check (since when, contributors, the latest release) are + fine; they carry their date and link to GitHub. +- **Short, honest, in this order.** A reader gives the page a few minutes: + the visible text outside `
` stays under 2,600 words (the test holds + it). The comparison names where abap2UI5 is *not* ahead (rows marked `even`, + the "Where something else fits better" box) and the support it has (community, + best effort, no vendor SLA on offer - `SUPPORT.md` in the framework is the + source). Proof ("Who runs it") comes before the comparison, cost before AI. + No superlatives ("better than every", "made for"); a claim a reader cannot + check is cut, not softened. Add-ons, Basis steps and other developer topics + are links into the manual, not sections. +- **Every table cell carries its column.** `data-th` on each ``: under + 700px a row becomes a card and the cell shows its column name. The test + refuses a `` without it. - **Toolchain:** Node 22 (`.nvmrc`, `engines`), every dependency pinned exactly (astro 7.3.8), actions pinned to commits. - **The one place for decision makers.** The manual (abap2UI5/docs) is for diff --git a/README.md b/README.md index 7e2e61c..509e609 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # abap2UI5 for decision makers The page that presents abap2UI5 to IT management, product owners and -architecture boards: what you can build with it, why it beats every other way -to build UI5 apps on SAP — commercial platforms included — what your -organization keeps, where it runs, what it costs, and how to start with one -real screen. +architecture boards: what you can build with it, who runs it, where it is the +shorter path to a UI5 app on SAP and where it is not, what your organization +keeps, where it runs, what it costs, and how to start with one real screen. **→ https://abap2ui5.github.io/test-docs/** diff --git a/public/walkthrough-preview.webp b/public/walkthrough-preview.webp deleted file mode 100644 index f92c7a77ab4ae36c0e2b291cde8f3023dada04bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22254 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 N0000000000001h^b>jd4 diff --git a/src/components/CostCalculator.astro b/src/components/CostCalculator.astro index 0838d39..7dc4b36 100644 --- a/src/components/CostCalculator.astro +++ b/src/components/CostCalculator.astro @@ -1,7 +1,7 @@ --- -/* The cost calculator - once the manual's, now only here: set the - * landscape, press Calculate, read off the sheet. Every line is zero, and the - * page says why on each one. +/* The cost calculator - once the manual's, now folded under "What it costs": + * set the landscape, press Calculate, read off the sheet. Every line is zero, + * and the page says why on each one. * * It works without its script: the sheet is in the page with the default * values, and /test-docs/calc.js (public/calc.js, a file of its own because the @@ -40,14 +40,6 @@ const lines = [ ["Support", ": GitHub issues and Slack are open to everybody either way", "support"], ["Upgrades", " of releases, each one an abapGit pull", "term"], ]; -const give = [ - ["Star the repository.", `One click on GitHub, and the next visitor sees a project rather than an experiment.`], - ["Answer somebody.", `One reply under an issue or in Slack saves somebody else an afternoon of searching.`], - ["Report what broke.", `An issue with a class that reproduces the bug is half of the fix already.`], - ["Post about it.", `A short post that mentions the page and carries #abap2UI5 is how the word gets around.`], - ["Add your company.", `One row under Who runs it is what answers is anybody actually running this?`], - ["Sponsor the work.", `The contributors, and the open-source projects it stands on - the smallest amount is a real one.`], -]; ---
@@ -87,10 +79,5 @@ const give = [

The formula is short: every line is zero, and a sum of zeros is zero - no matter what you set. abap2UI5 is MIT licensed, commercial use included, and what you build with it is a standard UI5 app served by the ABAP stack you already run.

-
-

Free to use is not the same as free to make

-

Those zeros were written in somebody's evenings - the release you will pull next month, the answer under your issue, the 7.02 downport nobody asked for. That part of the bill is real; it is just not addressed to you. And it is payable in a currency you already have:

-
    {give.map(([b, t]) =>
  • {b}
  • )}
-
diff --git a/src/components/Stats.astro b/src/components/Stats.astro index eb558d6..94c9ac9 100644 --- a/src/components/Stats.astro +++ b/src/components/Stats.astro @@ -1,13 +1,14 @@ --- /* The headline under the hero: what a decision maker takes away in five - * seconds. Claims, not counts - the technical figures (tests, specs, gates) - * belong to the framework's README, not to this page. */ + * seconds. Claims a reader can check, not counts of tests or specs - those + * belong to the framework's README. The figures are from October 2026 and + * link to their source in "Who runs it". */ const tiles = [ - ["0 €", "license fees - now and later, for any number of users"], - ["1 class", "per app - no frontend project, no extra platform"], - ["Minutes", "to a first screen, built by the ABAP team you have"], + ["0 €", "license fees, for any number of users, systems and apps"], + ["1 class", "per app: no frontend project, no extra platform"], ["7.02 → Cloud", "every SAP release, from one source"], - ["100 % yours", "open source, no vendor, no lock-in"], + ["Since 2022", "open source on GitHub, MIT, every release listed"], + ["25+", "contributors, from several companies"], ]; ---
diff --git a/src/layouts/Page.astro b/src/layouts/Page.astro index f4f70e1..797ab9c 100644 --- a/src/layouts/Page.astro +++ b/src/layouts/Page.astro @@ -5,7 +5,11 @@ * Policy is a . The page runs one script, the cost calculator's * public/calc.js, as a file from this origin - script-src is 'self', no inline * script, no handler attribute, nothing from anywhere else - and everything - * else is this origin too. test/site.test.mjs holds the page to it. */ + * else is this origin too. test/site.test.mjs holds the page to it. + * + * THE HEADER. The section links stay on every width: on a narrow screen they + * become a second row that scrolls sideways, so a reader on a phone has a + * table of contents rather than only a button. */ import "../styles/global.css"; interface Props { title: string; description: string } @@ -24,15 +28,15 @@ const CSP = [ ].join("; "); const sections = [ ["the-problem-it-answers", "Use cases"], - ["when-to-use-it-and-when-not", "Comparison"], - ["ai", "AI"], + ["who-runs-it", "Who runs it"], + ["when-to-use-it-and-when-not", "Where it fits"], ["what-you-keep", "Governance"], - ["no-strings-attached", "No strings"], - ["where-it-runs", "Platform"], ["what-it-costs", "Cost"], ["the-objections", "FAQ"], ["how-to-evaluate-it-in-a-week", "Get started"], ]; +// the build date, so a reader knows how old the figures on the page are +const updated = new Date().toISOString().slice(0, 10); --- @@ -47,7 +51,7 @@ const sections = [ - + @@ -58,10 +62,10 @@ const sections = [
abap2UI5 + Examples - Try it
@@ -69,7 +73,7 @@ const sections = [
- abap2UI5 · MIT licensed · built in the open + abap2UI5 · MIT licensed · built in the open · page updated · contact@abap2UI5.org
diff --git a/src/pages/index.astro b/src/pages/index.astro index 8ae317f..394b6c8 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -19,7 +19,7 @@ import CostCalculator from "../components/CostCalculator.astro"; const DOCS = "https://abap2ui5.github.io/docs/"; const PLAYGROUND = "https://abap2ui5.github.io/playground/"; const GITHUB = "https://github.com/abap2UI5/abap2UI5"; -const GITHUB_PAGE = "https://github.com/abap2UI5/test-docs"; +const GITHUB_PAGE = "https://github.com/abap2UI5/why"; 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; diff --git a/src/styles/global.css b/src/styles/global.css index de82bb1..1a1c252 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -9,7 +9,7 @@ font-style: normal; font-weight: 100 900; font-display: swap; - src: url("/test-docs/fonts/inter-roman-latin.woff2") format("woff2"); + src: url("/why/fonts/inter-roman-latin.woff2") format("woff2"); } :root { diff --git a/test/site.test.mjs b/test/site.test.mjs index 656d83e..2a641d0 100644 --- a/test/site.test.mjs +++ b/test/site.test.mjs @@ -8,7 +8,7 @@ import fs from "node:fs"; import path from "node:path"; const DIST = path.join(import.meta.dirname, "..", "dist"); -const BASE = "/test-docs/"; +const BASE = "/why/"; const html = fs.readFileSync(path.join(DIST, "index.html"), "utf8"); test("the eight section ids are the addresses the redirect and the README link to", () => { @@ -25,7 +25,7 @@ test("the page runs one script, as a file from this origin, and its policy says // the cost calculator's public/calc.js - and no inline script beside it const scripts = [...html.matchAll(/]*)>([\s\S]*?)<\/script>/gi)]; assert.equal(scripts.length, 1, "one diff --git a/src/layouts/Page.astro b/src/layouts/Page.astro index b02e711..fe8a350 100644 --- a/src/layouts/Page.astro +++ b/src/layouts/Page.astro @@ -2,10 +2,9 @@ /* The document around the page: head, the header with the sections, the foot. * * THE POLICY. GitHub Pages sets no headers of ours, so the Content-Security- - * Policy is a . The page runs one script, the cost calculator's - * public/calc.js, as a file from this origin - script-src is 'self', no inline - * script, no handler attribute, nothing from anywhere else - and everything - * else is this origin too. test/site.test.mjs holds the page to it. + * Policy is a . The page runs no script at all - script-src is 'self', + * no inline script, no handler attribute - and everything it loads is this + * origin too. test/site.test.mjs holds the page to it. * * THE HEADER. The section links stay on every width: on a narrow screen they * become a second row that scrolls sideways, so a reader on a phone has a diff --git a/src/pages/index.astro b/src/pages/index.astro index 3bbde1f..fe30a68 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -14,7 +14,6 @@ import Page from "../layouts/Page.astro"; import Stats from "../components/Stats.astro"; import Icon from "../components/Icon.astro"; -import CostCalculator from "../components/CostCalculator.astro"; const DOCS = "https://abap2ui5.github.io/docs/"; const PLAYGROUND = "https://abap2ui5.github.io/playground/"; @@ -292,11 +291,6 @@ const community = [
    {strings.map(([b, t]) =>
  • {b}{t}
  • )}
-
- Work it out for your landscape -

Set the sliders to your landscape, tick your systems, pick a currency, press Calculate. It stays zero; the sheet says why on each line.

- -

→ More on the License and Support.

diff --git a/src/styles/global.css b/src/styles/global.css index 2f752a7..09070b4 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -31,8 +31,6 @@ --hero-bg: #f8f9fb; --wash: rgba(208, 60, 74, .07); --wash-ink: rgba(15, 23, 42, .05); - --dark-card: #111a2e; - --dark-card-text: #e5eaf2; --header-bg: rgba(255, 255, 255, .86); --radius: 14px; --shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 8px 24px rgba(15, 23, 42, .06); @@ -61,8 +59,6 @@ --hero-bg: #0f1522; --wash: rgba(240, 96, 109, .10); --wash-ink: rgba(255, 255, 255, .03); - --dark-card: #172033; - --dark-card-text: #e5eaf2; --header-bg: rgba(15, 21, 34, .86); --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .25); } @@ -299,12 +295,12 @@ code { font-family: var(--mono); font-size: .9em; } .steps-basis li::before { content: counter(b); position: absolute; left: 0; top: 9px; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--brand-soft); color: var(--brand); font-weight: 700; font-size: 13px; } /* the cost */ -.price { padding: 32px; border-radius: var(--radius); background: var(--dark-card); color: var(--dark-card-text); box-shadow: var(--shadow); } -.price .big { display: block; font-size: 64px; line-height: 1; font-weight: 800; letter-spacing: -.04em; color: #fff; } -.price .big small { font-size: 20px; font-weight: 600; color: rgba(255, 255, 255, .7); letter-spacing: 0; } +.price { padding: 32px; border-radius: var(--radius); background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow); } +.price .big { display: block; font-size: 64px; line-height: 1; font-weight: 800; letter-spacing: -.04em; color: var(--brand); } +.price .big small { font-size: 20px; font-weight: 600; color: var(--muted); letter-spacing: 0; } .price ul { margin: 22px 0 0; padding: 0; list-style: none; } -.price li { padding: 9px 0 9px 28px; position: relative; border-top: 1px solid rgba(255, 255, 255, .14); color: var(--dark-card-text); } -.price li::before { content: "✓"; position: absolute; left: 0; color: var(--brand-strong); font-weight: 800; } +.price li { padding: 9px 0 9px 28px; position: relative; border-top: 1px solid var(--line); color: var(--text); } +.price li::before { content: "✓"; position: absolute; left: 0; color: var(--good); font-weight: 800; } .sheet { padding: 8px 24px; border-radius: var(--radius); background: var(--card); border: 1px solid var(--line); } .sheet-line { display: flex; justify-content: space-between; gap: 18px; padding: 12px 0; border-top: 1px solid var(--line); } @@ -316,49 +312,6 @@ code { font-family: var(--mono); font-size: .9em; } .sheet-note { margin: 0; padding: 14px 0 12px; border-top: 1px solid var(--line); font-size: 13px; color: var(--muted); } .strings { margin-top: 32px; } -/* the cost calculator, folded */ -.calc-details { margin-top: 32px; } -.calc-details summary { cursor: pointer; list-style: none; font-size: 18px; font-weight: 650; color: var(--ink); } -.calc-details summary::-webkit-details-marker { display: none; } -.calc-details summary::before { content: "+ "; color: var(--brand); } -.calc-details[open] summary::before { content: "− "; } -.calc-details .intro { font-size: 16px; } -.calc { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; margin-top: 40px; align-items: start; } -@media (max-width: 900px) { .calc { grid-template-columns: minmax(0, 1fr); } } -.calc-inputs { padding: 24px; border-radius: var(--radius); background: var(--card); border: 1px solid var(--line); } -.calc-row { display: grid; grid-template-columns: 170px minmax(0, 1fr) 160px; gap: 14px; align-items: center; margin: 0; padding: 12px 0; border: 0; border-top: 1px solid var(--line); } -.calc-row:first-child { border-top: 0; } -.calc-row label, .calc-row legend { font-weight: 600; color: var(--ink); font-size: 14px; } -.calc-row output { font-size: 14px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; } -.calc-row input[type=range] { width: 100%; accent-color: var(--brand); } -.calc-row select { justify-self: start; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--card); color: var(--ink); font: inherit; } -.calc-choices { display: block; } -.calc-choices legend { float: left; width: 170px; padding: 0; } -.calc-choices > span { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-left: 184px; font-size: 14px; color: var(--text); } -.calc-choices label { font-weight: 400; color: var(--text); white-space: nowrap; } -.calc-choices input { accent-color: var(--brand); } -@media (max-width: 620px) { - .calc-row { grid-template-columns: minmax(0, 1fr) auto; } - .calc-row input[type=range] { grid-column: 1 / -1; grid-row: 2; } - .calc-choices legend { float: none; width: auto; margin-bottom: 8px; } - .calc-choices > span { margin-left: 0; } -} -.calc-actions { margin: 18px 0 0; } -.calc-actions .btn { border: 0; cursor: pointer; font-family: inherit; } -.calc-inputs input:disabled, .calc-inputs select:disabled { opacity: .55; } -.calc-result { border-radius: var(--radius); background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow); overflow: hidden; } -.calc-sheet { padding: 8px 24px; } -.calc-line { display: flex; justify-content: space-between; gap: 18px; padding: 12px 0; border-top: 1px solid var(--line); } -.calc-line:first-child { border-top: 0; } -.calc-what { color: var(--ink); font-weight: 600; font-size: 15px; } -.calc-what small { display: block; margin-top: 2px; font-weight: 400; font-size: 13px; color: var(--muted); } -.calc-amount { flex: none; font-weight: 700; color: var(--good); font-variant-numeric: tabular-nums; } -.calc-total { padding: 20px 24px 24px; background: var(--good-soft); border-top: 1px solid var(--line); } -.calc-total div { display: flex; justify-content: space-between; padding: 4px 0; color: var(--muted); } -.calc-total div:first-child { color: var(--ink); font-size: 18px; font-weight: 700; } -.calc-total output { color: var(--good); font-weight: 800; font-size: 18px; } -.calc-total p { margin: 14px 0 0; font-size: 13px; color: var(--muted); } - /* the objections */ .faq { margin-top: 36px; border-top: 1px solid var(--line); } .faq details { border-bottom: 1px solid var(--line); } diff --git a/test/site.test.mjs b/test/site.test.mjs index 490772e..eae1e73 100644 --- a/test/site.test.mjs +++ b/test/site.test.mjs @@ -21,13 +21,10 @@ test("the eight section ids are the addresses the redirect and the README link t ]) assert.match(html, new RegExp(`id="${id}"`), `#${id}`); }); -test("the page runs one script, as a file from this origin, and its policy says so", () => { - // the cost calculator's public/calc.js - and no inline script beside it +test("the page runs no script, and its policy says so", () => { + // the FAQ and the folded references are
, the header is anchors const scripts = [...html.matchAll(/]*)>([\s\S]*?)<\/script>/gi)]; - assert.equal(scripts.length, 1, "one