RFCs are a way for Atlassian to share what we’re working on with our valued developer community.
An RFC builds shared understanding of a topic and describes a proposed technical solution. It is not an approval or a commitment to deliver. We use feedback to shape the proposal and find serious flaws early.
Please keep feedback constructive and on topic, and comment on the idea rather than the people. Thanks!
Project summary
Atlassian has been exploring how to extend UI Modifications (“UIM”) to work with Forge Custom Fields (“FCF”) in Jira and Jira Service Management (“JSM”). This would let apps adapt these fields to the context of a work item or a user’s input – for example, showing or hiding a field, changing its description, or updating its value when another field changes.
This RFC follows on from our earlier RFC 125: UI Modification for Forge Custom Fields which explored enabling UI Modifications to interoperate with Forge Custom Fields. As we expanded our plans to also add support for Forge Custom Fields using the object storage type, and interactions across two different apps, we realised a more complex approach would be necessary - requiring further feedback and validation with the community.
-
Publish: 30th October 2026
-
Discuss: 13th November 2026
-
Resolve: 18th November 2026
Problem
Our initial proposal RFC 125: UI Modification for Forge Custom Fields did not allow Forge apps providing a Forge Custom Field to intercept write requests from the UI Modifications layer before the request was written to the work item’s field data. This meant that a Forge app could not prevent or manipulate write requests that are deemed invalid; especially if the request came from an app that was implemented by a different app developer.
We discovered this would not be sufficient for apps that need to validate writes at runtime, such as permitting value updates only from a defined allowlist of apps, or verifying a value against a remote API.
The app providing the field needs a way to check and accept changes without having to reimplement the complete set of supported operations on the UI Modifications API.
Proposed solution
This solution supersedes the solution proposed in RFC 125: UI Modification for Forge Custom Fields .
Our initial solution is designed to support the object custom field type at first, with support expanded to other types in future.
An app can make its custom field (either a jira:customField or jira:customFieldType module) available to UIM through an explicit manifest flag. On a supported screen, a UIM app could read or change the field using the APIs available there. For value writes and option visibility changes, the field app would provide handlers to facilitate that request.
These handlers only apply to write operations to the field performed using UI Modifications. Writes through other channels, such as REST API updates or direct edits by users, do not trigger the handlers.
The optional edit.validation.expression expression and the optional schema property (for object fields) will be executed after the handler runs when the value is saved to the Jira work item (and invalid values will be rejected).
The following diagram outlines the intended sequence of operations:
Proposed screen support
Our initial release would support the following Jira and JSM screens:
-
Global Issue Create
-
Issue View
-
Issue Transition
-
JSM Request Create
Support for additional screens would be added in subsequent milestones.
The functionality will work for custom fields implemented using UI Kit and Custom UI.
Developer experience for apps providing custom fields
1. Opt in through the manifest
The field app would declare type: object and set isUIModificationsEnabled: true.
## Illustrative example
modules:
jira:customField:
- key: sample-object-field
name: Sample Object Field
type: object
isUIModificationsEnabled: true
schema:
properties:
example:
type: string
formatter:
expression: "`${value.example}`"
view:
resource: main
edit:
resource: main
2. Subscribe to field-data updates
To receive field data updates made through UIM, the field app must use a React provider or a non-React subscription.
React provider pattern: FieldDataProvider / useFieldData
This pattern is a good fit when the field UI is built with React and multiple components need current field data.
// Illustrative example
import { FieldDataProvider, useFieldData } from '@forge/hooks/jira';
import { Text } from "@forge/react";
type FieldSchema = {
example: string;
};
const App = () => (
<FieldDataProvider>
<CustomFieldView />
</FieldDataProvider>
);
const CustomFieldView = () => {
const { ready, fieldValue } = useFieldData<FieldSchema | null>();
return <Text>{ready ? fieldValue?.example ?? 'Not set' : 'Loading…'}</Text>;
};
Non-React pattern: subscribeToFieldData
This pattern is useful for non-React implementations or when a lightweight subscription model is preferred.
// Illustrative example
const subscription = await customFieldApi.subscribeToFieldData(({ fieldValue }) => {
render(fieldValue);
});
// Unsubscribe when no longer needed.
subscription.unsubscribe();
3. Register handlers with registerUIMHandlers
The custom field app uses registerUIMHandlers to expose logic for the UIM operations that require a custom implementation.
A UIM Handler is required for the setValue operation. A handler may be optionally registered for the setOptionsVisibility operation, if the field supports get/set options behaviour. All other operations in the Common Field API are implemented by the Forge platform and do not need to be supplied with handlers.
// Illustrative example
registerUIMHandlers({
setValue: async (proposedValue, context) => {
// the App ID of the UI Modification, and the renderContext (the view where the operation is taking place)
const {appId, renderContext} = context;
if (proposedValue === null) return { accepted: true, value: null };
if (!isValid(proposedValue)) return { accepted: false, code: 'INVALID_VALUE' };
return { accepted: true, value: proposedValue };
},
setOptionsVisibility: async (proposedVisibility, context) => {
return { accepted: true, value: proposedVisibility };
},
});
The handler receives the intended value to be set by a UIM operation in the proposedValue parameter, along with the App ID of the UI Modification and the render context in the context parameter.
The handler returns a response object indicating if the operation was accepted. If the operation was accepted, the accepted value is returned. If the operation was not accepted, an error code is returned.
Errors are trapped by the UIM app’s onError callback.
The handler could choose to:
-
Accept the provided value
-
Modify the value or enrich it with additional data before accepting it
-
Block the operation by returning an error code
4. Update how the field reads its value
Once your app is UIM-compatible, you must use one of the value subscription methods defined in Step 2 to read the field value.
Do not use view.getContext() from the Forge Bridge to read the value, as the addition of the UIM API stops the field from being remounted.
You can still use view.getContext() for details that stay the same while the field is open, such as extension.fieldId, extension.fieldType, and extension.renderContext.
Developer experience for apps providing UI Modifications
App developers writing UI Modifications would continue to use the existing UI Modifications API as-is.
Forge Custom Fields with the isUIModificationsEnabled flag would appear in the set of supported fields returned from getFields().
User experience
For end users, the goal is for an opted-in field to update when the UIM app changes it, without an app reload. For example, a field could be shown or hidden, or its value could change based on other information on the screen. The result depends on the screen and the UIM APIs available.
Asks
We welcome any reactions, including agreement or interest in the proposal. We’re especially interested in:
-
For app developers who build custom fields:
-
What use cases do you have that require this approach vs. just simply accepting the values as originally proposed in RFC-125?
-
Does this approach give you sufficient control over how other apps may interact with and manipulate your field’s data?
-
What additional context would you need beyond the calling App ID and render context?
-
-
For app developers who build UI Modifications: How would your app discover the value shape and option identifiers for a third-party object field? Would integration specific to each field app be workable?
-
What’s missing? Are there any particular use cases, known requirements or edge cases that are not covered by this proposal?
