GSOC'20 Result announced!

Congratulations to the selected candidates!! Would you please mind sharing your proposal? So that we can learn from them which can help us to finely curate our proposal for next year.

P.S. Unfortunately I didn't got selected. Better luck next time :slightly_smiling_face:
To those who are not selected here is the another chance of contributing to open-source by Major League Hacking similar to GSOC powered by GitHub.


Congrats @anjulalk and @naviji for getting selected.


I want to see it too and it will great if guys can share few tips too :smile:

Thanks for sharing this buddy.

1 Like

Let us know if Joplin apply for something like this in future. It will be great to join it.

And Is Joplin applying for this?

GSoC is our very first program we are joining.
GSoD would be second if Joplin gets accepted.

The idea is, that we may join other programs to but have to get certain things sorted first.
We keep you posted

Here’s my proposal.

Make Joplin’s Search Better.pdf (84.8 KB)


@naviji This has been something I’ve been hoping for. Thanks, and good luck!


work will be public feel free to watch and comment :slight_smile:

@naviji @anjulalk you can even combine your projects to provide search for commands function similar to how Sublime Text (Ctrl+Shift+P) or IntelliJ IDEA (Ctrl+Shift+A) do it.

Though Joplin does not have nearly that many commands. Not yet at least.


we still have to create the space for communication etc. but there is an official bonding period what will be used to bond with the community.
We mentors have been in touch with them for weeks, so we quite good bonded :grin:.

The project can be adapted to a certain degree but we have to ensure that all can be done within the timeline.
It also relies on the community how the result shell looks like. If the student sees the capacity to extend the scope, why not.

1 Like

This is something I want Joplin to have too. Though I can’t promise it’ll get done in GSOC, I’ll help in whatever way I can.

I would suggest creating SLACK or DISCORD channel which is highly adopted by open-source organizations for more effective & real-time communication.

there is already a discord channel see
We have to talk about how to optimize communication so that information is not scattered around in multiple topics and tools plus that topics won’t get super long that you don’t know what is going on

1 Like

Okay I’ll check it out.

Thank you! Here’s my project proposal.pdf (190.2 KB)


That’d be a great addition. We’ll discuss it. Thank you!

Hey everyone! That was a great participation by everyone. I don't really know why mine didn't get selected too. Here's it is though :stuck_out_tongue:
coderrsid GSOC Proposal.docx (1.2 MB)

I guess because i didn't write 20 lines of code for testing feature on my machine which wouldn't be at all helpful in making this whole component :grin:


Hi everyone! This is my GSoC proposal on supporting multiple profiles. I didn't get selected though, probably because I didn't have enough PR's :smile:


  • Name: Deep Majumder

  • Github handle: RedDocMD

  • Email:



I am interested in working on the following ideas for my GSoC
project, taken from the ideas page of Joplin
( Support for multiple profiles


The multiple profiles feature is important for people who use Joplin
heavily and for multiple purposes. While the concept of notebooks allow
grouping of notes, it does not insulate notebooks from each other. For
an example, it is a very common scenario for a user to use Joplin for
both taking notes at home and at work. Having separate work and home
profiles will be advantageous to them, so that the home notebooks don't
show up while working at his/her office. In general, the concept of
profiles allows for blackbox separation between notes.


Assuming that both these projects are assigned to me, users after the
completion of this project will be able to do the following:

The user will be able to create multiple profiles with different
names, apart from the default profile which is automatically created
when the user opens Joplin for the first time. The profiles will be
completely insulated from each other. On switching profiles, the app
may be required to restart (depending on the final implementation).
It may be possible to add support for multiple instances of Joplin
running on different profiles.

My plans are to first implement these features for the desktop version.
If time permits, I will implement it also for the mobile client.


The following details are based off the desktop client. I will work on
the mobile client if time permits and my mentor allows it.

Basic structure and Desktop UI

I will be taking ideas from the Github issue on this
( Currently, the files
and directories where the metadata and database is stored are hard-coded
in BaseApplication.js via a profileDir variable. I intend to make a
new class called in Profile in a file Profile.ts (As instructed in, I will be using Typescript). The class roughly would
look like this:

class Profile {
    id: number;
    directoryName: string;
    parentDirectory: string;

The BaseApplication object will contain a Profile object, which will
store the current Profile which is being used. In addition, since the
app will restart when profiles are switched, the next profile to open
must be stored in the root folder of all profiles (the .joplin-desktop
directory). As mentioned in the Github issue, it is a good idea to have
an additional Profiles.ini file in the root directory. For handling
that file, a separate class must be made, which I plan to call
ProfilesHandler. An object of this class will be loaded in app.js.
When the app restarts, it will look up the profile to load up and pass
the requisite Profile object to BaseApplication.

As for the user interface, I intend to add a menu option in the Files
menu, saying 'Switch Profile;, which will open up a screen or a
pop-over. It is easier to make a screen, but a pop-over will look
better. The pop-over will show the existing profiles as well as an
option to create a new one. Overall, this can be implemented in a file
called ProfileScreen.tsx, with some changes in app.js.

Where to change the code

Firstly, we need to change how the profile directory is determined, in determineProfileDir(initArgs) of lib/BaseApplication.js. Currently, it first checks whether a profile path is set in the command-line args, otherwise defaults to $HOME/.config/<app-name>/. Now, instead it will use the object of the ProfilesHandler class (created in the constructor), which will be defined in Profileshandler.ts. This class will read the profiles.ini file. This file will be stored in either the directory pointed by the JOPLINAPP_ROOT environment variable, if available, or else will default to $HOME/.config/<app-name>/. The profiles.ini file will point to the new profile to open. However, if the profile to open is passed via command-line args, then it will open that profile. As of now, the --profile option accepts the profile-dir but this will have to be changed to profile-name in handleStartFlags_(arg, setDefault).

Apart from this, it is necessary to write to profiles.ini when the app exits to indicate the profile to open next time. This change will be reflected in BaseApplication.exit(), using the object of the ProfilesHandler class to do it.

For handling conflicts between the global custom css file, to be stored in the profiles root directory, and the custom css file in the profile directory, code must be added after line 1291 of ElectronClient/app.js to load the global css file as well. Then CssUtils.injectCustomStyles() must be modified to compare the two custom css files and load the one in the profile directory in case of a conflict. I will figure out the details in future. However, a simple hack that works will be to append the css file from the profile directory after appending the css file from the profiles root directory. By the CSS convention if there are conflicting rules, a later rule will override the previous one.

Apart from this, there will of course be code for the ProfileScreen and for creating profiles, but I have described that in my proposal. A lot of the heavy lifitng of the profiles will be done in the ProfilesHandler.tsx.

A diagramatic view of how Profiles work

The following flowchart describes how the concept of Profiles is to be used in Joplin:

Simultaneously running multiple profiles

Now that there are seperate databases for seperate profiles, multiple instances of Joplin perhaps could be run on different profiles.
Several problems may arise from this however:

  1. How does the new instance of Joplin know the current profile(s) running?
    This can be fixed however by adding a section in the profiles.ini file listing the currently active profiles. An additional complication that may arise from this is that the instances may not be closed in the same order as they are opened. So the profiles.ini file has to be clobbered and rewritten to completely every time some modifications have to be made to it.(For an instance while closing the app or while creating a new profile).

  2. When modifications are made to profiles in one instance how do(es) the other instance(s) know that?
    A simple fix may be to outlaw making edits to profiles when multiple instances are running. A more complicated solution is to watch for file changes via the fs.watchfile or module. Even this solution has potential problems. Because of the buffering mechanisms of the IO interface, while writing to the profiles.ini file, potentially at several intermediate writes, the file will be left in an illegal state yet triggering the watch listener, and this may lead to the app crashing. Perhaps during the write phase, locking the profiles.ini from both read and write may solve this problem (having a lockfile mechanism, that is). Even so, we have to disallow editing names of profiles which are currently being run in a seperate instance.

  3. What happens to the Electron metadata of the multiple instances?
    This doesn't seem to be a problem, even in the current master build. The metadata of the last instance of Joplin to be closed will be the one that is used while opening new ones.

Structure of the $JOPLINAPP_ROOT folder

As I have mentioned above, I intend to introduce a new environment variable called JOPLINAP_ROOT. The user can set this to modify where the database and other metadata is stored (not the Electron metadata, however). THe structure of this folder will be as follows:

Note that

  • Rectangles indicate directories, ellipses files
  • profile0 is the default profile, which is created the first time the app is opened
  • profile<id>* denotes that there may be zero or more directorires of the name profile<id> where id is a number in the range 1, 2, 3 ... . The id is a number to denote the profile, the actual profile names will stored in profiles.ini.
  • All the profile directories have a similar structure. I have shown it fully only for the default profile.

Error handling

Malformed/Missing profiles.ini file

Malforming can occur if the user edits the file by hand, or due to some errors in the OS/harddisk (this is relatively rare on journalled file systems, such as in all relatively modern machines) or a computer virus. There will be an initial checking in the ProfilesHandler.tsx. Of course if a section is missing, it can be retrieved from the directory structure. However, under the current design, profile names will not be retrievable. Either the user has to re-input it or the profile name must also be stored in the profie directory (redundancy of data to recover from errors). This process extends to the case if the profiles.ini file is missing all together.

Altered directory structure

If the user modifies by hand contents of a profile directory, the error will be caught by existing code. If a profiles directory is missing, it will be detected when the user switches to that profile. The user will be informed and the profile directory will bw newly formed. Basically, this is the same as creating a new profile of a given name.

Restarting the app on the desktop

The Electron app can be relaunched using app.relaunch(); app.quit(); according to the official docs. A function encapsulating the same should be made in bridge.js.