GSoC 2026 Proposal Draft – Idea 4:Chat with your note collection using AI – Madhan_S

1. Introduction

Background / Studies: Second-year undergraduate student pursuing B.Tech in Artificial Intelligence and Data Science at Sri Eshwar College of Engineering(India). My academic focus lies in software engineering, machine learning pipelines, and AI-driven applications, with strong interest in modern web architectures and scalable plugin systems. I actively build full-stack TypeScript/React applications and have been exploring RAG (Retrieval-Augmented Generation) pipelines as part of my coursework and self-directed learning.

Programming experience: Solid experience with TypeScript, JavaScript, Node.js, React, Python, and REST API integrations. Comfortable with the full plugin development lifecycle — from architecture design to testing and documentation.

Experience with open source: I have cloned and explored the Joplin repository locally, studying the plugin API surface, the joplin.data.get() pagination behaviour, and the joplin.views.panels IPC model. I noticed that joplin.workspace.onNoteChange() is the correct hook for detecting note edits — a distinction that is critical for reliable incremental indexing in my proposed plugin. I am currently working on my first contribution to the Joplin codebase and will link my PR here once submitted.


2. Project Summary

What problem it solves: Joplin users accumulate thousands of carefully curated notes but can only explore them through keyword search. A user may remember a concept but not the exact words and synthesising knowledge across multiple notes requires manually opening each one. There is currently no way to have a natural language conversation with your own note collection without sending personal data to a third-party cloud service.

What will be implemented: A native Joplin plugin powered by a fully local RAG architecture. Notes are chunked, embedded using nomic-embed-text via Ollama, and stored in LanceDB a serverless, file-based vector database with a TypeScript SDK. A React chat panel inside Joplin lets users ask questions and receive grounded answers with clickable source citations. All processing happens on-device by default; cloud LLMs (OpenAI) are opt-in with explicit disclosure.

Expected outcome: A seamless chat panel where users ask a question and receive a synthesised answer backed by citations to their own notes with zero data leaving the machine unless explicitly opted in.


3. Proof of Concept

Before writing my proposal I built and ran a working RAG pipeline outside Joplin to validate the architecture. The script embeds sample notes using Ollama, stores them in LanceDB, retrieves the most relevant chunks via cosine similarity, and generates a grounded answer using llama3 — all locally.

Repository: PoC

Key observation from running it: nomic-embed-text correctly retrieved a note about "cutting travel costs" in response to the question "what did we decide about the budget?", even though the word "budget" does not appear in the note body. This confirms semantic search is the right approach for Joplin's use case.


4. Why this project

I use Joplin daily for my studies. The frustration of knowing that a piece of information is somewhere in my notes but being unable to surface it is something I experience personally. This project sits at the intersection of the skills I am most excited to develop: production-quality TypeScript/React plugin development, real-world RAG pipeline engineering, and meaningful contribution to a tool used by thousands of privacy-conscious users worldwide.

Introduction: Madhan Intro

madhan_s proposal.pdf (653.7 KB)

Thank you for your proposal. It would need to be updated as per the new template:

https://discourse.joplinapp.org/t/gsoc-2026-how-to-submit-your-proposal-draft/49137/3

Hello sir,
I’ve now updated my proposal to align with the official GSoC template you shared. I’ve attached the revised version here.

Could you please let me know if this looks good, or if I need to make any further changes or improvements?

madhan_s proposal.pdf (623.4 KB)

check again how we wrote out proposal
you need to post here in the forum itself rather than docs

1 Like

Got it Ashutoshx7 and thanks for the heads-up!

Links

1. Introduction

Hello! I’m Madhan S, a second-year B.Tech student at Sri Eshwar College of Engineering(India), specializing in Artificial Intelligence and Data Science. My academic focus on machine learning, neural networks, and software engineering provides me with a strong technical foundation that aligns perfectly with the requirements of this project.

Technical Background
I’ve spent significant time working with TypeScript and JavaScript, particularly building Node.js applications and managing asynchronous patterns. My experience with React has also prepared me to handle the UI components of the chat panel effectively. Additionally, I’m proficient in Python, which I’ve used extensively for data wrangling and ML-related scripting.

On the AI front, I have hands-on experience working with LLM APIs, vector embeddings, and RAG pipelines through both my coursework and personal projects.

Open Source Experience
I’m an active contributor to the open-source community, with merged PRs in:

  • Joplin: Resolved an issue with the openFolder x-callback-url on Android (#14286).

  • ESP-Website: Fixed a missing GIF asset in the Bigpicture theme (#3447).

I’ve already set up the full Joplin development environment locally and spent time diving into the plugin API and data access patterns. To ensure I hit the ground running, I’ve even built a small proof-of-concept before finalizing this proposal.

2. Project Summary

The Challenge
For many Joplin users, their note collection is a vast repository of research, personal insights, and project logs. However, as these collections grow into the thousands, traditional keyword search becomes a bottleneck. If a user cannot recall the exact phrasing used in a note from a year ago, that information is effectively buried. Currently, there is no way to truly "interrogate" your knowledge base; you can only search for specific terms.

Solution & Its Impact
This project introduces a native Joplin plugin that enables natural, conversational interaction with your personal knowledge base. By implementing a Retrieval-Augmented Generation (RAG) pipeline, users can query their notes as they would a knowledgeable colleague using plain language and following up with clarifying questions.

Crucially, this maintains Joplin's privacy-first, local-first philosophy. By prioritizing Ollama as the default local LLM runner, users gain the power of conversational AI with the assurance that zero data leaves their machine, a significant privacy advantage over cloud-based alternatives like Notion AI.

Key Deliverables
I aim to deliver a robust, end-to-end RAG implementation with the following core features:

  • Intuitive Interface: A ChatGPT-style React UI integrated directly into a Joplin panel, featuring real-time streaming responses.
  • Context-Aware Chat: Support for multi-turn conversations, where follow-up questions retain the context of the previous three interactions.
  • Citations & Navigation: Every AI-generated answer will include clickable citations, allowing users to jump directly to the source note within Joplin.
  • Flexible Backends: Default support for Ollama (local) with an opt-in for OpenAI (API-based) for maximum user choice.

Performance & Reliability
I have set clear benchmarks for success, including a Recall@3 score of ≥ 0.85 on a standardized test set and high-speed indexing (5,000 notes in under 3 minutes). The final delivery will include a comprehensive test suite and full documentation for both users and future developers.

Project Scope
To ensure a high-quality initial release, the project will focus exclusively on the core RAG experience within the chat interface. Features such as cloud-sync collaboration, additional LLM providers, or direct note editing via the chat are considered out of scope for this initial phase.

3. Technical Approach

Architecture & Components
The plugin is designed with a modular, three-tier architecture to ensure reliability and ease of testing:

  • Layer A - Ingestion Pipeline: This layer handles note discovery via the joplin.data.get() API. To maintain performance, notes are processed into overlapping 512-token chunks using a Markdown-aware splitter. These are then embedded and stored in LanceDB, a high-performance, file-based vector database that requires no external server. To keep the index current, the pipeline listens for onNoteChange events to re-index only modified content.

  • Layer B - Retrieval Engine: When a user asks a question, this engine performs an Approximate Nearest Neighbor (ANN) search. I am implementing a Hybrid Ranking system (combining semantic search with BM25 keyword scores via RRF) to ensure the most relevant context is found. To prevent context window overflow, tiktoken manages token counts, while the last three dialogue turns are preserved for conversational continuity.

  • Layer C - Chat UI: Built as a native React panel, the interface communicates with the backend via Joplin's postMessage bridge. It supports real-time token streaming for a responsive feel and includes clickable citations that link directly to the referenced notes.

Technology Stack

Component Technology
Language & UI TypeScript, React, Joplin Panel API
Vector Database LanceDB (Local, file-based)
AI Models (Local) Ollama: llama3 (LLM) & nomic-embed-text (Embeddings)
AI Models (Cloud) OpenAI: GPT-4o & text-embedding-3-small
Processing LangChain.js (Chunking), tiktoken (Token management)
Search/Ranking flexsearch (BM25) + RRF Re-ranking

Addressing Potential Challenges

  • Scalability: For users with 10,000+ notes, indexing will run in batched background workers with a progress indicator to ensure the UI remains fluid.
  • Markdown Formatting: I’ll extend the MarkdownTextSplitter to handle Joplin-specific syntax, ensuring code blocks and tables remain intact and readable for the LLM.
  • Environment Readiness: If Ollama isn't detected, the plugin will provide a graceful setup guide rather than failing, offering a seamless fallback to OpenAI if a key is provided.

Testing & Documentation
I am committing to a rigorous testing strategy, moving from unit tests for chunking and database integrity to full integration tests that validate multi-turn coherence. The project will be benchmarked on a 10,000-note collection to ensure we maintain a Recall@3 ≥ 0.85.

Final deliverables will include a comprehensive User README (with a dedicated Ollama walkthrough), a Developer Architecture Doc, and full JSDoc coverage for the codebase to ensure long-term maintainability by the Joplin community.

4. Implementation Plan

The following roadmap outlines the development phases, with primary deliverables marked as [R] and optional stretch goals as [O]. I have allocated a total of 350 hours for this project, including a dedicated buffer for mentor feedback and rigorous testing.

Phase 1: Foundation & Ingestion (Weeks 1 - 6)

  • Weeks 1 - 2 (May 27 - Jun 9): Community Bonding & Prototyping [R]
    Deep-dive into Joplin’s API and the LanceDB SDK. Prototype the MarkdownTextSplitter using real-world note exports to ensure code block integrity and finalize the design doc with my mentors.
  • Week 3 (Jun 10 - 16): Note Fetcher Implementation [R]
    Develop the paginated joplin.data.get() loop. Validation will include unit tests for pagination accuracy and ensuring a 250-note fixture returns full data.
  • Week 4 (Jun 17 - 23): Advanced Chunking [R]
    Integrate the text splitter with specific focus on chunk size bounds (512 tokens), 64-token overlaps, and maintaining heading-boundary integrity.
  • Week 5 (Jun 24 - 30): Vector Database Integration [R]
    Set up LanceDB and define the schema (id, noteId, title, chunk, vector). Conduct performance benchmarks for indexing speeds at scales of 1k, 5k, and 10k notes.
  • Week 6 (Jul 1 - 7): Embedding Providers [R]
    Build the EmbeddingProvider interface to support both Ollama and OpenAI backends. Test for vector dimensionality and seamless provider switching.

Phase 2: Retrieval & Intelligence (Weeks 7 - 10)

  • Week 7 (Jul 8 - 14): Midterm Checkpoint [R]
    Demonstrate an end-to-end ingestion pipeline. Goal: 500 notes indexed with a terminal query successfully retrieving the top-3 relevant chunks with source IDs. Initial Recall@3 measurement.
  • Week 8 (Jul 15 - 21): Hybrid Retrieval Engine [R]
    Implement hybridRetrieve() combining ANN search with BM25 keyword scoring via RRF re-ranking. Integrate tiktoken for precise context window management.
  • Week 9 (Jul 22 - 28): LLM & Streaming Integration [R]
    Connect the retrieval engine to Ollama and OpenAI. Enable token streaming to the Joplin panel via the postMessage bridge and verify source citation accuracy.
  • Week 10 (Jul 29 - Aug 4): React Chat Interface [R]
    Build the frontend panel featuring the message thread, real-time streaming display, and interactive citations that navigate directly to notes in Joplin.

Phase 3: Refinement & Scale (Weeks 11 - 14)

  • Week 11 (Aug 5 - 11): Multi-turn Conversation & QA [R]
    Implement conversational memory (last 3 turns). Execute comprehensive integration tests for dialogue coherence and bridge latency.
  • Week 12 (Aug 12 - 18): UX & Incremental Indexing [R]
    Develop the settings panel for provider/API configuration. Implement onNoteChange() background indexing and build robust error handling for edge cases (e.g., Ollama missing, disk full).
  • Week 13 (Aug 19 - 25): Large-Scale Validation [R]
    Perform end-to-end stress tests on a 10,000-note collection to validate Recall@3 ≥ 0.85. [O] Implement a visual progress bar for the initial indexing build.
  • Week 14 (Aug 26 - Sep 1): Final Documentation & Launch [R]
    Complete the User README, Developer Architecture Doc, and full JSDoc pass. Submit the plugin to the Joplin marketplace and finalize the project evaluation.

Resource Allocation

  • Development: 340 Hours
  • Buffer: 10 Hours (Reserved for PR reviews and mentor feedback iterations)

5. Deliverables

The primary outcome of this project will be a production-ready, installable Joplin plugin that provides a seamless "Chat with your Notes" experience. The specific deliverables include:

  • Production Plugin: A fully functional Joplin plugin implementing an end-to-end RAG (Retrieval-Augmented Generation) pipeline with a native React chat interface.
  • Core Ingestion Pipeline:
    • A robust, paginated note fetcher.
    • A customized MarkdownTextSplitter for intelligent note chunking.
    • A local, high-performance LanceDB vector store.
    • Support for both Ollama (local) and OpenAI (cloud) embedding backends.
  • Advanced Retrieval Engine:
    • Hybrid search capabilities (ANN + BM25) with RRF re-ranking for maximum accuracy.
    • Precise context management using tiktoken.
    • Multi-turn conversational memory for follow-up questions.
  • Conversational UI:
    • A responsive chat panel featuring real-time token streaming.
    • Interactive, clickable citations that link directly to source notes.
    • A comprehensive settings panel for model and API configuration.
  • Smart Indexing:
    • Incremental indexing triggered via onNoteChange() to keep the database current.
    • A manual re-indexing option for full library refreshes.
  • Quality Assurance Suite:
    • A full suite of unit, integration, and scale tests.
    • Performance validation on a 10,000-note collection (targeting Recall@3 ≥ 0.85).
  • Documentation:
    • User README: Clear setup and usage instructions, including an Ollama walkthrough.
    • Developer Architecture Doc: A deep dive into the data flow and extension points.
    • Code Documentation: Full JSDoc coverage for all public functions to ensure maintainability.

6. Availability

Weekly Commitment
I am fully committed to dedicating approximately 30 hours per week throughout the GSoC coding period (May 27 - September 1, 2024). My goal is to maintain a consistent development pace to meet all milestones on schedule.

Communication & Time Zone

  • Time Zone: IST (UTC +5:30).
  • Sync-ups: I am available for weekly video calls with mentors and will be highly responsive to asynchronous communication via the Joplin forum and GitHub.

Academic & Other Commitments
My end-of-semester exams typically conclude in early May, ensuring I am clear of academic hurdles before the coding period begins. I have no conflicting internships, part-time jobs, or other programs during this window. Should any minor academic assessments arise during the summer, I will provide mentors with at least one week's notice to ensure project continuity.

Post-Program Maintenance
I view this project as a long-term contribution to the Joplin ecosystem. Beyond the GSoC period, I intend to maintain the plugin by incorporating community feedback, expanding support for additional LLM providers, and ensuring compatibility with future Joplin API updates.

Hey @Madhan_S, thanks for posting the full text.

LanceDB's JavaScript client - have you tested whether it loads in an Electron plugin without native module issues?

For the hybrid search: does flexsearch implement BM25 scoring (TF-IDF with length normalisation), or is it a different scoring model?

For the Recall@3 ≥ 0.85 target - how do you plan to build the test set? Do you have labelled query/note pairs?

Hi sir, thank you for the questions, they pushed me to research deeper than I had before.

On LanceDB in Electron: I had not tested it in an Electron plugin environment. After your question I looked into it and found that LanceDB's JS client uses native binaries that need to be recompiled against Electron's specific ABI(Application Binary Interface) which introduces significant compatibility risks and deployment overhead within a restricted plugin environment. This is a real gap in my PoC, since my PoC ran outside Joplin entirely. sqlite-vec via better-sqlite3 is what will work here : better-sqlite3 is already used in Joplin's own codebase, meaning it has already been compiled against Joplin's Electron version and loads cleanly inside a plugin. I will rebuild the PoC inside an actual Joplin plugin environment to confirm this end-to-end.

On flexsearch and BM25: I should not have called it BM25 scoring. After reading the flexsearch source, it uses its own index-matching model without TF-IDF length normalisation, the k1/b parameters that define true BM25 are absent. orama is what will work here: it implements proper BM25 with length normalisation, has a TypeScript-first API, runs fully in-process with no native binaries, and therefore has zero Electron compatibility issues. I will replace flexsearch with orama and update the hybrid retrieval section of the proposal.

On the Recall@3 test set: I was treating Recall@3 as a future metric without thinking through how to actually build it. Your question made me realise I need a concrete plan from day one. What will work: during week1 - week2 community bonding I will hand-label 20 query/note pairs covering the main Joplin note types (short meeting notes, web clippings, to-do lists, long structured articles), store them as JSON fixtures in the repo, and run the metric against the actual plugin at midterm. This makes Recall@3 a reproducible, falsifiable target rather than a number I picked arbitrarily.

I will ensure all three of these updates are reflected in the final version of the proposal and I will update my PoC to reflect the actual Joplin plugin environment.

Thank you for the detailed feedback and for pointing out these specific constraints. It has been a significant help in refining the architecture for the final proposal.

On sqlite-vec via better-sqlite3: is this based on testing in a Joplin plugin, or inferred from better-sqlite3's presence in the core app?

Hi sir, this was inferred from better-sqlite3's presence in Joplin's core codebase, not from direct testing of sqlite-vec inside a plugin.

However, the PoC now confirms that better-sqlite3 itself loads and runs correctly inside the Joplin plugin environment, it successfully embedded and stored 45 chunks across 8 notes. The current implementation uses plain better-sqlite3 with BLOB storage for embeddings and cosine similarity computed in JavaScript, which is working end-to-end.

sqlite-vec specifically, loading it as an extension via

db.loadExtension()

on top of better-sqlite3 inside the plugin, has not been tested yet. This is a real open question since Joplin may restrict native extension loading inside plugins. I will test this explicitly in the next iteration.

Result:

PoC repo for reference: GitHub - madhan112007/joplin-embeddings-poc · GitHub

Hello sir,

In my current architecture, the local inference path is restricted to the desktop environment. I am using sqlite-vec (via better-sqlite3) for the vector store and bge-small-en-v1.5 (via @xenova/transformers) for embeddings. Since these rely on Node.js native modules and WASM execution within the Electron environment, they are incompatible with the React Native sandbox used on Android. Currently, only the OpenAI API backend would function on mobile as it relies on standard HTTPS calls.

To help me define the project scope, I have a few questions:

  1. Environment Constraints: Does Joplin’s Android plugin environment provide a React Native-compatible SQLite binding that could support sqlite-vec, or is the sandbox too restricted for native extensions?

  2. Core App Changes: You mentioned that mobile might require PRs to the app itself. Does this imply that supporting embeddings on Android necessitates changes to the core codebase rather than staying strictly within the plugin level?

  3. GSoC Scope: Given the 350-hour limit, would you recommend keeping mobile support out of scope for this project while ensuring the EmbeddingProvider interface is designed to be "mobile-ready" for future integration? Or is mobile functionality considered a high-priority requirement for this GSoC cycle?

My goal is to design the abstraction layer correctly now so that we can integrate a mobile-compatible backend later without needing to rearchitect the entire plugin.

The child process approach in your PoC is a practical way to handle the native module constraint.

On your mobile questions: plugins can't spawn child processes, load native extensions, or run WASM reliably on mobile. So the current architecture (child process + better-sqlite3 + Transformers.js) is desktop-only. Local embeddings on mobile would need core app changes to expose the right APIs to plugins. What does work on mobile today is API-based embeddings and generation (just HTTPS calls), and Joplin's built-in search API for keyword retrieval.

Good luck with the submission!

Thank you so much sir! Your guidance was instrumental in helping me structure this proposal. I'm very grateful for your support.

1 Like