This Confluence user macro uses the Confluence Cloud REST API to fetch the current page details, its ancestors, and direct children, then computes a depth-first “previous” and “next” page by combining child, sibling, and ancestor-sibling relationships. The macro resolves target pages to their web UI URLs and renders compact circular AUI-styled buttons that stick to the bottom-right of the viewport, dynamically adjusting position based on whether one or both navigation buttons are visible.
## Styles
#set($navBgColor = "transparent")
#set($navWidth = "4em")
#set($navTop = "92%")
#set($navRight = "3.7%")
#set($maxDepthDown = 20)
## Fetch all ancestors (both pages and folders)
#set($ancestorsRaw = $ConfluenceManager.get("/wiki/api/v2/pages/${page.id}/ancestors?limit=250").results)
#set($parentType = "")
#set($parentId = "")
#set($closestPageAncestorId = "")
#if($ancestorsRaw && $ancestorsRaw.size() > 0)
#set($lastIndex = $ancestorsRaw.size() - 1)
#set($parent = $ancestorsRaw.get($lastIndex))
#set($parentId = $parent.id)
#set($parentType = $parent.type)
## Track the closest ancestor that is an actual page (used for 'Back' fallback)
#foreach($a in $ancestorsRaw)
#if($a.type == "page")
#set($closestPageAncestorId = $a.id)
#end
#end
#end
## GET SIBLINGS
#set($siblings = [])
#if($parentId != "")
## Route to proper API based on parent type
#if($parentType == "folder")
#set($siblings = $ConfluenceManager.get("/wiki/api/v2/folders/${parentId}/direct-children?limit=250").results)
#else
#set($siblings = $ConfluenceManager.get("/wiki/api/v2/pages/${parentId}/direct-children?limit=250").results)
#end
#end
## FORWARD LOGIC
#set($forwardTargetId = "")
## 1. Look for direct child pages of the current page
#set($children = $ConfluenceManager.get("/wiki/api/v2/pages/${page.id}/direct-children?limit=250").results)
#foreach($c in $children)
#if($c.type == "page")
#set($forwardTargetId = $c.id)
#break
#end
#end
## 2. If no children, look to the next valid sibling
#if($forwardTargetId == "")
#set($nextSibling = "")
#set($after = false)
#foreach($s in $siblings)
#if($after && $nextSibling == "")
#set($nextSibling = $s)
#end
#if($s.id == $page.id)
#set($after = true)
#end
#end
#if($nextSibling != "")
#if($nextSibling.type == "page")
#set($forwardTargetId = $nextSibling.id)
#elseif($nextSibling.type == "folder")
## Dig into the folder's descendants to find the first actual page
#set($fDescendants = $ConfluenceManager.get("/wiki/api/v2/folders/${nextSibling.id}/descendants?limit=250").results)
#foreach($d in $fDescendants)
#if($d.type == "page")
#set($forwardTargetId = $d.id)
#break
#end
#end
#end
#end
#end
## Resolve Forward Link
#set($forwardHref = "")
#if($forwardTargetId != "")
#set($p = $ConfluenceManager.get("/wiki/api/v2/pages/${forwardTargetId}"))
#if($p && $p._links && $p._links.webui)
#set($forwardHref = "${baseUrl}${p._links.webui}")
#end
#end
## BACK LOGIC
#set($backTargetId = "")
#set($prevSibling = "")
## Find the sibling immediately prior to this page
#foreach($s in $siblings)
#if($s.id == $page.id)
#break
#else
#set($prevSibling = $s)
#end
#end
#if($prevSibling != "")
#if($prevSibling.type == "page")
## Target starts as prev sibling page, dig to its deepest last page
#set($backTargetId = $prevSibling.id)
#foreach($d in [1..$maxDepthDown])
#set($kids = $ConfluenceManager.get("/wiki/api/v2/pages/${backTargetId}/direct-children?limit=250").results)
#set($lastPage = "")
#foreach($k in $kids)
#if($k.type == "page")
#set($lastPage = $k.id)
#end
#end
#if($lastPage != "")
#set($backTargetId = $lastPage)
#else
#break
#end
#end
#elseif($prevSibling.type == "folder")
## Target is a folder, find the very last page in its descendants
#set($fDescendants = $ConfluenceManager.get("/wiki/api/v2/folders/${prevSibling.id}/descendants?limit=250").results)
#set($lastFPage = "")
#foreach($d in $fDescendants)
#if($d.type == "page")
#set($lastFPage = $d.id)
#end
#end
#if($lastFPage != "")
#set($backTargetId = $lastFPage)
#else
## Fallback if folder was empty
#set($backTargetId = $closestPageAncestorId)
#end
#end
#else
## No previous sibling exists. Go back to the closest ancestor that is an actual page.
#if($closestPageAncestorId != "")
#set($backTargetId = $closestPageAncestorId)
#end
#end
## Resolve Back Link
#set($backHref = "")
#if($backTargetId != "")
#set($p = $ConfluenceManager.get("/wiki/api/v2/pages/${backTargetId}"))
#if($p && $p._links && $p._links.webui)
#set($backHref = "${baseUrl}${p._links.webui}")
#end
#end
## UI
#set($hasBack = $backHref != "")
#set($hasForward = $forwardHref != "")
#if($hasBack && $hasForward)
#set($navRight = "5.3%")
#elseif($hasBack || $hasForward)
#set($navRight = "3.75%")
#end
<div class="aui-dialog2 aui-layer"
style="top:$navTop;right:$navRight;display:block;visibility:hidden;z-index:10;">
<div style="padding:0.4em;float:right;width:$navWidth;background-color:$navBgColor;visibility:visible;text-align:center;">
#if($hasBack)
<a href="$backHref" style="border:1px solid grey;border-radius:50%;display:inline-block;width:25px;height:25px;text-decoration:none;">←</a>
#end
#if($hasForward)
<a href="$forwardHref" style="border:1px solid grey;border-radius:50%;display:inline-block;width:25px;height:25px;text-decoration:none;">→</a>
#end
</div>
</div>Show an expandable page tree for a selected parent page (defaults to the current page)
Based on CQL it shows a table with: Page title, Author, Updated, Status
Find image within page attachments. Handy for reuse files and update them all at once
Displays a list of pages in specific space with certain title or label
Display a list of guest users in a specific Confluence space
Shows page creation date
User macro for displaying issues using custom JQL filter
Display and interact with an OpenAPI / Swagger specification directly in Confluence by rendering a fully featured Swagger UI from a provided JSON URL
Basic greeting for user
An overview of all pages within one space which contains the title, the version, and the last updated date