<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://www.kozubek.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.kozubek.dev/" rel="alternate" type="text/html" /><updated>2021-12-12T16:11:34+00:00</updated><id>https://www.kozubek.dev/feed.xml</id><title type="html">kozubek.dev</title><subtitle>Blog about web development
</subtitle><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><entry><title type="html">How do I share my bookmarks on the web</title><link href="https://www.kozubek.dev/2020/11/15/awesome-bookmarks.html" rel="alternate" type="text/html" title="How do I share my bookmarks on the web" /><published>2020-11-15T00:00:00+00:00</published><updated>2020-11-15T00:00:00+00:00</updated><id>https://www.kozubek.dev/2020/11/15/awesome-bookmarks</id><content type="html" xml:base="https://www.kozubek.dev/2020/11/15/awesome-bookmarks.html">&lt;p&gt;Whenever I read something valuable around software engineering I save it in categorized browser bookmarks. You can find them in the Awesome section on this website as well. In this article I described how they are kept in sync.&lt;/p&gt;

&lt;p&gt;Find the repo &lt;a href=&quot;https://github.com/archiewald/awesome-links&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/6-bookmarks.png&quot; alt=&quot;bookmarks picture&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@quasichiara&quot;&gt;Chiara F&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I thought it would be worth sharing them with the world. As for myself, I would love to see what particular materials my colleagues find interesting.&lt;/p&gt;

&lt;p&gt;So there are bookmarks in my browser and the platform I use to share my thoughts is this very blog. How about creating a page with a list of awesome links, kept in sync with my bookmarks so I don’t need to upload it manually each time I add a new awesome article.&lt;/p&gt;

&lt;p&gt;This blog is using &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;jekyll&lt;/a&gt; platform to create and deploy content on GitHub in a famous &lt;a href=&quot;https://jamstack.org/&quot;&gt;Jamstack&lt;/a&gt; manner. The process of how I create a blog post is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;create a markdown file with the article content in a &lt;a href=&quot;https://github.com/archiewald/archiewald.github.io&quot;&gt;blog repository&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;as far as the article is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt;ed, GitHub handles the build process, deploy and make it available to the world. The process is so simple because of &lt;a href=&quot;https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/setting-up-a-github-pages-site-with-jekyll&quot;&gt;GitHub Pages &amp;amp; Jekyll integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming back to the bookmarks, the first step was to check how I can approach them in a machine-friendly manner to automate the process. The answer I found was &lt;a href=&quot;https://developer.chrome.com/extensions/bookmarks&quot;&gt;chrome.bookmarks api&lt;/a&gt; available for Google Chrome extensions.&lt;/p&gt;

&lt;p&gt;With the above knowledge I came out with the process on how to go from awesome bookmarks to the awesome links page on my blog:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a chrome extension able to get my bookmarks&lt;/li&gt;
  &lt;li&gt;Send serialized bookmarks over HTTP to a simple node app&lt;/li&gt;
  &lt;li&gt;On the node app:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;Clone the blog repository&lt;/li&gt;
  &lt;li&gt;Parse bookmarks and create awesome-links.md page which will be compiled to a HTML page in build process later&lt;/li&gt;
  &lt;li&gt;Commit changes and push to the repo&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;Wait until the page is deployed and available on &lt;a href=&quot;https://www.kozubek.dev/awesome-links.html&quot;&gt;kozubek.dev/awesome-links&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;chrome-extension&quot;&gt;chrome extension&lt;/h2&gt;

&lt;p&gt;Bookmarks are available as a tree, getting them and sending to the node app was pretty straightforward:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sendAwesomeBookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;chrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getTree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;awesomeBookmarks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;awesome&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})),&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;bookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;awesomeBookmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SECRET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// more on that later ;p&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-to-handle-git-operations-in-a-node-app&quot;&gt;How to handle git operations in a node app&lt;/h2&gt;

&lt;p&gt;I tried some git specific node libraries like &lt;a href=&quot;https://github.com/nodegit/nodegit&quot;&gt;nodegit&lt;/a&gt; and it was a hard experience. I felt like I used an overcomplicated tool for basic git operations, whereas you can simply run a shell command from your node script with a built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;child_process&lt;/code&gt; library.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;promisify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;child_process&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;git clone &quot;https://github.com/archiewald/archiewald.github.io&quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;stdout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;git status&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./archiewald.github.io&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// required if you want to run a command in a different folder&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// On branch master Your branch is up to date with 'origin/master'...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Few things happen here. Since most of the node api was built when promises were not available yet, typically it uses callbacks to handle asynchronous operations which results in hardly maintainable code because of &lt;a href=&quot;http://callbackhell.com/&quot;&gt;callback hell&lt;/a&gt;. That’s why we wrap it with, builtin as well, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util.promisify()&lt;/code&gt;. It’s doing a great job transforming a callback style &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(err, value) =&amp;gt; ...&lt;/code&gt; function into a version that returns a promise.&lt;/p&gt;

&lt;p&gt;Interestingly, there is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util.callbackify()&lt;/code&gt; function available as well, if you need one :)&lt;/p&gt;

&lt;p&gt;On the other hand, the file system library has a promises API already available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(&quot;fs&quot;).promises&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;making-it-secure-enough&quot;&gt;Making it secure enough&lt;/h2&gt;

&lt;p&gt;A disclaimer: I consider below solution good enough for my personal scripting project but it shouldn’t be used in production for customer-oriented web apps - keeping API Access Tokens on the client side hardcoded wouldn’t be a good idea!&lt;/p&gt;

&lt;p&gt;I needed some pain-free GitHub integration to commit updated bookmarks to the blog repo. As I learned, perhaps the easiest to do it is passing the credentials when cloning the repository:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &lt;span class=&quot;s2&quot;&gt;&quot;https://&amp;lt;GIT_USERNAME&amp;gt;:&amp;lt;GIT_PERSONAL_ACCESS_TOKEN&amp;gt;@github.com/archiewald/archiewald.github.io
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But I wouldn’t dare to pass my personal, real GitHub account credentials there. I came out with a hacky solution - just creating a new GitHub user with the one and only responsibility - to commit and push awesome bookmarks updates. Then the account was added as a collaborator to this particular repo.&lt;/p&gt;

&lt;!-- picture --&gt;

&lt;p&gt;Another problem is how to keep my credentials out of the repository. You can create an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.env&lt;/code&gt; file to be consumed by webpack so the api url and secret are injected in the build process:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// in .env&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;awesome-links.example.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// in webpack.config.js:&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dotenv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dotenv&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DefinePlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;process.env&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dotenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// in script.js:&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// in build/script.js:&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;awesome-links.example.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="tools" /><category term="node" /><category term="javascript" /><category term="git" /><summary type="html">Whenever I read something valuable around software engineering I save it in categorized browser bookmarks. You can find them in the Awesome section on this website as well. In this article I described how they are kept in sync. Find the repo here</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/6-bookmarks.png" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/6-bookmarks.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The pomodoro app is out 🍅❤</title><link href="https://www.kozubek.dev/2020/07/13/yapa.html" rel="alternate" type="text/html" title="The pomodoro app is out 🍅❤" /><published>2020-07-13T00:00:00+00:00</published><updated>2020-07-13T00:00:00+00:00</updated><id>https://www.kozubek.dev/2020/07/13/yapa</id><content type="html" xml:base="https://www.kozubek.dev/2020/07/13/yapa.html">&lt;!--more--&gt;

&lt;p&gt;Check out on &lt;a href=&quot;https://yapa.kozubek.dev/&quot;&gt;yapa.kozubek.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yapa code is open-source:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/yapa-frontend&quot;&gt;web client&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/yapa-server&quot;&gt;backend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/pomodoros.jpg&quot; alt=&quot;tomatoes&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@galex&quot;&gt;Alex Gzilla&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="tools" /><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/pomodoros.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/pomodoros.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Deep work app I am about to create</title><link href="https://www.kozubek.dev/2020/03/19/my-deep-work-flow.html" rel="alternate" type="text/html" title="Deep work app I am about to create" /><published>2020-03-19T00:00:00+00:00</published><updated>2020-03-19T00:00:00+00:00</updated><id>https://www.kozubek.dev/2020/03/19/my-deep-work-flow</id><content type="html" xml:base="https://www.kozubek.dev/2020/03/19/my-deep-work-flow.html">&lt;p&gt;I am creating a tool to help with focused yet healthy work with a computer. Doing it for myself because I didn’t find an app which meets my expectation in 100%. I don’t plan to make a fortune out of it, rather develop a simple open-source, free to use app.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;TLDR: pomodoro 🍅 timer + todo-list + healthy habits reminder + reports to track your progress. Does it click for you? Please read further and let me know what do you think in the comments.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/5-woodwork.jpg&quot; alt=&quot;woodworker&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@bobrodriguez&quot;&gt;Filipe de Rodrigues&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;struggling-to-stay-focused&quot;&gt;Struggling to stay focused&lt;/h2&gt;

&lt;p&gt;Looking back in the past I reckon myself as a kid who was hard to distract from a cognitive task. If there was a piece of work to be made and I enjoyed it - like preparation for a math competition, physics test - it was relatively easy for me to stay focused for a few hours. That stuff was quite comparable to my current day to day work. Yet I feel now it is much harder for me to keep myself undistracted. Had anything changed since that time?&lt;/p&gt;

&lt;p&gt;Certainly it did. To start with, I work on a computer. All day long. I don’t think this will ever change - maybe the form of what a personal computer itself is, but I am pretty sure I will be around creating/handling digital products - like many of us.&lt;/p&gt;

&lt;p&gt;And as much as I love it and feel this is a right environment for me, being able to stay focused on an assigned task becomes much more challenging. Digital services I daily use are craving for my attention all the time. With the content, with the way they look, with the User Experience they offer. There are top paid engineers and marketers who have a clear goal - make me stay on their portals as long as it is possible and bring me back when I leave.&lt;/p&gt;

&lt;h2 id=&quot;deep-work-as-a-valuable-skill&quot;&gt;Deep work as a valuable skill&lt;/h2&gt;

&lt;p&gt;Another interesting perspective I got from a book &lt;a href=&quot;https://www.goodreads.com/book/show/25744928-deep-work&quot;&gt;Deep Work&lt;/a&gt; by Cal Newport. What he says makes much sense with my experience - staying focused on a task gets harder so learning it gives you a competitive advantage.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;One of the most valuable skills in our economy is becoming increasingly rare. If you master this skill, you’ll achieve extraordinary results.&lt;br /&gt;&lt;br /&gt;
Deep work is the ability to focus without distraction on a cognitively demanding task. It’s a skill that allows you to quickly master complicated information and produce better results in less time. Deep work will make you better at what you do and provide the sense of true fulfillment that comes from craftsmanship. In short, deep work is like a super power in our increasingly competitive twenty-first century economy. And yet, most people have lost the ability to go deep-spending their days instead in a frantic blur of e-mail and social media, not even realizing there’s a better way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;🍅⌚&lt;/h2&gt;

&lt;p&gt;I arranged a toolset to fight with digital interruptions. Pomodoro technique is I believe the most important one. How it works? After &lt;a href=&quot;https://francescocirillo.com/pages/pomodoro-technique&quot;&gt;the author&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;Choose a task you’d like to get done&lt;/li&gt;
    &lt;li&gt;Set the Pomodoro for 25 minutes&lt;/li&gt;
    &lt;li&gt;Work on the task until the Pomodoro rings&lt;/li&gt;
    &lt;li&gt;When the Pomodoro rings, put a checkmark on a paper&lt;/li&gt;
    &lt;li&gt;Take a short break&lt;/li&gt;
    &lt;li&gt;Every 4 pomodoros, take a longer break&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;It works very well for me when I’m programming or writing. Every time I switched OS I find some app to serve me :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;on macOS I used &lt;a href=&quot;https://xwavesoft.com/be-focused-pro-for-iphone-ipad-mac-os-x.html?utm_source=zapier.com&amp;amp;utm_medium=referral&amp;amp;utm_campaign=zapier&quot;&gt;beFocused&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;on Linux I used &lt;a href=&quot;https://gnomepomodoro.org/&quot;&gt;Gnome Pomodoro&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;on Windows I am using &lt;a href=&quot;https://pomotodo.com/&quot;&gt;Pomotodo&lt;/a&gt; - actually the best among these&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly I can call myself a pomodoro app heavy user :)&lt;/p&gt;

&lt;h2 id=&quot;work-ergonomics&quot;&gt;Work ergonomics&lt;/h2&gt;

&lt;p&gt;Who made me think about it was a lecturer at Berkeley University of Computer Science course I used to listen.&lt;/p&gt;

&lt;p&gt;We rarely have an opportunity to listen the elder people talking about using a computer or programming. So I believe if one has some piece of advice for you it worths listen:&lt;/p&gt;

&lt;div class=&quot;videoWrapper&quot;&gt;
  &lt;iframe src=&quot;https://www.youtube.com/embed/8aFp84teahw?start=81&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Among the few rules he mentions, the most important one - take a break every ~ half an hour. Plays very well with Pomodoro technique, right?&lt;/p&gt;

&lt;p&gt;These breaks we can use even further for our health. Sure there is an app for this purpose, let me introduce you &lt;a href=&quot;https://slgobinath.github.io/SafeEyes/&quot;&gt;Safe Eyes&lt;/a&gt;.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/5-safe-eyes.png&quot; alt=&quot;safe eyes&quot; /&gt;
  &lt;figcaption&gt;
    Safe Eyes break screen  
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;It does a great job of presenting you exercise each break, preventing you from repetitive strain injuries (RSI). But, in my case, it needs to be in sync with pomodoro app as well so using it day to day was a pain in the ass.&lt;/p&gt;

&lt;h2 id=&quot;the-perfect-app&quot;&gt;The perfect app&lt;/h2&gt;

&lt;p&gt;What would make a great tool to enhance a deep and healthy workflow with a computer?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a tomato timer with editable work/break/long break time&lt;/li&gt;
  &lt;li&gt;present healthy short exercises to do each break&lt;/li&gt;
  &lt;li&gt;ability to put the pomodoros I have done in some context (simple todo-list and/or tagging system like #work #blog #studies etc)&lt;/li&gt;
  &lt;li&gt;statistics of how much deep work time I was able to perform each day/week&lt;/li&gt;
  &lt;li&gt;get reports presenting above with some nice looking charts (in weekly emails?)&lt;/li&gt;
  &lt;li&gt;multiplatform desktop app - would like it to run on Windows/macOS/Linux since I tend to switch between them a lot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The closest I found is &lt;a href=&quot;https://pomotodo.com/&quot;&gt;Pomotodo&lt;/a&gt;, but it doesn’t have the healthy tips and is not so UX friendly, at least the Windows version.&lt;/p&gt;

&lt;h2 id=&quot;about-the-tech&quot;&gt;About the tech&lt;/h2&gt;

&lt;p&gt;So, I am about to make such. I am excited to use &lt;a href=&quot;https://youtu.be/2KhRmFHLuhE&quot;&gt;Progressive Web App&lt;/a&gt; approach to create a multiplatform app, it seems like PWA support on desktop should bring me there ❤.&lt;/p&gt;

&lt;p&gt;It is far from being finished but is already useful enough for me to use it - basic pomodoro timer with desktop notification.&lt;/p&gt;

&lt;p&gt;Here it is, &lt;del&gt;&lt;a href=&quot;https://www.kozubek.dev/yapa-frontend/&quot;&gt;Yet Another Pomodoro App (CLICK ME)&lt;/a&gt;&lt;/del&gt; (Yapa is out! &lt;a href=&quot;https://www.yapa.kozubek.dev&quot;&gt;Find more&lt;/a&gt;). It is super simple and ugly. As long as you open it in Google Chrome on any system, you should be able to install it as a stand-alone, offline first app. It is a website but you don’t need an internet connection to use it after you enter it! This is probably the future of how apps, both desktop and mobile, will be distributed.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/5-yapa.png&quot; alt=&quot;yet another pomodoro app&quot; /&gt;
  &lt;figcaption&gt;
    the ugliest pomodoro app - installable and offline first
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/archiewald/yapa-frontend&quot;&gt;Code repository&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-next&quot;&gt;What next&lt;/h2&gt;

&lt;p&gt;I am about to add next features to &lt;a href=&quot;https://yapa.kozubek.dev/&quot;&gt;Yet Another Pomodoro App&lt;/a&gt; (and think about some proper name, though YAPA acronym sounds tempting). And sure, polish it to look much better ;) Would love to get some feedback about the idea. Do you find such problems in your workflow? Do you use any tools in this area that I might check for reference? Would you use YAPA when it’s finished? Let me know guys!&lt;/p&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="tools" /><summary type="html">I am creating a tool to help with focused yet healthy work with a computer. Doing it for myself because I didn’t find an app which meets my expectation in 100%. I don’t plan to make a fortune out of it, rather develop a simple open-source, free to use app.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/5-woodwork.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/5-woodwork.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Web development setup on Ubuntu</title><link href="https://www.kozubek.dev/2019/12/12/set-up-dev-envrionment.html" rel="alternate" type="text/html" title="Web development setup on Ubuntu" /><published>2019-12-12T00:00:00+00:00</published><updated>2019-12-12T00:00:00+00:00</updated><id>https://www.kozubek.dev/2019/12/12/set-up-dev-envrionment</id><content type="html" xml:base="https://www.kozubek.dev/2019/12/12/set-up-dev-envrionment.html">&lt;p&gt;A shortlist on how I create a basic web development setup on Ubuntu system. Not really a blog post, something to warm up after I abounded blogging for some time, definitely needed such thing, maybe you find it useful too.&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/4-cover.jpg&quot; alt=&quot;hacker&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@hidd3n&quot;&gt;Kevin Horvat&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;shell&quot;&gt;Shell&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH&quot;&gt;Zsh&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;zsh
chsh &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;which zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ohmyzsh/ohmyzsh#basic-installation&quot;&gt;Oh My Zsh&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;if&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The command could not be located because '/snap/bin' is not included in the PATH environment variable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/57121916/the-command-could-not-be-located-because-snap-bin-is-not-included-in-the-path&quot;&gt;Path error solution&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;code-editor&quot;&gt;Code editor&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://snapcraft.io/&quot;&gt;Snap&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;snapd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://snapcraft.io/vscode&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;snap &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;code &lt;span class=&quot;nt&quot;&gt;--classic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;set up as default code editor&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xdg-mime default code.desktop text/plain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;gitgithub&quot;&gt;git/github&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/astrand/xclip&quot;&gt;xclip&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;xclip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Follow:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh&quot;&gt;authenticate to github with zsh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/the-andela-way/a-practical-guide-to-managing-multiple-github-accounts-8e7970c8fd46&quot;&gt;manage multiple github/gitlab accounts&lt;/a&gt; - for example home with work one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;yadm&quot;&gt;yadm&lt;/h2&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;yadm
yadm clone https://github.com/archiewald/dev-configs.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Set powerline font in editor/terminal&lt;/p&gt;

&lt;h2 id=&quot;jekyll&quot;&gt;jekyll&lt;/h2&gt;

&lt;p&gt;follow &lt;a href=&quot;https://jekyllrb.com/docs/installation/ubuntu/&quot;&gt;this&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;node&quot;&gt;node&lt;/h2&gt;

&lt;p&gt;follow &lt;a href=&quot;https://github.com/nodesource/distributions#debinstall&quot;&gt;this&lt;/a&gt;&lt;/p&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="tools" /><summary type="html">A shortlist on how I create a basic web development setup on Ubuntu system. Not really a blog post, something to warm up after I abounded blogging for some time, definitely needed such thing, maybe you find it useful too.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/4-cover.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/4-cover.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Create React App with TypeScript tutorial</title><link href="https://www.kozubek.dev/2019/03/31/react-typescript.html" rel="alternate" type="text/html" title="Create React App with TypeScript tutorial" /><published>2019-03-31T00:00:00+00:00</published><updated>2019-03-31T00:00:00+00:00</updated><id>https://www.kozubek.dev/2019/03/31/react-typescript</id><content type="html" xml:base="https://www.kozubek.dev/2019/03/31/react-typescript.html">&lt;p&gt;This tutorial followed step by step will help you understand why TypeScript + React are awesome 💪 while building a simple to-do app. I made it beginner friendly but it requires some basic React and JavaScript knowledge.&lt;/p&gt;

&lt;!--more--&gt;

&lt;iframe class=&quot;stackblitz&quot; src=&quot;https://stackblitz.com/edit/react-ts-todo-list?embed=1&amp;amp;file=App.tsx&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;BTW StackBlitz (tool for online editing used above) is powered with VS Code and great TypeScript support. You can check most of the TypeScript features just manipulating the code there!&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/3-cover.jpg&quot; alt=&quot;notebook&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@nesabymakers?utm_medium=referral&amp;amp;utm_campaign=photographer-credit&amp;amp;utm_content=creditBadge&quot;&gt;NESA by Makers&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;TypeScript can help you create maintainable and scalable web apps. It is ready to use with React out of the box! Thanks to Create React App package with TypeScript support, configuration part is very easy nowadays.&lt;/p&gt;

&lt;h2 id=&quot;why-use-typescript-in-react&quot;&gt;Why use TypeScript (in React)&lt;/h2&gt;

&lt;h3 id=&quot;recognize-those-silly-errors&quot;&gt;Recognize those silly errors&lt;/h3&gt;

&lt;p&gt;I ❤️ TypeScript for giving me instant feedback if I am wrong with my code. Look for top 10 JavaScript error. I am sure that as a web developer you know them well.&lt;/p&gt;

&lt;figure&gt;
  &lt;img style=&quot;width:100%; max-width: 600px&quot; src=&quot;https://www.kozubek.dev/assets/images/3-js-errors.png&quot; alt=&quot;top 10 js errors&quot; /&gt;
  &lt;figcaption&gt;
    top 10 JavaScript errors in 1000 projects by &lt;a href=&quot;https://rollbar.com/blog/top-10-javascript-errors/t&quot;&gt;Rollbar&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;7 of them are about mixing up your types, not accessing the right variable, object property, etc. With TypeScript, you will rarely see them! Your configured IDE will tell you about them in advance.&lt;/p&gt;

&lt;p&gt;Another thing is code maintaining and refactor. Did you ever modified some property in your large app and went through all the classes and properties wondering what you just messed up and fixing here and there? Here TypeScript + your IDE will be your help as well.&lt;/p&gt;

&lt;h3 id=&quot;fits-react-very-well&quot;&gt;Fits React very well&lt;/h3&gt;

&lt;p&gt;If you ever liked Angular for having TypeScript support you will love React even more. Template engine from a developer point of view is very different - in Angular you have dummy HTML-like files, in React there is JSX, turning into TSX with TypeScript. This means you get static type checking in your templates as well!&lt;/p&gt;

&lt;h3 id=&quot;supported-via-create-react-app&quot;&gt;Supported via Create React App&lt;/h3&gt;

&lt;p&gt;As our prophet once announced, Create React App supports TypeScript out of the box, which makes starting a new app (also migrating from these relatively new) A LOT EASIER 🎉&lt;/p&gt;

&lt;div class=&quot;twitterWrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Create React App 2.1 + TypeScript = 💜 &lt;a href=&quot;https://t.co/tpb04toZ95&quot;&gt;https://t.co/tpb04toZ95&lt;/a&gt; &lt;a href=&quot;https://t.co/zBTVb0qa3U&quot;&gt;pic.twitter.com/zBTVb0qa3U&lt;/a&gt;&lt;/p&gt;&amp;mdash; Dan Abramov (@dan_abramov) &lt;a href=&quot;https://twitter.com/dan_abramov/status/1057118684479537152?ref_src=twsrc%5Etfw&quot;&gt;October 30, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;h3 id=&quot;got-super-trendy&quot;&gt;Got super trendy&lt;/h3&gt;

&lt;p&gt;Just see the results from the latest State of JS survey:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/3-state-of-js.png&quot; alt=&quot;js flavors&quot; /&gt;
  &lt;figcaption&gt;
    State of JS 2019 - &lt;a href=&quot;https://2018.stateofjs.com/javascript-flavors/overview/)&quot;&gt;JavaScript flavors&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;TypeScript is gaining popularity of &lt;a href=&quot;https://flow.org/&quot;&gt;Flow&lt;/a&gt; which is a very similar library of Facebook. Even Jest, the 1st choice testing library in React ecosystem, &lt;a href=&quot;https://github.com/facebook/jest/pull/7554#issuecomment-454358729&quot;&gt;got migrated to TypeScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Summing up, I heard a nice comparison on the &lt;a href=&quot;https://reactpodcast.com/41&quot;&gt;React Podcast&lt;/a&gt; which was more less:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TypeScript is like a cool buddy you would like to pair program with 💪&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;how-to-start-&quot;&gt;How to start 🚀&lt;/h2&gt;

&lt;h3 id=&quot;the-right-ide&quot;&gt;The right IDE&lt;/h3&gt;

&lt;p&gt;For your best experience, you should use &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt;. It is Microsoft open-source IDE and TypeScript is from Microsoft as well. You will have the best integration there and I know people moved from WebStorm to VS Code since they started using TypeScript.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TypeScript is all about developer experience, what is going on in your IDE. How fast and well will you be informed about errors you are about to make&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;create-react-app&quot;&gt;Create React App&lt;/h3&gt;

&lt;p&gt;We start with lunching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create-react-app&lt;/code&gt; project. It is recommended by CRA creators to use &lt;a href=&quot;https://www.npmjs.com/package/npx&quot;&gt;npx&lt;/a&gt; instead of installing create-react-app globally, to make sure you start with the latest version.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Important! Before running below make sure you don’t have CRA globally installed anymore! You might encounter issues like &lt;a href=&quot;https://github.com/facebook/create-react-app/issues/6119&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
  &lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;npm uninstall -g create-react-app
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;We will make use of a fresh new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--typescript&lt;/code&gt; flag.&lt;/p&gt;

&lt;div class=&quot;language-terminal highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;go&quot;&gt;npx create-react-app react-ts --typescript
cd react-ts
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then your TS based app should appear. Check if it starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm start&lt;/code&gt;. Then have a quick look at how it differs from regular CRA starter:&lt;/p&gt;

&lt;h3 id=&quot;ts-and-tsx-files&quot;&gt;.ts and .tsx files&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ts&lt;/code&gt; are regular TypeScript files, basically replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.js&lt;/code&gt;. While using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jsx&lt;/code&gt; for files containing React Components with JSX code is not mandatory, with TypeScript you need to always use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tsx&lt;/code&gt; when you write TSX code.&lt;/p&gt;

&lt;h3 id=&quot;tsconfigjson&quot;&gt;tsconfig.json&lt;/h3&gt;

&lt;p&gt;This file indicates that the directory is a root of a TypeScript project. It is a starting point for compiler so it contains some configuration options:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dom&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dom.iterable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;esnext&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;allowJs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;skipLibCheck&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;esModuleInterop&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;allowSyntheticDefaultImports&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;strict&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;forceConsistentCasingInFileNames&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;esnext&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;moduleResolution&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;resolveJsonModule&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;isolatedModules&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;noEmit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;jsx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;preserve&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can look up what particular options are for in &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot;&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An interesting one is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strict&lt;/code&gt; which is provided by default in CRA configuration. Following documentation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Enable all strict type checking options. 
Enabling –strict enables –noImplicitAny, –noImplicitThis, –alwaysStrict, –strictBindCallApply, –strictNullChecks, –strictFunctionTypes and –strictPropertyInitialization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Strict mode enables you to use the power of TypeScript and not neglecting type checks possibilities. You might not turn it on if you transfer your JavaScript app to TypeScript but for a start it is definitely recommended.&lt;/p&gt;

&lt;h2 id=&quot;coding-the-app&quot;&gt;Coding the app&lt;/h2&gt;

&lt;p&gt;Let’s clear the app, delete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.css&lt;/code&gt; and leave only a dummy skeleton in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.tsx&lt;/code&gt;
.&lt;/p&gt;
&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Hello React TS!&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So far it looks identical to a JS React component. Next thing we might consider is what data will our app keep. Basically, some tasks. We will define a model of a task in a separate folder which is a good practice. In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/models/task.ts&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might see people adding an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I&lt;/code&gt; prefix to annotate that this is an interface (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITask&lt;/code&gt; here), mostly coming from Java or C# background. I wouldn’t consider it a good practice. I didn’t see any case ever in my TypeScript code to use it and certainly we are good with simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Task&lt;/code&gt; here.&lt;/p&gt;

&lt;h3 id=&quot;creating-a-task&quot;&gt;Creating a task&lt;/h3&gt;

&lt;p&gt;Let’s create our first component in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;components/NewTaskForm.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;../models/task&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ChangeEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTMLInputElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FormEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTMLFormElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NewTaskForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;onAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onSubmit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onAdd&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Add a task&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You need to annotate a type to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewTaskForm&lt;/code&gt; component, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionComponent&lt;/code&gt; imported from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react&lt;/code&gt; . The funny &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; brackets indicates that this is a &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/generics.html&quot;&gt;generic&lt;/a&gt; interface. Thanks to this you can get type checking inside of the component in your TSX code. You are supposed to put your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Props&lt;/code&gt; interface, which describes what properties this component gets from the parent one.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Props&lt;/code&gt; interface looks bit cryptic with these callbacks. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onChange&lt;/code&gt; property expects to get a function with one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; argument. If you ever dealt with forms in React you probably know this one well. We will use data from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; object in the parent component, so we need to annotate its type. It’s not that hard as you might think!&lt;/p&gt;

&lt;p&gt;Just move your mouse over the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onSubmit&lt;/code&gt; and your IDE should help you to find out what property type is expected. We pass a callback to form instead of a button to get action on both clicking the button end hitting enter after typing.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/3-callback.png&quot; alt=&quot;react callback&quot; /&gt;
  &lt;figcaption&gt;
    VS Code + TypeScript being helpful with callback types
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Anyway, if annotating types is somehow blocking you, or isn’t possible at the moment, you can always get away with:&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// TODO: annotate event types properly&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;bringing-to-life&quot;&gt;Bringing to life&lt;/h3&gt;

&lt;p&gt;We will use React State to handle tasks changes so we need to annotate a type to it as well. In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/App.tsx&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Hello React TS!&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NewTaskForm&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;onAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addTask&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;onChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleTaskChange&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This time we annotated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;State&lt;/code&gt; interface and put it into a generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Component&lt;/code&gt; interface as a second argument. The first one is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Props&lt;/code&gt; again, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App&lt;/code&gt; component doesn’t have any, we put an empty object.&lt;/p&gt;

&lt;p&gt;Since we don’t need to perform any tasks in the class constructor we are ok to use a class property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; to define it. Just look how TypeScript is making sure we declare it properly, say we forgot to initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tasks&lt;/code&gt; with an empty array:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/3-react-state.png&quot; alt=&quot;react state&quot; /&gt;
  &lt;figcaption&gt;
    TypeScript helping us with initializing state
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Cool stuff!&lt;/p&gt;

&lt;p&gt;Lets add some methods to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewTaskForm&lt;/code&gt; component work and finally render something:&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addTask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FormEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTMLFormElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;handleTaskChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ChangeEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTMLInputElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We mark them &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private&lt;/code&gt; since this is how we annotate methods which shouldn’t be accessed outside of the class. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; property doesn’t have such prefix, so it’s public - this is a default behavior you can read more about &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/classes.html&quot;&gt;here&lt;/a&gt;. Try to mark it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private&lt;/code&gt;, TypeScript won’t let you!&lt;/p&gt;

&lt;p&gt;If you write them by yourself, you will see how helpful TypeScript is with autocompletion. If we would annotate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;any&lt;/code&gt;, we wouldn’t get any help with it, just with React &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;You should see only a simple form where you can name a task and add it since we do not render &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.state.tasks&lt;/code&gt; yet. Let’s make it happen!&lt;/p&gt;

&lt;h3 id=&quot;render-tasks-and-delete&quot;&gt;Render tasks and delete&lt;/h3&gt;

&lt;p&gt;To complete our simple app let’s add a method to delete a task.&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;deleteTask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;taskToDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previousState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;taskToDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then a task list with an item inside:&lt;/p&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/components/TaskList.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;../models/task&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TaskListItem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./TasksListItem&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TasksList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onDelete&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TaskListItem&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/components/TaskListItem.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;../models/task&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TaskListItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FunctionComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Props&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onDelete&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;onDelete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;X&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since I don’t use any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; item in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deleteTask&lt;/code&gt; method I decided to not pass it, rather just the task itself. This might be handled many other ways :)&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;After we add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TaskList&lt;/code&gt; component in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.tsx&lt;/code&gt; we are done with creating a simple to-do list app with React + TypeScript! I am so excited how Create React App with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--typescript&lt;/code&gt; flag made the configuration part so simple. As you see, writing components, TSX, handling state doesn’t differ much! After you combine it with static types with superfast feedback from your IDE you might get in love in TypeScript like me ❤️.&lt;/p&gt;

&lt;p&gt;There are many other areas worth explanation where TypeScript helps. Refactoring, handling external libraries and so on… I will made next parts of this tutorial which will emphasize these parts.&lt;/p&gt;

&lt;p&gt;I encourage you to write the code by yourself in your IDE, see if TypeScript helps you and play around with the app.  In case of any problems - the comment section is here below with me eager to help 🙂&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/todo-list-react-ts&quot;&gt;source code on github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackblitz.com/edit/react-ts-todo-list&quot;&gt;the app on StackBlitz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="react" /><category term="typescript" /><category term="tutorial" /><summary type="html">This tutorial followed step by step will help you understand why TypeScript + React are awesome 💪 while building a simple to-do app. I made it beginner friendly but it requires some basic React and JavaScript knowledge.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/3-cover.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/3-cover.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to keep programming related notes</title><link href="https://www.kozubek.dev/2019/03/11/programming-notes.html" rel="alternate" type="text/html" title="How to keep programming related notes" /><published>2019-03-11T00:00:00+00:00</published><updated>2019-03-11T00:00:00+00:00</updated><id>https://www.kozubek.dev/2019/03/11/programming-notes</id><content type="html" xml:base="https://www.kozubek.dev/2019/03/11/programming-notes.html">&lt;p&gt;Inspired by “The Pragmatic Programmer” book and “sharpening the saw” idea, I will write some posts on tools I use every day to be a more efficient developer. Lepton gist client is a way to keep your notes organized.&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/2-notebook.jpg&quot; alt=&quot;notebook&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/photos/pUAM5hPaCRI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;JESHOOTS.COM&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;why-&quot;&gt;Why? 🤔&lt;/h2&gt;

&lt;p&gt;Once I found I need a systematic way to keep notes. There is something to learn each day and keeping notes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;helps to memorize stuff important for you,&lt;/li&gt;
  &lt;li&gt;with writing you go to another level of understanding since you need to explain it to your future self (at least),&lt;/li&gt;
  &lt;li&gt;if you keep it organized you will easily find an answer for a problem you already solved once but forgot.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Above combined makes you a more efficient developer 🤓&lt;/p&gt;

&lt;h2 id=&quot;options&quot;&gt;Options:&lt;/h2&gt;

&lt;h3 id=&quot;notebook&quot;&gt;Notebook&lt;/h3&gt;

&lt;p&gt;I keep some stuff written in notebook or post-its. With a pen and paper you can express your thoughts quick and easy.&lt;/p&gt;

&lt;p&gt;But you don’t want to keep code snippets or shell commands in your notebook to use daily. You would rather put that stuff in more copy-paste friendly environment.&lt;/p&gt;

&lt;p&gt;I still use a notebook with my calendar to sum-up challenges I met every day. I write them as short tags I can recognize in few next days. When I find the time I evaluate them into digital notes with code snippets or so.&lt;/p&gt;

&lt;h3 id=&quot;google-keep&quot;&gt;Google Keep&lt;/h3&gt;

&lt;p&gt;Someday I started using Google Keep. It is a simple app, has a nice UX and integrates easily with Chrome, Gmail, Google Calendar. What I missed is a code snippets/markdown support which is crucial to keep software related notes. The same goes for Evernote and every usual note capturing app.&lt;/p&gt;

&lt;h3 id=&quot;github-gists&quot;&gt;Github gists&lt;/h3&gt;

&lt;p&gt;Most of us developers use Github every day to store git repositories and handle code development. The lesser-known Github feature is gists, they are something more light - you can keep code and markdown snippets there and then share easily.&lt;/p&gt;

&lt;p&gt;But it lacks good UX. You can’t categorize them, can’t search through them quickly. So I use them as a storage for my notes + I can embed them easily in HTML as below:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/archiewald/783deb46a1e75e69f3898d6fa052fdae.js&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;final-choice---lepton-gist-client&quot;&gt;Final choice - Lepton gist client!&lt;/h2&gt;

&lt;p&gt;Finally, I found an open-source desktop app which meets my expectations. &lt;a href=&quot;http://hackjutsu.com/Lepton/&quot;&gt;Lepton gist client&lt;/a&gt; synchronizes with your GitHub account and lets you handle your snippets more efficient:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;add a new one with keyboard shortcuts,&lt;/li&gt;
  &lt;li&gt;categorize via hashtags and snippets type,&lt;/li&gt;
  &lt;li&gt;search through your gists easily,&lt;/li&gt;
  &lt;li&gt;do all above with intuitive keyboard shortcuts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Handling gists is a breeze now 🌊 Check out a short video on that below:&lt;/p&gt;

&lt;div class=&quot;videoWrapper&quot;&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/ozrKcOuOdZU&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="tools" /><summary type="html">Inspired by “The Pragmatic Programmer” book and “sharpening the saw” idea, I will write some posts on tools I use every day to be a more efficient developer. Lepton gist client is a way to keep your notes organized.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/2-notebook.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/2-notebook.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to fix an npm package</title><link href="https://www.kozubek.dev/2019/02/23/fixing-npm-package.html" rel="alternate" type="text/html" title="How to fix an npm package" /><published>2019-02-23T00:00:00+00:00</published><updated>2019-02-23T00:00:00+00:00</updated><id>https://www.kozubek.dev/2019/02/23/fixing-npm-package</id><content type="html" xml:base="https://www.kozubek.dev/2019/02/23/fixing-npm-package.html">&lt;p&gt;It might happen that an npm package you want to use has some bugs. Should you just wait for maintainers to fix them? Sure not 😉. You can eliminate the bug and host package by yourself. Then create a pull request and possibly become an open-source contributor 💪.&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/1-collaboration.jpg&quot; alt=&quot;collaboration&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/photos/a2VqhP3d4Vg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;rawpixel&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;bugs-happens-&quot;&gt;Bugs happens 🐛&lt;/h2&gt;

&lt;p&gt;Recently I used a &lt;a href=&quot;https://www.npmjs.com/package/react-ga&quot;&gt;react-ga&lt;/a&gt; npm package to connect React based Single Page App to Google Analytics services.&lt;/p&gt;

&lt;p&gt;To start I followed an usual procedure, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-ga&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; went well, then on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm start&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Failed to compile.

/Users/arturkozubek/projects/orbicobeauty-web/node_modules/react-ga/types/index.d.ts
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;87,20&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: A rest parameter must be of an array type.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;🙀 This is unusual… Clearly there is a TypeScript related bug in this package… Having a look on the mentioned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.d.ts&lt;/code&gt; file, line 87:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, I guess I just follow the message of TypeScript compiler and make it:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ga&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So I saved the changes locally and tested. It worked! But you can’t just rely on modifying a node module source files… You probably ignore &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; files in your repo, which is a good common practice. Any time you (or your colleague) reinstall the package it will be downloaded again from original source.&lt;/p&gt;

&lt;h2 id=&quot;fork-and-fix-&quot;&gt;Fork and fix 🍴&lt;/h2&gt;

&lt;p&gt;Usually (if not always, not sure) package source code is served on github. What’s more, you can point a github repository in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; to download a package from there. Can you see where it goes 😉?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I forked the package,&lt;/li&gt;
  &lt;li&gt;cloned to my machine so I can edit the source code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone https://github.com/archiewald/react-ga.git&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;created a fix branch, committed the fix,&lt;/li&gt;
  &lt;li&gt;pushed it to my forked repo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt;, instead of version number, I pointed to the repo I just forked and created, with fix commit hash to make it explicit what code I refer to:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;react-ga&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;git+https://github.com/archiewald/react-ga.git#e9d592e940260017f23815bcee9703a2a4866705&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After re-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; I could enjoy implementing this great package!&lt;/p&gt;

&lt;h2 id=&quot;contribute-&quot;&gt;Contribute 💪&lt;/h2&gt;

&lt;p&gt;Don’t be afraid to share your fix with the community! Raise &lt;a href=&quot;https://github.com/react-ga/react-ga/issues/342&quot;&gt;an issue&lt;/a&gt; and create &lt;a href=&quot;https://github.com/react-ga/react-ga/pull/343&quot;&gt;a pull request&lt;/a&gt; with your changes. Once you implemented them in your forked repo, it is easy!&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;https://www.kozubek.dev/assets/images/1-pull-request.png&quot; alt=&quot;pull request&quot; /&gt;
    &lt;figcaption&gt;
      Fix =&amp;gt; contribute
    &lt;/figcaption&gt;
&lt;/figure&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><category term="npm" /><category term="typescript" /><summary type="html">It might happen that an npm package you want to use has some bugs. Should you just wait for maintainers to fix them? Sure not 😉. You can eliminate the bug and host package by yourself. Then create a pull request and possibly become an open-source contributor 💪.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/1-collaboration.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/1-collaboration.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Being a frontend developer for 1 year</title><link href="https://www.kozubek.dev/2019/01/06/being-dev-1-year.html" rel="alternate" type="text/html" title="Being a frontend developer for 1 year" /><published>2019-01-06T00:00:00+00:00</published><updated>2019-01-06T00:00:00+00:00</updated><id>https://www.kozubek.dev/2019/01/06/being-dev-1-year</id><content type="html" xml:base="https://www.kozubek.dev/2019/01/06/being-dev-1-year.html">&lt;p&gt;So here it is, another article summarizing how the 2018 was :) For me it was a very special time, since exactly on December 2017 I started my first job as a frontend developer. It was an intense year but I am happy to say that I’ve learned a lot, I feel bit more confident about my programming skills and look forward to learn new.&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://www.kozubek.dev/assets/images/new-year.jpg&quot; alt=&quot;collaboration&quot; /&gt;
  &lt;figcaption&gt;
    by &lt;a href=&quot;https://unsplash.com/@cristian1?utm_medium=referral&amp;amp;utm_campaign=photographer-credit&amp;amp;utm_content=creditBadge&quot;&gt;Cristian Escobar&lt;/a&gt; 
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Software developer is a very demanding job.&lt;/strong&gt; I worked before as a so-called Sales Engineer and as a Technical Support Engineer, each for around 1 year long. And I can say with no doubt that as a frontend developer I worked hardest, had to learn most and it was the most stressful time in my short professional career. But this is what I wanted - to have a challenging surrounding I can grow and eventually get well rewarded for my work.&lt;/p&gt;

&lt;h3 id=&quot;what-i-like-&quot;&gt;What I like? 😍&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;I feel I work as a real engineer.&lt;/strong&gt; I get specifications and transform it into solutions with my skills. Coding is my craft which I can polish every day, no one can take it from me - this gives me a great feeling of freedom.&lt;/li&gt;
  &lt;li&gt;Learning in IT feels much easier then in other businesses I worked. Literally, &lt;strong&gt;every person I met was eager to share his knowledge with me&lt;/strong&gt;. Obviously there is a ton of materials in the net you can learn from. If you are lucky as I am, you will find a company which cares for a great growth environment as &lt;a href=&quot;https://codequest.com/&quot;&gt;codequest&lt;/a&gt; does 🎉.&lt;/li&gt;
  &lt;li&gt;I am amazed by the &lt;strong&gt;power of open source&lt;/strong&gt;, how much tools we get for our everyday work for free. It is really different from a Factory Automation business for example. There are &lt;a href=&quot;https://en.wikipedia.org/wiki/Programmable_logic_controller&quot;&gt;PLC&lt;/a&gt; programmers who don’t have such easy ways to share their code with git, don’t have libraries for every problem they face, so many tools for project management etc. BTW I think this is a great niche for startups 🚀.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Javascript community in Warsaw is awesome&lt;/strong&gt;. You can attend some meetup almost every week I think. Most of the time you will find well prepared speakers with a ton of knowledge to share and free snacks and beverages 🍻🍕. There is a special one I feel most grateful - &lt;a href=&quot;https://warsawjs.com/&quot;&gt;WarsawJS&lt;/a&gt; I will write more about in the credits part :).&lt;/li&gt;
  &lt;li&gt;There is a huge demand for software developers on the market what make me feel secure about my career and finances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-i-dont-like-&quot;&gt;What I don’t like? 😕&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;It was a really stressful time for me, especially at the beginning. With weekly sprints and daily standups I felt constant pressure that I need to provide a value in a short amount of time. Sure it got better after a year with my skills and self-confidence growing. If you are about to start working as a developer, just be prepared it might look the same for you :).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.codingdojo.com/blog/programmer-imposter-syndrome/&quot;&gt;Impostor syndrome&lt;/a&gt; is a thing!&lt;/strong&gt; I constantly felt I don’t belong here, that I lack some abilities, I am not smart enough, not fast enough, will not ever learn something etc. I still feel like this sometimes. I think I just got used to it and got an understanding that this is a common feeling in this dynamic IT industry.&lt;/li&gt;
  &lt;li&gt;I feel &lt;strong&gt;frontend stack is over-complicated&lt;/strong&gt;. Because of so many libraries and frameworks available, there are tons of ways to do the same thing and multiple different stacks to learn. &lt;strong&gt;I feel it all should be much simpler&lt;/strong&gt;. On the other hand, the simpler it gets then the less job will be there for us, frontend developers 🙀&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-project-per-month---how-it-went-&quot;&gt;1 project per month - how it went 🤔&lt;/h3&gt;

&lt;p&gt;There was a challenge I took in 2018 to make a blogpost about one technical project I made every month. I managed to write 9 posts, so for this part I made 75%. On my github there are few more projects made on WarsawJS workshops, which could make it for a blogpost after some polishing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/warsawjs-workshop-20-flights-search&quot;&gt;Flight search app with React&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/warsawjs-workshop-22-money-exchange&quot;&gt;Money exchange app with unit tests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/archiewald/warsawjs-workshop-24-admin-panel&quot;&gt;Admin panel with unit and integration tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Count them in and &lt;strong&gt;we have 12!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;h3 id=&quot;credits-&quot;&gt;Credits 🙏&lt;/h3&gt;

&lt;p&gt;It is a good moment do send kudos to people who helped me in the last year:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codequest.com/&quot;&gt;codequest&lt;/a&gt; - &lt;strong&gt;a great company I work in,&lt;/strong&gt; I was really lucky I applied there and got hired as a freshman. Let me point out how much support I got:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2 interesting projects I was involved in, starting from their planning phase - no legacy code!&lt;/li&gt;
  &lt;li&gt;great mentorship by a skillful senior developer,&lt;/li&gt;
  &lt;li&gt;individual growth path with constant feedback from mentor and company heads,&lt;/li&gt;
  &lt;li&gt;few hours a week to spend on projects/courses of my choice for my individual growth, some of them were described here on this blog 💪,&lt;/li&gt;
  &lt;li&gt;lighting talks each week,&lt;/li&gt;
  &lt;li&gt;atmosphere of friendship and helping each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://warsawjs.com/&quot;&gt;WarsawJS&lt;/a&gt; - local community giving &lt;strong&gt;so much&lt;/strong&gt; to developers in Warsaw (not only). Extremely positive organizers make every event a pleasure to attend. Personally I participated in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;monthly meetups,&lt;/li&gt;
  &lt;li&gt;workshops - really cool events where you get a pro training in some frontend related topic for a fraction of usual costs. You can find what we did on each on my &lt;a href=&quot;https://github.com/archiewald?utf8=%E2%9C%93&amp;amp;tab=repositories&amp;amp;q=warsawjs&amp;amp;type=&amp;amp;language=&quot;&gt;github&lt;/a&gt;. There is a post I wrote about one &lt;a href=&quot;https://www.kozubek.dev/1ppm/2018/03/03/battleship-MVC&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;slack group - I believe you need to attend some event to get an invitation. There is a lot of going on, you can get advices from other members of WarsawJS community, mostly frontend professionals who are really helpful!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are even more initiatives you can read about &lt;a href=&quot;https://warsawjs.com/about&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content><author><name>Artur Kozubek</name><email>artur@kozubek.dev</email></author><summary type="html">So here it is, another article summarizing how the 2018 was :) For me it was a very special time, since exactly on December 2017 I started my first job as a frontend developer. It was an intense year but I am happy to say that I’ve learned a lot, I feel bit more confident about my programming skills and look forward to learn new.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.kozubek.dev/assets/images/new-year.jpg" /><media:content medium="image" url="https://www.kozubek.dev/assets/images/new-year.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>