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 profilebrowser.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
userNotesin the UI pathandautoTagsare 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.0and existing text inuserNotes - Future fields are ignored by older versions
Auto-generate Tags Setting
- Default:
false(disabled) - When
true, extracts folder names frompathas 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_1bundle_work_chrome_1bundle_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:
notesis not valid JSON, ORnotesdoesn't contain aversionfield
Migration Process
- Parse existing notes
- If invalid/non-JSON → create structured notes with:
{ "version": 1.0, "path": "", "userNotes": "<existing text here>", "autoTags": [], "bundleTag": "<from config>" } - If valid but old version → update version field
- 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 bookmarksGET /api/bookmarks/check/?url=...- Check if URL is already bookmarkedPOST /api/bookmarks/- Create bookmarkPUT/PATCH /api/bookmarks/<id>/- Update bookmarkDELETE /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
pathfolder 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
bundleTagis 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:
pathfield is used for folder organizationuserNotesstores user-provided notesautoTagsis populated only whenautoGenerateTagsis enabledkeywordfield 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)
bundleTagis always added to bookmarks (enables bundle filtering)autoTagsis only populated whenautoGenerateTagssetting is enabled- Old bookmarks get migrated with empty
autoTagsarray - Firefox tags (
autoTags) are stored in Linkding bookmarks when present in Firefox
Bundle Feature
- Linkding bundle is created with
all_tagsset to thebundleTag - 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)