Hello - could you please explain or refer me to docs on how to create and register a custom content in my Forge App and how to register it to be rendered under SpaceCustomContentListView? Thanks a lot!
Hi @AsmaaHadir, thanks for reaching out.
Please refer to this page, which explains how to register custom content with Forge. Let us know if you have follow-up questions.
Hi @OleksandrBeztsinnyi - thank you for your reply. I had actually referred to the same page to understand how to create my custom content for my app but I still have a couple of questions. For instance, I have written the following code based on confluence’s REST API’s to test the creation a custom content ‘keyword’ but I keep getting errors regarding the values of the bodyData keys indicating that spaceId for instance is of type Long:
import api, { route } from "@forge/api";
const customContent = async () => {
const {spaceKey, localId, environmentType} = useProductContext();
const type = `forge:${localId}:${environmentType}:keyword`;
var bodyData = `{
"type": "<string>",
"status": "current",
"spaceId": "<string>",
"pageId": "<string>",
"blogPostId": "<string>",
"customContentId": "<string>",
"title": "<string>",
"body": {
"representation": "storage",
"value": "<string>"
}
}`;
const response = await api.asUser().requestConfluence(route`/wiki/api/v2/custom-content`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: bodyData
});
Also, How do I practically register/save the custom content that I have Posted? or the API call all what I need to perform? for context, my manifest.yml looks like this:
modules:
confluence:spacePage:
- key: keywise-test-space-page-hello-world
function: main
title: KeyWise-test for Asmaa
route: hello-world
function:
- key: main
handler: index.run
app:
id: ari:cloud:ecosystem::app/134c6c41-0af6-4788-adc3-bd01fd2fc3ec
permissions:
scopes:
- read:space:confluence
- read:confluence-content.summary
- read:content-details:confluence
- read:page:confluence
- write:custom-content:confluence
Thanks a lot in advance ![]()
Hey @AsmaaHadir ,
thanks for more details.
Do you register keyword custom content under the space container? (I don’t see this from your manifest example)
What do you put as a spaceId in bodyData?
Also, How do I practically register/save the custom content that I have Posted? or the API call all what I need to perform? for context
That’s right. The only way to create custom content is with REST API. Once a custom content module is registered, custom content can be created from any other registered module.
Hi @OleksandrBeztsinnyi - What do I need to modify about my manifest.yml to register the keyword custom content?
I have created a helper function to retrieve the current space ID as the following:
export const getSpaceIdByKey = async (spaceKey) => {
const response = await api.asUser().requestConfluence(route`/wiki/api/v2/spaces?${spaceKey}`, {
headers: {
'Accept': 'application/json'
}
});
const data_response = await response.json();
// Iterate through the results to find the space with the matching key
for (const space of data_response.results) {
if (space.key === spaceKey) {
return space.id; // Return the ID of the matching space
}
}
// If no matching space is found, you can return null or handle the error accordingly
console.log("space key not found")
return null;
}
and I insert the number that I retrieve from it into the spaceId field. Also, How do I add custom fields so that I can render them in the SpaceCutomContentViewList ? Thank you so much for the help.
Hey @AsmaaHadir,
you must register a module for custom content in your manifest. Something like
modules:
confluence:customContent:
- key: keyword
title: Keywords
description: Custom content for keywords
bodyType: raw
supportedContainerTypes:
- space
function: keywordView
confluence:spacePage:
....
having this module gives you the ability to use Custom Content REST API.
The way you get spaceId should work.
How do I add custom fields so that I can render them in the
SpaceCutomContentViewList?
SpaceCustomContentListView is a simple predefined component. It displays only icon, title, contributors, and last modified date. If you want to display your own custom fields in the list the SpaceCustomContentListView component can’t be used. You should create your own component for this purpose.
Thank you so much @OleksandrBeztsinnyi for the simplified explanation.
Regarding this point:
Even though I can’t display additional properties under the SpaceCustomContentListView UI, I can still add my own fields to my keyword custom content type in its bodyData and use custom UI to display them, right? Otherwise if I choose to use SpaceCustomContentListView the user would need to click on a custom content key to render the page with additional properties?
One more question: regarding the function field for my CustomContent module in manifest.yml, it is basically a function that I define which makes a REST API call and retrieves a custom content for me, or is it the main function in App() which displays the customContent in the UI? for example, based on the sample manifest.yml file that you have replied with, I could define a keywordView function which returns a keyword custom content with API calls and use it inside my App() main function?
Hey @OleksandrBeztsinnyi - sorry for the multiple questions but I got a bit confused reading the documentation. What does the extractAppId refer to when defining the type field for the custom content type below?
// extractAppId implementation omitted
const type = `forge:${extractAppId(localId)}:${environmentType}:note`;
I can still add my own fields to my
keywordcustom content type in itsbodyDataand use custom UI to display them, right?
Right.
Otherwise if I choose to use
SpaceCustomContentListViewthe user would need to click on a custom content key to render the page with additional properties?
Correct. SpaceCustomContentListView displays a list of custom content. However, actual custom content will be rendered when the user clicks on the title.
regarding the
functionfield for myCustomContentmodule
this function defines the UI that will be rendered for specific custom content (when the user clicks on the title of one of the list items of SpaceCustomContentListView). This function should fetch the body (or other params) of custom content before being displayed.
What does the
extractAppIdrefer to when defining thetypefield for the custom content type below?
As it was mentioned in the documentation, the type for registered Forge custom content will have this format
forge:[APP_ID]:[ENVIRONMENT_ID]:[MODULE_KEY]
For example:
forge:b44c55b2-251f-45e3-8ea4-b56762f82e8a:f7522737-117c-46e7-a7ca-03a73c99afcf:keyword
APP_ID: The identifier for your Forge app. To get the app ID, use the useProductContext hook. The app ID is a part of thelocalIdattribute.
To get APP_ID from localId you should parse it, that’s what extractAppId does.
Hope this helps
Thank you for the clear answers @OleksandrBeztsinnyi