Rate this page:
This tutorial describes how to make API calls to an external API from your Forge app and display the result on a Confluence Cloud page. You’ll use the GIPHY API to display GIFs on the Confluence page. The result will look like this:
To complete this tutorial, you need the following:
npm install -g @forge/cli@latest
on the command line.npm install @forge/ui@latest --save
on the command line.npm install @forge/api@latest
on the command line.We recommend that you complete all the steps in Getting started so that you’re familiar with the Forge development process.
Before we dive into the code, let's review how this app works.
The flow diagram shows the app’s 3 main parts.
These parts work together as follows:
Create an app based on the Hello world TypeScript template.
Navigate to the directory where you want to create the app.
Create your app by running:
1 2forge create
Enter a name for the app. For example, giphy-app.
Select the UI Kit category from the list.
Select the confluence-macro-typescript template from the list.
Open the app directory to see the app files.
This app uses a Confluence macro
module. Macros enable you to add functionality or include dynamic
content in a Confluence page.
manifest.yml
file.key
under macro
to giphy.title
under macro
to GIPHY.description
under macro
to View random GIPHY gifs![]
, an empty array.Your manifest file should look like this:
1 2permissions: scopes: [] modules: macro: - key: giphy function: main title: GIPHY description: View random GIPHY gifs! function: - key: main handler: index.run app: id: '<your-app-id>'
See Manifest to learn more about the manifest file.
Add UI kit components that render when the app is called. You’ll use a sample response from the GIPHY API to make a static app (steps 1 and 3 from the flow diagram above).
Open the src/index.tsx
file.
Replace the contents of the file with:
1 2// Import required components from the UI kit import ForgeUI, { render, Text, Fragment, Image } from '@forge/ui'; // ImageCardProps interface which will be used by ImageCard component interface ImageCardProps { title: string; src: string; } // ImageCard component containing text and image const ImageCard = ({title, src}: ImageCardProps) => ( <Fragment> <Text>{title}</Text> <Image src={src} alt={title}/> </Fragment> ); // App function will return the final output const App = () => { const {title, url} = { title: "awesome avalanche GIF", url: "https://media3.giphy.com/media/26vUJR5VABcUJaCTm/200.gif?cid=74f3ab6481fcd606c80e02418b301c17130050edc03b7521&rid=200.gif" }; return ( <Fragment> <Text>Random GIF!</Text> <ImageCard src={url} title={title}/> </Fragment> ); }; // Exporting the above App function by exporting via 'run' export const run = render(<App/>);
In this code:
Fragment
, Image
to display the GIF.
See UI kit components to learn more about these components.ImageCardProps
interface contains
title
and src
, which are used by the component ImageCard
. title
comes from the GIPHY API
response. src
is the URL and fixed height of the GIF.ImageCard
consists of a Fragment
, which contains a Text
component and an Image
component.App
function is where the GIPHY API call is linked to the components of the user interface.
This function returns a Fragment
that contains a Text
component and an ImageCard
component.
The code has values for a GIF. Later in this tutorial, you’ll update this to make a call to get
a random GIF. The sample response from GIPHY for obtaining a GIF by ID has the information you’ll use for title
and src
in ImageCard
.run
constant provides the mechanism that renders your app whenever the App
function returns.Build, deploy, and install the app to see it in your Confluence site.
In the app's top-level directory, deploy your app by running:
1 2forge deploy
Install your app by running:
1 2forge install
your-domain.atlassian.net
).Edit a Confluence page and insert the app using the quick insert menu (activated by pressing /), as shown below.
Next, we'll turn the static app into a dynamic app by replacing the hardcoded response with an API call (step 2 from the flow diagram above).
To allow our app to access external resources, we need to update the manifest to allow API calls to the GIPHY API. Add the GIPHY API domain (api.giphy.com
) to the list of approved domains under permissions.external.fetch.backend
.
Your manifest.yml
permissions should look like this:
1 2permissions: scopes: [] external: fetch: backend: - 'api.giphy.com'
See Permissions - External Permissions to learn more about external permissions.
You’ll speed up your development process by starting a tunnel, which uses the local code where your app is installed. You need to set the GIPHY API key as a local variable so your code can access it when making calls to the GIPHY API.
Start a tunnel with access to your GIPHY API key by running:
1 2FORGE_USER_VAR_GIPHY_API_KEY=<your-giphy-api-key> forge tunnel
Open the src/index.tsx
file.
Add the following code directly after the import
statement to call the GIPHY API:
1 2import api from "@forge/api"; // GIPHY API base URL const GIPHY_API_BASE = 'https://api.giphy.com/v1/gifs/'; // GiphyJson interface to be used by our getRandomGif function interface GiphyJson { title: string; url: string; } // getRandomGif function makes the GIPHY API call to get a random GIF and filter out title and url const getRandomGif = async (): Promise<GiphyJson> => { console.log("Making GIPHY API call...") const response = await api.fetch( `${GIPHY_API_BASE}random?api_key=${process.env.GIPHY_API_KEY}&rating=g`, ); const { data: { title, images: { fixed_height: { url }, }, }, } = await response.json(); return { title, url, }; };
In this code:
GIPHY_API_BASE
is a constant containing the URL to call the GIPHY API.GiphyJson
interface has title
and url
properties for the ImageCard
.getRandomGif
is an asynchronous function that makes the API call and returns the result in
the format of GiphyJson
.fetch
from the Runtime API makes a call to GIPHY’s random endpoint
and stores the response. This function uses the GIPHY API key from your environment variables
with process.env.GIPHY_API_KEY
.Add the UI kit hook useAction
to the import statement from @forge/ui
.
Replace const { title, url }
and its value in the App
function with the following to update
the state:
1 2const [{ title, url }, setRandomGif] = useAction(getRandomGif, getRandomGif);
The first parameter of useAction
defines how to update the state, and the second parameter is the initial value.
useAction
returns the current value, and a function you can call to update the value.
Your index.tsx
file should look like this:
1 2// Importing required components from the UI kit import ForgeUI, { render, Text, Fragment, Image, useAction } from '@forge/ui'; // Importing the api object import api from "@forge/api"; // GIPHY API base URL const GIPHY_API_BASE = 'https://api.giphy.com/v1/gifs/'; // GiphyJson interface to be used by our getRandomGif function interface GiphyJson { title: string; url: string; } // getRandomGif function makes the GIPHY API call to get a random GIF and filter out title and url const getRandomGif = async (): Promise<GiphyJson> => { console.log("Making GIPHY API call...") const response = await api.fetch( `${GIPHY_API_BASE}random?api_key=${process.env.GIPHY_API_KEY}&rating=g`, ); const { data: { title, images: { fixed_height: { url }, }, }, } = await response.json(); return { title, url, }; }; // ImageCardProps interface which will be used by ImageCard component interface ImageCardProps { title: string; src: string; } // ImageCard component containing text and image const ImageCard = ({title, src}: ImageCardProps) => ( <Fragment> <Text>{title}</Text> <Image src={src} alt={title}/> </Fragment> ); // App function will return the final output const App = () => { const [{ title, url }, setRandomGif] = useAction(getRandomGif, getRandomGif); return ( <Fragment> <Text>Random GIF!</Text> <ImageCard src={url} title={title}/> </Fragment> ); }; // Exporting the above App function by exporting via 'run' export const run = render(<App/>);
When you refresh the page in Confluence, a random GIF is displayed.
Instead of refreshing the page, add a button to load a new GIF. This will use the Button
component
from the UI kit.
Open the src/index.tsx
file.
Add Button
to the UI kit import statement.
Add the button by replacing the return statement in the App
function with:
1 2return ( <Fragment> <Text>Random GIF!</Text> <ImageCard src={url} title={title} /> <Button text="🔀 Shuffle!" onClick={() => { setRandomGif(); }} /> </Fragment> );
Your index.tsx
file should look like this:
1 2// Importing required components from the UI kit import ForgeUI, { render, Text, Fragment, Image, useAction, Button } from '@forge/ui'; // Importing the api object import api from "@forge/api"; // GIPHY API base URL const GIPHY_API_BASE = 'https://api.giphy.com/v1/gifs/'; // GiphyJson interface to be used by our getRandomGif function interface GiphyJson { title: string; url: string; } // getRandomGif function makes the GIPHY API call to get a random GIF and filter out title and url const getRandomGif = async (): Promise<GiphyJson> => { console.log("Making GIPHY API call...") const response = await api.fetch( `${GIPHY_API_BASE}random?api_key=${process.env.GIPHY_API_KEY}&rating=g`, ); const { data: { title, images: { fixed_height: { url }, }, }, } = await response.json(); return { title, url, }; }; // ImageCardProps interface which will be used by ImageCard component interface ImageCardProps { title: string; src: string; } // ImageCard component containing text and image const ImageCard = ({title, src}: ImageCardProps) => ( <Fragment> <Text>{title}</Text> <Image src={src} alt={title}/> </Fragment> ); // App function will return the final output const App = () => { const [{ title, url }, setRandomGif] = useAction(getRandomGif, getRandomGif); return ( <Fragment> <Text>Random GIF!</Text> <ImageCard src={url} title={title} /> <Button text="🔀 Shuffle!" onClick={() => { setRandomGif(); }} /> </Fragment> ); }; // Exporting the above App function by exporting via 'run' export const run = render(<App/>);
Now you can use the button to display a new GIF.
Now that the code is working, set your app environment variable and deploy the app so it keeps working after you close the tunnel.
Store the GIPHY API key in your app environment variables by running:
1 2forge variables set GIPHY_API_KEY <your-giphy-api-key>
Deploy the app by running:
1 2forge deploy
That’s it. You now have an app that fetches data from an external API and renders the result in the Confluence editor.
Continue to one of the other tutorials or look through the reference pages to learn more.
Rate this page: