As an Engineering Manager and Policy Reviewer/Maker within an Enterprise organization, I find connecting documents challenging. To reuse or avoid duplicating the contents, we often resorted to including links to another page for "more information".

As the pages and contents start to grow, is hard to keep track of what pages are referring to what. This makes it difficult for us to refactor our content, as we might indirectly obsolete some of the pages that are connecting to it. We also wouldn't want to create unwanted side effects on any of the important documents.

What it does

  • This app stores and indexes all the links (URL only) within the Confluence's page. This is done by storing the relationship of how each of them is linked together.
  • The visualizer is added at strategic places for the content creator to study related and connected documents before making big changes to the page they are editing.
  • With the visualizer, they are also able to have a high-level overview and analyze patterns of how their important documents are connected with each other.

How we built it

Foremostly, this app revolves around the Graph Database for us to build the relationship of each page and how they are linked. Luckily, we are able to leverage existing technology (Neo4j) for this purpose.

We are able to leverage the FaaS nature of the Atlassian Forge to host the apps. This reduces the need for us to host on cloud platforms. (With the exception that we still need to connect to Neo4j explained in the challenges later) Other than that, we also have to opt for CustomUI since we want to use the existing frontend charting library to display the relationship and nodes.

Upon installing the App, admin will the run the initial seed so that we can map the whole confluence to the existing state. After that, we listen to the page create and update events to update the relationship for the follow-up events.

Challenges we ran into

To begin. As you can see, links in confluence are always formatted to make them readable.

<ri:page ri:content-title=\"Brainstorming\" ri:version-at-save=\"1\" /><ac:link-body>Brainstorming</ac:link-body></ac:link> </p><p><strong><span style=\"color: rgb(64,50,148);\"><sub>🗑 Remove this panel once you're ready to share your space with team members.</sub></span></strong></p></ac:adf-content></ac:adf-node><ac:adf-fallback><div class=\"panel conf-macro output-block\" style=\"background-color: rgb(234,230,255);border-color: rgb(153,141,217);border-width: 1.0px;\"><div class=\"panelContent\" style=\"background-color: rgb(234,230,255);\">...

From the application, is nice to look at, but on the backend side of things, there are plenty of tags and edge cases that we need to carefully handle. Examples would be links to Confluence Page, Jira Issue, external URL, etc...

Besides that, we initially wanted to directly connect to Neo4j within the Forge Apps using neo4j-driver. After many trials and errors, we weren't able to connect to the unsupported neo4j protocol used. As a result, we created an additional service to handle the neo4j query, and pass the results back to the Forge app.

Accomplishments that we're proud of

It is interesting to see that we manage to complete the app with a level of completeness that exceeds our expectations. It was interesting to see the nodes that are connected and make sense of the content layout of the confluence space.

While we're building the app, we have also improved the Developer Experience (DevEx) of building the Forge App using CustomUI. One example here is to build a Single Page Application (SPA) by passing the context to determine the route (Component) to load.

We also hack around the web trigger for us to mock the Forge Bridge's invoke function, so that, we can have a separate development space with hot-reloading to speed up our frontend development.

What's next for Content Dependency Analyzer

What we have done here is just the beginning.

  • We could further expand these use cases to map the links within the comment.
  • Introduce search query for advanced users.
Share this project: