Der Spickzettel für die Bauphase einer Forge-App mit UI Kit: Wo die App erscheint, wie das Manifest aussieht, welche Komponenten und Hooks es gibt und wie Frontend und Backend zusammenkommen. Das zweite Blatt, Daten, Sicherheit, Betrieb, führt weiter — Speicher, Scopes, Tests und Rollout.
Forge ändert sich schnell. Für Manifest-Schlüssel, Komponentennamen und den Status einzelner Funktionen bleibt die Atlassian-Doku maßgeblich; dieses Blatt trifft die Auswahl, nicht die Vollständigkeit.
Erweiterungspunkte: wo die App erscheint
| Modul | Wo es erscheint | Typischer Zweck |
|---|---|---|
jira:issuePanel | Bereich im Vorgang | Zusatzdaten zum Vorgang |
jira:issueContext | Seitenleiste des Vorgangs | kompakte Statusanzeige |
jira:projectPage | eigene Seite im Projekt | Übersichten und Listen |
jira:globalPage | eigene Seite in der Navigation | Verwaltung, Auswertung |
confluence:macro | im Seiteninhalt | eingebettete Inhalte |
confluence:contentByline | Kopfzeile der Seite | Hinweis, kleiner Status |
Die Wahl entscheidet über den Kontext: Ein Panel kennt den Vorgang, eine globale Seite kennt ihn nicht. Nachträglich zu tauschen heißt, den Kontext zu verlieren.
Modul: Plattform und Architekturentscheidungen
manifest.yml und Projektaufbau
modules:
jira:issuePanel:
- key: klarpfad-panel
resource: main
render: native # kennzeichnet UI Kit
resolver:
function: resolver
resources:
- key: main
path: src/frontend/index.jsx
app:
runtime:
name: nodejs24.x # ohne runtime bricht das Deployment ab
memoryMB: 512
permissions:
scopes:
- read:jira-work
| Pfad | Inhalt |
|---|---|
manifest.yml | Module, Ressourcen, Funktionen, Berechtigungen |
src/frontend/index.jsx | Komponenten und Rendern der Oberfläche |
src/resolvers/index.js | Resolver, API-Zugriffe, Speicherzugriffe |
package.json | Abhängigkeiten, darunter @forge/react |
Grenzen: Das Manifest darf höchstens 200 KB groß sein. Eine CLI-Version wird sechs Monate ab Erscheinen unterstützt, Laufzeiten werden abgekündigt — die Versionsstände gehören auf die Tagesordnung, nicht ins Archiv.
Modul: Entwicklungsumgebung und App-Lebenszyklus
Komponenten nach Aufgabe
| Aufgabe | Komponenten |
|---|---|
| Anordnung | Box, Stack, Inline |
| Text | Heading, Text, List, Code |
| Status | Lozenge, Badge, Tag, SectionMessage |
| Listen | DynamicTable, EmptyState, Pagination |
| Aktionen | Button, ButtonGroup, Link |
| Overlays | Modal, Popup, Tooltip |
Abstände kommen über space-Token, nicht über leere Textzeilen. Einzelne
Komponenten sind als Vorschau oder Frühzugang gekennzeichnet — Status vor dem
Einsatz prüfen.
import React from 'react';
import ForgeReconciler, { Stack, Inline, Heading, Lozenge, Text }
from '@forge/react';
const App = () => (
<Stack space="space.100">
<Inline space="space.100" alignBlock="center">
<Heading as="h3">Messreihe freigeben</Heading>
<Lozenge appearance="inprogress">offen</Lozenge>
</Inline>
<Text>Zuständig: Team Kalibrierung</Text>
</Stack>
);
ForgeReconciler.render(
<React.StrictMode><App /></React.StrictMode>
);
Komponenten kommen aus @forge/react, die Hooks weiterhin aus react.
Modul: Oberflächen mit UI Kit gestalten
Drei Zustände vor dem Inhalt
if (laden) return <Spinner label="Lade Daten" />;
if (fehler) return (
<SectionMessage appearance="error">
<Text>Die Liste ist gerade nicht verfügbar.</Text>
</SectionMessage>
);
if (eintraege.length === 0) return (
<EmptyState header="Noch nichts erfasst" />
);
Laden, Fehler und Leerstand sind drei verschiedene Fälle mit drei verschiedenen Meldungen. Im Tunnel sind die Daten sofort da, deshalb fällt ein fehlender Ladezustand dort nie auf.
Barrierefreiheit ist hier billiger als sonst: Rollen, Beschriftungen, Kontraste und Tastaturbedienung bringen die Komponenten mit — eigene Konstruktionen verlieren sie wieder.
Modul: Oberflächen mit UI Kit gestalten
Formulare
const { register, handleSubmit, formState } = useForm();
<Form onSubmit={handleSubmit(speichern)}>
<Label labelFor="titel">Titel</Label>
<Textfield {...register('titel', { required: true })} />
{formState.errors['titel'] && (
<ErrorMessage>Titel fehlt</ErrorMessage>
)}
<Button type="submit">Sichern</Button>
</Form>
Die Prüfung im Formular ist Komfort. Verbindlich wird sie erst im Resolver — siehe das zweite Blatt. Die Schaltfläche während des Absendens sperren, sonst legt ein Doppelklick zwei Einträge an.
Modul: Oberflächen mit UI Kit gestalten
Hooks in UI Kit
| Hook | Anmerkung |
|---|---|
useState, useReducer | Zustand wie gewohnt |
useEffect | für Datenabrufe nach dem Rendern |
useContext, useMemo, useCallback | unverändert nutzbar |
useRef | ohne Bezug auf DOM-Knoten |
useDebugValue, useDeferredValue, useId | unterstützt |
useProductContext, useTranslation | aus @forge/react |
Hooks, die auf das DOM zugreifen, funktionieren nicht — auch dann nicht, wenn der Zugriff in einer Unterabhängigkeit steckt.
const kontext = useProductContext();
if (!kontext) return <Spinner label="Lade Kontext" />;
const vorgangId = kontext.extension.issue.id;
Der Kontext ist beim ersten Rendern undefined. Dieselbe Angabe liefert
view.getContext aus @forge/bridge als Promise.
useEffect(() => {
let aktuell = true;
invoke('getEntscheidungen', { vorgangId })
.then((d) => aktuell && setEintraege(d))
.catch(() => aktuell && setFehler(true))
.finally(() => aktuell && setLaden(false));
return () => { aktuell = false; };
}, [vorgangId]);
Die Aufräumfunktion verhindert, dass eine späte Antwort einen alten Zustand setzt. Jeder Aufruf geht über die Plattform, zählt gegen Grenzen und erzeugt Kosten — doppelte Abrufe fallen im Tunnel nicht auf, im Betrieb schon.
Modul: React-Erfahrung auf UI Kit übertragen
Bridge und Resolver
| Funktion | Wofür |
|---|---|
invoke | eigene Backend-Funktion aufrufen |
requestJira, requestConfluence | Produkt-API im Nutzerkontext |
view.getContext | Kontext der Ansicht lesen |
view.close, view.submit | Modal schließen, Eingabe übergeben |
showFlag | kurze Rückmeldung anzeigen |
router | Navigation im Produkt auslösen |
Die Bridge kennt kein asApp. App-Rechte gibt es nur im Resolver.
// src/resolvers/index.js
import Resolver from '@forge/resolver';
const resolver = new Resolver();
resolver.define('getEntscheidungen', async (req) => {
const { vorgangId } = req.payload;
return ladeEintraege(vorgangId);
});
export const handler = resolver.getDefinitions();
// Frontend
import { requestJira } from '@forge/bridge';
const antwort = await requestJira(
`/rest/api/3/issue/${vorgangId}?fields=summary`
);
const vorgang = await antwort.json(); // Statuscode vorher prüfen
In den Resolver gehört jeder Zugriff auf Speicher und externe Dienste, alles mit App-Rechten, jede verbindliche Fachregel und alles, was Geheimnisse berührt oder Kosten auslöst.
Modul: Frontend und Backend verbinden
Mehrsprachigkeit
translations:
resources:
- key: de-DE
path: locales/de-DE.json
- key: en-US
path: locales/en-US.json
fallback:
default: de-DE
In der Komponente: const { ready, t } = useTranslation();, danach
t('klarpfad.titel'). Ohne abgewartetes ready zeigt die Oberfläche kurz die
Schlüssel. Die Standardsprache muss in resources stehen, sonst scheitert die
Auflösung — und auch Texte aus dem Manifest, etwa der Modultitel, wollen
übersetzt werden.
Modul: React-Erfahrung auf UI Kit übertragen
Was UI Kit nicht kann
// nicht möglich: HTML und DOM
<div className="liste">Offen</div>
document.querySelector('#eintrag')
Es gibt keine eigenen CSS-Klassen, keine Messung am gerenderten Element, keine Animationen oder Fokus-Tricks über das DOM, und DOM-basierte Testwerkzeuge greifen an der Oberfläche nicht. Komponentenbibliotheken, die HTML erzeugen, lassen sich nicht einbinden.
Ein Beispiel aus dem Netz, das trotzdem funktioniert, stammt meist aus einer Custom-UI-App — das ist ein anderes Modell, kein Gegenbeweis.
Modul: Plattform und Architekturentscheidungen
Von UI Kit 1 auf heute
| Vorher | Jetzt |
|---|---|
@forge/ui | @forge/react |
ForgeUI.render | ForgeReconciler.render |
useAction | useReducer aus react |
TextField, ButtonSet | Textfield, ButtonGroup |
Table, ModalDialog | DynamicTable, Modal |
function im Modul | resource plus resolver |
API über @forge/api im Frontend | @forge/bridge, App-Rechte nur im Resolver |
Rahmenkomponenten wie IssuePanel oder AdminPage sind ersatzlos
entfallen. Vier Merkmale verraten ein altes Beispiel auf einen Blick: das
Paket, der Einstiegspunkt, useAction und die Rahmenkomponente.
Solcher Code taucht weiter auf, weil ältere Artikel gut auffindbar sind und Sprachmodelle die häufigere, also ältere Fassung wiedergeben. Er wirkt plausibel und scheitert erst beim Ausrollen.
Modul: Bestehende Apps und besondere UI-Anforderungen
Vorschau und Frühzugang einordnen
| Funktion | Stand (09/2026) | Bedeutung für ein Projekt |
|---|---|---|
| Dashboard-Module | allgemein verfügbar | einsetzbar, mit Zusagen |
| Frontend-Protokolle | Frühzugang | hilfreich, aber nicht verlassen |
rovo:skill | Frühzugang | nur Umgebung development |
Der Stand gehört vor jedem Release neu nachgeschlagen — im Änderungsprotokoll der Plattform, nicht im Blogartikel. Trägt eine Frühzugangsfunktion eine Kernfunktion der App, fehlt ein Weg ohne sie.
Modul: Bestehende Apps und besondere UI-Anforderungen
Typische Fallen
- Die Änderung wirkt nur im Tunnel und fehlt nach dem Schließen.
- Ausgerollt, aber nicht neu installiert — nach einer Manifest-Änderung
gehört
forge install --upgradedazu, sonst läuft die alte Fassung weiter. - Der Kontext wird ohne Prüfung gelesen und bricht beim ersten Rendern.
- Die Abhängigkeitsliste enthält ein Objekt, das bei jedem Rendern neu entsteht — der Effekt läuft endlos.
- Der Modulschlüssel wird geändert, ohne die Ressource nachzuziehen.
- Ein Label fehlt, das Feld ist nur optisch zugeordnet.
- Der Status steckt nur in der Farbe des
Lozengeund fehlt im Text. - Fachlogik wandert ins Frontend, weil sie dort schneller sichtbar ist.
- Ein Paket lädt im Tunnel und scheitert erst in der Instanz, weil eine
Unterabhängigkeit auf
windowzugreift. - Ein halb übernommenes Beispiel mischt UI Kit 1 und die aktuelle Fassung.
Dieses Thema als Schulung für Ihr Team
Dieser Beitrag erklärt das Thema. Damit Ihr Team es danach auch anwendet, gibt es Atlassian Forge mit UI Kit als Schulung — an Ihrem eigenen Code, mit den Fragen, die ein Text nicht beantwortet. Sie wählen die Module, wir bauen daraus ein Programm.
5 Tage·ab 900 EUR netto pro Tag (bis 3 Teilnehmende) ·Termin nach Vereinbarung
Als Team-Schulung anfragenZum Seminar Atlassian Forge mit UI Kit →