Zettlr 2.0.0 released
What a journey this has been. On Januar 16, 2021 – nine months ago – I released Zettlr 1.8.6, beginning the release notes with the sentence “This is the last patch before we begin working on Zettlr 1.9, which will feature much better flexibility in exporting.” How modest I was.
Instead, what we are looking at today is not Zettlr 1.9 but Zettlr 2.0, and we are not just looking at better flexibility in exporting. We are looking at a wholly new application! I think I decided to develop Zettlr 2.0 rather than 1.9 sometime in March, when I realized that the amount of changes I put in were already so many that I couldn’t justify just a minor revision – no, it had to be a major revision.
And here we are, after nine months of development, nights and weekends spent just to make this the best experience possible. It has been an incredible journey, and I learned so much along the way – not just in terms of coding because I finally understand the benefits of Map
s and Set
s, but also in interaction with you, the community. We now have a community Discord server (which I warmly invite you to join!) and more and more discussions on our new GitHub Discussions forum. In general, I think the community around Zettlr is finally flourishing, and it’s amazing to see!
But let’s return to the reason we are all here today: To celebrate the release of Zettlr 2.0! This blogpost will be structured as follows: First, I will say something general about what has changed in this release. Then I will go on to spotlight a few especially notable changes of which I’m specifically proud. In a third section, I will give you some advice on how to upgrade safely. Lastly, I will dedicate a section to the incredible support I had during development of 2.0, before closing with some final thoughts.
Introducing Zettlr 2.0
What you are looking at today is the result of months of hard work. I really wanted to make Zettlr 2.0 the best version it could be, and I think I succeeded for the most part. The driving force behind the fully rewritten and redesigned app was twofold:
- Make the app look native. Zettlr is not a website or some web app, but a real desktop app. And as such, it should look and feel like a desktop app. To accomplish this, I read through and implemented the Apple Human Interface Guidelines, the Windows Metro UI Design Guidelines, and the GNOME Human Interface Guidelines. Zettlr 2.0 will look native on all platforms for the first time, and to the best of my knowledge, Zettlr 2.0 is the only Electron app that looks native.
- Fix all the remaining teething troubles. When I first announced Zettlr 1.0 it was rather because it felt nice to release 1.0 stable after exactly one year of development. But even then I knew that the real 1.0 release was still not ready yet, and in fact today I’m convinced that Zettlr 1.3 was the actual 1.0 release, where everything I initially envisioned was implemented. But even in 1.3, and all the versions that followed, many aches plagued the app, because as I have pointed out on numerous occasions, before starting the development of the app in the Summer of 2017, I had close to no knowledge of JavaScript. But now, after four years of experience, my skills have advanced far enough that I can state that even internally, Zettlr will now look like a mature, production-ready app. As a user, you will notice that when using it: Zettlr now feels snappy, fast, and reliable. No more sluggish start up times and slow writing anymore!
The first goal I had was mainly driven by discussions internal to the Electron community. When Electron was first announced, many people took the opportunity to write a desktop-ready app, but with web technologies. This also determined the structure of those who would make use of Electron: Web developers. Those people, due to the virtue of their skills, are very good at designing things, but not necessarily at making an app that feels “right” to users. This is because good app design doesn’t require you to be a good designer. Good app design requires you to be good at designing user interfaces. And good user interfaces are boring from a purely design perspective. This has, in turn, prompted many critiques of the Electron framework on a fundamental level. Electron was determined by many observers of the ecosystems especially around the Apple operating system to be the wrong approach altogether. I thought they were wrong, but I also saw that their critique was very sensible. In fact, many Electron apps to this day feel slow and more like a website, rather than an app.
Take, for example, Slack and Discord. Both apps are fairly similar in capabilities, and both apps take an immense time to start. Before you can actually interact with the app, it takes several seconds of loading – even on a powerful, modern computer. And they implement a completely custom design which is not native to any of the operating systems these apps run on. This makes it easy for power users to switch from one computer to the other and still have exactly the same app. But for a person who only uses one operating system, these apps will always feel alien. What prominent people such as John Gruber have criticized is that this is not the way to go when you’re developing a desktop app. And, in fact, even when you use Electron to write a desktop app, this won’t relieve you of the duty to implement a design that looks and feels native on macOS, on Windows, or on Linux. While Electron makes your job much easier, it can’t take all responsibility off you, and I feel the critiques are right in pointing out that many Electron developers don’t take that responsibility serious. I wanted to do better, and I think I succeeded. Whether you are on macOS, on Windows, or on Linux: Zettlr will now fit into whatever operating system you use. You will see the same interface elements as all the other apps you have installed have. It will behave just like other apps on your computer. It won’t stick out with some design that could also be a website. And I think that is the most noble goal Zettlr 2.0 achieves.
The second goal I followed during development is to finally drive out all the childhood aches the app still had. Because a good app not only features a good look and feel, it also means that the app should be efficient, fast, and bug-free. This is actually quite hard to achieve. One of the main things I learned over the past four years is that bad state management leads to sometimes horrible bugs. Many early versions of Zettlr suffered especially under this problem. Oftentimes, you had to restart the whole app just because I made some logical error that caused the whole internal state to become faulty, leading to an unusable app. So the second goal was to fix all of that. Thanks to Tobias Diez, who has basically forced me to adopt a few novel design patterns, but also to my general experience I have accumulated, I was able to rewrite basically every piece of code inside the app so that it was stable no matter what you did, and also managed to make many parts of the code much more efficient.
The result will be apparent once you start Zettlr 2.0 the first time. The loading time has now decreased to a fraction of what it was back in 1.8.9, and everything will be much faster. Switching files, changing between tabs, adapting some settings: Everything will now feel snappy, and most changes will be applied as soon as you tick the box for the specific setting. All of this has been made possible by fully switching to Vue.js under the hood. Up until 1.8.9 only the sidebar was written in Vue, as a kind of case study, while the rest of the app was still the manual JavaScript driven state which frequently broke down and was just not scalable. Now, the whole app is powered by Vue.js, which makes the app extremely stable, fast, and a joy to work with. You will notice this in many parts throughout the app. Feel free to browse the different windows, popovers and other visual elements to see how the new internal design makes a difference!
A last thing I would like to mention at this point is that despite all the visual changes, what I strove to do is retain the overall usability of the app. While I cleaned up the toolbar and moved quite a few things around, many things will still be where they were before. The active file info is still in the top-right corner of the toolbar, the sidebar is still to the right of the main editor and the general icons are still grouped together to the left of the toolbar. The three file manager modes you know from before are still there, and so are the themes. To put it short: Zettlr 2.0 will feel completely new but still familiar.
Spot on: Notable Changes from Zettlr 1.x
Now, let us move on to the next section: A spotlight on all the things that are completely new and of which I am extremely proud.
The Exporter
Above I mentioned that my main goal initially was just to make the exporter better, so how about we start off with the new exporter experience? Visually, the exporter has not changed all too much. The export of both single documents and whole projects works still as it did before. But there are a few changes. First, the single-file export is not a group of tiles anymore. Rather, you will have a dropdown list with all available formats you can export into. This is because the exporter is now much more flexible, and I plan to add many more exporter options in the future. Internally, we switched to a plugin-based system, which means that adding and updating exporters is now much easier.
When scrolling through the list of available exporters, you will also notice that now there are two different PDF-exports, called “PDF Document” and “PDF (LaTeX)”. What do they mean? In the past, if you wanted to export anything, you had to manually install Pandoc and LaTeX. This was always a hassle, and certainly not user friendly. Thanks to advice from my friend Albert Krewinkel, I began bundling Pandoc with the app. So now you don’t have to install Pandoc anymore. Exporting and importing files will now be available without any additional effort from your part! This means that the app itself is now 100MB bigger (that’s how large Pandoc is), but since most of you had installed Pandoc either way, it won’t make a difference. If you don’t use Pandoc outside of Zettlr at all, you can now even uninstall the system-wide Pandoc install and don’t have to install it ever again! However, PDF export is a little bit more complex. LaTeX is a typesetting system that produces advanced and beautiful PDF files, but it’s still quite large and complicated. That is why I couldn’t bundle LaTeX with the app. This means, if you plan on exporting advanced PDF files, you will still have to install a LaTeX distribution yourself. But, and that’s the beauty of the two export formats: If you don’t need the power of LaTeX, you can choose the “PDF Document” export, which will also produce a PDF document, but that option only requires Pandoc, and not LaTeX. If you’re interested: What happens internally is that Zettlr will export your document as HTML, and then use the printing capabilities of Chromium to convert that into a PDF file. Remember: Electron is basically just a browser!
The project’s exporting features have also received an update. Previously, you only had the chance to select one of four exporting formats for your projects, and not the full phalanx that Zettlr offered for single document exports. That was an arbitrary limitation which has been rightfully protested on the GitHub issue tracker. The new project settings give you the power of the full exporter, because Pandoc doesn’t care if it should export one document, or many. So you will now have the ability to select any export format you desire: Projects now have access to every format the regular exporter has to offer. Also, you’re now not limited to only one export at a time: Select as many as you want, and Zettlr will export your project into all of them, one after another.
A last change involves how we organize the whole fun: You may well remember the awful “Pandoc command” that was sitting in the advanced preferences and where you had to fiddle around within a limited space to get Pandoc to do something custom. And, more often than not, someone broke the command. And since there were always some errors in the command, we had to tell users repeatedly to please “reset” that command after an update. This is certainly not a great way to convey simplicity, but it was also due to the fact that I didn’t really know how powerful Pandoc could be if you understood it correctly. Again thanks to the advice of Albert, we completely abandoned the command approach to Pandoc. Instead, Pandoc will now always be run using the command pandoc --defaults "/path/to/defaults.yml"
. This command is hard coded and cannot be changed anymore. Where the whole magic happens is now this “defaults file.” Defaults files are a powerful way to have Pandoc do whatever you want, since everything you can do on the command line, you can do with a defaults file. For every export, there is a dedicated defaults file that ships with sensible defaults for now, but which make it much easier for you to customize your exporting experience. And this leads us to the next new feature: the assets manager.
The Assets Manager
The assets manager is both the replacement for the “PDF Preferences” dialog, which doesn’t exist anymore, and a wholly new dialog. It allows you to comfortably edit any one of the many text files Zettlr now uses to perform various tasks. It features quite a few tabs that expose many useful settings to you. The first two tabs, “Exporting” and “Importing,” expose the new defaults files to you. For every import and every export format, you now have a corresponding defaults file. This allows you to fine-tune Pandoc, but not for every format, but for each format separately. The files are written in YAML and are located within the application data directory. We can’t go into much details here, but the Pandoc manual has got you covered as to how they work.
A third tab contains the custom CSS. We have moved it from its own dialog to the assets manager since it’s strictly speaking also just a file in the app data directory. Furthermore, you will notice that now the new custom CSS will be applied immediately after you save your changes, so you won’t have to close the dialog anymore to see the changes. You can comfortably have the custom CSS window next to Zettlr’s main window and play around with the styles!
Snippets
A last tab within the assets manager allows you to define files for another novel feature of Zettlr: Snippets. This feature has long been demanded, and with all the other changes in place I was finally able to implement it. Snippets are reusable pieces of text which you can insert into your documents. This allows you, for example, to define a YAML frontmatter with some properties already populated so that it will be easier for you to begin writing in a new file, without having to look up any property names or spend time typing the whole frontmatter anew every time. There are also a few variables that you can use so that even things like a date are filled in automatically. We have documented those variables in our documentation.
To get you started, here is one example snippet that will enable you to quickly start a new document:
---
title: "${1:Enter a title}"
date: $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE
id: $ZKN_ID
author: ${2:Enter your name}
---
# ${1:Enter a title}
$0
To insert it into your document, you just have to type a colon (:
), followed by the file name (which you can edit in the snippets tab). Then you can comfortably Tab
through the fields you have defined until you end up where the $0
is defined.
The New File and Folder Properties
Let us now move on to another novel feature of Zettlr which will make working with your files and folders much more convenient: properties. Previously, much of the information you needed to know about your individual files and folders was scattered across the user interface. But now, we have collected everything in one place. If you right-click any file or folder, you will see a new menu item, “Properties.” Clicking that will open a popover that shows you all information Zettlr has about that particular file or folder. It will show you precisely when the item has been created, when you last modified it, and also include a word counter. For files, you can set your writing targets here, and for folders, you can select a custom icon. Lastly, for folders, you will notice a new toggle which allows you to turn that folder into a project. And that leads us to an introduction to all the new stuff we did there as well!
Projects
When you open the properties of a project directory, or click the switch to turn one into a project, a host of new options will appear. First and foremost, as usual, you can set your title, but then you will have two tabs with more options available. In the first tab, you can select all the export formats you would like your project to be exported to. These options correspond to all the options you have for single-document exports, and you can select as many as you want. In the second tab, you can choose a specific CSL stylesheet to have your references render using a different citation style. Also, we have added the option to further filter out files. Previously, you had to make sure that no unwanted Markdown files are part of the project directory, since these would’ve ended up in your final export. This restriction does not apply anymore. Now you can define a so-called ‘glob’-filter which you can use to specify which files should be included when exporting your project. This allows you to store additional Markdown files in your project folder, or even YAML or JSON files, and instruct Zettlr to remove them from the list of files to be exported. For the rare cases in which one glob-pattern might not be enough, you can define multiple ones, each being applied subsequently and filtering the list further.
I’m pretty sure the projects will receive many more awesome features in further versions, but for now that is how they improve your experience already! Let us swiftly move to the next feature!
The New Full-Text Search
The next feature is not new, but it received a complete restauration that it could almost count as a new feature. You will notice that the global search input has disappeared from the toolbar. While it was certainly neat to have that innocent-looking input field in the toolbar with such a large amount of power under its hood, but a full-text search is capable of even more. Now, instead of simply entering some query and searching for things, the global search, rebranded as a full-text search, you have many more powers at your disposal!
First and foremost, you are now able to restrict the full-text search to a single directory. By default, it will restrict the search to your currently selected directory, but if you want to search all your open workspaces, simply click the x
in the text field. The field will also give you autocomplete capabilities so you don’t have to remember the exact name for the folder you want to search. Then, after the search has completed, you will see all search results in a much more comprehensive way. While the heatmap search was certainly a beautiful view, it didn’t convey as much information as possible, so we abandoned that approach. Instead, you will now see all files together with the search results in context. Each search result now conveys a number of information:
- The relevancy (which formerly was the intensity of the color in the heatmap search) is indicated with a small icon in front of the filename. A less relevant search result will have a gray icon, a relatively relevant result will feature a blue icon, and a very relevant search result will have a green icon.
- After the icon you will see the filename. Rather: The filename, if there is no title, or the first heading level 1, depending on your settings.
- To the right of the result, you will see an arrow pointing down. Clicking the arrow will hide the individual search results. You can also hide all results at once by clicking the button “Toggle results” that appears after you ran a search.
- Below the filename, you will see the full path from the root of the containing workspace to the individual filename so you immediately know where that file is coming from.
- Following that you will see the search results, beginning with the line number and then the full content of that line where Zettlr found your query. The actual matched part of the line is shown in bold.
To open search results, you can either click the file, middle-click the file to force Zettlr to open the result in a new tab, or right-click the result, which also allows you to open the file in a new Quicklook window.
Lastly, you can now further filter the search results in case you got way too many.
Wrapping Up the New Features
There are plenty more improvements to discover in Zettlr 2.0; too many in fact to enumerate them all here. Feel free to take a look around and see what has changed specifically! I’m sure you will be very happy with all new changes!
Upgrading Zettlr: What you should know
Before coming to an end in this rather long and packed article, I would like to shed some light onto upgrading your existing Zettlr install. While I spent a fair amount of time making sure that Zettlr will migrate your old configuration files and I haven’t gotten any complaints that something didn’t work, before upgrading to Zettlr 2.0 you might want to create a backup of your important files as outlined in the docs. Especially, you must backup all your writing targets, if you have any!! That configuration unfortunately can’t be migrated, so the writing targets will all be lost after the upgrade. However, if you simply note them down somewhere and then once re-apply them, you’re good to go. This is unfortunately one thing I cannot save you from, but I figured it’s not that bad, given all the perks and benefits!
The acknowledgment section
Zettlr 2.0 was a good chunk of work, and while it’s still more or less a one-man show, several people have congregated around the app in the past years, and many of which have played central roles in shaping Zettlr 2.0. In this section, I wanna give a big shoutout to all of those magnificent people who have helped make Zettlr what it is today! Please show your support for these people as well, because they’re part of the backbone of Zettlr and all deserve a good part of the merits!
I want to start with Tobias Diez, a fellow academic and also part of the core team of the JabRef reference manager. He basically initiated the whole journey to 2.0 with a pretty large Pull Request last year that brought Zettlr onto the path to a modern app. While that PR initially broke many things in the app, it enabled me to go full throttle with the whole Vue.js / TypeScript approach that I wanted to incorporate into the app for some time before his PR. And even afterwards, Tobias has proven to be a reliable helper in making sure that especially the formula- and math-capabilities of Zettlr continue to evolve. So, let me say thank you at this point for the help and support in the past!
The next person I would like to thank for this release is my friend Albert Krewinkel. Albert first contacted me in the beginning of 2020 to ask whether we should try to apply for a grant of the German Prototype fund. While that one didn’t turn out quite as we would’ve wanted, Albert continued to be a valuable friend to have. As one of the core developers of Pandoc, he was the one who suggested that I could simply bundle Pandoc with Zettlr, and he helped quite a bit whenever I had questions regarding some programming aspect where I simply wasn’t experienced enough. Albert is a great person who is always helpful and open for a good chat, and I am more than happy to have him among my close circle. Most of the capabilities of Pandoc Zettlr uses is not my knowledge, but Albert’s. So thanks to you as well, for mentorship, all the help you gave and for not losing your mind because I asked you way too often in a short amount of time!
Another valuable person during the development is Matt Jolly, who has been the primary driver of the exporter enhancements. Although notoriously short on time, he has always found time to discuss new ideas, and implement a few things himself. I would like to thank him especially for being a good community support who has not just helped me figure out how to do certain features, but who’s also pretty active on the GitHub discussions section and Reddit in helping others master Zettlr!
Lastly, with regard to developing Zettlr 2.0 I would also like a group of students from the University of Adelaide, Australia, for helping in development. Under the mentorship of Prof. Christoph Treude, several groups of students of the Open Source Software development course at the School of Computer Science have contributed great improvements to the source code of Zettlr during the summer. They managed to fix a few long-standing issues with the code base and added new features, such as the note-preview which lets you have a peek at linked notes without having to follow those links, the ability to scroll and select text also on the left side of the editor area, and the tray icon which is new in Zettlr 2.0. It was a pleasure working together with these students, and I’m honored that Zettlr has been chosen as a project for that course! Cheers to you!
A final named acknowledgment I would like to direct towards Arthur Perret, the bastion of the French Zettlr community. He has contributed the Bordeaux-theme to the app in the past, and continues to spread the word about Zettlr. One of his newest projects is a graph analyzing software, Cosma, which he and his team developed especially with Zettlr users in mind. Thank you!
Now, there are many people who’ve played a role in making Zettlr 2.0 a reality whom I cannot all name here. But let me say thank you to all the beta testers who have meticulously checked every feature to make sure we don’t overlook any bugs, who have provided feedback to ideas of mine, who shared dozens of screenshots and recordings, outlined specific problems, where things went south and how to mitigate this. Those, who have sifted through thousands of lines of logging entries to filter out when something went wrong, and where. Those, who were not afraid to potentially mess up some parts of their files in order to help me pinpoint severe problems that have all been found and fixed before the stable release. And all of those who reported feedback to me on Twitter, Reddit, the discussion forum, and, as of lately, Discord. Without the massive support the development of Zettlr has received throughout this difficult year, 2.0 would not have been possible, so to all of you: Thank you!!
Wrapping Up
Here we are, after almost a year of constant development, and I’m very proud of Zettlr has become as an app. I hope you enjoy this new version to the fullest while I take a break from development to focus solely on my PhD in the coming months. To wrap things up, here’s a coarse road map of what will be happening in the coming weeks and months with regard to Zettlr:
- Oct 15th, 2021: Zettlr 2.0 is released
- Nov 12th, 2021: The old translation strings that were deprecated after 1.8.9 will be removed, meaning that by then you should have switched to Zettlr 2.0. Otherwise, you will notice that some strings in the app will look weird and are missing.
- Dec 10th, 2021: I will disable the old deprecated API and fully switch to the new one, which means that no more updates are available to versions prior to 2.0
- January 2022: I will begin working on 2.1, which will feature the full switch to both Vue.js 3.0 and TypeScript across the full app.
Additionally, please keep in mind that updating the documentation will take a few weeks. Until then, please don’t hesitate asking on Discord or Reddit how something works, if the documentation hasn’t yet been updated for the particular feature you’re interested in!
Happy writing!