<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kevin Lin</title>
    <description>The latest articles on Forem by Kevin Lin (@kevinslin).</description>
    <link>https://forem.com/kevinslin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F456385%2Ffd9870c8-d023-4131-9b9b-fb906504c9a3.jpeg</url>
      <title>Forem: Kevin Lin</title>
      <link>https://forem.com/kevinslin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kevinslin"/>
    <language>en</language>
    <item>
      <title>Cache All the Things - A PKM workflow to incrementally retain (and find) everything</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Thu, 29 Sep 2022 15:53:40 +0000</pubDate>
      <link>https://forem.com/dendron/cache-all-the-things-a-pkm-workflow-to-incrementally-retain-and-find-everything-ne3</link>
      <guid>https://forem.com/dendron/cache-all-the-things-a-pkm-workflow-to-incrementally-retain-and-find-everything-ne3</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;An engineering manager that will remain unnamed told me his story of trying to find the solution to a technical problem on the internet. &lt;br&gt;
It's the typical &lt;code&gt;question -&amp;gt; google -&amp;gt; stack overflow -&amp;gt; answer&lt;/code&gt; pathway with a twist - when he finally found the answer, he realized that &lt;strong&gt;he himself had created&lt;/strong&gt; the question a year prior.&lt;/p&gt;

&lt;p&gt;I like this story because it's easy to relate to. Haven't we all searched for something that turned out to be a problem we've already encountered?&lt;/p&gt;

&lt;p&gt;The process of searching for answers on the internet is what doing software (and much of knowledge work) is like in the 20th century. &lt;/p&gt;

&lt;p&gt;There is an overwhelming amount of information we need to process just to do our job. It is impossible (nor useful) to keep this information in our heads so we rely on services like google to help look up what we don't know (or have forgotten). &lt;/p&gt;

&lt;p&gt;While this can work, there is a problem when we come to depend on this workflow for getting through the day. It's like &lt;strong&gt;only relying&lt;/strong&gt; on google maps to get home - while this works, you also lose the ability to navigate on your own in the process.  &lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;groundhog day loop&lt;/strong&gt; - regardless of how much you search, learnings are quickly forgotten and mastery is never built. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2Fgroundhog-loop_excalidraw_png___dendron__Workspace__AZhYnQ8c8.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1664217920426" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2Fgroundhog-loop_excalidraw_png___dendron__Workspace__AZhYnQ8c8.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1664217920426" alt="Groundhogs day loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now imagine the same workflow where instead of starting with a search, you look up information in your personal knowledge &lt;a href="https://en.wikipedia.org/wiki/Cache_(computing)" rel="noopener noreferrer"&gt;cache&lt;/a&gt;. This cache contains every problem you have ever encountered and is accessible in seconds. If you find the answer, you're done, and if not, you can be &lt;strong&gt;certain that it is not there&lt;/strong&gt;. Only then do you fall back to search. When you find the answer, you add it to your cache so you can make use of it in the future.&lt;/p&gt;

&lt;p&gt;This is a mastery loop - instead of losing your place on every question, you build and reinforce your understanding of things with each problem you encounter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2Fgroundhog-loop_excalidraw_png___dendron__Workspace__EAz4ggBhd.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1664217901697" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2Fgroundhog-loop_excalidraw_png___dendron__Workspace__EAz4ggBhd.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1664217901697" alt="Mastery Loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key to building this particular mastery loop comes from combining the following  PKM workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a modified version of the &lt;a href="https://fortelabs.com/blog/progressive-summarization-a-practical-technique-for-designing-discoverable-notes/" rel="noopener noreferrer"&gt;progressive summarization method&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dendron.so/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64" rel="noopener noreferrer"&gt;A Hierarchy First Approach to Note Taking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they let you &lt;strong&gt;cache all the things!&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Progressive Summarization
&lt;/h2&gt;

&lt;p&gt;If you're not familiar with the term, &lt;strong&gt;progressive summarization&lt;/strong&gt; is the means of incrementally retaining insights from text to be used at a future date. It is built around five layers of summarization and pioneered by &lt;a href="https://fortelabs.com/" rel="noopener noreferrer"&gt;Tiago Forte&lt;/a&gt;, a big influencer in the PKM space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2FIs_Progressive_Summarization_a_Waste_of_Time____JamesStuber_com_amM-cCvqM.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1661467439325" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Ffpjzhqpv1%2FIs_Progressive_Summarization_a_Waste_of_Time____JamesStuber_com_amM-cCvqM.png%3Fik-sdk-version%3Djavascript-1.4.3%26updatedAt%3D1661467439325" alt="Progressive summarization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steps are described in more detail below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you come across useful information, save excerpts from it.  This is layer 1. The benefit: next time you revisit the notes, you can just go over your excerpts instead the entire text. &lt;/li&gt;
&lt;li&gt;If you happen to need the text again, &lt;strong&gt;bold specific passages&lt;/strong&gt; that stand out as you're reviewing.  This is layer 2 and serves to make future skimming easier.&lt;/li&gt;
&lt;li&gt;If you require the text again, ==highlight from the bolded parts== insights that are especially poignant. This is layer 3 and it represents the highest quality insights that you've derived from the specific text. &lt;/li&gt;
&lt;li&gt;If you still have need of the text, make a summary of it in your own words. This is layer 4 and represents the start of reframing the text in your own words.&lt;/li&gt;
&lt;li&gt;If you then find the text relevant in some current project, the final step is to remix it into your own material. This is layer 5 and represents the culmination of all the prior layers. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are some highly desirable characteristics of &lt;strong&gt;progressive summarization&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;just in time vs ahead of time&lt;/strong&gt;: you only do the work when you need to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;incremental work&lt;/strong&gt;: you only do minimal work at each layer which can then be leveraged in later layers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;active vs passive&lt;/strong&gt;: you actively read the text instead of skimming it&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  A Hierarchy First Approach to Knowledge Management
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://blog.dendron.so/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64" rel="noopener noreferrer"&gt;Hierarchy First Approach to Knowledge Management&lt;/a&gt; excels at helping people organize lots of information in a consistent structured way for later retrieval. &lt;/p&gt;

&lt;p&gt;It provides a foundation to create a knowledge base that can grow to any size while ensuring that information remains accessible. You can read more about the details of this workflow in the original blog post - &lt;a href="https://www.kevinslin.com/notes/e1455752-b052-4212-ac6e-cc054659f2bb" rel="noopener noreferrer"&gt;It's Not You - It's Your Knowledge Base&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Cache all the Things
&lt;/h2&gt;

&lt;p&gt;Progressive Summarization helps with retaining key insights from text, the Hierarchy First Approach helps organize those summaries so that they can be found again later. The combination of the two lets us create a knowledge base of distilled insights that can be accessed at a moment's notice. &lt;/p&gt;

&lt;p&gt;There are five levels to this hybrid technique and we'll spend some time explaining each in greater detail below.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Note&lt;/li&gt;
&lt;li&gt;Expand&lt;/li&gt;
&lt;li&gt;Split&lt;/li&gt;
&lt;li&gt;Standardize&lt;/li&gt;
&lt;li&gt;Refactor&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Level 1 - Note
&lt;/h3&gt;

&lt;p&gt;When you come across information that turns out to be useful, make a note of it. This is done by copying the relevant excerpts from the source material. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Greg is a new engineer at Literal, a social VR company. Their first assignment is to change a hard-coded welcome string to an internationalized string. Their mentor recommends using the CLI tool &lt;code&gt;grep&lt;/code&gt; to find all instances of the string. Greg has never used &lt;code&gt;grep&lt;/code&gt; before so spends some time learning about it.  He captures a basic example of running the command in his notes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;
## Synopsis



```
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...] 
```



## Example



```sh
grep 'python' *
```


&lt;/pre&gt;
&lt;h3&gt;
  
  
  Level 2 - Expand
&lt;/h3&gt;

&lt;p&gt;If you find yourself continuously going back to the source material because you end up using more functionality, invest in adding more information to your note. For example, this could detail instructions for the new functionality or hard-won insights you've discovered through trial and error. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Greg finishes his first assignment and ends up doing more localization work. He uses &lt;code&gt;grep&lt;/code&gt; quite a lot and discovers that he can use regex to speed up his workflow. He has also at this point noticed some mistakes he keeps making with the options. Greg makes a note of all of this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;
## Synopsis



```
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...] 
```



## Gotchas

- large repetitions can cause memory exhaustion
- must escape `()|-` signs
- set option flags **before** the PATTERN

## Options

- \-P  use perl like regex (you can lookahead and lookbehind)
- \-i: Ignore casecase
- \-x: Force search to match line

## Example



```sh
grep 'python' *
```



&lt;/pre&gt;
&lt;h3&gt;
  
  
  Level 3 - Split
&lt;/h3&gt;

&lt;p&gt;If you continue to expand the note, the note will eventually exceed the limit of a single page (eg. 800 words). At this point, you want to split your notes into smaller notes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The process of splitting of large notes into smaller notes is also known as the &lt;a href="https://wiki.dendron.so/notes/e780000d-c784-4945-8e42-35218a3ecf10" rel="noopener noreferrer"&gt;amoeba pattern&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Greg finds himself using grep all the time and he now has to spend time scrolling through his &lt;code&gt;grep&lt;/code&gt; note to find what he needs. He has a section on snippets that makes up most of the note so he decides to split it off into its own note.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── grep
    └── snippets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Level 4 - Standardize
&lt;/h3&gt;

&lt;p&gt;As you continue the process of expanding and splitting notes, you tend to find certain clusters of notes will all have the same shape. When this pattern starts to emerge, you can standardize these patterns into hierarchies. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As Greg takes on bigger assignments, he also expands his arsenal of CLI commands. Greg realizes after a while that all CLI commands have a similar structure and so he consolidates it in a hierarchy.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── cli/
    ├── grep
    │   └── snippets
    ├── sed
    ├── awk
    │   └── snippets
    ├── git
    ├── test
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Level 5 - Refactor
&lt;/h3&gt;

&lt;p&gt;In software engineering, &lt;a href="https://en.wikipedia.org/wiki/Code_refactoring" rel="noopener noreferrer"&gt;refactoring&lt;/a&gt; is "the process of restructuring existing (information) — changing the factoring — without changing its external behavior"&lt;/p&gt;

&lt;p&gt;Refactoring is done because the original structure can outgrow its usefulness. Sometimes the underlying information changes or your understanding of it does. Regardless, this means that you will need to update your hierarchies to account for this change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Greg is tasked with a new assignment that involves working with windows and the PowerShell instead of the Linux terminal. He discovers that the PowerShell has its own set of commands and that the same commands in Linux will have slightly different behavior for Powershell. Greg proceeds to refactor his original hierarchy&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── cli/
    ├── linux
    │   ├── grep
    │   │   └── snippets
    │   ├── sed
    │   ├── awk
    │   │   └── snippets
    │   ├── git
    │   └── test
    │   └── ...
    └── powershell
        ├── CopyCmd
        ├── grep
        └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;The workflow we just described can be applied outside of &lt;code&gt;CLI&lt;/code&gt; commands to cover any information you might want to track. It allows you to systematically build up both your reference of "facts" in a domain as well as an underlying mental model of said domain. &lt;/p&gt;

&lt;p&gt;The challenge in actually implementing this workflow generally surfaces in the latter two levels: standardization and refactoring. &lt;/p&gt;

&lt;p&gt;Standardization into hierarchies is difficult because creating hierarchies is usually time-consuming and adds friction to both the retrieval and capture of new information. &lt;/p&gt;

&lt;p&gt;Refactoring is hard because it usually relies on manually moving old notes into new hierarchies and also breaks links in the process.&lt;/p&gt;

&lt;p&gt;This is why we created &lt;a href="https://wiki.dendron.so/" rel="noopener noreferrer"&gt;Dendron&lt;/a&gt; - a note-taking tool that helps people &lt;strong&gt;organize and refactor&lt;/strong&gt; their notes.&lt;/p&gt;

&lt;p&gt;By making it easy to standardize into hierarchies and refactor as needed, Dendron makes it possible to create, maintain, and make use of knowledge bases that span from a single README file to hundreds of thousands of notes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Information can be overwhelming but it doesn't have to be. &lt;/p&gt;

&lt;p&gt;We've long passed the point where we can keep everything in our heads. While that information is available on the internet, it takes time to find and is hard to retain. &lt;/p&gt;

&lt;p&gt;By combining Progressive Summarization with a Hierarchy First Approach to Knowledge Management, we've created a workflow that lets us &lt;strong&gt;externalize an unlimited amount of information&lt;/strong&gt; and the means to &lt;strong&gt;quickly find it again&lt;/strong&gt; when needed.&lt;/p&gt;

&lt;p&gt;This incremental caching of everything represents an escape from the endless cycle of searching for things we've already done and instead, lets us focus our efforts on the novel and bigger challenges of the day. &lt;/p&gt;

&lt;p&gt;Imagine how much more effective we could be, as individuals, teams, and as a society, if we could build on top of what we knew instead of spending time forgetting and re-discovering hard-earned knowledge?&lt;/p&gt;

&lt;p&gt;And now stop imagining and start caching!&lt;/p&gt;

</description>
      <category>pkm</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Dendron 100</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Tue, 21 Jun 2022 15:28:47 +0000</pubDate>
      <link>https://forem.com/dendron/dendron-100-35of</link>
      <guid>https://forem.com/dendron/dendron-100-35of</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Dendron is launching on product hunt today. If Dendron has been of use to you, please leave feedback on our &lt;a href="https://www.producthunt.com/posts/dendron-v100"&gt;launch page&lt;/a&gt; - this would help us out a lot! 🙏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;Two years ago, we launched Dendron because we believed there was a &lt;a href="https://www.kevinslin.com/notes/e1455752-b052-4212-ac6e-cc054659f2bb.html"&gt;better way of managing knowledge&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The problem - we are all drowning in information! Existing tools try to make it easy to get knowledge in but fail at getting that information back out when needed.&lt;/p&gt;

&lt;p&gt;Dendron is a developer-focused, open-source, note-taking tool.  It combines the simplicity of markdown with the power of VSCode.  To manage information at scale, Dendron applies the insights we've learned from five decades of developer tooling and brings it to general knowledge. &lt;/p&gt;

&lt;p&gt;Since 2020, we've been iterating on this thesis with weekly releases to make Dendron better, faster and stronger! With the v100 release, we'll take a moment to go over some highlights.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better
&lt;/h3&gt;

&lt;p&gt;In a well-designed system, easy things should be easy and hard things possible. &lt;/p&gt;

&lt;p&gt;This hasn't always been the case at Dendron and it's something we've put in a lot of effort addressing through improved documentation, feature work, and better defaults.&lt;/p&gt;

&lt;p&gt;Besides creating a catalog of &lt;a href="https://wiki.dendron.so/notes/ordz7r99w1v099v14hrwgnp"&gt;talks&lt;/a&gt; and &lt;a href="https://wiki.dendron.so/notes/9313b845-d9bf-42c9-aad1-0da34794ce26"&gt;guides&lt;/a&gt; of how Dendron is used in the wild, we've also kicked off a &lt;a href="https://handbook.dendron.so/notes/ebpudfrf6rg5uut75d29lhg"&gt;standardization effort&lt;/a&gt; across all our docs so that any feature, command, or config is just a &lt;a href="https://wiki.dendron.so/notes/a7c3a810-28c8-4b47-96a6-8156b1524af3"&gt;lookup&lt;/a&gt; away!&lt;/p&gt;

&lt;p&gt;Feature wise, the following are some areas we've invested in to make common workflows easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;a href="https://wiki.dendron.so/notes/9b059u38o0b7fydjgoazt06"&gt;Dendron Sidebar&lt;/a&gt; provides one click access to most frequently used features like backlinks and the tree view&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://wiki.dendron.so/notes/eea2b078-1acc-4071-a14e-18299fc28f47"&gt;Import Obsidian Vault&lt;/a&gt; command provides a one click method for importing your notes&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://wiki.dendron.so/notes/c877f1204xn2ev5djgwc7do"&gt;Help and Feedback&lt;/a&gt; panel provides a cheatsheet of useful resources and docs&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://wiki.dendron.so/notes/te9obzegtn5vjrsdf4sp5xx"&gt;Tip of the Day&lt;/a&gt; panel highlights new features and enhancements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, many of Dendron's core use cases now come with better defaults. For example, &lt;a href="https://wiki.dendron.so/notes/ogIUqY5VDCJP28G3cAJhd"&gt;daily journals&lt;/a&gt; and &lt;a href="https://wiki.dendron.so/notes/5c213aa6-e4ba-49e8-85c5-1bdcb33ce202"&gt;meeting notes&lt;/a&gt; have built-in &lt;a href="https://wiki.dendron.so/notes/861cbdf8-102e-4633-9933-1f3d74df53d2"&gt;templates&lt;/a&gt; that get created the first time these commands are invoked. &lt;/p&gt;

&lt;h3&gt;
  
  
  Faster
&lt;/h3&gt;

&lt;p&gt;Life is too short to wait for your notes to load. &lt;/p&gt;

&lt;p&gt;Dendron has always been fast - much of this we get for free because your notes are just local plaintext files stored in your computer. &lt;br&gt;
Over the past year, we've optimized all the parts of Dendron's lifecycle, which include initialization, lookup, publishing, and autocomplete just to name a few. &lt;/p&gt;

&lt;p&gt;These changes resulted in orders of magnitude better performance across the board and &amp;lt;100ms of latency for the most common actions in Dendron   🚀 🚀 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Stronger
&lt;/h3&gt;

&lt;p&gt;Our goal is to make Dendron an IDE for knowledge. &lt;br&gt;
Since 2020, we've released &lt;strong&gt;over 600 features&lt;/strong&gt; to augment what you can do with plaintext.&lt;/p&gt;

&lt;p&gt;Some highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wiki.dendron.so/notes/1mu1qb1vilhqr7tlatwyqxm"&gt;Handlebar Templates&lt;/a&gt; that allow augmentation of your templates with conditions, variables, and for loops&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.dendron.so/notes/ckkmesn09bye11sdnaoqcut"&gt;Hovers&lt;/a&gt; over links and backlinks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.dendron.so/notes/bdZhT3nF8Yz3WDzKp7hqh"&gt;Note Traits&lt;/a&gt; that allow you to create notes with custom behavior&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.dendron.so/notes/4ushYTDoX0TYQ1FDtGQSg"&gt;Publishing using NextJS&lt;/a&gt; with selective publishing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the full changelog of all features, see the &lt;a href="https://wiki.dendron.so/notes/FPXeGgv44ZlJHVoXmU8Ku"&gt;release notes&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Prior to Dendron, I worked at Amazon for over half a decade. &lt;br&gt;
Something that stuck with me from my time there is that it's always &lt;a href="https://aws.amazon.com/executive-insights/content/how-amazon-defines-and-operationalizes-a-day-1-culture/"&gt;day one&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is especially relevant when dealing with knowledge management today because how humans manage information in the age of the internet is fundamentally an unsolved problem.&lt;br&gt;
With Dendron, we think we have something that works. &lt;br&gt;
Whether you are an individual managing a handful of notes or a team with tens of thousands of notes, Dendron helps you stay organized and on top of it all.&lt;/p&gt;

&lt;p&gt;We've spent the past 100 releases iterating on our &lt;a href="https://blog.dendron.so/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64"&gt;hierarchy first approach to note taking&lt;/a&gt; and we'll spend a few hundred more building on top of this foundation.  On behalf of the entire Dendron team, I would like to say thanks to everyone that helped make this happen - chiefly our wonderful community and our steadfast investors.  Here's to the next 100 releases!&lt;/p&gt;

&lt;p&gt;Sincerely, &lt;br&gt;&lt;br&gt;
- Kevin&lt;/p&gt;

</description>
      <category>pkm</category>
      <category>opensource</category>
      <category>devjournal</category>
      <category>vscode</category>
    </item>
    <item>
      <title>VSCode - Markdown Edition</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Mon, 09 May 2022 15:57:50 +0000</pubDate>
      <link>https://forem.com/dendron/vscode-markdown-edition-e73</link>
      <guid>https://forem.com/dendron/vscode-markdown-edition-e73</guid>
      <description>&lt;p&gt;With the &lt;a href="https://code.visualstudio.com/updates/v1_67"&gt;1.67 release&lt;/a&gt;, markdown gains programming language like tooling in VSCode &lt;/p&gt;

&lt;p&gt;Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;drag and drop files into the editor to create a markdown link&lt;/li&gt;
&lt;li&gt;find all references to header|links|files|urls inside of markdown&lt;/li&gt;
&lt;li&gt;rename headers|links inside markdown  (and propagate the changes to all places where the link is used)&lt;/li&gt;
&lt;li&gt;rename markdown files (and propagate changes to all links referencing said file)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we move past drag and drop, it's notable that all other functions are related to referencing and renaming symbols. These are capabilities that are more commonly associated with programming languages than markdown. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A programming language is any set of rules that converts strings... to various kinds of machine code output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Programming_language#Static_semantics"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Programming languages generally have a strict syntax that constrains the language. IDEs leverage this strict syntax to offer features to manipulate symbols within the language. &lt;/p&gt;

&lt;p&gt;Markdown also has &lt;em&gt;&lt;a href="https://daringfireball.net/projects/markdown/syntax"&gt;syntax&lt;/a&gt;&lt;/em&gt; (albeit more loosely defined) . This makes it possible to introduce similar transformations onto markdown. &lt;/p&gt;

&lt;p&gt;The reason that this functionality is useful (and necessary) for programming languages is because codebases today can be massive, surpassing &lt;a href="https://www.quora.com/How-many-lines-of-code-is-Google-Chrome"&gt;hundreds of millions of lines of code&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Repositories of markdown can also be massive. They are increasingly used to document and store general knowledge - both in the context of personal knowledge management (PKM) and team knowledge management (TKM). &lt;/p&gt;

&lt;p&gt;For purposes of illustration - the primary &lt;a href="https://wiki.dendron.so/notes/6682fca0-65ed-402c-8634-94cd51463cc4"&gt;vault&lt;/a&gt; (the circle titled &lt;code&gt;private&lt;/code&gt;) for the Dendron team has over &lt;strong&gt;400k lines&lt;/strong&gt; of markdown. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w5aMfxoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://org-dendron-public-assets.s3.amazonaws.com/images/upyp4ow9fkpwvu50n8wsvnp-dendron-private.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w5aMfxoq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://org-dendron-public-assets.s3.amazonaws.com/images/upyp4ow9fkpwvu50n8wsvnp-dendron-private.png" alt="Dendron workspace" width="880" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The illustartion is generated using a fork of github's &lt;a href="https://github.com/kevinslin/repo-visualizer"&gt;repo-visualization&lt;/a&gt; code, first described &lt;a href="https://githubnext.com/projects/repo-visualization/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Running &lt;code&gt;cloc&lt;/code&gt; returns the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cloc --vcs=git .
github.com/AlDanial/cloc v 1.92  T=7.82 s (1472.4 files/s, 65739.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Markdown                     11494         108500             19         404711
JSON                             3              5              0            369
YAML                            14              1              0            351
-------------------------------------------------------------------------------
SUM:                         11511         108506             19         405431
-------------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given the shared syntactical properties and problems of scale between programming languages and markdown, it makes sense that the same tooling can work for both.&lt;/p&gt;

&lt;p&gt;VSCode, and IDEs more broadly, help developers manage large code bases by making available tools to leverage and manipulate the &lt;strong&gt;syntax&lt;/strong&gt; of programming languages. By shifting some of this tooling to markdown, can we do the same for large markdown repositories?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.dendron.so/notes/N9VxT7G5SovmncezBAGO2"&gt;Our bet&lt;/a&gt; at &lt;a href="https://www.dendron.so/"&gt;Dendron&lt;/a&gt; is a resounding &lt;strong&gt;yes!&lt;/strong&gt; This is why we built our knowledge management platform inside of VSCode. By leveraging the paradigms from IDEs and applying them to &lt;a href="https://wiki.dendron.so/notes/c5e5adde-5459-409b-b34d-a0d75cbb1052"&gt;structured&lt;/a&gt; markdown, our mission is to help &lt;strong&gt;humans&lt;/strong&gt; &lt;a href="https://www.kevinslin.com/notes/e1455752-b052-4212-ac6e-cc054659f2bb"&gt;manage any amount of information&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>markdown</category>
      <category>pkm</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Writing a Visual Studio Code Completion Provider</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Thu, 23 Sep 2021 16:43:43 +0000</pubDate>
      <link>https://forem.com/dendron/writing-a-visual-studio-code-completion-provider-198f</link>
      <guid>https://forem.com/dendron/writing-a-visual-studio-code-completion-provider-198f</guid>
      <description>&lt;p&gt;Visual Studio Code (VSCode) provides many powerful features for extension developers. Autocomplete, warnings, tasks, and many more features are included out-of-the-box and are available for extension developers to take advantage of. However, figuring out how you can take advantage of these features as an extension developer can require digging through API documentation to learn the exact behavior. Using the API incorrectly can lead to issues that are hard to debug, as I learned working on the block autocomplete feature for Dendron.&lt;/p&gt;

&lt;p&gt;This post is an overview of VSCode autocomplete —also called intellisense— feature from the viewpoint of an extension developer. I especially want to highlight a few pitfalls: VSCode provides defaults for many of the options around autocomplete, but the behavior of these defaults can be confusing if you don't know what they are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entry point
&lt;/h3&gt;

&lt;p&gt;Your entry point into adding an autocomplete feature is &lt;code&gt;languages.registerCompletionItemProvider&lt;/code&gt;. This allows you to attach a function that will generate the options when requested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerCompletionItemProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;provideCompletionItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;provideBlockCompletionItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above is how Dendron attaches the completion provider for blocks. This part is straightforward, although note the symbols at the end. These are the symbols that when written will trigger your completion provider automatically. While you can define multiple symbols, each symbol has to be a single character. If An overview &amp;amp; tutorial of writing VSCode completion providers (intellisense) as an extension developer&lt;/p&gt;

&lt;p&gt;Next, let's take a look at the completion function. Here is the function signature for Dendron:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;provideBlockCompletionItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TextDocument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;CancellationToken&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CompletionItem&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;document&lt;/code&gt; and &lt;code&gt;position&lt;/code&gt; are straightforward. &lt;code&gt;token&lt;/code&gt; is used to cancel completions, for example if the user hits cancel while waiting for the completions. Key thing about the token is to remember that javascript is single-threaded: the token won't suddenly get cancelled in the middle of your function. The only point where it can become cancelled is if you &lt;code&gt;await&lt;/code&gt; for something and yield the execution. This means you don't have to check if the token is cancelled everywhere in your code, just check after any &lt;code&gt;await&lt;/code&gt;ed operation that might take a significant amount of time. Checking the token is easy, &lt;code&gt;if (token?.isCancellationRequested) return;&lt;/code&gt; is enough.&lt;/p&gt;

&lt;p&gt;The more important thing here is how the function gets called. One way the function will get called is if the user types one of the trigger symbols you registered. Another way is if the user hits the key for "Trigger Suggest" (&lt;code&gt;Ctrl+Space&lt;/code&gt; by default), &lt;em&gt;all&lt;/em&gt; registered completion providers for this language will run. Crucially, this means your completion provider may be activated at any point in the document, with or without your trigger key.&lt;br&gt;
It's up to your implementation to check if the current &lt;code&gt;position&lt;/code&gt; is somewhere that this completion is appropriate for, and &lt;code&gt;return;&lt;/code&gt; if not. Let's look at a simplified version of how Dendron handles this for the autocomplete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RegExpMatchArray&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lineAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// There may be multiple links within this line&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LINK_WITH_BLOCK_REGEX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;entireLink&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// If the current position is within this link, then we are trying to complete it&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;entireLink&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gist of it is that we get the text for the current line, and check if the current position is inside a link with a block that we can complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;CompletionItem&lt;/code&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;label&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;A key part of the completion item is the label. The label is not only displayed for the completion items, but it's also used as a default for many of the options in a &lt;code&gt;CompletionItem&lt;/code&gt;. The text that gets inserted when the user selects something, deciding the order in which these items are displayed, and how these options are narrowed when the user types are all based on the label by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FQu2LPJR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FQu2LPJR.png" alt="A screen shot displaying several completion items. "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;range&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The range is the most confusing part of the &lt;code&gt;CompletionItem&lt;/code&gt; in my opinion. The range determines 2 things: where the selected item will be inserted, and also what counts as "stuff that the user typed to narrow the items".&lt;/p&gt;

&lt;p&gt;For the first use of range, whatever range you provide will be replaced with the &lt;code&gt;insertText&lt;/code&gt; (or missing that, &lt;code&gt;label&lt;/code&gt;) of the completion item. If you have nothing to replace, the range can have &lt;code&gt;start === end&lt;/code&gt; in which case the text is just inserted at that point.&lt;/p&gt;

&lt;p&gt;The second use of range makes things a bit more tricky. Because the range determines what counts as "stuff the user typed", you have to be careful about what you include in the range. For example, Dendron's autocomplete allows users to type &lt;code&gt;[[^&lt;/code&gt; to get all blocks within a text as autocomplete options.&lt;/p&gt;

&lt;p&gt;The problem? The user needs to type &lt;code&gt;^&lt;/code&gt; to activate the completion, but &lt;code&gt;^&lt;/code&gt; is not part of any completion item, and also &lt;code&gt;^&lt;/code&gt; needs to be removed once an item is selected because the text is supposed to look like &lt;code&gt;[[#^something]]&lt;/code&gt; after the completion. &lt;/p&gt;

&lt;p&gt;While it would be convenient to just set the range to anything within the brackets, this will result in all completion items being narrowed out because &lt;code&gt;^&lt;/code&gt; will also count as "stuff the user typed to narrow the items".&lt;/p&gt;

&lt;p&gt;Something important to bring up here is the default for &lt;code&gt;range&lt;/code&gt;. If you look&lt;br&gt;
into the docs, you'll see that the default is the "range of the current word",&lt;br&gt;
effectively the output of &lt;code&gt;TextDocument.getWordRangeAtPosition&lt;/code&gt; function.&lt;br&gt;
&lt;code&gt;getWordRangeAtPosition&lt;/code&gt; allows you to set a custom regex to select what&lt;br&gt;
"current word" means, so this might sound like a good way to calculate the&lt;br&gt;
range. While this would work in some cases, I found that&lt;br&gt;
&lt;code&gt;getWordRangeAtPosition&lt;/code&gt; is extremely inefficient if your regex is more complex&lt;br&gt;
than &lt;code&gt;[...]+&lt;/code&gt;. Especially using lookaheads or lookbehinds causes VSCode to&lt;br&gt;
completely hang. I'd recommend avoiding this function unless the default mostly&lt;br&gt;
works for you.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;code&gt;sortText&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This field is used to determine in what order the completion items are &lt;em&gt;initially&lt;/em&gt; ordered. Initially is important here, as VSCode may move the items around once the user starts typing if it decides some items match the text better.&lt;/p&gt;

&lt;p&gt;The annoying part about &lt;code&gt;sortText&lt;/code&gt;: it simply sorts the items using basic string sorting. Issue here being that if you have a loop to generate your completion items, you can't just use the index to sort the items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// These won't sort right, because "11" &amp;lt; "9" in string sort&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sortText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is to pad your &lt;code&gt;sortText&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sortText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a perfect fix of course, but it's unlikely that you'll have over 99999 completion items.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;insertText&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is the text to be inserted when the user selects a completion. By default&lt;br&gt;
it's set to the label, but you'll want to set this if you are using the label to&lt;br&gt;
display something more informative to the user. For example, when completing&lt;br&gt;
blocks, Dendron uses the label to display the actual line the user is selecting.&lt;br&gt;
But the text we need to insert into the wikilink is not the same as the line&lt;br&gt;
itself, so we set this to get it to link to the right place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;insertText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`#&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AnchorUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;anchor2string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;additionalTextEdits&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;insertText&lt;/code&gt; replaces the part of the text that is selected by the &lt;code&gt;range&lt;/code&gt;. This&lt;br&gt;
is actually quite limiting: As I mentioned before, &lt;code&gt;range&lt;/code&gt; not only selects the&lt;br&gt;
what will be replaced but also what VSCode considers "typed by the user to&lt;br&gt;
narrow options". What if you want something to be replaced along with what the&lt;br&gt;
user typed, but you don't want it to be used in narrowing?&lt;/p&gt;

&lt;p&gt;For example, when autocompleting for blocks in Dendron the user might type&lt;br&gt;
&lt;code&gt;[[^some-header&lt;/code&gt;, but the resulting link will look like&lt;br&gt;
&lt;code&gt;[[#some-header-text-here]]&lt;/code&gt;. We need to remove &lt;code&gt;^&lt;/code&gt; along with whatever the user&lt;br&gt;
typed, but if we set the &lt;code&gt;range&lt;/code&gt; to include it then the narrowing would be&lt;br&gt;
thrown off because it would look for options where the label includes &lt;code&gt;^&lt;/code&gt;.&lt;br&gt;
To get around this, we use the &lt;code&gt;additionalTextEdits&lt;/code&gt; to automatically remove the&lt;br&gt;
&lt;code&gt;^&lt;/code&gt; part.&lt;/p&gt;

&lt;p&gt;Another use for &lt;code&gt;additionalTextEdits&lt;/code&gt; is to insert text somewhere completely&lt;br&gt;
different in the document. Think of auto-imports for some languages, where you&lt;br&gt;
type something and the language automatically adds &lt;code&gt;import ...&lt;/code&gt;. Or in Dendron,&lt;br&gt;
if the user selects a block that doesn't already have a block anchor when&lt;br&gt;
completing blocks, we need to insert a block anchor there. &lt;code&gt;additionalTextEdits&lt;/code&gt;&lt;br&gt;
have no limits to where they can put the text, as long as it's within the same&lt;br&gt;
document. In any case, let's see what this code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;edits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TextEdit&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;edits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEdit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;anchor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;genUUIDInsecure&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blockPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VSCodeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;point2VSCodePosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;edits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEdit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blockPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blockPosition&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="s2"&gt;` &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;AnchorUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;anchor2string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part adds a text edit to remove the &lt;code&gt;^&lt;/code&gt; part the user typed by&lt;br&gt;
calculating the range from a regex match, then replacing it with &lt;code&gt;""&lt;/code&gt;. The&lt;br&gt;
second part adds the &lt;code&gt;^...&lt;/code&gt; part to a block by calculating the range from the&lt;br&gt;
parsed document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Autocomplete is a ubiquitous feature in text editing today, both for writing&lt;br&gt;
natural languages and coding. It is an incredibly easy-to-use yet powerful&lt;br&gt;
feature for your users, and it enables unmatched user experiences when done&lt;br&gt;
right. But when done wrong, it can cause a disconnect and confusion around your&lt;br&gt;
product. At Dendron, we strive for the former and hope that the learnings from&lt;br&gt;
our experience will help you do the same.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>typescript</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Dendron - Super Fast Open Source Note-Taking inside VSCode</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Tue, 16 Mar 2021 15:54:08 +0000</pubDate>
      <link>https://forem.com/kevinslin/dendron-super-fast-open-source-note-taking-inside-vscode-igj</link>
      <guid>https://forem.com/kevinslin/dendron-super-fast-open-source-note-taking-inside-vscode-igj</guid>
      <description>&lt;p&gt;I started &lt;a href="https://dendron.so/"&gt;Dendron&lt;/a&gt; because I was frustrated with the lack of good note-taking tools while working as a developer at AWS. &lt;/p&gt;

&lt;p&gt;I wanted something with the ease of notepad, the structure of evernote, and the speed of redis.&lt;/p&gt;

&lt;p&gt;Iterating over these features for nearly a decade led me to Dendron and its been battle-tested with my own collection of 30K+ notes. &lt;/p&gt;

&lt;h2&gt;
  
  
  VSCode, Lookup, and Hierarchies
&lt;/h2&gt;

&lt;p&gt;Dendron is built into VSCode and also runs in VSCode compatible editors like VSCodium and Code Server. All notes are in plaintext markdown with frontmatter to store optional metadata at the top of the file. &lt;/p&gt;

&lt;p&gt;Creating and finding files works in seconds and work through the same interface. If a note doesn't exist, Dendron creates it. This interface is called &lt;a href="https://wiki.dendron.so/notes/a7c3a810-28c8-4b47-96a6-8156b1524af3.html"&gt;lookup&lt;/a&gt; and it is used to quickly navigate note hierarchies. &lt;/p&gt;

&lt;p&gt;Dendron helps with organizing notes using &lt;a href="https://wiki.dendron.so/notes/f3a41725-c5e5-4851-a6ed-5f541054d409.html"&gt;note hierarchies&lt;/a&gt; that are represented by dot delimited filenames. For example, &lt;code&gt;foo.bar.baz&lt;/code&gt; would be represented in dendron as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── foo
    └── bar
        └── baz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Schemas, Markdown, and All the Links
&lt;/h2&gt;

&lt;p&gt;Dendron gives you &lt;a href="https://wiki.dendron.so/notes/c5e5adde-5459-409b-b34d-a0d75cbb1052.html"&gt;schemas&lt;/a&gt;, optional YAML that you can associate with each hierarchy which describes their shape and allows Dendron to autocomplete and enforce your organization.&lt;/p&gt;

&lt;p&gt;Dendron has its own flavour of markdown that includes additional functionality that enables, latex, mermaid diagrams, and the ability to include &lt;a href="https://wiki.dendron.so/notes/f1af56bb-db27-47ae-8406-61a98de6c78c.html"&gt;content from other notes&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It also has &lt;a href="https://wiki.dendron.so/notes/3472226a-ff3c-432d-bf5d-10926f39f6c2.html"&gt;numerous ways&lt;/a&gt; of linking your notes together. There are wikilinks to quickly link to any other note, backlinks to see what notes a given note is linked to, hierarchical links to find the parent and children of any note and relative links to go to a specific part of any document. &lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing, Vaults, and Pods
&lt;/h2&gt;

&lt;p&gt;Dendron comes with built-in &lt;a href="https://wiki.dendron.so/notes/579e379b-3eca-4676-b51c-c66eb26a11b8.html"&gt;publishing&lt;/a&gt; - you can compile your notes to static HTML and publish them anywhere. &lt;a href="https://wiki.dendron.so/notes/3a82c5ff-7945-46ae-8bf9-3b2275fc6642.html"&gt;Dendron published sites&lt;/a&gt; have been deployed on GitHub pages, S3, Azure, Vercel, Netlify, and more.  You have fine-grained control of what gets published and Dendron takes care of the details - any links to private notes from public notes are automatically overwritten with a custom 403 page during the built stage.&lt;/p&gt;

&lt;p&gt;Dendron employs a vault-based model for storing notes where a &lt;a href="https://wiki.dendron.so/notes/c6fd6bc4-7f75-4cbb-8f34-f7b99bfe2d50.html#vaults"&gt;vault&lt;/a&gt; is a logical collection of notes, typically backed by git. You can mix and match vaults in a &lt;a href="https://wiki.dendron.so/notes/c6fd6bc4-7f75-4cbb-8f34-f7b99bfe2d50.html#workspace"&gt;workspace&lt;/a&gt; and store them in different places (eg. personal notes on dropbox but company notes locally on the computer). Dendron gives you one unified interface to reference all your notes across all vaults. These vaults can be imported natively in Dendron, either by a relative path or a remote git URL. &lt;/p&gt;

&lt;p&gt;Lastly, Dendron has a &lt;a href="https://wiki.dendron.so/notes/66727a39-d0a7-449b-a10d-f6c438185d7f.html"&gt;pod system&lt;/a&gt; to help you import/export your notes from Dendron to any other tool and format. We have a JSON pod to export notes and metadata to JSON so you can &lt;a href="https://wiki.dendron.so/notes/401c5889-20ae-4b3a-8468-269def4b4865.html#analyze-notes-using-elasticsearch"&gt;index it to elasticsearch&lt;/a&gt; or create custom visualizations. We have a markdown pod to convert Dendron markdown to regular markdown so that Dendron is interoperable with any tool that accepts markdown. &lt;/p&gt;

&lt;h2&gt;
  
  
  Today
&lt;/h2&gt;

&lt;p&gt;To date, Dendron has been downloaded over 20 thousand times and powers everything from personal journals to team-based knowledge bases. We ship features weekly and has an active Discord community around note-taking that exchange hundreds of messages a day. My goal is to grow Dendron to be the best note-taking tool for developers, and in time, everyone. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We are overwhelmed with information and we don't have the tools to properly index and filter through it. [The development of these tools, which] will give society access to and command over the inherited knowledge of the ages [should] be the first objective of our scientist" - Vannevar Bush, 1945&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The north star of this project is to achieve Vannevar Bush's original vision - to build a tool of thought that can give humanity "access to and command over the inherited knowledge of the ages".&lt;/p&gt;

&lt;p&gt;If you are reading this, you too, are now part of the journey. Let's take back control of our information and use it to build something better, together!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>tooling</category>
      <category>vscode</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Dendron</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Fri, 26 Feb 2021 02:47:21 +0000</pubDate>
      <link>https://forem.com/kevinslin/dendron-638</link>
      <guid>https://forem.com/kevinslin/dendron-638</guid>
      <description>&lt;p&gt;This contains the public notes for &lt;a href="https://dendron.so"&gt;Dendron&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dendron - A Hierarchical Tool for Thought</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Sun, 01 Nov 2020 17:51:49 +0000</pubDate>
      <link>https://forem.com/kevinslin/dendron-a-hierarchical-tool-for-thought-356b</link>
      <guid>https://forem.com/kevinslin/dendron-a-hierarchical-tool-for-thought-356b</guid>
      <description>&lt;p&gt;Dendron is a note-taking tool I've been thinking about building for much of the last decade. &lt;/p&gt;

&lt;p&gt;All note taking tools help you put notes in, but after a point, they all make it difficult to get your notes back out. Dendron helps you find your notes no matter how many notes you have and works better the more notes you have. &lt;/p&gt;

&lt;p&gt;Dendron works by taking a &lt;a href="https://www.kevinslin.com/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64.html"&gt;hierarchal first approach&lt;/a&gt; to note taking. It provides users with flexible hierarchies that can be used to create, manage, and reference any amount of notes. &lt;/p&gt;

&lt;p&gt;Dendron starts with the foundation of flexible hierarchies and builds on top of this foundation with other constructs such as tags, backlinks, and note references (a means to embed notes within other notes). This is so to arrive at a usable centers between purely networked notes (which are often too flexible) and purely hierarchal notes (which are often too rigid). &lt;/p&gt;

&lt;p&gt;You can read more about our methodology and try out our tool by visiting our &lt;a href="http://dendron.so/"&gt;site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ps. We officially launched on product hunt today. Would love to hear feedback and comments on our &lt;a href="https://www.producthunt.com/posts/dendron"&gt;product hunt page&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>pkm</category>
      <category>notes</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Dendron - an open source, local first, anti-roam note-taking tool</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Fri, 18 Sep 2020 15:09:40 +0000</pubDate>
      <link>https://forem.com/kevinslin/dendron-an-open-source-local-first-anti-roam-note-taking-tool-4j36</link>
      <guid>https://forem.com/kevinslin/dendron-an-open-source-local-first-anti-roam-note-taking-tool-4j36</guid>
      <description>&lt;p&gt;&lt;a href="https://dendron.so"&gt;Dendron&lt;/a&gt; is meant to be the fastest way for people to create, reference, and collaborate on knowledge. It is based on a &lt;a href="https://www.kevinslin.com/notes/3dd58f62-fee5-4f93-b9f1-b0f0f59a9b64.html"&gt;hierarchal first approach to note taking&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hierarchy first means that Dendron helps you effortlessly create, manage, and reference your notes through flexible hierarchies. I call it anti-roam because instead of having every note be everywhere, every note is exactly in one well defined place (which you can change over time). &lt;/p&gt;

&lt;p&gt;You can read about our principles &lt;a href="https://dendron.so/notes/7fcebd7d-6411-4c9d-8baf-65629dc018a1.html"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use Dendron to manage a corpus of 20k+ markdown notes. When I need to lookup information inside Dendron, I know I can either &lt;strong&gt;find it in a few seconds&lt;/strong&gt;, or if I don't, to know for certain that it is &lt;strong&gt;not there&lt;/strong&gt;. This is an incredibly empowering feeling of control in an age of information overload and it is an ability I want to give to every person in the world.&lt;/p&gt;

</description>
      <category>node</category>
      <category>pkm</category>
    </item>
    <item>
      <title>Dendron – a Roam like, open source, markdown based note taking app built on top of VSCode (dendron.so)</title>
      <dc:creator>Kevin Lin</dc:creator>
      <pubDate>Fri, 21 Aug 2020 16:31:52 +0000</pubDate>
      <link>https://forem.com/kevinslin/dendron-a-roam-like-open-source-markdown-based-note-taking-app-built-on-top-of-vscode-dendron-so-3kg9</link>
      <guid>https://forem.com/kevinslin/dendron-a-roam-like-open-source-markdown-based-note-taking-app-built-on-top-of-vscode-dendron-so-3kg9</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnpnpazowjv2bnsulffn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnpnpazowjv2bnsulffn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dendron is a knowledge management tool that focuses on hierarchal note taking. It provides the freedom of Roam’s every note exists everywhere philosophy while layering on top flexible hierarchies to keep track of it all.&lt;/p&gt;

&lt;p&gt;While Dendron works with knowledge bases of any size, it really shines once you’ve accumulated a few hundred notes. I created it to handle my personal knowledge base of 20k+ markdown notes - Dendron lets me track and find any specific note in it in seconds.&lt;/p&gt;

&lt;p&gt;Notes created in dendron can be published using github pages. Dendron's &lt;a href="https://dendron.so" rel="noopener noreferrer"&gt;homepage&lt;/a&gt; is published from this &lt;a href="https://github.com/dendronhq/dendron-template" rel="noopener noreferrer"&gt;github repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dendron is currently in preview and under active development. If you are looking for a better way of taking notes, I encourage you to give Dendron a try. &lt;/p&gt;

&lt;p&gt;For folks coming from DEV, I'm also offering a &lt;a href="https://calendly.com/thence/dendron" rel="noopener noreferrer"&gt;30min onboarding&lt;/a&gt; to help get started and setup a workspace that matches your note taking goals :) &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vscode</category>
      <category>typescript</category>
      <category>github</category>
    </item>
  </channel>
</rss>
