Caveats & Limitations
Riffle converts between two fundamentally different document formats — Confluence’s rich storage format (XHTML with custom macros) and Markdown. Not everything survives the round trip. This page documents what syncs cleanly, what degrades, and what doesn’t sync at all.
What syncs well
Section titled “What syncs well”These elements convert cleanly in both directions:
| Element | Confluence → GitHub | GitHub → Confluence |
|---|---|---|
| Headings (H1–H6) | ✅ | ✅ |
| Paragraphs | ✅ | ✅ |
| Bold / Italic / Strikethrough | ✅ | ✅ |
| Inline code | ✅ | ✅ |
| Code blocks (with language) | ✅ | ✅ |
| Links | ✅ | ✅ |
| Images (external URLs) | ✅ | ✅ |
| Ordered and unordered lists | ✅ | ✅ |
| Nested lists | ✅ | ✅ |
| Blockquotes | ✅ | ✅ |
| Tables | ✅ | ✅ |
| Horizontal rules | ✅ | ✅ |
| Task lists (checkboxes) | ✅ | ✅ |
| Expand/collapse sections | ✅ | ✅ |
| Status lozenges | ✅ | ✅ |
What degrades gracefully
Section titled “What degrades gracefully”These elements are converted but may lose some fidelity:
| Element | Behavior |
|---|---|
| Status lozenges | Confluence’s status macro converts to bold bracketed text like **[IN PROGRESS]** with an HTML comment <!-- status:Blue --> to preserve the color. The color comment enables lossless round-tripping. Both colour and color parameter spellings are handled. Defaults to Grey if no color is specified. |
| Expand/collapse sections | Confluence’s expand macro converts to HTML <details><summary> blocks. GitHub renders these as collapsible sections. The expand title maps to <summary>. Content inside is converted as normal markdown. |
| Code blocks with macros | Confluence’s code macro converts to a fenced code block. Language hints are preserved. Macro parameters (line numbers, theme, collapse) are lost. |
| Table header rows | Markdown tables require a header row. Confluence tables without headers get a synthetic header on conversion to Markdown. |
| Nested tables | Markdown doesn’t support nested tables. Inner tables are flattened to text. |
| Text color and highlights | Confluence supports inline color and background color. These are stripped in Markdown (no equivalent). |
| Font size | Stripped — Markdown has no font size control. |
What doesn’t sync
Section titled “What doesn’t sync”These elements are not converted and will be lost or ignored:
| Element | Reason |
|---|---|
| Confluence macros (Jira issues, roadmaps, etc.) | No Markdown equivalent. Custom macros are too varied to map generically. Expand macros, info/warning/note/tip panels, and status lozenges are supported — see above. |
| Embedded attachments | Confluence attachments are stored in Confluence’s own file system. Images referenced by attachment ID (not URL) cannot be resolved from GitHub. |
| Page permissions | Confluence page-level restrictions don’t have a GitHub equivalent. |
| Page comments | Comments are separate from page content and are not synced. |
| Inline comments | Confluence inline comments (annotations on specific text) have no Markdown representation. |
| Labels | Confluence labels are not included in the Markdown output. |
| Page history / versions | Each sync creates a new version. Historical versions are not transferred. |
| Confluence templates | Templates are not pages and are not synced. |
| Live docs (whiteboards, databases) | Only standard pages and blog posts are supported. |
| Emojis (Confluence-specific) | Confluence has its own emoji format (:emoji: with custom IDs). Standard Unicode emoji work fine. |
Behavioral caveats
Section titled “Behavioral caveats”Loop prevention
Section titled “Loop prevention”Riffle prevents infinite sync loops using identity-based detection. When Riffle updates Confluence, the resulting event carries Riffle’s own Atlassian account ID — the forward sync recognizes this and skips it. Similarly, commits made by Riffle include a [riffle-sync] tag that the reverse sync ignores. This is precise and instant — human edits are never dropped.
Conflict resolution
Section titled “Conflict resolution”Riffle uses a last-write-wins strategy. If the same page is edited in both Confluence and GitHub between sync cycles, the most recent change overwrites the other. There is no merge or conflict detection.
Sync manifest
Section titled “Sync manifest”Riffle tracks page-to-file mappings in a .sync-manifest.json file committed alongside your Markdown files. This manifest maps file paths to Confluence page IDs, space keys, and titles. Do not delete this file — Riffle uses it to detect renames, prevent duplicates, and track sync state.
If you previously used YAML front matter (confluence_id, space_key fields), Riffle automatically migrates to the manifest on the next sync and strips the front matter from your files.
Page and file renames
Section titled “Page and file renames”Riffle handles renames in both directions:
- Confluence page rename → GitHub: When a page title changes, Riffle detects the rename via the manifest, deletes the old file, and creates the new file — all in a single atomic commit. No orphaned files.
- GitHub file rename → Confluence: When a file is renamed (appears as delete + add in a push), Riffle matches the old and new files via the manifest and updates the Confluence page title instead of trashing and recreating the page. Page history and comments are preserved.
File renames that change the H1 title will also update the Confluence page title. If the H1 title is unchanged (or absent), the page title is derived from the new filename.
Branch scope
Section titled “Branch scope”Riffle only syncs with the repository’s default branch (typically main). Changes on feature branches are not synced until merged.
File path mapping
Section titled “File path mapping”Confluence page hierarchy maps to folder structure:
Space Root├── Parent Page → docs/target-dir/parent-page.md│ ├── Child Page → docs/target-dir/parent-page/child-page.md│ └── Another Child → docs/target-dir/parent-page/another-child.mdPage titles are slugified (lowercased, spaces replaced with hyphens, special characters removed).
Rate limits
Section titled “Rate limits”- GitHub API: 5,000 requests/hour for authenticated tokens. Each page sync uses 2–3 API calls. Large bulk operations may hit limits.
- Confluence API: Subject to Atlassian’s standard rate limits for Forge apps.
- Forge invocation limits: Forge functions have a 25-second execution timeout. Very large pages may time out during conversion.