User Guide

Panelforge lets Jira administrators add custom widgets ("Panels") to issue screens by writing plain HTML, CSS, and JavaScript — no separate app, no deploy pipeline.

Creating a panel

Open Jira Settings → Apps → Panelforge — Panel Builder. There are two kinds of panel:

Each panel has three code tabs (HTML / CSS / JS), a live preview (against sample data or a real issue key), a placement selector, and per-panel permissions (writable fields, embed domains). Panels sharing a placement stack by Order; two or more render as tabs.

Placements: Issue panel (inline on the issue view) · Modal (issue action menu) · Issue glance (sidebar).

The jira bridge API

Widget code runs in a locked-down sandbox. Its only connection to Jira is the jira object, available globally in your panel's JS:

jira.getField(fieldId) → Promise<value>

Read-only access to the current issue's fields, as the viewing user (people never see more through a panel than Jira already shows them). Field values arrive in Jira REST shapes: summary is a string, priority is { name }, assignee is { accountId, displayName }, labels is an array, rich-text fields are ADF documents. The pseudo-field 'key' returns the issue key (e.g. "PROJ-123").

jira.getField('priority').then(function (p) {
  console.log(p && p.name); // "Highest"
});

jira.getUser() → Promise<{ accountId }>

The viewing user's account id.

jira.requestAction('updateField', { field, value }) → Promise

Requests a field write. The server allows it only if all of these hold:

  1. the field id is listed in this panel's Writable fields (admin-configured);
  2. the panel actually targets this issue (personal panels: the caller is the assignee);
  3. the acting user's own Jira permissions allow the edit (writes run as the viewer).

Rejections return an error whose message explains why. Plain-string values written to rich-text fields are converted to Atlassian Document Format automatically.

jira.requestAction('updateField', { field: 'duedate', value: '2026-08-05' })
  .then(function () { /* saved */ })
  .catch(function (e) { console.log(e.message); });
Pattern — per-issue storage: point a panel at a (hidden) text custom field and persist widget state as JSON via requestAction. State survives reloads, syncs between viewers, and every change is recorded in the issue history.

jira.embed(url, { height }) → Promise

Asks the trusted shell to render an external page below your widget (external iframes cannot load inside the sandbox itself). The URL's hostname must exactly match one of the panel's Allowed embed domains — https only, no wildcards — and the domain must also be permitted by the installed app version (zero-egress installs block all embeds). Max 3 embeds per panel; repeating a URL updates its height (80–800px).

jira.onIssueChanged(callback)

Registers a callback fired whenever the issue changes (field edits, transitions, reassignment). Subsequent jira.getField() calls always answer from fresh data.

jira.onIssueChanged(function () { load(); });

Where your data lives

Panelforge has no database of its own — panels are the program, Jira is the database. Three kinds of data, three homes:

Your data Where it lives Protected by
Panel definitions
the code & rules admins write
Atlassian Forge storage, scoped to your site Revision history, trash, conflict checks, JSON export
Widget state
checklist ticks, saved values
Your own Jira custom fields, on the issue itself Jira's permissions, issue history (a free audit trail), your existing backups
Momentary state
a running timer, an unsaved slider
The viewer's browser tab only Nothing — deliberately ephemeral

Widgets save into Jira fields so that every change is permissioned, recorded in the issue history, and covered by the backups you already run. Export your panels and back up Jira, and you hold 100% of your data — there is nowhere else it could be.

Data safety

Export regularly — uninstalling the app permanently deletes all panels (Atlassian Forge removes app storage on uninstall).

Templates

Ready-to-paste panel templates are available: an escalation-style live banner, SLA countdown ring, cost estimator with guarded write-back, persistent compliance checklist, a domain-rules deadline calculator, and a personal "Mission Control" HUD. An in-app template gallery is on the roadmap — until then, contact support and we'll send you any of them.