GSoC 2026 Proposal Draft – Idea 9: LAN Sync – Justin Charles


Links:

GitHub profile: justin212407 (Justin Charles) · GitHub
Contributions to Joplin:

  • #14547 :- Fix ++insert++ syntax rendering fix in markdown (Merged)
  • #14563:- Fix Prevent unclosed frontmatter from breaking Markdown rendering (Merged)
  • #14626:- add plugin website link to /help (Merged)
  • #14634:- Application crashes when deleting a notebook (Closed but considered for GSoC)
  • #14674:- hide new note/todo buttons when no notebook exists (Merged)
  • #14692:- Always require password confirmation when changing master password after encryption (Merged)
  • #14824:- Add warning dialog before JEX import to prevent note duplication (Approved)

1. Introduction

I am Justin Charles, a B.Tech Information Science Engineering student with a strong interest in full-stack systems and distributed architectures. I am a year-long contributor at Sugar Labs and an C4GT DMP 2025 contributor, where I have worked on the Music Blocks v4 project. Through this, I have gained experience collaborating on large open source codebases and understanding project architecture,.

For this proposal, I have spent time exploring Joplin’s codebase, understanding how synchronization and conflict handling work, and analyzing areas where user experience and automation can be improved. Through this proposal, I aim to implement a native LAN-based synchronization mechanism that integrates seamlessly with Joplin’s architecture while maintaining its offline-first philosophy.


2. Project Summary

What problem it solves

Joplin currently relies on centralized synchronization targets such as WebDAV, Joplin Server, or filesystem-based sync. While these are reliable, they introduce several limitations:

  • Dependence on internet connectivity or external infrastructure
  • Slower synchronization compared to local network speeds
  • Manual setup complexity (especially for WebDAV or shared filesystem)
  • Poor performance of filesystem sync on mobile devices

Even when multiple devices are on the same local network, there is no built-in way to synchronize them directly.

This results in:

  • unnecessary latency
  • reliance on third-party services
  • reduced usability in offline-first workflows

What will be implemented

This project introduces a new synchronization target:

SyncTargetLAN

that enables direct device-to-device synchronization over LAN without requiring any external server.

The system consists of:

  • SyncTargetLAN → integrates with Joplin sync system
  • FileApiDriverLAN → handles LAN communication
  • LANSyncServer → exposes local device as sync endpoint

Key features:

  • Direct peer-to-peer communication over HTTP
  • Incremental synchronization using delta
  • Bidirectional sync (each device acts as client + server)
  • Lock-based coordination to prevent concurrent conflicts
  • Built-in authentication and peer handling

The implementation follows a incremental approach:

  • Phase 1: primary-peer model
  • Phase 2: extendable to full P2P


3. Technical Approach and Implementation


3.1 SyncTargetLAN and Settings Integration

The SyncTargetLAN component serves as the entry point for integrating LAN-based synchronization into Joplin’s existing sync architecture. It will be implemented as a new sync target within packages/lib/SyncTargetLAN.ts and registered through the sync target registry so that it can be selected via the application settings. Its primary responsibility is to initialize a FileApi instance backed by FileApiDriverLAN, allowing the Synchronizer to operate without any awareness of the underlying transport mechanism.

Unlike traditional sync targets such as WebDAV or filesystem, this target does not represent a remote storage system but instead acts as a communication bridge between devices. It validates configuration parameters such as peer address, port, and authentication key before initiating synchronization. By ensuring that connectivity and authentication are verified upfront, it prevents invalid sync attempts from entering the pipeline. This design keeps the integration non-invasive, meaning no modifications are required in Synchronizer.ts, while still enabling LAN-based communication through the existing abstraction layers.


3.2 FileApiDriverLAN (Core Communication Layer)

The FileApiDriverLAN is the core component responsible for translating Joplin’s file-based synchronization operations into HTTP requests that can be executed over a local network. Implemented in packages/lib/file-api-driver-lan.ts, it adheres to the same interface as existing drivers, ensuring compatibility with the FileApi abstraction. Each operation (get, put, delete, list, delta, stat) is mapped to a corresponding HTTP endpoint exposed by the peer device.

From a design perspective, this driver acts as a thin but critical translation layer. It ensures that all network communication remains consistent with Joplin’s expectations, without introducing additional logic that could interfere with synchronization semantics. The driver incorporates retry mechanisms, bounded timeouts, and idempotent request handling to ensure reliability under unstable network conditions. Importantly, it does not implement conflict resolution or state tracking itself; instead, it delegates these responsibilities to the existing synchronization engine, preserving Joplin’s proven consistency guarantees.


3.3 LANSyncServer (Peer-side Server)

The LANSyncServer, implemented in packages/lib/services/lan/LANSyncServer.ts, transforms each Joplin client into a synchronization endpoint capable of handling incoming requests from other devices. It exposes a minimal set of HTTP endpoints that mirror the operations expected by FileApiDriverLAN, such as /items, /delta, /locks, and /info. This ensures that peer devices can interact with each other using the same semantics as traditional sync targets.

A key design decision in this component is to delegate all data operations to Joplin’s existing model layer rather than introducing a separate storage system. Incoming requests are deserialized and applied using classes like BaseItem.ts and Note.ts, ensuring that updates are processed in the same way as local changes. This guarantees compatibility with sync metadata (sync_items), conflict detection, and encryption. The server is also responsible for handling concurrent requests safely, ensuring atomic write operations and preventing partial state exposure during interruptions.


3.4 Delta Sync over LAN

Delta synchronization is implemented by extending both the client-side driver and server-side endpoints to support cursor-based incremental updates. On the client side, FileApiDriverLAN.delta(context) sends requests to the /delta endpoint, while on the server side, LANSyncServer computes changes using the sync_items table. This allows the system to return only the items that have changed since the last synchronization, along with a continuation cursor.

This design ensures that LAN sync remains efficient and scalable even for large note collections. Instead of transferring entire datasets, changes are retrieved in paginated batches, reducing network load and memory usage. The cursor-based approach also enables recovery from interrupted sync cycles, as the client can resume from the last known state. By reusing Joplin’s existing delta semantics, this implementation avoids introducing new complexity while maintaining full compatibility with the synchronization pipeline.


3.5 Locking and Bidirectional Synchronization Model

In a LAN-based environment, multiple devices may attempt to synchronize simultaneously, leading to potential conflicts if writes are not coordinated. This deliverable introduces a lease-based locking mechanism that ensures safe and consistent synchronization. Lock acquisition, refresh, and release operations are implemented through FileApiDriverLAN and corresponding endpoints in LANSyncServer. Each lock is associated with a TTL (time-to-live), ensuring automatic recovery in case of unexpected client failures.

The system also enables true bidirectional synchronization by allowing each device to function as both a client and a server. While this increases flexibility, it introduces the need for coordination to prevent race conditions. The locking mechanism ensures that only one device performs write operations at a time, while others wait or retry. This approach avoids the need for complex distributed coordination systems while still providing strong consistency guarantees.


3.6 Robustness and Peer Handling

This deliverable focuses on ensuring that LAN synchronization remains reliable under real-world conditions such as network instability, device unavailability, and configuration errors. It introduces mechanisms for peer discovery, authentication, retry logic, and fallback handling. Peer discovery can be implemented optionally using mDNS, while manual configuration remains the default for deterministic setups.

From a reliability standpoint, the system is designed to fail gracefully and recover automatically. If a peer becomes unreachable, the driver retries or switches to a fallback peer. Partial transfers are handled through idempotent operations, ensuring that repeated requests do not corrupt state. Authentication is enforced using a shared key, preventing unauthorized devices from participating in synchronization. Combined with delta-based recovery, these mechanisms ensure that all devices eventually converge to a consistent state without requiring complex coordination logic.



4. Expected Outcome

At the end of the project, Joplin will support:

  • Native LAN-based synchronization
  • Direct device-to-device sync without servers
  • Faster sync within local networks
  • Seamless desktop and mobile compatibility
  • Improved usability with minimal configuration

The feature will behave like a standard sync target, making it intuitive for users while significantly enhancing performance and flexibility.


5. Potential Challenges

(Based on edge case analysis)

  • Device goes offline mid-sync - handled via retry + delta continuation

  • Partial data transfer - chunked operations + idempotent requests

  • Large note collections - handled via paginated delta

  • Concurrent sync attempts - lock-based coordination

  • Authentication mismatch - request rejection at server level

  • Cross-platform issues (desktop vs mobile) - lightweight HTTP-based implementation

  • Network instability - fallback peer + retry logic

  • Data consistency issues - resolved through repeated delta sync cycles


6. Timeline

Community Bonding

Study Joplin’s synchronization pipeline in depth, including Synchronizer.ts, FileApi, and existing sync targets (WebDAV, filesystem), and confirm integration points for introducing SyncTargetLAN without modifying core logic

Trace the full flow of update_remote, delete_remote, and delta phases and understand how sync_items drives incremental synchronization

Prototype a minimal LAN communication layer (basic HTTP server + client) to validate feasibility of device-to-device communication

Investigate how existing lock handling works in Joplin and confirm how lock semantics can be extended over LAN with mentors

Explore approaches used by tools like Syncthing and refine scope to ensure a practical, GSoC-feasible implementation


Weeks 1 and 2

Implement SyncTargetLAN in packages/lib/SyncTargetLAN.ts and register it in the sync target registry

Add configuration options (peer address, port, authentication key) and integrate with Joplin’s settings system

Implement initialization flow (initFileApi) to return a FileApi backed by FileApiDriverLAN

Verify that Synchronizer.start() can run end-to-end using the new sync target without modifying core sync logic


Weeks 3 and 4

Implement FileApiDriverLAN with core operations: get, put, delete, list, and stat

Map each operation to HTTP endpoints and establish communication with a basic peer server

Add authentication headers and basic request validation

Implement retry logic and bounded timeouts for network operations

Test basic data transfer between two devices (manual sync)


Weeks 5 and 6

Implement LANSyncServer in packages/lib/services/lan/LANSyncServer.ts

Add endpoints for /items and integrate them with Joplin’s model layer (BaseItem.ts, Note.ts)

Ensure incoming operations are applied correctly and reflected in local sync_items

Enable end-to-end synchronization:

  • upload (put)
  • delete (delete)

Verify that changes made on one device are correctly applied on another


Weeks 7 and 8

Implement delta synchronization over LAN:

  • Extend FileApiDriverLAN.delta()
  • Implement /delta endpoint in LANSyncServer

Integrate cursor-based pagination using sync_items

Handle large note collections efficien


8. Deliverables

  • SyncTargetLAN.ts – new sync target integrated into packages/lib/SyncTargetLAN.ts, registered in SyncTargetRegistry.ts, initializes FileApi with FileApiDriverLAN, validates peer configuration (address, port, auth key), and enables LAN sync selection in Joplin settings without modifying Synchronizer.ts

  • file-api-driver-lan.ts – implementation of LAN-backed FileApiDriver supporting get, put, delete, list, stat, and delta, mapping each operation to HTTP endpoints, including retry logic, bounded timeouts, and idempotent request handling for reliable communication with peers

  • LANSyncServer.ts – lightweight peer-side server in packages/lib/services/lan/ exposing /items, /delta, /locks, and /info endpoints, applying incoming operations through Joplin’s model layer (BaseItem.ts, Note.ts) so that remote updates integrate directly with sync_items and existing sync behavior

  • Delta synchronization over LAN – extension of FileApiDriverLAN.delta() and /delta endpoint in LANSyncServer, implementing cursor-based incremental sync using sync_items, with paginated responses and deletion (tombstone) handling to support large note collections and interrupted sync recovery

  • Locking mechanism over LAN – lease-based lock system implemented via driver methods and server endpoints (acquire, refresh, release) with TTL-based expiration, ensuring safe execution of update_remote and delete_remote phases without concurrent write conflicts

  • Bidirectional sync model – integration of dual-role behavior where each device operates as both client (FileApiDriverLAN) and server (LANSyncServer), enabling direct device-to-device synchronization while preserving compatibility with Joplin’s sync pipeline

  • Robust peer handling layer – implementation of authentication (shared key via headers), retry and timeout handling in driver, and fallback peer selection logic in SyncTargetLAN, with optional peer discovery (mDNS) to improve usability in multi-device LAN environments


8. Availability

Weekly availability during GSoC

I can dedicate approximately 40 hours per week on average to the project throughout the GSoC period.

Timezone

India Standard Time (IST) (GMT+5:30).

Other commitments during the programme

I do not have any exams, internships, or other major commitments during the GSoC period. I will prioritize this project fully and ensure consistent progress. I will maintain regular communication with mentors through the Joplin forum and Discord, and provide structured weekly updates on progress.


9. Future Work

Possible extensions after GSoC include:

  • Full peer-to-peer synchronization model
    Extending the current primary-peer approach into a fully decentralized multi-peer synchronization system.

  • Advanced peer discovery mechanisms
    Supporting discovery across subnet boundaries and improving automatic device detection reliability.

  • Background synchronization optimization (especially mobile)
    Improving performance and resource usage for continuous LAN sync on Android and iOS devices.

  • Enhanced conflict handling for LAN scenarios
    Introducing smarter conflict diagnostics or optional visualization tools for understanding sync behavior.

  • Performance optimizations for large-scale note collections
    Further improving delta efficiency and reducing sync latency in large datasets.

  • Security enhancements
    Exploring stronger authentication mechanisms such as device pairing or encrypted key exchange.


Could you please review the suggested approach? @Daeraxa @CalebJohn @laurent