Merge desk for duplicate and conflicting Confluence pages

By General Input

Group look-alike wiki pages into clusters, see exactly where they disagree, and pick one source of truth without deleting anything.

Integrations

  • Confluence
  • AI Generation

Type

App

Categories

  • Operations

Build me a merge desk for duplicate and conflicting Confluence pages. We have six pages that are some version of "onboarding" and nobody knows which one is true. The app is a review queue I work through one cluster at a time. It must be strictly non-destructive: it never deletes a page, a comment, or a space. Do not use any delete operation from the Confluence catalog, even though the catalog has them.

The main screen has a search bar where I either type a topic or pick a Confluence space. Running it calls Search Content (CQL) to pull candidate pages, restricted to type=page, using a title and text match for the topic plus a space filter when I picked one. Cap the candidate set at a few hundred pages and paginate through results rather than trying to pull an entire site in one go.

Group the candidates into clusters of likely duplicates. Normalize titles first (lowercase, strip punctuation and filler words like draft, copy, old, new, final, v2) and group by title similarity, then use AI Generation to confirm or split the borderline groups by weighing title, space, and labels together. A cluster needs at least two pages; do not show singletons.

The queue lists one row per cluster showing the cluster name, the number of pages in it, the newest and oldest edit dates, and the people who last touched those pages. Pull the edit dates and last editors from Get Page Versions for each page in the cluster, and the rest of the page metadata from Get Page by ID.

Opening a cluster shows the pages side by side, each column with its title, space, last editor, last edit date, and body. Page bodies are not returned by default, so call Get Page by ID with body-format=storage (atlas_doc_format also works, and in that case the value field is a JSON encoded string rather than a raw object). Above the columns, show a plain English summary of where the pages actually disagree, produced in the app with AI Generation from the fetched bodies. The summary must name concrete differences, for example "Page A requires manager approval and Page B requires manager plus finance approval" or "Page A says Greenhouse and Page C says Lever", so I can tell a stale copy from a genuine variant. Cache the summary per cluster so reopening a cluster does not regenerate it.

In each cluster I pick one page as canonical and the rest get marked superseded. Confirming that decision runs three writes. Add Labels (v1 API) tags the canonical page and the superseded pages with distinct labels. Create Footer Comment posts a comment on each superseded page telling readers the page is superseded and linking to the canonical page. Update Page puts a short "this page has moved" banner at the top of each superseded page body.

Updating a page requires sending version.number as the current version plus one, so the banner edit must always fetch the page first with Get Page by ID using body-format=storage, prepend the banner to the existing body, and send the full body back with the incremented version. Never replace a body, always prepend, because the original content has to survive intact.

Remove Label undoes a decision if I change my mind. Undo takes the labels off the canonical and superseded pages with Remove Label (v1 API), runs Update Page again to strip the banner block back out of the superseded bodies, and returns the cluster to the queue as undecided. Leave the original footer comment in place and post a short follow-up comment saying the decision was reversed, so the app never has to call a delete operation.

A cluster I dismiss as "not duplicates" stays dismissed and does not resurface next session. Store dismissals and decisions in app storage shared across everyone in the workspace rather than per user, since the labels and comments they produce are shared anyway. Key each dismissal on the exact set of page IDs in that cluster, so that if a new page later joins the group it surfaces again as a new cluster instead of staying hidden forever.

Show the decision state on every row (undecided, decided, dismissed) and let me filter down to just the undecided ones. Before running any writes, show me exactly what is about to happen: which page gets the canonical label, and which pages get the banner and the comment. Confluence enforces points-based rate limits and returns 429 with a Retry-After header, so if a batch of writes fails partway, report which pages succeeded and let me retry only the failures rather than redoing the whole cluster.

Related prompts

Explore more prompts
One inbox for every Jira Service Management approval waiting on youAssign owners to stale Confluence pages, space by spaceSee every open Confluence action item on one boardDocumentation ownership register for your Confluence wikiTrack who has read every onboarding page in ConfluenceHubSpot prospecting desk for personalized first-touch emailsHiring content studio for job descriptions and interview kitsA response desk for RFPs and security questionnairesWeekly Statuspage reliability report for leadershipTurn repeat support tickets into draft help articles