Get AI summaries of any video or article — Sign up free
Zettlr Development: Writing a Feature thumbnail

Zettlr Development: Writing a Feature

Zettlr·
5 min read

Based on Zettlr's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Alt/Option-clicking a link triggers an editor-side auto-search that extracts the link text and sends an IPC request to the main process with a force-open behavior.

Briefing

A practical feature request—“open a note by clicking an ID, and create it if it doesn’t exist”—turns into a tour of how Zettlr’s internals are wired together. The core finding is that the existing “link click → exact search → open result” pipeline already has almost everything needed; the missing piece is deciding where to insert “create file when not found,” and then threading a user-controlled preference through the renderer, IPC layer, and main process.

The workflow begins with the current behavior: holding Alt/Option while clicking an underlined link triggers an editor-side auto-search. That click path extracts the link text from CodeMirror-highlighted elements and sends it to the main process via IPC as a “find exact” request with a force-open flag. In the main process, the exact-match logic tries to resolve the term to a file by checking the current directory for allowed extensions (the app’s displayable types are limited to Markdown, text, and TeX-like files). If a match exists, the app opens it; if not, nothing happens.

To add auto-creation, the contributor reorganizes the code so the relevant behavior lives in the right place. Instead of inventing a new mechanism, the solution adds a new IPC command that mirrors the existing “first open” flow: it receives the term, attempts to find the exact file, and—only when the file is missing—optionally creates it. The creation step deliberately reuses existing file-system abstractions (the module responsible for file operations) and reuses an existing “file new” command to avoid duplicating sanitization and safety logic. This preserves Zettlr’s conventions for naming, ID handling, and error handling.

Because auto-creation should not surprise users, the feature is gated behind a preference. The implementation adds a new configuration key to the Handlebars-based preferences templates, then extends the corresponding renderer dialogue to read the checkbox state and send it to the main process. The preference is validated through the existing config template system, which filters invalid values when users edit configuration files. The UI wording is treated as part of the technical contract: the option is framed specifically as “create linked files,” not “create files on any search,” to reduce ambiguity.

Once the preference and command wiring are in place, the feature behaves as intended: clicking a link whose target doesn’t exist can create the corresponding Markdown/text/TeX file and open it. The implementation also surfaces real-world integration friction—debug artifacts like duplicated console output, promise rejection noise, and an observed interaction where the auto-search flow can interfere with the file list during creation. The takeaway is less about the final checkbox and more about the engineering pattern: identify the existing click/search/open pipeline, add one targeted command branch for “not found,” and route user intent through preferences so the app remains predictable.

Overall, the change is framed as a blueprint for contributing to Zettlr: understand the editor event path, trace the IPC call into the main process, reuse existing commands and file-system actions, and keep preferences and localization identifiers aligned with the project’s conventions before shipping a pull request to beta or release channels on GitHub and the forum.

Cornell Notes

Zettlr already supports “Alt/Option-click a link → extract link text → send exact-search/open request to the main process.” The missing feature is what happens when the target file doesn’t exist. The solution adds a new IPC command that performs the same exact-match lookup, but—when no file is found—optionally creates the file and then opens it. File creation is implemented by reusing Zettlr’s existing file-system abstraction and the existing “file new” command to avoid unsafe duplication of sanitization logic. A new preference checkbox (“create linked files”) gates the behavior, with the renderer dialogue reading the checkbox and the main process honoring it.

What exact click path triggers link opening in Zettlr, and where does the “force open” behavior come from?

Alt/Option-clicking a link in the editor routes through the editor’s click listener (often wrapped by CodeMirror). When the link element is detected, the editor triggers an auto-search with a parameter that sets a force-open flag. The editor then extracts the link text from the highlighted element (the inner text of the link span) and sends an IPC request to the main process to perform an exact lookup and open behavior.

How does Zettlr decide which file corresponds to a clicked link term?

The main-process exact-match routine first tries to resolve the term as a file ID/name, then falls back to trying the term with allowed extensions. The allowed file types are constrained to what Zettlr can display: Markdown, text, and TeX-like files. If the term includes no extension, the resolver attempts combinations like name.md, name.txt, and name.tex (based on the app’s extension list).

Why add a new IPC command instead of changing the existing exact-open logic directly?

The implementation keeps the existing “find exact” behavior intact and introduces a parallel command that can branch on “file not found.” This makes the change more targeted: the new command can check the new preference and only create files when the user opted in. It also aligns with Zettlr’s command registration pattern, where renderer-to-main IPC events map to command handlers.

How does the preference checkbox get from the UI to the main process?

A new configuration key is added to the Handlebars preferences templates (with validation handled by the config template system). Then the renderer dialogue that manages preferences overrides a data-processing function to include the checkbox state. That state is sent through the existing command/IPC plumbing so the main process can read the preference and decide whether to create missing files.

Why reuse the existing “file new” command for creation rather than writing a direct file-creation snippet?

Direct creation risks missing Zettlr’s safety steps—especially filename sanitization and other invariants. By calling the existing “file new” command, the feature inherits the app’s established logic for creating valid notes and ensuring IDs and metadata are handled consistently. This reduces the chance of edge-case breakage.

What integration issue appeared during testing, and what does it imply about coupling between search UI and file creation?

During testing, the auto-search flow appeared to interfere with the file list while the new file was being created, producing confusing artifacts (including duplicated-looking entries). The observation suggests that UI search state and file-system updates can race or trigger re-rendering in ways that affect what the user sees, so contributors should watch for side effects when combining “search/open” and “create/open” behaviors.

Review Questions

  1. Trace the flow from Alt/Option-clicking a link to the main-process function that performs exact matching. Where would you insert “create if missing”?
  2. What are the allowed file types Zettlr uses for exact resolution, and how does the resolver behave when the clicked term has no extension?
  3. How should a new preference be implemented so its value is validated, localized, and available to the main process when an IPC command runs?

Key Points

  1. 1

    Alt/Option-clicking a link triggers an editor-side auto-search that extracts the link text and sends an IPC request to the main process with a force-open behavior.

  2. 2

    Exact file resolution in the main process tries ID/name matching and then appends allowed extensions (Markdown, text, TeX-like) when needed.

  3. 3

    A new IPC command can mirror the existing exact-open flow but add a conditional branch for “file not found,” gated by a preference.

  4. 4

    File creation should reuse Zettlr’s file-system abstraction and the existing “file new” command to avoid unsafe duplication of sanitization and metadata logic.

  5. 5

    A new preference checkbox (“create linked files”) must be added to Handlebars templates, wired through the renderer dialogue, and validated via the config template system.

  6. 6

    Testing revealed that search UI state can interact unexpectedly with file creation, so contributors should watch for race conditions and UI artifacts.

Highlights

The feature fits into an existing pipeline: link click already becomes “exact search/open,” so “create if missing” is a small, targeted extension rather than a rewrite.
Preference gating is treated as part of correctness: the checkbox must clearly mean “create linked files,” not “create files on any search,” to avoid user surprise.
Reusing “file new” is a safety strategy—creation logic is centralized so contributors don’t accidentally bypass sanitization or ID conventions.

Topics

  • Zettlr Internals
  • IPC Commands
  • File Resolution
  • Preferences
  • Auto Creation

Mentioned

  • IPC