Files

11 KiB

LinkdingSync Extension - Design Document

Overview

linkdingsync is a Firefox browser extension that synchronizes bookmarks with a self-hosted Linkding instance. It supports folder hierarchy, bi-directional sync, configurable sync modes, and tag-based bundle management.

Project Location

Linkding Browser Extension/LinkdingSync/

Extension Name

linkdingsync - Firefox extension name (manifest.json)


1. Data Storage Structure

Configuration (stored in browser.storage.local)

{
  "serverUrl": "https://links.blabber1565.com",
  "apiKey": "your-api-token-here",
  "bundleTag": "bundle_personal_firefox_1",
  "syncMode": "bi-directional",
  "autoGenerateTags": false,
  "lastSyncTimestamp": 1715012345678
}

Storage Areas

  • browser.storage.local - Persistent data per browser profile
  • browser.storage.session - Temporary session data

Supported Values

Value Description
bi-directional Replicate both directions; keep both versions
write-only Browser is authoritative source; update Linkding only
read-only Linkding is authoritative source; download only

Default: bi-directional


2. Bookmark Notes Structure

The notes field uses a JSON-compatible structure with versioning for forward compatibility:

{
  "version": 1.0,
  "path": "Work/Resources/Development",
  "userNotes": "Development resources and references",
  "autoTags": [
    {"name": "Work"},
    {"name": "Resources"},
    {"name": "Development"}
  ],
  "bundleTag": "bundle_personal_firefox_1"
}

Display Format

  • Only show userNotes in the UI
  • path and autoTags are hidden from regular users

Version Handling

  • version 1.0: Basic structured format with path, userNotes, autoTags
  • version 2.0: Adds bundleTag field for tag-based bundle identification
  • Extension version tracking: Uses extension version number for notes version
  • Backward compatibility:
    • Old bookmarks without structured notes are detected
    • Non-JSON notes are migrated to structured format
    • Old notes get version: 1.0 and existing text in userNotes
    • Future fields are ignored by older versions

Auto-generate Tags Setting

  • Default: false (disabled)
  • When true, extracts folder names from path as tag suggestions
  • User must organize folders intentionally for tag auto-generation to work correctly

3. Bundle/Tag Configuration

Instead of creating actual Linkding bundles, we use Linkding's "required tags" feature:

Bundle Tag Convention

All bookmarks in a bundle must have the bundle tag. The bundle tag name follows this pattern:

bundle_{BUNDLE_NAME}_{BROWSER}

Examples:

  • bundle_personal_firefox_1
  • bundle_work_chrome_1
  • bundle_personal_edge_1

Linkding Query Parameters

In Linkding, create a bundle with these parameters:

  • Search: (empty)
  • Required tags: {bundleTag}
  • Any tags: (empty)
  • All tags: (empty)
  • Excluded tags: (empty)

This means all bookmarks with the bundle tag appear in this bundle.

Updating Extension Version

The extension version is used as the notes version:

  • Extension v1.0.x → notes version 1.0
  • Extension v2.0.x → notes version 2.0
  • Extension v1.0.1 → notes version 1.0 (patch versions don't change notes version)

4. Extension File Structure

LinkdingSync/
├── manifest.json              # Firefox manifest v2
├── popup.html                 # Main extension popup
├── popup.css                  # Popup styling
├── popup.js                   # Popup UI logic
├── background.html            # Settings/config page
├── background.js              # Service worker
├── README.md                  # User documentation
├── docs/
│   ├── design.md              # Design document
│   └── TODOs.txt             # Version compatibility notes
└── icons/
    ├── icon-48.svg            # 48x48 icon
    └── icon-96.svg            # 96x96 icon

5. Key Features

Popup UI

  • Quick bookmark add with optional notes
  • Sync status indicator
  • Settings button → opens config page

Config Page (background.html)

  • Server URL input (with validation)
  • API key input (with "Get from Linkding Settings" guidance)
  • Bundle tag input (e.g., "bundle_personal_firefox_1")
  • Sync mode selector (bi-directional | write-only | read-only)
  • Auto-generate tags toggle
  • Last sync timestamp (human-readable with timezone)
  • Test connection button
  • Save Settings button
  • Reset config button

Background Service

  • Monitor bookmark events (add, remove, modify)
  • Perform sync operations with Linkding API
  • Cache recent API responses
  • Handle errors and show notifications
  • Apply bundle tag to all new bookmarks
  • Migrate old notes to structured format

6. Sync Logic Flow

1. Browser bookmark change detected
   ↓
2. Check syncMode:
   - read-only: download from Linkding only
   - write-only: sync to Linkding only
   - bi-directional: sync both directions
   ↓
3. For new bookmarks:
   - Add bundleTag to notes
   - Check if URL already in Linkding
   - If no → create new bookmark with bundle tag
   - If yes + different URL → create new bookmark
   - If yes + same URL → update notes (keep title/description)
   ↓
4. For updates (same URL, different folder):
   - Update path in notes
   - Merge with existing notes
   - Apply sync mode rules
   ↓
5. For deletions:
   - write-only → delete from Linkding
   - read-only → ignore (keep Linkding version)
   - bi-directional → delete from Linkding
   ↓
6. Migrate old notes:
   - If notes not JSON or lacks version field → treat as old notes
   - Convert to structured format with version 1.0
   - Preserve existing content in userNotes

7. Notes Migration

Old Notes Detection

Old notes are detected if:

  • notes is not valid JSON, OR
  • notes doesn't contain a version field

Migration Process

  1. Parse existing notes
  2. If invalid/non-JSON → create structured notes with:
    {
      "version": 1.0,
      "path": "",
      "userNotes": "<existing text here>",
      "autoTags": [],
      "bundleTag": "<from config>"
    }
    
  3. If valid but old version → update version field
  4. If same or newer version → keep as-is

Forward Compatibility

When new fields are added to notes structure:

  • Older extension versions ignore unknown fields
  • Newer extension versions add new fields
  • This allows gradual feature rollouts

8. API Endpoints Used

Authentication

Authorization: Token <Token>

Bookmarks

  • GET /api/bookmarks/ - List bookmarks
  • GET /api/bookmarks/check/?url=... - Check if URL is already bookmarked
  • POST /api/bookmarks/ - Create bookmark
  • PUT/PATCH /api/bookmarks/<id>/ - Update bookmark
  • DELETE /api/bookmarks/<id>/ - Delete bookmark

9. Implementation Status

Phase 1: Core Setup

  • Create manifest.json with options_ui
  • Create popup HTML/CSS/JS
  • Create background service worker
  • Implement storage helpers

Phase 2: Sync Logic

  • Implement bookmark manipulation
  • Implement notes parser with versioning
  • Implement sync logic
  • Implement conflict resolution

Phase 3: Configuration UI

  • Create config page
  • Implement config form logic
  • Add API key guidance

Phase 4: Polish

  • Add icons
  • Add error handling
  • Add notifications
  • Implement notes migration
  • Implement tag-based bundle approach

10. Version History

Version Date Changes
0.1.0 2026-05-06 Initial design document
1.0.0 2026-05-06 Initial implementation
1.0.1 TBD Tag-based bundle support
1.0.2 TBD Notes version migration

11. Notes

This document should be referenced during implementation to ensure all requirements are met. Any deviations from this design should be documented here.


Last Updated: 2026-05-06

LinkdingSync - Version Compatibility Notes

Version 1.0.x - Basic Structured Notes

Notes Structure

{
  "version": "1.0",
  "path": "",
  "userNotes": "",
  "autoTags": [],
  "bundleTag": "bundle_links_blabber1565_firefox_42",
  "keyword": ""
}

Auto-Generate Tags Feature

When autoGenerateTags is enabled in settings:

  • Tags are automatically derived from the path folder structure
  • Example: path = "Work/Resources/Development"autoTags = ["Work", "Resources", "Development"]
  • These tags are added to the bookmark on Linkding
  • Important: Tags are only auto-generated if this setting is enabled
  • Tags will always be present in the structured notes field

When autoGenerateTags is disabled (default):

  • Tags array remains empty ([])
  • Only bundleTag is added to the bookmark
  • Old bookmarks without structured notes are migrated without tags

Bundle Tag Behavior

Always Applied:

  • The bundleTag (e.g., bundle_links_blabber1565_firefox_42) is always added to new bookmarks
  • This enables Linkding bundle filtering via the all= API parameter
  • When viewing bookmarks in Linkding UI with this tag filter, you'll see only bookmarks from this browser
  • Bundle feature works as expected: queries by tag filter, UI shows filtered results

Not Applied:

  • path field is used for folder organization
  • userNotes stores user-provided notes
  • autoTags is populated only when autoGenerateTags is enabled
  • keyword field is used for Firefox-style quick-access bookmarks

Migrations

Old Non-JSON Notes:

"old text notes"

→ Migrated to:

{
  "version": "1.0",
  "path": "",
  "userNotes": "old text notes",
  "autoTags": [],
  "bundleTag": "bundle_...",
  "keyword": ""
}

Old Structured Notes (no version field):

{
  "path": "",
  "userNotes": "notes",
  "autoTags": []
}

→ Migrated to:

{
  "version": "1.0",
  "path": "",
  "userNotes": "notes",
  "autoTags": [],
  "bundleTag": "bundle_...",
  "keyword": ""
}

Version 2.x - Future Features

Version 2.x will add new fields while maintaining backward compatibility. Older extension versions will continue to work but won't use new fields.


Implementation Notes

Current State (v1.0.x)

  • bundleTag is always added to bookmarks (enables bundle filtering)
  • autoTags is only populated when autoGenerateTags setting is enabled
  • Old bookmarks get migrated with empty autoTags array
  • Firefox tags (autoTags) are stored in Linkding bookmarks when present in Firefox

Bundle Feature

  • Linkding bundle is created with all_tags set to the bundleTag
  • All bookmarks with this tag appear in the bundle
  • Bundle filtering uses all= API parameter (exact match on all tags)
  • Querying works correctly with pagination for large bookmark sets

Cross-Browser Sync

  • All browsers share the same Linkding collection via tag filtering
  • Firefox bookmarks with tags sync to Linkding
  • Other browsers read from Linkding with same tag filter
  • Keywords are preserved in structured notes but not synced (Linkding doesn't support keywords)