<?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>DEV Community: Thomas Kainrad</title>
    <description>The latest articles on DEV Community by Thomas Kainrad (@tkainrad).</description>
    <link>https://dev.to/tkainrad</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%2F420621%2Fe166515f-bd44-4c2c-bca4-9f3464d5f50a.png</url>
      <title>DEV Community: Thomas Kainrad</title>
      <link>https://dev.to/tkainrad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tkainrad"/>
    <language>en</language>
    <item>
      <title>App to show the shortcuts of the current application for Windows, Linux, and macOS</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Sun, 13 Dec 2020 10:43:41 +0000</pubDate>
      <link>https://dev.to/tkainrad/app-to-show-the-shortcuts-of-the-current-application-for-windows-linux-and-macos-5eg3</link>
      <guid>https://dev.to/tkainrad/app-to-show-the-shortcuts-of-the-current-application-for-windows-linux-and-macos-5eg3</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Looking up keyboard shortcuts on the web takes you out of the current context and breaks your workflow. That's why, &lt;a href="https://tkainrad.dev/posts/setting-up-linux-workstation/"&gt;as a Linux user&lt;/a&gt;, I have always been a bit envious of macOS users, who had access to tools that could instantly show the current application's shortcuts, such as &lt;a href="https://www.mediaatelier.com/CheatSheet/"&gt;CheatSheet&lt;/a&gt;, and &lt;a href="https://github.com/amiechen/pretzel"&gt;Pretzel&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;On Windows and Linux, there was no such thing. You had to find shortcut information in the software's documentation and hope that it was searchable. Or even worse, suffer a massive context switch and google for the shortcuts, until now. KeyCombiner Desktop is free to use and can show the active application's shortcuts on Windows, Linux, and macOS.&lt;/p&gt;

&lt;p&gt;Suppose you are on macOS and already use one of the existing solutions. In that case, you might still want to read further because KeyCombiner goes far beyond looking up the active application's shortcuts.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it look like?
&lt;/h1&gt;

&lt;p&gt;If a picture says more than 1000 words, an animation will speak for itself:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BHVoWd3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0esv4eb3ld89hanodrrx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BHVoWd3p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0esv4eb3ld89hanodrrx.gif" alt="Instant shortcut lookup for three example applications."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon pressing the global trigger, the lookup will appear with a search field in focus, where you can start to type right away. The default trigger is super+shift+c on Windows and Linux, and cmd+shift+k on macOS. This can be configured, I use super+c on Linux.&lt;/p&gt;

&lt;p&gt;The search terms will be applied to the shortcut description, the key binding, and some hidden fields like the shortcut category. Do you want to search for all file-related bindings that use Ctrl? Type something like &lt;code&gt;file ctrl&lt;/code&gt; and you have your answer.&lt;/p&gt;

&lt;p&gt;The lookup window disappears whenever you click outside of it, when you press esc, or when you switch to another application via cmd/ctrl+tab. If you close via esc, the search term will be cleared. If you use cmd/ctrl+tab, you can switch back to the active application without losing the cursor position.&lt;/p&gt;

&lt;h1&gt;
  
  
  What else can it do?
&lt;/h1&gt;

&lt;p&gt;If you carefully watched the animation above, you might have noticed that the rows are grouped. The first group has the prefix &lt;code&gt;Active:&lt;/code&gt; and is highlighted with a blue background. This group shows the shortcuts for the active application. Everything that is shown below this group is from the user's personal shortcut and command collections.&lt;/p&gt;

&lt;p&gt;To explain what these are, I have to provide some background. KeyCombiner is an application to organize, learn, and practice keyboard shortcuts. A core idea is to learn precisely the shortcuts you need. The only way to achieve this is to choose them yourself, which is done by creating personal collections of shortcuts and text snippets. I like to compare this concept to how you build playlists in music software. Instead of browsing your favorite artists’ albums, KeyCombiner allows you to browse shortcut collections of your favorite applications. Instead of adding songs to your playlists, you can add keyboard shortcuts and text snippets to your personal collections.&lt;/p&gt;

&lt;p&gt;The instant lookup of KeyCombiner Desktop profits immensely from these collection building features, and vice-versa. Having instant access to your collections makes them a lot more valuable. In short, these two features complete each other.&lt;/p&gt;

&lt;p&gt;The instant lookup works offline. Your personal collections are downloaded only on application startup. If you modified your collections while KeyCombiner Desktop was running, you may reload the lookup via (Ctrl/Cmd+R).&lt;/p&gt;

&lt;p&gt;I will try to illustrate this with my personal experience. Currently, I have 10 personal KeyCombiner collections. My largest one contains more or less all shortcuts that I already knew when I started to use KeyCombiner. This collection is publicly accessible via this &lt;a href="https://keycombiner.com/collecting/collections/shared/89e47af4-0f2e-4d5d-98fa-6966bc7453cc/"&gt;shareable link&lt;/a&gt;. Then, I did a &lt;a href="https://tkainrad.dev/posts/how-i-learned-50-new-keyboard-shortcuts-in-42-minutes/"&gt;blog post challenge to learn 50 new keyboard shortcuts as fast as possible&lt;/a&gt;. More recently, I &lt;a href="https://tkainrad.dev/posts/learning-all-vscode-shortcuts-evolved-my-developing-habits/"&gt;learned &lt;em&gt;all&lt;/em&gt; VSCode keyboard shortcuts&lt;/a&gt;, which evolved my developing habits and added another collection with 151 shortcuts to my repertoire.&lt;br&gt;
Add to that a few smaller collections I used for learning the shortcuts of Chrome DevTools, Nautilus, Spotify, and Vimium. Having instant access to all of these shortcuts without leaving my current context feels like a superpower, even though I admit that some of those superpowers you see in movies look even more powerful.&lt;/p&gt;

&lt;p&gt;My most recent new use case is to look up regular expressions. There is an &lt;a href="https://tkainrad.dev/posts/automatically-add-kbd-tags-with-a-single-regex/"&gt;article&lt;/a&gt; on how to automatically add HTML &amp;lt;kbd&amp;gt;-tags to any text via a single regex replace operation. I use this for all of my blog posts, all &amp;lt;kbd&amp;gt; tags you see in this post are added this way. However, it wouldn't be so convenient if I couldn't instantly look up and copy-paste the required regular expression:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TmHKd9cT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bz48ckrr8i743156pu7a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TmHKd9cT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bz48ckrr8i743156pu7a.gif" alt="The lookup also shows shortcuts and text snippets from your personal collections."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KeyCombiner's instant lookup is a cheatsheet of sorts. But it is context-aware, searchable, and you can expand it quickly by importing from public or shared collections. It is also friendlier to the environment than printing out PDFs and hanging them next to your desk.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it know the active application's shortcuts?
&lt;/h1&gt;

&lt;p&gt;There is a very boring answer to this question: By maintaining an extensive public database of keyboard shortcuts. You might have noticed from reading this post that I am quite excited about Keycombiner. That's why I spend considerable time to parse the documentation pages of software tools for their keyboard shortcuts. It's not as dull as it sounds like; creative use of regular expressions makes it quite fun. Don't judge me; everyone has a weird hobby.&lt;/p&gt;

&lt;p&gt;You can browse the database at &lt;a href="https://keycombiner.com/collections/"&gt;https://keycombiner.com/collections/&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
The instant lookup works for all desktop-based applications that are listed there.  In particular, it should work for all apps that an average software developer uses (VSCode, JetBrains IDEs, Vim, Eclipse, Chrome, Firefox, Safari, Nautilus, Finder, Notion, Slack, Explorer, Terminal, iTerm2, Obsidian,...). This list is growing fast, and I am happy to take suggestions.&lt;/p&gt;

&lt;p&gt;One downside of this approach is that KeyCombiner can only show the default bindings for the active application. If you have changed these bindings, that's not ideal. Fortunately, If you went through the trouble of changing a binding, you usually won't need to look it up. In any case, you can add the customized binding to a personal collection, and the lookup will show it as explained above.&lt;/p&gt;

&lt;p&gt;Existing tools for macOS use a different approach. They rely on a macOS API to retrieve menu keyboard shortcuts for the current application. This has its advantages and disadvantages. The great thing about it is that it works automatically for all applications that have a menu. On the other hand, applications&lt;br&gt;
don't necessarily register all of their shortcuts as menu shortcuts.&lt;/p&gt;

&lt;h1&gt;
  
  
  How can I use it?
&lt;/h1&gt;

&lt;p&gt;Simply go to &lt;a href="https://keycombiner.com/desktop/"&gt;https://keycombiner.com/desktop/&lt;/a&gt; and grab the installer for your system. On macOS, you need to grant some permissions for the instant lookup to work. Please refer to the bottom of the linked page for instructions on how to do that.&lt;/p&gt;

&lt;p&gt;KeyCombiner is a SaaS with a generous free tier. &lt;strong&gt;All features described in this article are entirely free to use.&lt;/strong&gt; If you use KeyCombiner a lot, please consider upgrading to a Pro subscription to get access to additional features and to support hosting and development efforts. &lt;/p&gt;

&lt;p&gt;If you are a developer, you might be interested in how I implemented the checkout process for the Pro subscription. I recently &lt;a href="https://tkainrad.dev/posts/implementing-paddle-payments-for-my-django-saas/"&gt;published a blog post describing the implementation&lt;/a&gt; in detail.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;KeyCombiner can do a lot more things than what's described in this post. However, the instant lookup has quickly become one of my favorite features. Admittedly, I don't use KeyCombiner every day for learning shortcuts. Usually, after I have &lt;a href="https://tkainrad.dev/posts/learning-all-vscode-shortcuts-evolved-my-developing-habits/"&gt;mastered all shortcuts&lt;/a&gt; of a new collection, it takes a couple of days or even weeks until I get back to frequent practice.&lt;/p&gt;

&lt;p&gt;In contrast, I use the instant lookup &lt;em&gt;all the time&lt;/em&gt;. If I am on a different computer without KeyCombiner installed, I notice that something is missing after a couple of minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enough about me, though. I'd be thrilled to hear about your experience with the software.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>keyboard</category>
    </item>
    <item>
      <title>Automatically add kbd-tags to Your Posts with a Single Regex</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Sat, 05 Dec 2020 10:00:17 +0000</pubDate>
      <link>https://dev.to/tkainrad/automatically-add-kbd-tags-to-your-posts-with-a-single-regex-3hnd</link>
      <guid>https://dev.to/tkainrad/automatically-add-kbd-tags-to-your-posts-with-a-single-regex-3hnd</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Until about a year ago, I had the same approach to regular expressions as most developers: Doing trial and error until the damn thing was working.&lt;/p&gt;

&lt;p&gt;Then came &lt;a href="https://keycombiner.com"&gt;KeyCombiner&lt;/a&gt; and with it some very specific challenges around parsing text that contains keyboard shortcuts. One of these challenges is writing blog posts about KeyCombiner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tkainrad.dev/posts/a-collection-of-all-keyboard-shortcuts-i-use/"&gt;A Collection of all Keyboard Shortcuts I use&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tkainrad.dev/posts/learning-all-vscode-shortcuts-evolved-my-developing-habits/"&gt;Learning all VSCode shortcuts evolved my developing habits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tkainrad.dev/posts/how-i-learned-50-new-keyboard-shortcuts-in-42-minutes/"&gt;How I learned 50 new keyboard shortcuts in 42 minutes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These posts contain &lt;em&gt;a lot&lt;/em&gt; of keyboard shortcuts that should be highlighted via &amp;lt;kbd&amp;gt; tags. By now, these tags are supported by most static site generators and blogging platforms, such as DEV.to. However, typing them in manually is extremely tedious. Initially, I felt quite smart when I added a user snippet in VSCode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"kbd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"markdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kbd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;kbd&amp;gt;$0&amp;lt;/kbd&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Insert HTML kbd tags"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets me type &lt;code&gt;kbd&lt;/code&gt;, press ctrl+space and hit enter to put my cursor in-between an opening and a closing &lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt; tag. However, it does not help with copy-pasted text, which is an essential use case for me. I write the first draft of my posts in Notion, as described in &lt;a href="https://tkainrad.dev/posts/managing-my-personal-knowledge-base/"&gt;my post about personal knowledge management&lt;/a&gt;. Even if this were not an issue, it's still quite a lot of keys to hit for just adding two tags. Another solution would be to write a script in some interpreted language and do all kinds of fancy things to this text. The problem is, this script will likely end up like many single-purpose scripts do: Abandoned and buggy.&lt;/p&gt;

&lt;p&gt;So, I needed a better, more timeless solution: Regular Expressions.&lt;br&gt;&lt;br&gt;
Fear not, I won't try to teach you general regex syntax. Instead, I will show how to use it for this particular use case.&lt;br&gt;
I will explain in detail how and why this works, but you can also just copy-paste the final regex and apply it for yourself. One of the best tools for putting the regex to work is Visual Studio Code, but any editor that supports regex-based replace operations will do.&lt;/p&gt;
&lt;h1&gt;
  
  
  How-To
&lt;/h1&gt;

&lt;p&gt;Suppose we have the following text:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modifier keys, such as ctrl, shift, alt, and cmd do nothing by themselves but can be used in combination with other keys. To paste without the original formatting, use ctrl+shift+v. Debugging is controlled via f5, f6, f10, and f11. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What we want to have is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modifier keys, such as ctrl, shift, alt, and cmd  do nothing by themselves, but can be used in combination with other keys. To paste without the original formatting, use ctrl+shift+v. Debugging is controlled via f5, f6, f10, and f11. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next sections will describe how we get there.&lt;/p&gt;
&lt;h2&gt;
  
  
  Modifiers and F-keys
&lt;/h2&gt;

&lt;p&gt;We can already go pretty far with this regex that uses or operators (&lt;code&gt;|&lt;/code&gt;) to match a predefined set of strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(f1|f2|f3|f4|f5|f6|f7|f8|f9|f10|f11|f12|backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Putting the expression in brackets &lt;code&gt;()&lt;/code&gt; means that it is a capture group. Capture groups are an essential concept when working with regular expressions. One of their greatest features is that we get to reference them by number in the replacement string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;kbd&amp;gt;&lt;/span&gt;$1&lt;span class="nt"&gt;&amp;lt;/kbd&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we will replace a match of the first capture group with itself (&lt;code&gt;$1&lt;/code&gt;) surround by the desired tags.&lt;/p&gt;

&lt;p&gt;The above text will become:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modifier keys, such as ctrl, shift, alt, and cmd  do nothing by themselves, but can be used in combination with other keys. To paste without the original formatting, use ctrl+shift+v. Debugging is controlled via f5, f6, f10, and f11. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a good start, but we are not quite there yet. Non-modifier keys that are part of key combinations do not yet have the proper tags. We will deal with them in the next section. But before, we can shorten our expression a bit, by switching out the f-keys with a single sub-expression: &lt;code&gt;f([2-9]|1[0-2]?)&lt;/code&gt;. This will match any &lt;code&gt;f&lt;/code&gt;-character followed by either &lt;code&gt;2-9&lt;/code&gt; or a sequence of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0-2&lt;/code&gt;. It is equal to typing out the f-keys, but a little more fun. So we end up with this expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(f([2-9]|1[0-2]?)|backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Regular keys in combinations
&lt;/h2&gt;

&lt;p&gt;Matching regular keys is a bit more tricky. We cannot just match any &lt;code&gt;v&lt;/code&gt; characters in our text. One approach is to match any single alphanumeric character that is preceded by a &lt;code&gt;+&lt;/code&gt;-sign. To do this, we need to use something called &lt;em&gt;Lookarounds&lt;/em&gt;, ore more specifically, a &lt;em&gt;Lookbehind&lt;/em&gt;: &lt;code&gt;(?&amp;lt;=\+)&lt;/code&gt;&lt;br&gt;
The nice thing about lookarounds is that they do not increase the matched character sequence. Instead, they specify what must (or must not) come before or after the matched part, which is very useful when applying replacement operations. Adding this to our expression results in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;((?&amp;lt;=\+)[\w\d]{1}|f([2-9]|1[0-2]?)|backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this expression, we end up with the desired text already:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modifier keys, such as ctrl, shift, alt, and cmd  do nothing by themselves, but can be used in combination with other keys. To paste without the original formatting, use ctrl+shift+v. Debugging is controlled via f5, f6, f10, and f11. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, we shouldn't celebrate too early. There are still some issues and special cases to take care of:&lt;/p&gt;

&lt;p&gt;1) What happens if a modifier appears within another word, such as &lt;em&gt;ins&lt;/em&gt; in &lt;em&gt;&lt;strong&gt;ins&lt;/strong&gt;ert&lt;/em&gt;?&lt;br&gt;
2) What happens if we apply this to text that already has some &lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt; tags?&lt;/p&gt;

&lt;p&gt;The answer to both questions is clear: Terrible things will happen. We will have to go a bit deeper.&lt;/p&gt;
&lt;h2&gt;
  
  
  Avoiding False Positives
&lt;/h2&gt;

&lt;p&gt;Now that we already know the &lt;em&gt;Lookaround&lt;/em&gt; concept, this is relatively easy. We will ensure that the expression only matches occurrences surrounded by one of these characters: &lt;code&gt;[\+ .,\n]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(?&amp;lt;=[\+ .,\n])(backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta|f([2-9]|1[0-2]?)|(?&amp;lt;=\+)[\w\d]{1})(?=[\+ .,\n])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Achieving Idempotence
&lt;/h2&gt;

&lt;p&gt;An idempotent operation is one that can be applied more than once without changing the outcome. To achieve idempotence, we will make use of another advantage of our beloved lookarounds: They can be stacked one after another. All we have to do is make sure that our matches are not already preceded by a &lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt; tag, using a negative &lt;em&gt;Lookbehind&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(?&amp;lt;!&amp;lt;kbd&amp;gt;)(?&amp;lt;=[\+ .,\n])(backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta|f([2-9]|1[0-2]?)|(?&amp;lt;=\+)[\w\d]{1})(?=[\+ .,\n])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could add a negative &lt;em&gt;Lookahead&lt;/em&gt; for the closing tag, too, but it is not needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final regex
&lt;/h2&gt;

&lt;p&gt;That's it. We have a regular expression that we can use in VSCode and other editors to automatically surround all occurences of keys with &lt;code&gt;&amp;lt;kbd&amp;gt;&lt;/code&gt; tags. To use it, search for this expression with the &lt;em&gt;Use Regular Expression&lt;/em&gt; (alt+r)-toggle enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(?&amp;lt;!&amp;lt;kbd&amp;gt;)(?&amp;lt;=[\+ .,\n])(backspace|tab|enter|shift|ctrl|cmd|alt|capslock|pageup|pagedown|ins|del|option|meta|f([2-9]|1[0-2]?)|(?&amp;lt;=\+)[\w\d]{1})(?=[\+ .,\n])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, replace all occurrences  string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;kbd&amp;gt;&lt;/span&gt;$1&lt;span class="nt"&gt;&amp;lt;/kbd&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to go one step further, you could even apply this in a build pipeline, e.g., after pushing to GitHub Pages or GitLab Pages. Personally, I like to do it myself in VSCode. These are very satisfying 30 seconds of work before publishing a new blog post.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Hopefully, I could help a bit to improve the bad reputation of regular expressions. But I will let you in on a little secret. Just like everyone else, I have a hard time remembering the syntax.&lt;br&gt;
The good thing is, I have a superpower to overcome this: KeyCombiner's instant shortcut lookup. Whenever I press super+c, I have instant access to the shortcuts of the active application, all other shortcuts that I like to use, and even regex syntax:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--plpPHtfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r70tc7ozkzu36s0nhhav.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--plpPHtfT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r70tc7ozkzu36s0nhhav.gif" alt="Instant regex lookup with KeyCombiner's free to use desktop app."&gt;&lt;/a&gt;&lt;br&gt;Instant shortcut lookup of KeyCombiner's free to use &lt;a href="https://keycombiner.com/desktop/"&gt;desktop app&lt;/a&gt;.
  &lt;/p&gt;

</description>
      <category>writing</category>
      <category>productivity</category>
      <category>blogging</category>
      <category>vscode</category>
    </item>
    <item>
      <title>How I learned 50 new keyboard shortcuts in 42 minutes</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Fri, 27 Nov 2020 20:31:16 +0000</pubDate>
      <link>https://dev.to/tkainrad/how-i-learned-50-new-keyboard-shortcuts-in-42-minutes-3kae</link>
      <guid>https://dev.to/tkainrad/how-i-learned-50-new-keyboard-shortcuts-in-42-minutes-3kae</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;As developers, we frequently use keyboard shortcuts. Some enthusiasts know hundreds, others are contempt with the essential ones. But every developer does know some.  It is unthinkable to browse the Web, searching for a solution to your CSS alignment problem without using Ctrl+f. Debugging would be tedious if we couldn't pause and resume a program's execution with the keyboard.&lt;/p&gt;

&lt;p&gt;In recent weeks, I have been able to significantly expand my keyboard shortcut knowledge with my new side-project web app &lt;a href="https://keycombiner.com" rel="noopener noreferrer"&gt;KeyCombiner&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
In particular, I knew only a few shortcuts for the web-based tools I am using in my daily work. This post describes how it took me less than 1 hour to learn &lt;a href="https://keycombiner.com/collecting/collections/shared/76f3eec4-d45d-4d15-b521-6798addbba4e" rel="noopener noreferrer"&gt;50 new key combinations&lt;/a&gt;. Fortunately, KeyCombiner keeps a detailed history of a user's learning progress, so that I could write this post retrospectively.&lt;/p&gt;

&lt;p&gt;Admittedly, the 42 minutes of learning time was interrupted by breaks, and the process involved some other tasks, such as creating the collection of shortcuts I wanted to learn. However, I did, in fact, spend only 42 minutes practicing the shortcuts and have had similar results with other shortcut collections.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;The first step to learning new keyboard shortcuts is to define which. I don't think it is efficient to try and learn all shortcuts for a particular application. You will end up with many that you do not use in your daily work and that you will soon forget again.&lt;/p&gt;

&lt;p&gt;Creating custom collections of keyboard shortcuts is perhaps the greatest strength of KeyCombiner and sets it apart from any other tool. Within minutes or less, you can have a personal collection by importing shortcuts from popular apps. I like to compare its approach to how you build playlists in music software. Instead of browsing your favorite artists’ albums, you browse categories of your favorite applications. Instead of adding songs to your playlists, you can add keyboard shortcuts to your collections.&lt;/p&gt;

&lt;p&gt;For this challenge, I created a new collection named "&lt;a href="https://keycombiner.com/collecting/collections/shared/76f3eec4-d45d-4d15-b521-6798addbba4e" rel="noopener noreferrer"&gt;50 to learn&lt;/a&gt;". &lt;br&gt;
Then, I browsed KeyCombiner's &lt;a href="https://keycombiner.com/collecting/collections/public/" rel="noopener noreferrer"&gt;public collections&lt;/a&gt; and started to import everything I wanted to learn. As my goal was to get better with web application shortcuts, I focused on the public collections for Gmail, GitHub, GDrive, Docs, Slack, and Twitter. Importing the combinations into my new shortcut collection looked like this:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdksr4pui0x9fj8m664dp.gif" 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%2Fdksr4pui0x9fj8m664dp.gif" alt="collecting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, I added a few shortcuts for &lt;a href="https://www.syntevo.com/smartgit/" rel="noopener noreferrer"&gt;Smartgit&lt;/a&gt; manually. It is a graphical Git client that I am using extensively. For some reason, I never learned its shortcuts. Unfortunately, KeyCombiner does not yet have a public shortcut collection for Smartgit that I could rely on. However, manual input does the job:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdfhhsrgsid66b71pcaro.gif" 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%2Fdfhhsrgsid66b71pcaro.gif"&gt;&lt;/a&gt;&lt;br&gt;Manually adding keyboard shortcuts to my new collection.
  &lt;/p&gt;

&lt;p&gt;You can browse the resulting collection with 50 keyboard shortcuts here: &lt;a href="https://keycombiner.com/collecting/collections/shared/76f3eec4-d45d-4d15-b521-6798addbba4e" rel="noopener noreferrer"&gt;50 to learn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am afraid you will have to trust me that I did not know these shortcuts already before this experiment. However, as reassurance, you can check &lt;a href="https://tkainrad.dev/posts/a-collection-of-all-keyboard-shortcuts-i-use/" rel="noopener noreferrer"&gt;my previous blog post&lt;/a&gt; covering all the shortcuts I was using until a few weeks ago. The list there does not include these new ones.&lt;/p&gt;

&lt;p&gt;To validate the success of this experiment, I will simply use KeyCombiner's confidence metric. It will analyze my performance and tell me which shortcuts are already etched into my muscle memory during practice. So, the challenge will be completed successfully once this card says &lt;strong&gt;50/50&lt;/strong&gt;:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh0fat5jl8lj3vnpwpm5w.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%2Fh0fat5jl8lj3vnpwpm5w.png"&gt;&lt;/a&gt;&lt;br&gt;Overview of my new collection with 50 shortcuts to learn.
  &lt;/p&gt;

&lt;h1&gt;
  
  
  Learning the shortcuts
&lt;/h1&gt;

&lt;p&gt;Learning new shortcuts with KeyCombiner is dead simple. You click on the practice button for a particular collection, and the software does the rest. It will create 60-seconds training exercises where you are supposed to type the shortcuts of a collection as fast and as correct as possible. &lt;/p&gt;

&lt;p&gt;With every input, KeyCombiner remembers if it was correct and how long you took. It will use this information along with some machine learning to calculate a so-called confidence value for each key combination in your collections. A high confidence value means that you mastered a combination. Key combinations with a low value will occur more often in practice sessions, so you are not stuck repeating what you know already.&lt;br&gt;
There are a few additional aspects to it, but the good thing is that users do not have to bother with the learning algorithm's internal workings. Repeatedly doing practice runs is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting to remember the keys
&lt;/h2&gt;

&lt;p&gt;The very beginning of learning a new collection is the hardest part. While I do not yet know any of the shortcuts, I have to rely on KeyCombiner's delayed key hints to type any. Sometimes, I just skip combinations immediately to see what the keys are.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzjnd5e3u863lbj8txk5w.gif" 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%2Fzjnd5e3u863lbj8txk5w.gif"&gt;&lt;/a&gt;&lt;br&gt;The very first practice runs with a new collection are quite slow.
  &lt;/p&gt;

&lt;p&gt;This is how results for such a practice run look like:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd0s9ae1rnp9fanfs1nbl.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%2Fd0s9ae1rnp9fanfs1nbl.png"&gt;&lt;/a&gt;&lt;br&gt;Typical practice statistics for a collection you do not know yet.
  &lt;/p&gt;

&lt;p&gt;Surprisingly, even in the first practice run, I got a couple of combinations right without key hints. This means that they occurred multiple times already or simply that I was able to guess them correctly. The latter is often the case for &lt;em&gt;go to&lt;/em&gt; shortcuts, which have been made popular by Gmail and are now used in many web applications.&lt;/p&gt;

&lt;p&gt;After a few practice runs, I started to disable key hints and only relied on skipping combinations where I couldn't remember the keys. KeyCombiner will then display the skipped combination's keys, so I have a shot at remembering them next time. &lt;/p&gt;

&lt;p&gt;The statistics for the 10th practice run looked as follows:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1qemomzlwzekv70w8rvf.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%2F1qemomzlwzekv70w8rvf.png"&gt;&lt;/a&gt;&lt;br&gt;After just 10 minutes of practice, I already know some of the shortcuts.
  &lt;/p&gt;

&lt;p&gt;KeyCombiner recognizes 9 shortcuts as mastered. So far, so good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building muscle memory
&lt;/h2&gt;

&lt;p&gt;After another 10 practice runs, statistics showed that I knew already most of the shortcuts:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faub4c47tn3cpwdvfy7lv.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%2Faub4c47tn3cpwdvfy7lv.png"&gt;&lt;/a&gt;&lt;br&gt;Statistics for my 20th practice run.
  &lt;/p&gt;

&lt;p&gt;However, KeyCombiner punishes errors quite heavily and is hesitant to show keys as mastered that I have just recently mistyped. &lt;br&gt;
At this stage, it starts to get interesting to check the collection and see which specific shortcuts have very low confidence values. Usually, it is obvious to see some patterns:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkayqoufp81u550nack4h.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%2Fkayqoufp81u550nack4h.png"&gt;&lt;/a&gt;&lt;br&gt;The combinations with lowest confidence values after 20 practice runs.
  &lt;/p&gt;

&lt;p&gt;The figure shows that I had problems knowing which modifiers to use for GSuite shortcuts (Gmail, GDrive and Docs). Some use Ctrl + Shift , some Ctrl + Alt and some don't have a modifier at all (e.g. forwarding a mail in Gmail). I found that having a good look at such problems between practice runs can speed my progress, but it is not required. &lt;/p&gt;

&lt;p&gt;All that is needed is to keep hitting the practice button. At this stage, muscle memory starts to build, and the average time I need for each combination goes down quickly. KeyCombiner considers the average time metric for its confidence values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Completing the challenge
&lt;/h2&gt;

&lt;p&gt;After 35 practice runs, things started to look very good:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe5tuzm3xbg4e3595hym1.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%2Fe5tuzm3xbg4e3595hym1.png"&gt;&lt;/a&gt;&lt;br&gt;Only few shortcuts with low confidence values remain.
  &lt;/p&gt;

&lt;p&gt;A confidence value of 3 means that I mastered a particular combination.&lt;/p&gt;

&lt;p&gt;Let's have a look at the combination with the lowest confidence value. Surprisingly, it is the relatively simple shift+a:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcwyiha518nr8ayzmlyu1.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%2Fcwyiha518nr8ayzmlyu1.png"&gt;&lt;/a&gt;&lt;br&gt;Aggregated statistics for a specific combination. A combination is not guaranteed to appear in every practice. Furthermore, it can appear multiple times, especially when it has a low confidence value compared to the other shortcuts of a collection. Consequently, the above figure shows only 11 practice runs but 15 correct occurrences and 3 errors.
  &lt;/p&gt;

&lt;p&gt;I made quite a few mistakes with this combination in the beginning. Therefore KeyCombiner's algorithm is skill skeptical about my skills. Errors usually mean that I thought I knew the shortcut but then typed a wrong combination. In this case, I suspect it is because I was hitting Ctrl+a instead or missing the a key. shift+a is a bit tricky to type if you are used to hit both shift and a with your little finger. However, my performance has been much better recently. Just a couple more practice runs to go and KeyCombiner will forgive my earlier mistakes.&lt;/p&gt;

&lt;p&gt;Then, finally, after another 7 practice runs, I had reached my goal:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffgl1huzpanco53vu67eh.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%2Ffgl1huzpanco53vu67eh.png"&gt;&lt;/a&gt;&lt;br&gt;Collection overview card after I have mastered all 50 shortcuts.
  &lt;/p&gt;

&lt;p&gt;Practicing on this collection looks much different now than in the beginning:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3iyyon5lgltgx2y3lh9w.gif" 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%2F3iyyon5lgltgx2y3lh9w.gif"&gt;&lt;/a&gt;&lt;br&gt;Pratice run after completing the challenge.
  &lt;/p&gt;

&lt;h1&gt;
  
  
  Tips
&lt;/h1&gt;

&lt;p&gt;It is straightforward to do a similar challenge. Simply go to &lt;a href="https://keycombiner.com" rel="noopener noreferrer"&gt;https://keycombiner.com&lt;/a&gt;, create an account, import some shortcuts from public collections, and start practicing. However, I would like to share some additional&lt;br&gt;
tips that make learning new shortcuts more pleasant for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a bit more fun in the beginning if you throw in some shortcuts that you already know. Even better, just extend one of your existing collections with new shortcuts that you want to learn. KeyCombiner will automatically show the new ones more frequently during practice.&lt;/li&gt;
&lt;li&gt;I sometimes activate key hints &lt;em&gt;without&lt;/em&gt; delay, which brings some variety to the learning experience and can help build muscle memory. If you are a good typist, you will be able to type a lot of shortcuts within the 60 seconds time limit.&lt;/li&gt;
&lt;li&gt;KeyCombiner will try to filter out shortcuts that cannot be captured during training. Those are marked with a yellow background in your collections. However, sometimes an invalid combination may still make it into your practice session, for example, if a browser extension does not pass it on to KeyCombiner. Simply append an underscore to any of the keys, e.g. shift_+a, so that KeyCombiner will recognize it as invalid.&lt;/li&gt;
&lt;li&gt;Depending on how frequently use a shortcut in your daily work, your memory may fade over time. To counter this, I suggest practicing also mastered collections from time-to-time. A couple of one-minute practice sessions can be a nice break from work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Results &amp;amp; Conclusion
&lt;/h1&gt;

&lt;p&gt;I have already learned many new keyboard shortcuts with KeyCombiner before this challenge. However, I never kept track of how long it took exactly until I knew them. I am thrilled with finding out that I could learn 50 new shortcuts in just 42 minutes of practice time. &lt;/p&gt;

&lt;p&gt;Believe it or not, without thinking much about it, I have started to use every single one of the 50 learned shortcuts in my daily work. I guess that's the benefit of learning, not just any shortcuts, but precisely the ones you pick.&lt;/p&gt;

&lt;p&gt;Clearly, the experience will vary between people and also depend on the complexity of the shortcuts. Given that I spent much of my free time working with the keyboard shortcuts domain during the last months, I can probably pick up new ones faster than an average user. Still, I am confident that you could achieve similar results. &lt;/p&gt;

&lt;p&gt;I think this post makes a good argument that 42 minutes spent with &lt;a href="https://keycombiner.com" rel="noopener noreferrer"&gt;https://keycombiner.com&lt;/a&gt; are an excellent investment in your productivity.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>keyboard</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Learning all VSCode Shortcuts Evolved my Developing Habits</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Fri, 20 Nov 2020 17:18:58 +0000</pubDate>
      <link>https://dev.to/tkainrad/learning-all-vscode-shortcuts-evolved-my-developing-habits-33d5</link>
      <guid>https://dev.to/tkainrad/learning-all-vscode-shortcuts-evolved-my-developing-habits-33d5</guid>
      <description>&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;I spent a few hours spread over the last couple of weeks to learn every single one of VSCode's keyboard shortcuts, specifically the 149 shortcuts from the &lt;a href="https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf"&gt;official keyboard shortcuts reference&lt;/a&gt;. These are also present in &lt;a href="https://keycombiner.com/collections/vscode/"&gt;KeyCombiner's searchable table of VSCode shortcuts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Admittedly, I started this challenge to write a blog post about it afterward and as a way to promote &lt;a href="https://keycombiner.com/"&gt;KeyCombiner&lt;/a&gt; via content marketing. The blog post I had in mind would be similar to my previous one, &lt;a href="https://tkainrad.dev/posts/how-i-learned-50-new-keyboard-shortcuts-in-42-minutes/"&gt;documenting my process of learning 50 new web application shortcuts in 42 minutes&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;But, as it usually happens only in romantic comedies, my intentions changed over time. This article turned out much different. It is not about the learning process but about how this challenge changed some of the developing habits I had for many years. Workflows that I grew used to during many projects, different IDEs, and even varying programming languages suddenly evolved. &lt;/p&gt;

&lt;h1&gt;
  
  
  Habits are Hard to Break
&lt;/h1&gt;

&lt;p&gt;As software engineers, we like to think that we are continually learning and improving our skills. This is certainly true when it comes to the technologies we are using. However, our development habits, such as which features of our IDEs we use, are much more rigid. I believe most of our core workflows are formed early on and very hard to change. &lt;br&gt;
I don't have data to back this up, but when I look at myself, my co-workers, and other developers I know, this certainly seems true. If you think about it, it is not surprising, the same thing happens in other areas of life. For this very reason, you will find that developers who have studied or worked together will often use similar shortcuts, similar IDE features, and have similar limitations in their workflows.&lt;/p&gt;

&lt;p&gt;The usual way to combat this is reading books, blog posts, attending conferences, well, everything that is used in our industry to extend our knowledge. However, with fundamental developing habits, I have found that this works poorly. You might read about a neat feature of your IDE, or see someone demo their workflow, but when you are eventually sitting in front of your screen and writing code, it is easy to fall back to what we already know, what is already set up, and proven to work.&lt;/p&gt;

&lt;p&gt;After this experiment, I am convinced that keyboard shortcuts are the main factor in how we form our developing habits, and they can also stop us from evolving our habits.&lt;br&gt;
Even before this challenge, I felt that I was good with shortcuts. I knew quite a few refactoring shortcuts, knew how to pause and stop program executing during debugging, was decent at jumping around between files, searching through my project, and all the other usual stuff. When I saw a co-worker using a shortcut that I didn't know, I was quick to incorporate it into my workflow, too. After all, I was enough into shortcuts that I built a whole side-project around learning them. &lt;br&gt;
&lt;strong&gt;The thing is, all new shortcuts that I learned were the ones that would augment my existing habits.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a hen and egg problem; if you don't know the shortcuts, you will not start to change your habits and use new IDE features because without shortcuts, they are too tedious to use or not at all usable. But if you don't form new habits, you will not learn the shortcuts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without intending it, I think I found a way to break out of this cycle: &lt;br&gt;
Learning all IDE shortcuts very well &lt;em&gt;before&lt;/em&gt; getting back to work. By learning &lt;em&gt;all&lt;/em&gt; shortcuts, you are not limited to what somebody shows you and might not be compatible with your situation. You can naturally include what makes sense, in addition to your existing skills.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next section shows how this worked for me.&lt;/p&gt;

&lt;h1&gt;
  
  
  Evolving my Habits
&lt;/h1&gt;

&lt;p&gt;I started the learning process as it is usually done with KeyCombiner: By importing some shortcuts from the &lt;a href="https://keycombiner.com/collections/vscode/"&gt;public collection of VSCode shortcuts&lt;/a&gt; into a personal collection. Intuitively, I started with the ones I already knew and some additional that seemed most useful to me. Back then I was still trying to show that I could learn all shortcuts very quickly with KeyCombiner. I didn't expect that shortcuts that had nothing to do with my existing workflows will be the real deal.&lt;/p&gt;

&lt;p&gt;Some of the first combinations that I picked and that I did not know previously were alt+w/r/c for toggling find options (match whole word, regex, case sensitivity) because I was already using those features. This went on for a few days. I did a couple practice runs every day and added new shortcuts whenever KeyCombiner was saying that I mastered all of the previous ones.&lt;/p&gt;

&lt;p&gt;Eventually, I knew all shortcuts that seemed useful for how I was using VSCode back then. So I had to start adding shortcuts that had nothing to do with my existing habits. This brought up an interesting misconception. Often keyboard shortcuts are seen as a way to do things faster, compared to using the mouse. While that is true, I think there is an even more important aspect to shortcut usage in IDEs: Many features are not used at all, if you don't know the shortcut!&lt;/p&gt;

&lt;p&gt;As I was learning new VSCode shortcuts every day, I started to use features that I previously didn't even know of. One of the first things that suddenly made a lot of sense was &lt;em&gt;Select all Occurences of Find Match&lt;/em&gt; with Alt+Enter as default binding, especially when combined with regex search. I was so excited about it, that I even &lt;a href="https://twitter.com/ThomasKainrad/status/1305608337799761920"&gt;tweeted a Gif&lt;/a&gt; showing how I use it to modify the CSV files that are the source for KeyCombiner's public collection tables.&lt;/p&gt;

&lt;p&gt;The process worked both ways: Sometimes, while I was practicing a shortcut on KeyCombiner, it seemed apparent that this was useful and that I should include it into my workflow. Sometimes it hit me while coding that I had just learned a shortcut that can make the current task more efficient.&lt;/p&gt;

&lt;p&gt;In the following, I describe the most significant changes in my daily development habits. The list is far from complete though; there are many more small things that I picked up and frequently use now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Editor and Panel Management&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Since knowing all the shortcuts to switch focus between panels and move editors around, I am using VSCode's powerful layouting capabilities much more. I have 3-5 editor panels open at pretty much all times, seeing many related pieces of code at once. Working this way by using the mouse is very impractical.&lt;br&gt;
I switch between editor panels with keyboard shortcuts and move editors from one group to the other.&lt;/p&gt;

&lt;p&gt;There is one negative side-effect, though: I am starting to get annoyed when I use other IDEs (PyCharm, Eclipse), because they lack far behind VSCode when it comes to using multiple editors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-cursor Editing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you don't know the shortcut to add additional cursors, I doubt you will ever use this incredibly powerful feature of VSCode. It is a typical feature that only blends into your habits once you know the shortcuts.&lt;br&gt;
The basic commands are Ctrl+Alt+Up/Down for adding cursors above/below. However, I found the commands to &lt;em&gt;Insert cursor at end of each line selected&lt;/em&gt; (Shift+Alt+i), and the above-mentioned &lt;em&gt;Select all Occurences of Find Match&lt;/em&gt; (Alt+Enter) even more powerful. These commands are why I frequently paste text snippets into VSCode, apply a few operations, and then copy-paste it back into whatever application I was using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opening views by shortcut&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I sometimes tried to do this before, but it never stuck. Now I finally switch to all views (Explorer, Debug, Search, Problems, etc.) with dedicated keyboard shortcuts. These shortcuts translate very nicely to other IDEs. After learning the VSCode default bindings, which are Ctrl+Shift+&amp;lt;char&amp;gt;, I set the same bindings also for Eclipse and PyCharm. Especially Ctrl+Shift+e for switching to the explorer view and Ctrl+Shift+d for switching to the debug view are among my most used shortcuts now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Making Selections&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I hate to admit it, but I did not use shortcuts to expand and shrink AST selections before.  AST stands for &lt;em&gt;abstract syntax tree&lt;/em&gt;, which means that the IDE will take the current language's syntax into account for modifying the selection. Finally, I picked up Ctrl+Shift+left/right to shrink and expand selections. Not all IDEs handle this in the same way, which can be a bit annoying, but it works well for the most frequent tasks, such as expanding the selection to enclose the current string, method, class, or HTML tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Folding&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I have started to use folding much more.  For years, I have rarely used this feature that all IDEs support to a great extent. Now, I do it frequently. Folding is one of these things that are just not feasible with the mouse. Of course, if you need to fold code, &lt;a href="https://blog.codinghorror.com/the-problem-with-code-folding/"&gt;chances are that you need to structure your code better&lt;/a&gt;. Many organizations even apply automatic code linters that will complain when methods or classes are too long. However, I have never seen someone recommend splitting up blog posts into multiple files.  The same goes for other non-code file types, such as JSON. All we have there is folding.&lt;/p&gt;

&lt;p&gt;I am not saying these are the things you should start to learn now, far from it. These are the things I personally integrated deep into my workflows after doing this challenge, without choosing them deliberately, but naturally. Who knows what you will pick up.&lt;/p&gt;

&lt;p&gt;Of course, some of the shortcuts I learned still seem a bit, let's say nonessential, but a little useless knowledge never killed nobody.&lt;/p&gt;

&lt;h1&gt;
  
  
  More Unexpected Benefits
&lt;/h1&gt;

&lt;p&gt;In addition to finally breaking out of old habits and experiencing a real evolution of my IDE usage, there were some other, less significant, but still delightful second-order effects.&lt;/p&gt;

&lt;p&gt;As a shortcut enthusiast, I often had the problem that I needed to decide which binding to use for a particular operation and application pair. KeyCombiner's public shortcut search helps to find out which binding is the convention for a particular operation, but it can still be tricky. For example, take the frequently used &lt;em&gt;Step Over&lt;/em&gt; operation used for debugging. &lt;a href="https://keycombiner.com/collecting/collections/public/search/?description=step+over&amp;amp;keys=&amp;amp;mac_keys=&amp;amp;submit=Search"&gt;KeyCombiner shows that VSCode, Eclipse, and JetBrains IDEs all use a different default binding&lt;/a&gt;(F6,F8,F10). Learning every single VSCode shortcut has freed me from this mental load of deciding what the best binding for a particular IDE operation is. I simply use VSCode's bindings everywhere. There are good arguments for why VSCode is a good reference. With the rise of GitHub CodeSpaces and its thriving extensions marketplace, I think it is likely that it will emerge as the industry standard of IDEs within a few years. That's the topic for a future post, though.&lt;/p&gt;

&lt;p&gt;Another effect is that I rarely use the mouse anymore when working in VSCode. This is not ideological for me. I hold no grudges against mouse usage. It just so happens that the need to touch it rarely comes up anymore.&lt;br&gt;
I guess most people that can do this use Vim or some Vim extension for their IDE. I can say confidently that it also works to learn all the default shortcuts. However, if you aim to eliminate the mouse completely while using VSCode, you should probably still go for one of the popular Vim emulators.&lt;/p&gt;

&lt;p&gt;And finally, maybe most importantly, VSCode feels like home now. As someone who also uses other IDEs daily, it's hard to develop a feeling towards a particular one that this is &lt;em&gt;your&lt;/em&gt; professional tool: &lt;em&gt;The&lt;/em&gt; place where the magic happens. Now that I have a complete picture of VSCode's feature set, I feel that I have truly made it my own. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;Of course, you don't have to learn all shortcuts of your IDE. I never thought I would either. You can pick up a new shortcut here or there. Read blog posts where developers show off their selection of favorite shortcuts or exchange favorites with your co-workers. That's a perfectly fine approach, and it is how a large majority of developers tackle this topic. It is even a core idea of my own project KeyCombiner to build collections of selected keyboard shortcuts that can be learned, shared, and organized.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But&lt;/em&gt;, you can also invest a few hours spread over a couple of weeks, stop making compromises, and learn &lt;em&gt;all the shortcuts&lt;/em&gt;.&lt;br&gt;
There is no way of knowing beforehand how this will influence your habits, how it will amend your existing workflows, and which entirely new possibilities will open up for you.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>keyboard</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using Hugo, GitLab Pages, and Cloudflare to create and run my Blog Site</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Thu, 10 Sep 2020 15:47:29 +0000</pubDate>
      <link>https://dev.to/tkainrad/using-hugo-gitlab-pages-and-cloudflare-to-create-and-run-my-blog-site-3p4h</link>
      <guid>https://dev.to/tkainrad/using-hugo-gitlab-pages-and-cloudflare-to-create-and-run-my-blog-site-3p4h</guid>
      <description>&lt;p&gt;In this post, I outline how I develop and run my &lt;a href="https://tkainrad.dev"&gt;blog site&lt;/a&gt;. I briefly explain my technology choices and give detailed instructions about how to use the resulting stack to create such a project. If you stick with me until the end, you will know how to run a beautiful, easily customizable static website for free.&lt;/p&gt;

&lt;p&gt;When I decided to start my blog for the reasons outlined in &lt;a href="//../writing-a-swe-blog"&gt;my first post&lt;/a&gt;, I was already familiar with GitLab Pages, and the &lt;a href="https://www.mkdocs.org/"&gt;MkDocs&lt;/a&gt; static site generator. I am using this combination for creating documentation websites, and it is working very well.&lt;/p&gt;

&lt;p&gt;Therefore, it was an easy choice for me to rely on GitLab Pages also for my blog site. I will cover its features in a later section of this post. With hosting already covered, I just needed to create the actual site.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the site with &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Before starting this blog, the only static site generator I used in production environments was MkDocs, which is intended for documentation and clearly not a good choice for creating a personal blog site. &lt;/p&gt;

&lt;p&gt;A good overview of more appropriate alternatives is given on &lt;a href="https://www.staticgen.com/"&gt;staticgen.com&lt;/a&gt;. For my purpose, probably all the popular projects would have been good choices. I decided to go with Hugo for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is written in Go, a language with a promising future that I wanted to try out for a while already.&lt;/li&gt;
&lt;li&gt;There is a very well-curated list of open-source themes directly &lt;a href="https://themes.gohugo.io/"&gt;on the official website&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's get to work. &lt;/p&gt;

&lt;p&gt;To get started on Ubuntu, we can execute just two commands to install hugo and create a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install hugo&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;hugo

&lt;span class="c"&gt;# create a new project&lt;/span&gt;
hugo new site personal-blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are not using Ubuntu, it is likely that your system's package manager provides a similarly easy experience. Refer to &lt;a href="https://gohugo.io/getting-started/installing"&gt;the official documentation&lt;/a&gt; for installation instructions for other operating systems.&lt;/p&gt;

&lt;p&gt;Before we start to work on our site, we want to install a theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install the theme&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;personal-blog
git init
git submodule add https://github.com/luizdepra/hugo-coder.git themes/hugo-coder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like that Hugo is very forward about using &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules"&gt;GIT submodules&lt;/a&gt; to install themes. This makes it easy to apply changes to the theme while keeping the connection to the original theme project. In an upcoming blog post, I will detail which changes I made to the theme itself. For now, we are perfectly fine with the default &lt;a href="https://github.com/luizdepra/hugo-coder/"&gt;Hugo-Coder&lt;/a&gt; theme. &lt;/p&gt;

&lt;p&gt;We only need to apply some basic configuration. Simply replace the content of &lt;code&gt;config.toml&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;baseurl = "http://www.example.com"&lt;/span&gt;
&lt;span class="s"&gt;title = "johndoe"&lt;/span&gt;

&lt;span class="s"&gt;theme = "hugo-coder"&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;author = "John Doe"&lt;/span&gt;
    &lt;span class="s"&gt;description = "John Doe's personal website"&lt;/span&gt;
    &lt;span class="s"&gt;keywords = "blog,developer,personal"&lt;/span&gt;
    &lt;span class="s"&gt;info = "Full Stack Magician"&lt;/span&gt;
    &lt;span class="s"&gt;avatarurl = "images/avatar.jpg"&lt;/span&gt;
    &lt;span class="s"&gt;footercontent = "Enter a text here."&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;taxonomies&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;series = "series"&lt;/span&gt;

&lt;span class="c1"&gt;# Menu links&lt;/span&gt;
&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;menu.main&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
    &lt;span class="s"&gt;name = "Blog"&lt;/span&gt;
    &lt;span class="s"&gt;weight = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="s"&gt;url  = "/posts/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we create the first post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hugo new posts/my-first-post.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the theme to properly recognize the new blog post, we have to replace the content of the newly created &lt;code&gt;/content/posts/my-first-post.md&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;+++&lt;/span&gt;
&lt;span class="s"&gt;date = "2019-01-01"&lt;/span&gt;
&lt;span class="s"&gt;title = "My first Post"&lt;/span&gt;
&lt;span class="s"&gt;slug = "my-first-post"&lt;/span&gt; 
&lt;span class="s"&gt;tags = []&lt;/span&gt;
&lt;span class="s"&gt;categories = []&lt;/span&gt;
&lt;span class="s"&gt;series = []&lt;/span&gt;
&lt;span class="s"&gt;+++&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can get a first look at our new personal portfolio and blogging site, by starting up the Hugo development server. Simply type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hugo server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go to &lt;a href="http://localhost:1313/"&gt;http://localhost:1313/&lt;/a&gt; to see your new site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tTydgP6T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hxy6nsikadzfzyh8tkkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tTydgP6T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hxy6nsikadzfzyh8tkkk.png" alt="hugo-coder-default-page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Testing your site locally is great, but showing the whole world that you are &lt;em&gt;John Doe, the Full Stack Magician&lt;/em&gt; is something else entirely. Luckily, we are very close to doing just that.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hosting with &lt;a href="https://docs.gitlab.com/ee/user/project/pages/"&gt;GitLab Pages&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;GitLab Pages is similar to GitHub Pages.&lt;br&gt;
Both allow free hosting of static websites. GitLab Pages enables you to build the hosted static content via GitLab's CI/CD features. This means that your site will automatically be rebuilt on every commit to the repository. Until the release of GitHub Actions, GitHub could not do this. Instead, you had to build the site locally and commit the static files to the repository. Nowadays, both GitLab and GitHub are perfectly fine choices to host your static site.&lt;/p&gt;

&lt;p&gt;Naturally, we start by creating a new repository.  Before pushing anything to this repository, you might want to perform some usual GIT maintenance tasks, such as creating a &lt;code&gt;.gitignore&lt;/code&gt; file. If you do not know it yet, you should have a look at the &lt;a href="https://www.gitignore.io/"&gt;gitignore.io service&lt;/a&gt; service. The site generates &lt;code&gt;.gitignore&lt;/code&gt; files depending on your technology stack. For Hugo, it will for example exclude the &lt;code&gt;/public/&lt;/code&gt; folder, which is very much what we want, because we will build this folder via a GitLab CI pipeline on every push to the repository.&lt;/p&gt;

&lt;p&gt;Once everything is in order, we can simply follow GitLab's instructions for pushing our existing project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;personal-blog
git remote add origin git@gitlab.com:&amp;lt;path-to-your-repository&amp;gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we get to the exciting part: Having our site built and published on every new commit to the repository. If you are not yet familiar with GitLab's CI/CD features, check out &lt;a href="https://docs.gitlab.com/ee/ci/"&gt;their docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fortunately, getting started is very simple. Simply put a file called &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; in the root of your project. This YAML configuration file holds all CI/CD configuration. For our Hugo-powered blog, the following file content is sufficient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monachus/hugo&lt;/span&gt;

&lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;hugo&lt;/span&gt;
    &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;public&lt;/span&gt;
    &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line specifies the docker base image to use for our pipeline. For this brief tutorial, we will not use any testing stages, instead, we have just one simple job called &lt;code&gt;pages&lt;/code&gt;. It executes the &lt;code&gt;hugo&lt;/code&gt; command, which will build the static site content in the &lt;code&gt;public&lt;/code&gt; directory. Somewhat incidentally, this is also where GitLab Pages expects to find our static site content. The only thing left to do is publishing the &lt;code&gt;public&lt;/code&gt; directory as &lt;a href="https://docs.gitlab.com/ee/user/project/pipelines/job_artifacts.html"&gt;a job artifact&lt;/a&gt;. The last two lines are optional and state that the site should only be built and published on commits to the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Once you push this file to your repository's master branch, the static site will be built and published within a few minutes. Go to &lt;em&gt;Settings-&amp;gt;Pages&lt;/em&gt; to verify that everything is in order and to see the default URL of your new website. If you own a domain you would like to use rather than the default *.gitlab.io one, you can head &lt;a href="https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html"&gt;to the docs&lt;/a&gt; or check out this &lt;a href="https://about.gitlab.com/2016/04/07/gitlab-pages-setup/"&gt;more detailed tutorial&lt;/a&gt;. If you want, you can enable &lt;a href="https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html"&gt;automatic certificate management using Let’s Encrypt&lt;/a&gt; for your custom domain. In case you use Cloudflare as described in the next section, you will not need this though.&lt;/p&gt;

&lt;h1&gt;
  
  
  Speeding up load times and configuring URL redirections with &lt;a href="https://www.cloudflare.com/"&gt;Cloudflare&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;My initial reason for trying out Cloudflare with this setup was that I had problems redirecting from www to non-www URLs with Namecheap, which is my domain name registrar. The issue was complicated by the fact that the site uses a .dev domain which is by default on the &lt;a href="https://opensource.google.com/projects/hstspreload"&gt;HSTS preload list&lt;/a&gt;. Namecheap seems to prefer selling their own SSL certificates rather than fully support and document working with Let's Encrypt.&lt;/p&gt;

&lt;p&gt;I solved this issue by simply signing up to Cloudflare. The free version is perfectly fine for me. After signing up, Cloudflare provides very simple and precise instructions for getting started. Basically, you have to configure your domain to use their nameservers instead of the ones provided by your original domain name registrar. &lt;/p&gt;

&lt;p&gt;Once your site is configured to run with Cloudflare, you can use their &lt;em&gt;Page Rules&lt;/em&gt; feature to easily redirect traffic from the &lt;a href="http://www"&gt;www&lt;/a&gt;. subdomain to your canonical non-www URL or the other way around.&lt;/p&gt;

&lt;p&gt;Furthermore, Cloudflare provides SSL encryption out of the box from their servers to your clients. All your static sites hosted with GitLab Pages and served via Cloudflare will be accessible over HTTPS without any additional configuration. Of course, we also want to encrypt the traffic from Cloudflare to the origin GitLab Pages host. For this, Cloudflare offers &lt;em&gt;Origin Certificates&lt;/em&gt;. I will not explain this further, as there is an excellent &lt;a href="https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/"&gt;tutorial on this provided directly by GitLab&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is hard to put a number on the speedup that Cloudflare provides for my site. I can say though that it is able to handle a significant load without any issues. My busiest weekend has been when &lt;a href="https://tkainrad.dev/posts/managing-my-personal-knowledge-base/"&gt;my post on personal knowledge management&lt;/a&gt; reached the front page of Hacker News and attracted more than 30k unique viewers in two days. The site didn't flinch.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The biggest advantage of this setup is its financial cost. Apart from buying the &lt;a href="http://tkainrad.dev"&gt;tkainrad.dev&lt;/a&gt; domain, creating my blog site did not cost any money. Furthermore, it is now running at absolutely zero cost. This is not restricted to a limited timeframe, thanks to GitLab Pages. This is much better than having to resort to chemistry puns for reducing our hosting bills:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XAX-oWOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/reduce_your_payments.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XAX-oWOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/reduce_your_payments.png" alt="xkcd Comic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have basic programming skills, I highly recommend hosting your static sites with this free service instead of paying a monthly fee to a hosting provider.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>git</category>
    </item>
    <item>
      <title>Using VueJS alongside Django</title>
      <dc:creator>Thomas Kainrad</dc:creator>
      <pubDate>Wed, 02 Sep 2020 19:23:45 +0000</pubDate>
      <link>https://dev.to/tkainrad/using-vuejs-alongside-django-29ka</link>
      <guid>https://dev.to/tkainrad/using-vuejs-alongside-django-29ka</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;I am the creator of &lt;a href="https://keycombiner.com"&gt;https://keycombiner.com&lt;/a&gt;. It is a web application to organize the keyboard shortcuts you use, get better at using them, and to learn new ones. The whole thing is quite challenging because the project's scope is significant, and I am doing it alone in my spare time while working full time. So I have to be very efficient. Fortunately, I am using Django with its &lt;a href="https://docs.djangoproject.com/en/3.0/ref/contrib/"&gt;&lt;em&gt;batteries-included&lt;/em&gt;&lt;/a&gt; approach. &lt;/p&gt;

&lt;p&gt;I use all kinds of Django features that speed up my development, and I wouldn't want to miss its template engine. Therefore, using Django only in the backend and building a JavaScript SPA for the frontend is not an option for me.&lt;br&gt;&lt;br&gt;
However, even the most avid backend developer has to admit that some things warrant a client-side implementation. Small user actions should not require page reloads. Also, some parts of the web application I am building require rather sophisticated user interaction. &lt;/p&gt;

&lt;p&gt;Traditionally, one would mix Django with some jQuery to achieve the desired behavior. But there are newer JavaScript technologies now: &lt;a href="https://vuejs.org/"&gt;React&lt;/a&gt; and &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Since our goal is to find a framework that we can use alongside Django without rethinking everything, we will go for Vue as the more lightweight alternative.&lt;br&gt;
In this post, I will show that you can start to use Vue alongside Django's template language with minimal effort.&lt;/p&gt;
&lt;h1&gt;
  
  
  Installation and Setup
&lt;/h1&gt;

&lt;p&gt;One of the reasons to use Vue is its excellent &lt;a href="https://vuejs.org/v2/guide/"&gt;documentation&lt;/a&gt;. It includes many examples, has a decent search, and a reasonably clear table of contents.&lt;/p&gt;

&lt;p&gt;This post aims to show that you can start to use Vue with your Django projects immediately without any sophisticated setup that will take hours to complete. Therefore, we will use the simplest method to use Vue.js: Including it via a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- development version, includes helpful console warnings --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it, we are now ready to create our first Vue.js instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{ message }}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;delimiters&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;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello Vue!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is taken from the official Getting Started Guide. However, there is one addition. Per default, Django and Vue use the same template tags. Hence, we need to set the Vue delimiters explicitly to avoid conflicts with Django's template engine.&lt;/p&gt;

&lt;h1&gt;
  
  
  Access Django Data from Vue
&lt;/h1&gt;

&lt;p&gt;The simplest way to do so is the &lt;a href="https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script"&gt;built-in Django jscon_script filter&lt;/a&gt;.&lt;br&gt;
This way you can immediately start using your Django models as data for your Vue instances.&lt;/p&gt;

&lt;p&gt;In HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{{ django_template_variable|json_script:"djangoData" }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in JavaScript, we load this data into a variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;jsVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;djangoData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it is ready to use with Vue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;delimiters&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;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsVariable&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Make async Backend Requests
&lt;/h1&gt;

&lt;p&gt;One of the most frequent tasks of a Vue frontend is to make requests to a backend server application. With a full-stack Django application, we don't have to do this for every user interaction. In some cases, a full page reload might be perfectly fine, and Django's templating system provides all kinds of advantages. But to enhance user experience and to reap the full benefits of using Vue, we may still want to make backend requests in some places.&lt;/p&gt;

&lt;p&gt;Vue itself cannot handle requests. In this post, I will use &lt;a href="https://github.com/axios/axios"&gt;axios&lt;/a&gt;, because it is also recommended in the official Vue Docs. Other alternatives are perfectly fine too.&lt;/p&gt;

&lt;p&gt;To pass Django's CSRF protection mechanism, axios needs to include the respective cookie in its requests. The easiest way to accomplish this is to set global axios defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xsrfCookieName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;csrftoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xsrfHeaderName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-CSRFTOKEN&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;Alternatively, we could also create an axios instance with the required settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;xsrfCookieName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;csrftoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;xsrfHeaderName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-CSRFTOKEN&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your Django template needs to contain the tag &lt;code&gt;{% csrf_token %}&lt;/code&gt; or, alternatively, the respective view must use the decorator &lt;a href="https://docs.djangoproject.com/en/3.0/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie"&gt;&lt;code&gt;ensure_csrf_cookie()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The rest of Django's default session backend for authentication will work out of the box, meaning that you can annotate your backend services with things like &lt;code&gt;loginRequired&lt;/code&gt; and it will just work.&lt;br&gt;
To make the request, we can use axios as usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/django/backend/endpoint&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsVariable&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle response&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle error&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This call can be done within a Vue instance's &lt;code&gt;mounted&lt;/code&gt; hook or any other place where you can put JavaScript code.&lt;/p&gt;

&lt;p&gt;If you activated &lt;code&gt;CSRF_USE_SESSIONS&lt;/code&gt; or &lt;code&gt;CSRF_COOKIE_HTTPONLY&lt;/code&gt; in your Django settings, you need to read the CSRF token from the DOM. For more details, see &lt;a href="https://docs.djangoproject.com/en/3.0/ref/csrf/#acquiring-the-token-if-csrf-use-sessions-or-csrf-cookie-httponly-is-true"&gt;the official Django docs&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;When you google for &lt;em&gt;Django + Vue&lt;/em&gt;, most results will be focused on using Django for your backend and Vue for a separate frontend project. Having two independent projects increases complexity, and you lose access to Django's template system, which is a very powerful timesaver. On the other hand, access to a frontend framework such as Vue can do wonders for web applications that go beyond CRUD functionality.&lt;/p&gt;

&lt;p&gt;Fortunately, we do not need to decide between the two. This guide shows that you can have the cake and eat it too!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally published on my personal blog site at &lt;a href="https://tkainrad.dev/posts/use-vuejs-with-django/"&gt;https://tkainrad.dev/posts/use-vuejs-with-django/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
