Start / Cheat Sheets

Cheat Sheet

Forge mit UI Kit: App bauen — Cheat Sheet

Stand: · Atlassian Forge mit UI Kit

Atlassian ForgeUI KitJiraReact

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

ModulWo es erscheintTypischer Zweck
jira:issuePanelBereich im VorgangZusatzdaten zum Vorgang
jira:issueContextSeitenleiste des Vorgangskompakte Statusanzeige
jira:projectPageeigene Seite im ProjektÜbersichten und Listen
jira:globalPageeigene Seite in der NavigationVerwaltung, Auswertung
confluence:macroim Seiteninhalteingebettete Inhalte
confluence:contentBylineKopfzeile der SeiteHinweis, 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
PfadInhalt
manifest.ymlModule, Ressourcen, Funktionen, Berechtigungen
src/frontend/index.jsxKomponenten und Rendern der Oberfläche
src/resolvers/index.jsResolver, API-Zugriffe, Speicherzugriffe
package.jsonAbhä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

AufgabeKomponenten
AnordnungBox, Stack, Inline
TextHeading, Text, List, Code
StatusLozenge, Badge, Tag, SectionMessage
ListenDynamicTable, EmptyState, Pagination
AktionenButton, ButtonGroup, Link
OverlaysModal, 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

HookAnmerkung
useState, useReducerZustand wie gewohnt
useEffectfür Datenabrufe nach dem Rendern
useContext, useMemo, useCallbackunverändert nutzbar
useRefohne Bezug auf DOM-Knoten
useDebugValue, useDeferredValue, useIdunterstützt
useProductContext, useTranslationaus @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

FunktionWofür
invokeeigene Backend-Funktion aufrufen
requestJira, requestConfluenceProdukt-API im Nutzerkontext
view.getContextKontext der Ansicht lesen
view.close, view.submitModal schließen, Eingabe übergeben
showFlagkurze Rückmeldung anzeigen
routerNavigation 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

VorherJetzt
@forge/ui@forge/react
ForgeUI.renderForgeReconciler.render
useActionuseReducer aus react
TextField, ButtonSetTextfield, ButtonGroup
Table, ModalDialogDynamicTable, Modal
function im Modulresource 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

FunktionStand (09/2026)Bedeutung für ein Projekt
Dashboard-Moduleallgemein verfügbareinsetzbar, mit Zusagen
Frontend-ProtokolleFrühzuganghilfreich, aber nicht verlassen
rovo:skillFrühzugangnur 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 --upgrade dazu, 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 Lozenge und 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 window zugreift.
  • 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 →