{"id":19632757,"url":"https://github.com/finesoftware/atlassian-jamstack-app","last_synced_at":"2025-07-17T03:07:36.274Z","repository":{"id":50985116,"uuid":"370568308","full_name":"finesoftware/atlassian-jamstack-app","owner":"finesoftware","description":"A Jamstack-based sample app for Jira Cloud, based on next.js. Compatible with Atlassian Connect and Atlassian Forge.","archived":false,"fork":false,"pushed_at":"2022-04-01T01:48:47.000Z","size":2309,"stargazers_count":23,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-20T03:03:30.779Z","etag":null,"topics":["atlassian","confluence","connect","forge","jamstack","jira","nextjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/finesoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-25T04:54:53.000Z","updated_at":"2025-04-30T22:10:44.000Z","dependencies_parsed_at":"2022-09-06T14:50:29.770Z","dependency_job_id":null,"html_url":"https://github.com/finesoftware/atlassian-jamstack-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/finesoftware/atlassian-jamstack-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finesoftware%2Fatlassian-jamstack-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finesoftware%2Fatlassian-jamstack-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finesoftware%2Fatlassian-jamstack-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finesoftware%2Fatlassian-jamstack-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/finesoftware","download_url":"https://codeload.github.com/finesoftware/atlassian-jamstack-app/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finesoftware%2Fatlassian-jamstack-app/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265562205,"owners_count":23788481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["atlassian","confluence","connect","forge","jamstack","jira","nextjs"],"created_at":"2024-11-11T12:15:17.991Z","updated_at":"2025-07-17T03:07:36.259Z","avatar_url":"https://github.com/finesoftware.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![image](packages/hello-charlie/libraries/assets/src/assets/banner-small.png)](https://jxl.app)\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"packages/hello-charlie/libraries/assets/src/assets/logo.png\" width=192 /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eGood morning Charlie 🍓 🍞\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eA \u003ca href=\"https://jamstack.org\"\u003eJamstack\u003c/a\u003e-based sample app for Jira Cloud, based on \u003ca href=\"https://next.js\"\u003enext.js\u003c/a\u003e ⚛️\u003c/p\u003e\n\u003cp align=\"center\"\u003eCompatible with \u003ca href=\"https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/\"\u003eAtlassian Connect\u003c/a\u003e and \u003ca href=\"https://developer.atlassian.com/cloud/jira/platform/getting-started-with-forge/\"\u003eAtlassian Forge\u003c/a\u003e\u003c/p\u003e\n\n## Background\n\nJamstack apps achieve performance, scalability, and developer productivity through static frontends that come straight from the CDN and interact with distributed backends through Javascript.\n\nThe Atlassian ecosystem, which runs app experiences in `iframes` within the host product (e.g., Jira or Confluence), lends itself well to such architecture: Not only do Jira or Confluence apps benefit from all features of the Jamstack, it also makes it very easy to migrate between [Atlassian Connect](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/) and the new [Atlassian Forge](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-forge/) platform.\n\nJamstack-based Connect apps fetch their resources from a CDN, and then invoke their own backends, as well as the host product's APIs, via Ajax. Forge apps are fundamentally different from Connect apps, in that Forge apps are deployed _into_ Atlassian infrastructure - meaning that app developers no longer need to provide their own CDN or SaaS infrastructure. For Jamstack-based apps, however, this is only a minor implementation detail - apps are _still_ fetched from a CDN, and apps _still_ invoke their backends via Ajax calls. If the platform-specific integration points are abstracted away behind common APIs, an app's business logic can remain largely unaffected by the underlying extension framework.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"packages/hello-charlie/libraries/assets/src/assets/overview.gif\" width=600 /\u003e\n\u003c/p\u003e\n\n\nIn this sample app, the same piece of business logic is consumed into two simple next.js apps; one for Connect, and one for Forge. These next.js apps are only lightweight \"shells\" around the business logic; their main responsibility, beyond providing next.js' Jamstack infrastructure, is\n\n1. to perform Connect- or Forge-specific set up steps, e.g. in the page `header`.\n1. in their `webpack` config, to \"inject\" Connect- or Forge-specific implementations of two abstractions around the platforms' extension points; one to invoke Jira's REST API, and one to navigate within Jira.\n\n\n\n\n## Repository structure\n\nThe repo is organised as a `yarn workspaces`-powered monorepo:\n\n##### `libraries/connect-api`\n\nA simple wrapper around Connect's [Javascript API](https://developer.atlassian.com/cloud/jira/platform/about-the-connect-javascript-api/). Exists to create type-safety and hide access to a global variable (`window.AP`) from consumers.\n\n##### `libraries/jira-request(-api/-forge/-connect)`\n\nThe stub implementation (`jira-request`), API (`*-api`), and Connect and Forge implementations (`*-connect`, `*-forge`) of the app's abstraction around [Jira's REST API](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/). Exposes a single `request` method that takes the URL of the REST endpoint and an optional `Options` object:\n\n```js\nimport { request } from '@hello-charlie/jira-request';\n\nconst projects = await request('/rest/api/3/project');\n\nconst issue = await request('/rest/api/3/issue', {\n  type: 'POST',\n  data: { fields: { project: { id: '42' }, summary: 'New issue', issuetype: { id: '42' } } },\n});\n```\n\n##### `libraries/react-link(-api/-forge/-connect)`\n\nThe stub implementation (`react-link`), API (`*-api`), and Connect and Forge implementations (`*-connect`, `*-forge`) of the app's abstraction around anchor tags. Exposes a single `Link` component that takes a `href` as well as an optional `style` prop:\n\n```js\nimport { Link } from '@hello-charlie/react-link';\n\nexport const View = () =\u003e (\n  \u003cp\u003e\n    Here's an \u003cLink href=\"https://jxl.app\"\u003eexternal link\u003c/Link\u003e,{' '}\n    and here's an \u003cLink href=\"/browse/JXL\"\u003einternal link\u003c/Link\u003e\n  \u003c/p\u003e\n);\n```\n\n##### `routes/hello`\n\nThe `/hello` route of our next.js sites. Contains your app's main business logic. Uses `@hello-charlie/jira-request` and `@hello-charlie/react-link` to fetch data from, and navigate within, Jira.\n\n##### `services/connect/site`\n\nThe next.js site of our Connect app. Imports `@hello-charlie/route-hello` as its `/hello` route. In its webpack configuration (`next.config.js`), replaces the stub implementations of `jira-request` and `react-link` by their Connect implementations. Provides the app's [app descriptor](https://developer.atlassian.com/cloud/jira/platform/connect-app-descriptor/) (`atlassian-connect.json`) through its `public` folder.\n\n##### `services/forge/site-hello`\n\nThe next.js site of our Forge app's `hello` resource. Imports `@hello-charlie/route-hello` as its `/index` route. In its webpack configuration (`next.config.js`), replaces the stub implementations of `jira-request` and `react-link` by their Forge implementations. As part of the build process, is exported into the Forge _app_ (see below).\n\n##### `services/forge/app`\n\nThe Forge app. Provides the app's `manifest.yml`, `index.js`, etc. in the expected file and folder structure. As part of the build process, receives its `hello` resource from the Hello site (see above).\n\n\n## Setup\n\n### Basics\n\n- Install [nvm](https://github.com/nvm-sh/nvm), [yarn](https://yarnpkg.com/lang/en/), [Typescript](https://www.typescriptlang.org/), and [ngrok](https://ngrok.com/).\n- In your repo folder, run `nvm use`. This enables Node 12, as is currently required by Forge.\n- In your repo folder, run `yarn`. This installs all required dependencies.\n\n### Running Hello Charlie as a Connect app\n\n- In your repo folder, run `yarn run hello-charlie:connect-site:dev`. This starts the next.js site of our Connect app, at `localhost:3000`.\n- Expose `localhost:3000` to the internet via `ngrok`, e.g. via `ngrok http 3000`.\n- In your [`atlassian-connect.json`](packages/hello-charlie/services/connect/site/public/atlassian-connect.json), replace `\u003cyour-base-url\u003e` with your tunnel's URL (e.g. `https://abcd1234.ngrok.io`).\n- Install your app as described [here](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#set-up-your-development-environment).\n- In your Jira site, navigate to a project. Find \"Hello Charlie\" in the sidebar. 🚀\n\n### Running Hello Charlie as a Forge app\n\n- Outside (!) of your repo folder, create a new Forge app for Jira, using the Forge CLI. Copy your app's `app ID` into the [`manifest.yml`](packages/hello-charlie/services/forge/app/manifest.yml) of this repo. You can then delete all files of your newly created app; we'll use the app code of this repo instead.\n- In your repo folder, run `hello-charlie:forge-site-hello:export`. This exports the next.js site of your Forge app into the `app` directory.\n- Navigate to your repo's `app` folder: `cd packages/hello-charlie/services/forge/app`.\n- In the `app` folder, use the Forge CLI to deploy and install the Forge app as described [here](https://developer.atlassian.com/platform/forge/getting-started/).\n- In your Jira site, navigate to a project. Find \"Hello Charlie\" in the sidebar. 🚀\n\n\u003cbr\u003e\n\n[![image](packages/hello-charlie/libraries/assets/src/assets/banner-large.png)](https://jxl.app)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesoftware%2Fatlassian-jamstack-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinesoftware%2Fatlassian-jamstack-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesoftware%2Fatlassian-jamstack-app/lists"}