Deploying a Fiori Elements App to SAP BTP involves several steps: From project creation in Business Application Studio through proper configuration to integration into the SAP Build Work Zone Launchpad. This article walks you through the complete process.
Overview: Deployment Process
┌─────────────────────────────────────────────────────────────────────┐│ Fiori Elements App Deployment │├─────────────────────────────────────────────────────────────────────┤│ ││ 1. Create App 2. Configure 3. Build & Deploy ││ ────────────── ───────────── ───────────────── ││ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ││ │ BAS │ │ manifest.json │ │ MTA Build │ ││ │ Generator │ → │ xs-app.json │ → │ cf deploy │ ││ │ │ │ mta.yaml │ │ │ ││ └───────────────┘ └───────────────┘ └───────────────┘ ││ │ ││ ▼ ││ 4. Launchpad Integration ││ ────────────────────── ││ ┌───────────────────────┐ ││ │ SAP Build Work Zone │ ││ │ • Create tile │ ││ │ • Assign space │ ││ │ • Configure roles │ ││ └───────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────┘Prerequisites
Before you start deployment:
| Prerequisite | Description |
|---|---|
| RAP Service | Working OData V4 service on BTP ABAP Environment |
| BAS Dev Space | SAP Fiori Dev Space in Business Application Studio |
| Cloud Foundry | Access to BTP subaccount with CF space |
| Build Work Zone | SAP Build Work Zone (Standard or Advanced) subscription |
| Destination | Configured destination to ABAP Environment |
1. App Creation in Business Application Studio
Prepare Dev Space
If not already available, create a Fiori Dev Space:
1. Open BAS → "Create Dev Space"2. Name: "FioriDevelopment"3. Type: Select "SAP Fiori"4. Activate extensions: ☑ HTML5 Application Template ☑ Fiori Tools ☑ MTA Build Tools5. Click "Create Dev Space"Generate Fiori Elements App
After dev space starts:
1. View → Command Palette (F1)2. Enter "Fiori: Open Application Generator"3. Select template: "List Report Page"4. Click nextConfigure Data Source
Data Source: "Connect to SAP System"
Service Selection:├── System: BTP ABAP Environment├── ABAP Environment: [Your service key]├── System URL: (automatically from service key)└── Service: ZUI_FLIGHTBOOK_O4 (your OData service)
Main Entity: FlightBookNavigation Entity: None (or child entity if available)Set Project Attributes
Project Name: flightbookingApplication Title: Manage Flight BookingsApplication Namespace: com.mycompanyDescription: Fiori Elements App for Flight BookingsMinimum SAPUI5 Version: 1.127.0 (or newer)
Project Folder: /home/user/projectsAdd deployment configuration: YesAdd FLP configuration: YesDeployment and FLP Configuration
Provide during generation:
Deployment Configuration:├── Target: Cloud Foundry├── Destination Name: BTP_ABAP_ENV (your destination)└── Add Application to managed App Router: Yes
FLP Configuration:├── Semantic Object: FlightBooking├── Action: manage├── Title: Manage Flight Bookings└── Subtitle: Create and edit bookings2. Understanding Deployment Configuration
After generation, your project contains several configuration files.
Project Structure
flightbooking/├── webapp/│ ├── manifest.json # App configuration│ ├── Component.js # UI5 Component│ ├── i18n/│ │ └── i18n.properties # Translations│ ├── localService/ # Mock data for local testing│ └── test/ # OPA5 tests├── xs-app.json # App Router routing├── mta.yaml # Multi-Target Application Descriptor├── package.json # Node.js dependencies├── ui5.yaml # UI5 build configuration└── ui5-deploy.yaml # Deployment-specific UI5 configmanifest.json
The manifest.json is the heart of app configuration:
{ "_version": "1.65.0", "sap.app": { "id": "com.mycompany.flightbooking", "type": "application", "title": "{{appTitle}}", "description": "{{appDescription}}", "applicationVersion": { "version": "1.0.0" }, "dataSources": { "mainService": { "uri": "/sap/opu/odata4/sap/zui_flightbook_o4/srvd/sap/zui_flightbook/0001/", "type": "OData", "settings": { "odataVersion": "4.0" } } }, "crossNavigation": { "inbounds": { "FlightBooking-manage": { "semanticObject": "FlightBooking", "action": "manage", "title": "{{flpTitle}}", "subTitle": "{{flpSubtitle}}", "signature": { "parameters": {}, "additionalParameters": "allowed" } } } } }, "sap.ui5": { "flexEnabled": true, "dependencies": { "minUI5Version": "1.127.0", "libs": { "sap.m": {}, "sap.ui.core": {}, "sap.fe.templates": {} } }, "routing": { "routes": [ { "pattern": ":?query:", "name": "FlightBookList", "target": "FlightBookList" }, { "pattern": "FlightBook({key}):?query:", "name": "FlightBookObjectPage", "target": "FlightBookObjectPage" } ], "targets": { "FlightBookList": { "type": "Component", "id": "FlightBookList", "name": "sap.fe.templates.ListReport", "options": { "settings": { "contextPath": "/FlightBook", "variantManagement": "Page", "navigation": { "FlightBook": { "detail": { "route": "FlightBookObjectPage" } } }, "initialLoad": "Enabled" } } }, "FlightBookObjectPage": { "type": "Component", "id": "FlightBookObjectPage", "name": "sap.fe.templates.ObjectPage", "options": { "settings": { "contextPath": "/FlightBook", "editableHeaderContent": false } } } } } }}Important Settings:
| Property | Description |
|---|---|
sap.app.id | Unique app ID (namespace + name) |
dataSources.mainService.uri | Path to OData service |
crossNavigation.inbounds | Launchpad integration (Semantic Object + Action) |
variantManagement | Save user-specific views |
initialLoad | Load data on startup |
xs-app.json
The Application Router uses this file for routing:
{ "welcomeFile": "/index.html", "authenticationMethod": "route", "routes": [ { "source": "^/sap/opu/odata4/(.*)$", "target": "/sap/opu/odata4/$1", "destination": "BTP_ABAP_ENV", "authenticationType": "xsuaa", "csrfProtection": false }, { "source": "^(.*)$", "target": "$1", "service": "html5-apps-repo-rt", "authenticationType": "xsuaa" } ]}Route Explanation:
| Route | Purpose |
|---|---|
/sap/opu/odata4/(.*) | Forward OData requests to ABAP Environment |
^(.*)$ | All other requests (HTML, JS, CSS) from HTML5 Repository |
mta.yaml
The Multi-Target Application Descriptor defines all components:
_schema-version: '3.2'ID: flightbookingversion: 1.0.0description: Flight Booking Fiori Elements App
parameters: enable-parallel-deployments: true deploy_mode: html5-repo
build-parameters: before-all: - builder: custom commands: - npm ci - npx ui5 build --config=ui5-deploy.yaml --clean-dest --dest dist
modules: # HTML5 App Deployer - name: flightbooking-deployer type: com.sap.application.content path: dist requires: - name: flightbooking-html5-repo-host parameters: content-target: true
# Destination Content - name: flightbooking-destination-content type: com.sap.application.content requires: - name: flightbooking-destination-service parameters: content-target: true - name: flightbooking-html5-repo-host parameters: service-key: name: flightbooking-html5-repo-host-key - name: flightbooking-uaa parameters: service-key: name: flightbooking-uaa-key parameters: content: instance: destinations: - Name: flightbooking_html5_repo_host ServiceInstanceName: flightbooking-html5-repo-host ServiceKeyName: flightbooking-html5-repo-host-key sap.cloud.service: com.mycompany.flightbooking - Authentication: OAuth2UserTokenExchange Name: flightbooking_uaa ServiceInstanceName: flightbooking-uaa ServiceKeyName: flightbooking-uaa-key sap.cloud.service: com.mycompany.flightbooking existing_destinations_policy: update
resources: # HTML5 Application Repository - name: flightbooking-html5-repo-host type: org.cloudfoundry.managed-service parameters: service: html5-apps-repo service-plan: app-host
# Destination Service - name: flightbooking-destination-service type: org.cloudfoundry.managed-service parameters: service: destination service-plan: lite config: HTML5Runtime_enabled: true
# UAA Service - name: flightbooking-uaa type: org.cloudfoundry.managed-service parameters: service: xsuaa service-plan: application path: ./xs-security.jsonxs-security.json
Defines security configuration:
{ "xsappname": "flightbooking", "tenant-mode": "dedicated", "scopes": [], "attributes": [], "role-templates": [], "oauth2-configuration": { "redirect-uris": [ "https://*.cfapps.*.hana.ondemand.com/**" ] }}3. Step-by-Step Deployment Process
Step 1: Cloud Foundry Login
In BAS terminal:
# CF CLI Logincf login -a https://api.cf.eu10.hana.ondemand.com
# Select org and spacecf target -o my-org -s devStep 2: Check Destination
In BTP Cockpit under Connectivity → Destinations, a destination to ABAP Environment must exist:
Destination: BTP_ABAP_ENVType: HTTPURL: https://<abap-env-host>.abap.eu10.hana.ondemand.comProxy Type: InternetAuthentication: OAuth2SAMLBearerAssertion
Additional Properties:├── sap-client: 100├── HTML5.DynamicDestination: true└── WebIDEUsage: odata_gen,odata_abapStep 3: MTA Build
# In project directorycd /home/user/projects/flightbooking
# Execute MTA buildmbt build
# Result: mta_archives/flightbooking_1.0.0.mtarThe build process:
┌─────────────────────────────────────────────────────────┐│ MTA Build │├─────────────────────────────────────────────────────────┤│ ││ 1. npm ci ││ └── Install dependencies ││ ││ 2. npx ui5 build ││ └── Compile UI5 app ││ └── Minify ││ └── Create dist/ directory ││ ││ 3. mbt build ││ └── Combine modules ││ └── Create .mtar archive ││ ││ Output: mta_archives/flightbooking_1.0.0.mtar ││ │└─────────────────────────────────────────────────────────┘Step 4: Deploy to Cloud Foundry
# Deploy MTARcf deploy mta_archives/flightbooking_1.0.0.mtar
# Alternatively with progress indicatorcf deploy mta_archives/flightbooking_1.0.0.mtar --version-rule ALLDeployment output:
Deploying multi-target app archive flightbooking_1.0.0.mtar...
Uploading 1 of 1 doneProcessing service "flightbooking-html5-repo-host"...Processing service "flightbooking-destination-service"...Processing service "flightbooking-uaa"...Uploading content module "flightbooking-deployer"...Deploying content module "flightbooking-destination-content"...
Process finished successfully.Step 5: Verify Deployment
# Check servicescf services
# Output:# NAME SERVICE PLAN# flightbooking-html5-repo-host html5-apps-repo app-host# flightbooking-destination-service destination lite# flightbooking-uaa xsuaa application
# List HTML5 appscf html5-list
# Output:# name version app-host-id# com.mycompany.flightbooking 1.0.0 abc123-def4564. Launchpad Integration
After deployment, the app must be integrated into SAP Build Work Zone Launchpad.
Open Site Manager
1. BTP Cockpit → Instances and Subscriptions2. SAP Build Work Zone, standard edition → Go to Application3. Channel Manager → Content Provider "HTML5 Apps" → RefreshContent Explorer
1. Content Manager → Content Explorer2. HTML5 Apps → Find your app3. Click "Add to My Content"Define Role
1. Content Manager → Create → Role2. Name: "FlightBookingUser"3. Description: "Access to Flight Booking App"4. Assign apps: ☑ Manage Flight Bookings (your app)5. SaveCreate Group
1. Content Manager → Create → Group2. Title: "Flight Booking"3. Assign apps: ☑ Manage Flight Bookings4. SaveCreate or Extend Site
1. Site Directory → Create Site (or open existing)2. Site Settings → Content Assignment3. Assign role "FlightBookingUser"4. SaveAssign Users
In BTP Cockpit:
1. Security → Role Collections2. Edit "FlightBookingUser_RC" (automatically created)3. Users → Add User4. Enter email or user ID5. Save5. Troubleshooting
Common Deployment Problems
| Problem | Cause | Solution |
|---|---|---|
| ”Service not found” | HTML5 Repo service unavailable | Check entitlement in subaccount |
| ”Destination not found” | Destination name wrong in xs-app.json | Check name in destination config |
| ”CSRF token validation failed” | csrfProtection enabled | Set to false in xs-app.json |
| ”Unauthorized” | Missing permission | Check UAA service key and roles |
| ”Cannot read property…“ | manifest.json syntax error | Use JSON validator |
Build Errors
# Error: Module not found# Solution: Update dependenciesnpm cinpm update
# Error: UI5 build failed# Solution: Update UI5 toolingnpm install -g @ui5/cli
# Clear cacherm -rf node_modulesnpm ciOData Connection Problems
Problem: "Failed to load metadata"
Check:1. Destination reachable? → BTP Cockpit → Connectivity → Destinations → "Check Connection"
2. Service Binding active? → ADT → Open Service Binding → "Publish" pressed?
3. CORS configured? → Destination: sap-client property set?
4. User authorized? → IAM Business Catalog assigned to user?Launchpad Problems
Problem: App doesn't appear in launchpad
Check:1. Content Explorer → App visible? → If not: Channel Manager → Refresh
2. Role assigned? → Content Manager → Role → App included?
3. Role Collection created? → Security → Role Collections → _RC exists?
4. User in Role Collection? → Role Collection open → Users tabActivate Debug Mode
For detailed error messages:
URL parameter: ?sap-ui-debug=true
Example:https://mysite.launchpad.cfapps.eu10.hana.ondemand.com/site#Shell-home?sap-ui-debug=trueAnalyze Logs
# App Router logs (if managed approuter)cf logs flightbooking-approuter --recent
# HTML5 Deployer logscf logs flightbooking-deployer --recent
# Service instance logscf service flightbooking-html5-repo-hostBest Practices
| Area | Recommendation |
|---|---|
| Versioning | Increment version in mta.yaml with each deployment |
| Naming Conventions | Consistent namespace structure (com.company.app) |
| Destination | HTML5.DynamicDestination: true for flexibility |
| Testing | Local testing with mock data before deployment |
| CI/CD | Automate MTA build in pipeline |
| Caching | Enable cache busting through version |
| Monitoring | Use Application Logging in BTP Cockpit |
Automated Deployment with CI/CD
For automated deployments in a pipeline:
# GitHub Actions examplename: Deploy Fiori App
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20'
- name: Install MTA Build Tool run: npm install -g mbt
- name: Install CF CLI run: | wget -q -O cf-cli.deb "https://packages.cloudfoundry.org/stable?release=debian64" sudo dpkg -i cf-cli.deb cf install-plugin multiapps -f
- name: Build MTA run: | npm ci mbt build
- name: Deploy to Cloud Foundry env: CF_API: ${{ secrets.CF_API }} CF_USER: ${{ secrets.CF_USER }} CF_PASSWORD: ${{ secrets.CF_PASSWORD }} CF_ORG: ${{ secrets.CF_ORG }} CF_SPACE: ${{ secrets.CF_SPACE }} run: | cf login -a $CF_API -u $CF_USER -p $CF_PASSWORD -o $CF_ORG -s $CF_SPACE cf deploy mta_archives/*.mtar -fConclusion
Deploying a Fiori Elements app to SAP BTP requires several configuration steps, but they are well supported by the Fiori generator. The key is understanding the individual components:
- manifest.json defines app metadata and OData connection
- xs-app.json configures routing via App Router
- mta.yaml orchestrates all services and modules
- Launchpad integration makes the app accessible to end users
With this knowledge, you can reliably deploy Fiori Elements apps to BTP and provide them in the Launchpad.
Related Articles
- Business Application Studio - Set up and use BAS
- SAP Build Work Zone Integration - Launchpad configuration in detail
- RAP Code Generation - Generate backend and frontend
- CI/CD for ABAP Cloud - Automated deployments