A tutorial hosting platform for developers.sap.com that replaces both Adobe Experience Manager (AEM) and the legacy Java IMS backend. Fetches tutorial markdown from the sap-tutorials GitHub organization at build time, renders static pages with SAP Fundamental Styles (Horizon theme) via Hugo, and deploys on SAP BTP Cloud Foundry behind an AppRouter with XSUAA authentication. The CAP Node.js backend provides progress tracking, event management, and all services previously handled by the Spring Boot IMS application.
Production system replacing AEM tutorial hosting, Git-based authoring interface, and Java IMS backend on developers.sap.com (April 2026).
Stack: Hugo Β· CAP Node.js (CDS 9.x) Β· SAP HANA Cloud Β· SAP Fundamental Styles Β· Vue 3 (apps) Β· TypeScript Β· SAP BTP Cloud Foundry
tutorials-ims/
βββ approuter/ # BTP AppRouter β serves static files + proxies to CAP via XSUAA auth
β βββ server.js # Custom AppRouter wrapper (VCAP merge, serve-static, proxy fixes)
β βββ static/ # Pre-built assets deployed to CF
β β βββ admin-ui/ # Admin shell (sap.tnt.ToolPage) + 11 Fiori Elements components
β β βββ analytics-ui/ # Analytics Explorer Vue 3 SPA bundle
β β βββ scanner-ui/ # UI5 barcode scanner bundle
β β βββ scanner-vue/ # Vue 3 barcode scanner bundle
β β βββ display-app/ # Display App SPA bundle (event monitor dashboard)
β β βββ qa/ # QA-channel Hugo build (gated by Tutorial.Author scope)
β β βββ css/img/js/ # Global stylesheets, images, shared JS injected into Hugo pages
β β βββ (no tutorials/) # Tutorials served dynamically from HANA, not static files
β βββ xs-app.json # Route definitions (/admin-ui, /analytics-ui, /scanner-*, /tutorials, /tutorials-qa, /api, /admin, /display, /chat, /search, /build, /content)
βββ app/ # Standalone UI applications (UI5 + Vue, deployed to approuter/static/)
β βββ admin-shell/ # sap.tnt.ToolPage shell with side navigation + theme switching
β βββ admin/ # 11 Fiori Elements feature components (events, missions, groups,
β β # accomplishments, prizes, tutorials, tags, operations, accounts,
β β # changelog, joule, feedback, analytics) loaded by the shell
β βββ analytics-explorer/ # Vue 3 + Vite + Monaco SQL editor over AnalyticsService
β βββ scanner/ # UI5 barcode scanner (sap.ndc.BarcodeScanner)
β βββ display-app/ # Standalone event monitor dashboard (Vue 3 + Vite, Socket.IO)
β βββ admin-annotations.cds # @UI/@Common annotations for all admin screens
β βββ change-tracking.cds # @cap-js/change-tracking config for admin entities
βββ hugo-apps/ # Vue 3 page-level islands compiled into Hugo's static JS (output: hugo/static/js/)
β βββ src/ # 9 entry points: navigator, app-space, event-display, nav-dropdown,
β β # scanner-vue, tutorial-feedback, tutorial-rating, cmd-palette, me
β βββ shared/ # Shared utilities, API client, types
βββ hugo/ # Hugo static site generator β tutorial pages + layouts
β βββ assets/css|js/ # PostCSS pipeline (Fundamental Styles Horizon) + page-level JS
β β # includes ui5-bootstrap.ts (UI5 Web Components shellbar/dialog/etc.)
β βββ config/ # Hugo configuration (hugo.toml, environment overrides)
β βββ content/
β β βββ tutorials/ # Generated tutorial markdown (gitignored, from fetch-tutorials)
β β βββ missions/ # Generated mission overview pages
β β βββ groups/ # Generated completion-path pages
β βββ data/ # Site-level data files (glossary, etc.)
β βββ i18n/ # en_us only (developers.sap.com is English-only)
β βββ layouts/ # _default, tutorials, missions, groups, partials, shortcodes
βββ hugo.qa.toml # Sibling Hugo config for QA channel (strips Joule FAB, rating, etc.)
βββ preview-site/ # Hugo preview-site renderer (used by srv-qa preview path)
βββ db/ # Production CAP data model β CDS schema + HANA native artifacts
β βββ schema.cds # Entity definitions (Users, Tutorials, Missions, Events, etc.)
β βββ views.cds # CDS views (NavigatorCatalog, SearchableItems, CompletionAnalytics, β¦)
β βββ persistence.cds # ContentFiles + ContentManifest (gzip-compressed tutorial BLOBs)
β βββ audit-logging.cds # @PersonalData annotations (Users, UserMetaData, TaskRecords)
β βββ change-tracking.cds # @cap-js/change-tracking annotations
β βββ schema-ext.cds # Service-layer schema extensions
β βββ src/ # Native HANA artifacts (.hdbsequence for legacy integer IDs)
βββ db-qa/ # QA-channel HDI container schema (peer of db/, deploys to tutorials-hana-qa)
βββ srv/ # CAP Node.js backend β production services
β βββ server.js # Bootstrap: registers Express routes + jobs on cds.on('served')
β βββ *-service.cds + .js # 9 services: developer, admin, analytics, exports, display,
β β # consolidation, scanner, search, chat, event-stream
β βββ ord-annotations.cds # Open Resource Discovery registration for all services
β βββ handlers/ # Express route handlers (recommendations.js)
β βββ exports/ # ExportsService backends (CSV/zip, XLSX, task records, etc.)
β βββ lib/ # Shared business logic (~40 modules):
β β # content-store (HANA BLOB serve), embedding-* (RAG), chat-* (Joule),
β β # accomplishment-evaluator, account-merge, build-catalog,
β β # navigator-catalog, recommend, co-completion, status-calculator,
β β # mail-client, ngds-client, adobe-analytics, qrcode-handler,
β β # analytics-sql-validator (SELECT-only allowlist for runSelectQuery),
β β # feedback-salt, ip-rate-limit, ttl-cache, pipeline-log, β¦
β βββ jobs/ # Scheduled tasks: scheduler, account-merge, cleanup,
β β # ngds-retry, embedding-reconciliation, job-lock (distributed)
β βββ templates/notification/ # Email HTML templates (Handlebars)
βββ srv-qa/ # QA-channel CAP app (peer of srv/, deploys to tutorials-srv-qa)
β βββ server.js # Mounts xsuaa-scope-middleware (Tutorial.Author gate) + preview renderer
β βββ search-service.cds # QA-only search projection
βββ scripts/ # Build-time scripts β fetch, parse, publish, migrate, seed
β βββ fetch-tutorials.ts # Main entry: fetches markdown from GitHub, generates Hugo pages
β βββ publish-content.ts # Delta-publish Hugo HTML β HANA BLOBs via /content/publish
β βββ parsers/ # Markdown pipeline: v1 (legacy ACCORDION) + v2 (H3) + images,
β β # options, cap, github, rules, sanitize-html, hugo-delimiters, types
β βββ grammars/ # TextMate grammars for syntax highlighting
β βββ highlight-cds.ts # CDS syntax highlighter
β βββ install-qa-workflows.ts # Distribute notify-qa.yml workflow to all -Contribution repos
β βββ verify-qa-build.ts # Post-build verification of QA Hugo output
β βββ check-qa-schema-drift.ts# Compare prod vs QA HDI schemas (CI step)
β βββ setup-dev-data.cjs # Slug population + autotest cleanup against DEV HANA
β βββ seed-*.cjs / seed-*.js # Various data seeding scripts
β βββ migrate-reference-data.js # Export/import tutorials, missions, events from Java IMS
β βββ migrate-user-progress.js # Export/import user progress (paged, resumable)
β βββ migrate-from-hana.js # Direct HANA-to-HANA migration
β βββ compare-systems.js # Endpoint-by-endpoint diff between Java IMS and CAP
βββ test/ # Vitest workspaces (unit, hybrid, hybrid-qa, smoke)
β βββ unit + integration/ # In-memory SQLite, fast, no external deps (npm test)
β βββ lib/ + jobs/ + parsers/ # Module-level unit tests
β βββ hybrid/ # Real HANA Cloud via cds bind --exec (npm run test:hybrid)
β βββ hybrid-qa/ # Hybrid tests against QA HDI
β βββ smoke/ # HTTP smoke tests against deployed URLs (npm run test:smoke)
β βββ srv-qa/ # QA-srv-specific tests (preview, scope middleware)
β βββ a11y/ # Accessibility tests
βββ docs/ # Architecture references and developer documentation
β βββ pilot-status.md # Pilot completion + locked production scope
β βββ testing-endpoints.md # Canonical UI + API endpoint reference (auth/scope mapping)
β βββ production-ready.md # Go-live checklist
β βββ theme-variants.md # Building event-specific theme variants (Joule, Sapphire, TechEd)
β βββ qa-channel-bootstrap.md # One-time QA author-preview channel setup
β βββ content-pipeline.md # Fetch β parse β Hugo β HANA pipeline deep-dive
β βββ authentication-architecture.md, mta-deployment.md, hugo-migration.md, ai-consumption.md, β¦
β βββ improvements.md, TODO.md# Feature backlog and gap tracking (largely historic)
β βββ superpowers/specs/+plans/ # Feature specs and step-by-step implementation plans
βββ .deploy/ # MTA build + deploy artifacts
β βββ mta.yaml # MTA descriptor (modules: approuter, srv, srv-qa, db, db-qa, destinations)
β βββ xs-security.json # XSUAA scopes + role collections (Admin, MobileApp, Tutorial.Author)
β βββ deploy-admin.sh # Standalone admin UI deploy helper (bypasses MTA build)
β βββ DEPLOY.md # Deploy procedure documentation
βββ deploy/ # MTA extension descriptors (environment overrides)
β βββ dev.mtaext # Development overrides (instance counts, memory)
β βββ qa.mtaext # QA/staging overrides
β βββ prod.mtaext # Production overrides
βββ .github/workflows/ # CI/CD pipelines (GitHub Actions)
β βββ deploy.yml # Build MTA + deploy to BTP CF + post-deploy smoke tests
β βββ rebuild-content.yml # Re-fetch tutorials + rebuild Hugo + publish HTML to HANA
β βββ rebuild-content-qa.yml # QA-channel content rebuild (triggered by repository_dispatch)
β βββ schema-drift-check.yml # Compare prod vs QA HDI schemas
β βββ notify-qa.yml.template # Template installed into every -Contribution repo
βββ openspec/ # OpenSpec change proposals + config
βββ .tutorial-cache/ # Cached prod-channel GitHub markdown + metadata (gitignored)
βββ .tutorial-cache-qa/ # Cached QA-channel markdown (gitignored, separate channel marker)
βββ .migration-data/ # Migration export files from Java IMS (gitignored)
βββ gen/ # CDS build output (gitignored)
βββ site/ # Legacy VitePress output (deprecated, gitignored)
βββ CLAUDE.md # Project context for Claude Code agents
βββ AGENTS.md # Agent-specific instructions (Codex/Gemini parity)
βββ package.json # Root dependencies + npm scripts (full list: jq '.scripts' package.json)
βββ vitest.config.ts # Vitest workspace config (inline projects array)
Prerequisites: Node.js >= 20, npm
npm install
npm run fetch-tutorials # Fetch tutorial markdown from GitHub + CAP catalog
cds watch # Start CAP server (http://localhost:4004)
npm run dev # Hugo dev server (separate terminal)
npm run build:all # Full production buildFor full setup including hybrid HANA development, environment variables, and the script reference, see docs/developers/getting-started.md.
Full list: jq '.scripts' package.json. The most operationally important ones:
| Script | Description |
|---|---|
npm install |
Install all dependencies |
npm run bind:setup |
First-time hybrid env binding (CAP + approuter against real HANA) |
npm run setup-dev-data |
Populate slugs + clean autotest data on DEV HANA (requires cds bind) |
| Script | Description |
|---|---|
cds watch |
Start CAP backend with in-memory SQLite (http://localhost:4004) |
npm run watch:hybrid |
CAP backend bound to real HANA via --profile hybrid |
npm run dev:hybrid |
CAP (hybrid) + approuter together β full local stack against real HANA |
npm run start:approuter |
Standalone approuter (port 5000) |
npm run dev |
Hugo dev server with live reload (requires fetch-tutorials first) |
| Script | Description |
|---|---|
npm run fetch-tutorials |
Fetch markdown from GitHub, parse, generate Hugo content pages |
npm run discover-repos |
List discoverable tutorial repos without fetching |
npm run build:cds |
Production CDS build |
npm run build:css |
PostCSS pipeline for SAP Fundamental Styles |
npm run build:hugo |
Hugo static site build (minified) |
npm run build:apps |
Build hugo-apps/ Vue islands into hugo/static/js/ |
npm run build:admin |
Build admin-shell into app/admin-shell/dist/ |
npm run build:analytics-explorer |
Build Analytics Explorer Vue 3 SPA |
npm run build:display |
Build Display App (event monitor dashboard) |
npm run build:highlight |
Generate CDS syntax highlighter assets |
npm run generate-dark-theme |
Regenerate dark-theme CSS variants |
npm run validate-tutorials |
Static validation of fetched tutorial markdown |
npm run build:all |
Full production pipeline (fetch + CSS + apps + Hugo + display) |
| Script | Description |
|---|---|
npm test |
Unit tests (in-memory SQLite, fast) |
npm run test:watch |
Unit tests in watch mode |
npm run test:hybrid |
Hybrid tests against real HANA (requires cf login to DEV) |
npm run test:hybrid:watch |
Hybrid tests in watch mode |
npm run test:smoke |
HTTP smoke tests (set SMOKE_BASE_URL / SMOKE_SRV_URL) |
npm run test:a11y |
Accessibility tests |
npm run test:a11y:lighthouse |
Lighthouse a11y audit (lhci autorun) |
npm run test:a11y:summary |
Print a11y test summary |
npm run test:all |
All Vitest workspaces (unit + hybrid + smoke + a11y) |
| Script | Description |
|---|---|
npm run publish-content |
Delta-publish Hugo HTML β HANA BLOBs (use -- --force to bypass delta β required for prod) |
| Script | Description |
|---|---|
npm run fetch-tutorials:qa |
Fetch from *-Contribution repos only (cache: .tutorial-cache-qa/) |
npm run build:qa |
Hugo build with QA flag, post-build verify |
npm run publish-content:qa |
Force-publish to QA srv |
npm run qa:full |
End-to-end QA pipeline |
| Script | Description |
|---|---|
npm run migrate:reference |
Export/import reference data from Java IMS |
npm run migrate:users |
Export/import user progress (paged, resumable) |
npm run migrate:hana |
Direct HANA-to-HANA migration |
npm run compare |
Compare Java IMS and CAP responses side-by-side |
Deploy-time variables for the MTA modules (CF env, role collections, secrets) are documented in .deploy/DEPLOY.md. The five most commonly set during local dev:
| Variable | Required | Description |
|---|---|---|
CAP_BASE_URL |
No (default http://localhost:4004) |
CAP srv URL β used by the build pipeline, publish-content, and migration scripts |
GITHUB_TOKEN |
No | Avoids GitHub API rate limits when fetching tutorial markdown + commit metadata |
CONTENT_API_KEY |
Yes (publish + srv) | Bearer token for POST /content/publish and /content/rollback; required on the srv to accept publish writes |
SUBMISSION_SALT_SECRET |
Yes (feedback) | IP-hash salt for /feedback/submit; bridge returns 503 if missing |
IMS_AUTH_TOKEN |
Yes (migrate) | Bearer token for the legacy Java IMS API during cutover |
For the full list, see docs/developers/getting-started.md#environment-variables.
See docs/developers/architecture/runtime.md for full details.
See docs/developers/architecture/build.md for full details.
See docs/developers/architecture/joule.md for full details.
See docs/developers/architecture/cap-backend.md for full details.
See docs/developers/architecture/build.md#build-pipeline for full details.
See docs/developers/architecture/frontend-apps.md for full details.
See docs/developers/operations/deployment.md for full details.
See docs/historic/data-migration.md for full details.
See docs/developers/operations/testing-guide.md for full details.
See docs/developers/reference/external-integrations.md for full details.
See docs/developers/reference/design-decisions.md for full details.
The full documentation set lives in docs/ and is organized by persona:
- End Users β finding tutorials, using Joule chat, progress and prizes
- Authors β writing tutorials, owning a repo group, running an event center
- Developers β architecture, operations, reference (you're probably here)
- Historic β AEM, IMS, completed migrations
Start at docs/README.md for the full index.
Copyright 2026 SAP SE or an SAP affiliate company and tutorials-ims contributors. Please see our LICENSE for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available via the REUSE tool.