Understand MTA modules, resources, and dependencies. Write a valid mta.yaml for a CAP + SPA + AppRouter stack.
mta.yaml: modules, resources, dependencies, and parametersA real BTP application is not one Cloud Foundry app — it is a collection of parts: a Node.js CAP service, a React frontend, an AppRouter, and a set of bound services (XSUAA, HANA, Destination, Object Store). Deploying each part manually is error-prone and hard to reproduce. The MTA (Multi-Target Application) standard packages everything into a single deployable archive (.mtar) with a declarative descriptor. One command deploys or re-deploys the whole stack in the right order with the right bindings.
| Concept | What it is |
|---|---|
| Module | A deployable artifact — a CF app, a content deployer |
| Resource | A managed service or existing CF service |
| Dependency | A requires / provides edge between modules and resources |
| Parameter | A value injected into module/resource config at deploy time |
mta.yaml |
The declarative descriptor of the whole MTA |
.mtar |
The built archive containing all modules + the descriptor |
mta.yaml for a CAP + SPA app_schema-version: '3.1'
ID: my-cap-app
version: 1.0.0
description: My CAP Application
modules:
# ── CAP Service ─────────────────────────────────────────────────────────────
- name: my-cap-app-srv
type: nodejs
path: .
parameters:
buildpack: nodejs_buildpack
memory: 512M
disk-quota: 1G
build-parameters:
builder: npm
build-result: gen/srv
ignore: [node_modules/, .env]
requires:
- name: my-xsuaa
- name: my-hana
- name: my-destination
provides:
- name: srv-api
properties:
srv-url: '${default-url}'
# ── HTML5 App UI Deployer ────────────────────────────────────────────────────
- name: my-cap-app-ui-deployer
type: com.sap.application.content
path: frontend
requires:
- name: my-html5-repo-host
parameters:
content-target: true
build-parameters:
build-result: dist
requires:
- name: my-cap-app-ui
artifacts:
- dist.zip
target-path: resources/
# ── AppRouter ───────────────────────────────────────────────────────────────
- name: my-cap-app-approuter
type: approuter.nodejs
path: approuter
parameters:
memory: 256M
disk-quota: 256M
requires:
- name: my-xsuaa
- name: my-html5-runtime
- name: my-destination
- name: srv-api
group: destinations
properties:
name: cap-backend
url: '~{srv-url}'
forwardAuthToken: true
resources:
- name: my-xsuaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
config:
xsappname: my-cap-app-${org}-${space}
tenant-mode: dedicated
- name: my-hana
type: com.sap.xs.hdi-container
parameters:
service: hana
service-plan: hdi-shared
- name: my-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
- name: my-html5-repo-host
type: org.cloudfoundry.managed-service
parameters:
service: html5-apps-repo
service-plan: app-host
- name: my-html5-runtime
type: org.cloudfoundry.managed-service
parameters:
service: html5-apps-repo
service-plan: app-runtime
provides / requires with group: destinations: The AppRouter needs to know the CAP service URL at deploy time. The CAP module publishes its URL under srv-api. The AppRouter consumes it in a destinations group, which AppRouter reads as an environment variable destinations — a JSON array of route configs.
${default-url}: A parameter placeholder that expands to the CF app route assigned at deploy time. Never hardcode URLs in mta.yaml.
${org} and ${space}: Namespacing XSUAA xsappname per org/space prevents collisions when the same app is deployed to multiple spaces (dev, test, prod).
# Install MTA Build Tool
npm install -g mbt
# Build the .mtar archive
mbt build -t ./
# Output: my-cap-app_1.0.0.mtar
mbt runs each module's build steps (npm build for Node.js, npm run build for Vite), then packages everything into a single archive.
| Mistake | Fix |
|---|---|
| Hardcoding space/org-specific URLs | Use ${default-url}, ${org}, ${space} parameters |
Missing ignore: [node_modules/] |
Including node_modules bloats the archive |
| Forgetting the HDI deployer module | HANA tables are not created unless you include a hdi-deployer module |
requires without provides |
The consuming module will fail — check that the provider declares the property group |
_schema-version mismatch |
Use 3.1 for modern MTAs; older schemas lack some features |
You understand the MTA concepts of modules, resources, and dependencies. You can write a valid mta.yaml for a CAP + SPA + AppRouter stack, use parameter placeholders for URLs and service names, and build a deployable .mtar archive with mbt build.