<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Metacognitive]]></title><description><![CDATA[Space for ideas]]></description><link>https://metacognitive.me/</link><image><url>https://metacognitive.me/favicon.png</url><title>Metacognitive</title><link>https://metacognitive.me/</link></image><generator>Ghost 5.46</generator><lastBuildDate>Fri, 02 Feb 2024 00:26:24 GMT</lastBuildDate><atom:link href="https://metacognitive.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Ask yourself too]]></title><description><![CDATA[When reading articles, books, or watching movies and news, ask your opinion. Not doing so is tempting because you're most probably used to consuming information, not questioning it.]]></description><link>https://metacognitive.me/ask-yourself-too/</link><guid isPermaLink="false">6469f7d43aea360001b817a7</guid><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 21 May 2023 10:55:40 GMT</pubDate><content:encoded><![CDATA[<p>There is much information noise out there. It will be more and more of such, especially with cheap language models that produce any text one wants for any audience. Each source of information tries to shape your opinion in one or another way. I&apos;m sure you know that (however, do you realize it?). Nonetheless, have you questioned yourself as to what direction those sources try to shape it after reading an article?</p><p>People can&apos;t define all the possible directions information shapes an opinion. Did you ask yourself why a text was written? What goal did the author follow? There are no facts, only interpretations, and it&apos;s alluring to perceive someone&apos;s perspective as a fact. Every author tries to deliver their ideas but the author&apos;s unique experience already frames them.</p><p>Even after understanding most of those ideas, did the author have other motivations rather than merely delivering information to you?</p><p>Do you agree or disagree with the author and why? Disregard this exercise and you consume information automatically without constructing and outlining your opinion. Neglect creating your attitude and you may discover you don&apos;t have many of them. Or, you don&apos;t have any of them at all &#x2014; only those perceived and formed automatically but not yours.</p><p>Ask yourself too.</p>]]></content:encoded></item><item><title><![CDATA[AI sets new limits for humanity]]></title><description><![CDATA[Humanity should evolve: in its beliefs, systems they build, and concepts they operate.]]></description><link>https://metacognitive.me/ai-sets-new-limits-for-humanity/</link><guid isPermaLink="false">6451dd870ab1d60001c01ce5</guid><category><![CDATA[ai]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Wed, 03 May 2023 04:15:44 GMT</pubDate><content:encoded><![CDATA[<p>Releasing more AI-related work (such as GPT-4 and Stable Diffusion) and projects show us new limits of automation and process optimization. These projects will automate more of today&apos;s jobs. Are we ready for that scenario? We aren&apos;t yet.</p><p>From today&apos;s perspective, it&apos;s both good and bad. It&apos;s good because humans can spend fewer resources on the same amount of work. It&apos;s bad because some people will be looking for new jobs and won&apos;t be able to find those: why pay someone for doing the routine work if a machine can do it much cheaper and faster?</p><p>To tackle the bad part, <strong>humanity should evolve</strong>: in its beliefs, systems they build, and concepts they operate.</p><p>The &quot;evolve&quot; part is the difficult one. To slightly initiate on that matter: humans require money to operate daily. To receive money, humans should bring value to society. What does society perceive as value? Is it a human that can do some work for others or the human itself? If we value the current operational value(=human work), a machine can bring that value for much fewer resources. If we value a human itself, we have the option to see an interesting future.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2023/05/photo_2023-05-03_08-14-56.jpg" class="kg-image" alt loading="lazy" width="1024" height="1024" srcset="https://metacognitive.me/content/images/size/w600/2023/05/photo_2023-05-03_08-14-56.jpg 600w, https://metacognitive.me/content/images/size/w1000/2023/05/photo_2023-05-03_08-14-56.jpg 1000w, https://metacognitive.me/content/images/2023/05/photo_2023-05-03_08-14-56.jpg 1024w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[How to create a story game with Javascript]]></title><description><![CDATA[Creating an interactive fiction or a text-adventure game using Twine and sometimes Javascript.]]></description><link>https://metacognitive.me/how-to-create-a-story-game-with-javascript/</link><guid isPermaLink="false">635a0fc0deb7e100014e4f02</guid><category><![CDATA[programming]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Thu, 27 Oct 2022 10:49:54 GMT</pubDate><content:encoded><![CDATA[<p>If you don&apos;t know Javascript or what that is, don&apos;t worry! You&apos;ll be able to learn along the way or even go without it at all. What we are going to explore is an open-source tool to build interactive stories - <a href="https://github.com/klembot/twinejs?ref=metacognitive.me">Twine </a>(or see its <a href="https://twinery.org/?ref=metacognitive.me">website</a>).</p><p>It allows us to make nonlinear stories. It can be presentations, fiction, or text-adventure games. In a nutshell, Twine creates an HTML file with all the content. So, it looks like a usual web page, and the tool is the constructor. You can upload such a &quot;website&quot; on the web or mobile platforms, i.e., anywhere that can parse HTML.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/10/image-7.png" class="kg-image" alt loading="lazy" width="870" height="700" srcset="https://metacognitive.me/content/images/size/w600/2022/10/image-7.png 600w, https://metacognitive.me/content/images/2022/10/image-7.png 870w" sizes="(min-width: 720px) 720px"><figcaption>An example of a non-linear story (interactive fiction)</figcaption></figure><p>If you&apos;re particularly interested in games / interactive fiction, see an <a href="https://itch.io/games/tag-twine?ref=metacognitive.me">extensive collection of them</a>. So what sort of games are possible? All of them since we can add Javascript. However, the easiest way is to do text-adventure games. Why? You don&apos;t need to program anything or much. You add stories and connect them in a meaningful way using links. I.e., if you choose &quot;A&quot;, the story &quot;AA&quot; will be shown, if you choose &quot;B&quot;, the story &quot;BB&quot; will be shown.</p><p>See also <a href="https://twinery.org/cookbook/questions/making.html?ref=metacognitive.me">what you can create</a> with the tool from their docs.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-12-46-13.png" class="kg-image" alt loading="lazy" width="951" height="226" srcset="https://metacognitive.me/content/images/size/w600/2022/10/Screenshot-from-2022-10-27-12-46-13.png 600w, https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-12-46-13.png 951w" sizes="(min-width: 720px) 720px"><figcaption>An example of an actual Twine page with a story</figcaption></figure><p>Creating such a page takes a few minutes on <a href="https://twinery.org/?ref=metacognitive.me">the Twine website</a>(you can do that online). You can add Javascript, videos, music, images, customize styles via CSS and do the linking and playing around. It&apos;s a great way to start. Next, I will show you a different approach if you&apos;re used to coding in any developer&apos;s editor and want version control.</p><p>Try online first, especially if your story/game is small and only needs a little custom functionality.</p><h2 id="why-you-may-need-javascript">Why you may need Javascript</h2><p>You can go without it and feel fine. But if you have custom stuff, you&apos;ll use some macros and scripts. What are they? Imagine Twine as a core, but it has various engines that do things differently. It supports four such engines(story formats) to make the creation process more accessible. Each of them varies in complexity. In this article, I&apos;ll be using <a href="https://www.motoslave.net/sugarcube/2/?ref=metacognitive.me">SugarCube</a>.</p><p>This story format has many built-in things you may need. For example:</p><ol><li>Saving a game, resuming it from a save.</li><li>Various events to react to. E.g., when a story is rendered, started rendering, etc.</li><li>Macros, i.e., useful built-in blocks/functions. For example, buttons, custom links, conditional rendering, setting variables, DOM manipulations, etc.</li><li>Audio handling.</li><li>And many other valuable things.</li></ol><h1 id="a-twine-project-in-a-developer-way">A Twine project in a developer way</h1><p>Let&apos;s create a simple project where we want to use custom Javascript and CSS styles, but more importantly - we want to have version control! I don&apos;t use the tool&apos;s online or desktop version because I can only manage stories as files and have their versions by commit.</p><p>You&apos;ll need to install <a href="https://www.motoslave.net/tweego/?ref=metacognitive.me">Tweego</a>, a tool that can parse stories as files in any preferred text editor. Be aware of its limitations, though:</p><ol><li>When writing this article, the last update of Tweego was two years ago.</li><li>Thus, you may not have all of the features from the supported story formats(e.g., Sugarcube).</li></ol><p>Now you need to create a project folder:</p><pre><code class="language-shell">$ mkdir twine-project
$ cd twine-project
$ git init</code></pre><p>You can move the Tweego executable to this folder as well and add it to <code>.gitignore</code></p><p>It&apos;s up to you how to organize files now! An example structure may look like the following:</p><pre><code>.gitignore
README.md
bin/
src/
&#x251C;&#x2500; config.tw
&#x251C;&#x2500; styles/
&#x2502;  &#x251C;&#x2500; menu.css
&#x2502;  &#x251C;&#x2500; main.css
&#x251C;&#x2500; modules/
&#x2502;  &#x251C;&#x2500; menu/
&#x2502;  &#x2502;  &#x251C;&#x2500; menu.tw
&#x2502;  &#x2502;  &#x251C;&#x2500; menu.js
</code></pre><p>In the <code>bin</code> folder you have the Tweego executable to build the output to HTML(we&apos;ll get to that). All the story(game)-related code is under <code>src</code> folder. Tweego will put all Twine(`.tw`) files, CSS styles, Javascript scripts into one HTML. Therefore, it doesn&apos;t matter what project structure you have.</p><h3 id="twine-format">Twine format</h3><p>Now, closer to the coding: what is <code>config.tw</code>? This is where your code will be in Twine format. Take a look at the <a href="https://github.com/iftechfoundation/twine-specs/blob/master/twee-3-specification.md?ref=metacognitive.me">specification</a>. You may name this file whatever you want. It&apos;s named <code>config</code> for readability. There, we specify the settings for our game:</p><pre><code>:: StoryTitle
My first game

:: StoryData
{
	&quot;ifid&quot;: &lt;a serial number of your game&gt;,
	&quot;format&quot;: &quot;SugarCube&quot;,
	&quot;format-version&quot;: &quot;2.30.0&quot;,
	&quot;start&quot;: &lt;a name of the story that will be shown first&gt;
}

:: StoryAuthor
&lt;your name if you want&gt;


&lt;&lt;script&gt;&gt;
// in case you&apos;ll need to have 3rd-party scripts
// remove this &lt;&lt;script&gt;&gt; section at all for now
importScripts(
	&apos;https://cdn.jsdelivr.net/npm/chance&apos;
)
&lt;&lt;/script&gt;&gt;</code></pre><p>You need to generate a serial number for your game, i.e., IFID. Read more about how to do that <a href="https://ifdb.org/help-ifid?ref=metacognitive.me">here</a>. But for now, you can use <code>0000A000-A0E0-00C0-00B0-CF000E000D0E</code> to skip this boring step.</p><p><code>format</code> tells Tweego which story format to use. We&apos;ll use <code>SugarCube</code>. <code>format-version</code> is a version for this story format, currently supported is <code>2.30.0</code> only. However, there are newer versions(a limitation of Tweego).</p><p><code>start</code> is a story that will be shown first. Let&apos;s create a file <code>start.tw</code> with this content:</p><pre><code>:: StartOfMyGame

This is the first screen of my game, yay!

[[Start playing]]
[[Read about the author]]
</code></pre><p>The <code>::</code> here indicates the ID of your passage(i.e., a page). It can be anything, e.g., <code>:: start-of-my-game</code> or <code>:: something like this</code>. Now that you have the ID, change your <code>config.tw</code> to have:</p><pre><code>&quot;start&quot;: &quot;StartOfMyGame&quot;</code></pre><p>After the passage(page) ID, you do whatever you want. In our case, we wrote, <em>&quot;This is the first screen of my game, yay!&quot;</em>, and it&apos;ll be rendered as regular text, that&apos;s it! The <code>[[Start playing]]</code> thing is a <strong>link</strong> to another passage(page).</p><p>To build that to HTML, run Tweego(it&apos;ll be watching for files changes):</p><pre><code class="language-sh">$ ./bin/tweego -w src -o ./output/index.html</code></pre><p>Here, we&apos;re telling it to watch the <code>src</code> folder and build an output HTML into the <code>output</code> folder as <code>index.html</code>. Run this command, and you&apos;ll see the HTML output in that folder. Don&apos;t forget to add <code>output</code> to <code>.gitignore</code>. Open <code>output/index.html</code> in a browser and you&apos;ll see something like this(with a more dark background color):</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-10-54-1.png" class="kg-image" alt loading="lazy" width="346" height="169"></figure><p></p><p>We create the links, but we also need to create such pages. So, we need to change the <code>start.tw</code>:</p><pre><code>:: StartOfMyGame

This is the first screen of my game, yay!

[[Start playing]]
[[Read about the author]]

:: Start playing
&lt;&lt;back&gt;&gt;
It&apos;s another page called &quot;Start playing&quot;.

:: Read about the author
&lt;&lt;back&gt;&gt;
I&apos;m the author. This is my page.</code></pre><p>We&apos;ve added two more pages, so whenever you click on, for example, &quot;Start playing&quot;, you&apos;ll be redirected to the &quot;Start playing&quot; passage:</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-14-55.png" class="kg-image" alt loading="lazy" width="344" height="95"></figure><p>We see a new link here - &quot;Back&quot;! <code>&lt;&lt;back&gt;&gt;</code> is a SugarCube <a href="https://www.motoslave.net/sugarcube/2/docs/?ref=metacognitive.me#macros-macro-back">macro</a> that redirects a user to the previous passage(`StartOfMyGame`). It&apos;s a more convenient way of doing that than storing a navigation history each time.</p><p>We might create these two new passages in the other files or create all the game passages in one file. It doesn&apos;t matter because Tweego puts all of the files together into a single HTML file. You don&apos;t need to care about importing something!</p><h3 id="adding-javascript-to-twine-stories">Adding Javascript to Twine stories</h3><p>Let&apos;s imagine we want to store some information about a player&apos;s choices. There are two approaches:</p><ol><li>We may use the <a href="https://www.motoslave.net/sugarcube/2/docs/?ref=metacognitive.me#macros-macro-set"><code>&lt;&lt;set&gt;&gt;</code> macro</a>.</li><li>We may use Javascript.</li></ol><p>When using <code>&lt;&lt;set&gt;&gt;</code>:</p><pre><code>:: StartOfMyGame

This is the first screen of my game, yay!

&lt;&lt;link &quot;Start playing&quot; &quot;StartPlaying&quot;&gt;&gt;
	&lt;&lt;set $choice to &quot;StartPlaying&quot;&gt;&gt;
&lt;&lt;/link&gt;&gt;
&lt;&lt;link &quot;Read about the author&quot; &quot;AboutTheAuthor&quot;&gt;&gt;
	&lt;&lt;set $choice to &quot;AboutTheAuthor&quot;&gt;&gt;
&lt;&lt;/link&gt;&gt;

:: StartPlaying
&lt;&lt;back&gt;&gt;
It&apos;s another page called &quot;Start playing&quot;.
The choice is &lt;&lt;= $choice&gt;&gt;

:: AboutTheAuthor
&lt;&lt;back&gt;&gt;
I&apos;m the author. This is my page.
The choice is &lt;&lt;= $choice&gt;&gt;</code></pre><p>A few new things here:</p><ol><li><code><a href="https://www.motoslave.net/sugarcube/2/docs/?ref=metacognitive.me#macros-macro-link">&lt;&lt;link&gt;&gt;</a></code><a href="https://www.motoslave.net/sugarcube/2/docs/?ref=metacognitive.me#macros-macro-link"> macro</a> does the same as <code>[[ ]]</code>, but it adds more customizability. In our case, we kept the link text, but indicated a different passage ID(`StartPlaying`, e.g.). Also, we can do something when a link is pressed, e.g., a <code>&lt;&lt;set&gt;&gt;</code> instruction below.</li><li><code>&lt;&lt;set&gt;&gt;</code> macro stores a variable.</li><li><code>&lt;&lt;= $choice&gt;&gt;</code> is a macro to evaluate expressions. In our case, it&apos;s displaying <code>$choice</code> variable we set before.</li></ol><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-38-20.png" class="kg-image" alt loading="lazy" width="340" height="135"></figure><p>We can achieve the same using Javascript(however, it seems unnecessary complicated in this example):</p><pre><code>:: StartOfMyGame

This is the first screen of my game, yay!

&lt;&lt;link &quot;Start playing&quot; &quot;StartPlaying&quot;&gt;&gt;
	&lt;&lt;script&gt;&gt;
		State.setVar(&apos;$choice&apos;, &apos;StartPlaying (Javascript)&apos;)
	&lt;&lt;/script&gt;&gt;
&lt;&lt;/link&gt;&gt;


:: StartPlaying
&lt;&lt;back&gt;&gt;
It&apos;s another page called &quot;Start playing&quot;.
The choice is &lt;&lt;= $choice&gt;&gt;</code></pre><p>I removed the second passage to not duplicate the code. Here are a few new things:</p><ol><li>We still do the scripting inside <code>&lt;&lt;link&gt;&gt;</code> macro. But we use <code>&lt;&lt;script&gt;&gt;</code> macro now. Inside of it, we use a global object <code>State</code>&apos;s method <code>setVar</code> which does the same as <code>&lt;&lt;set&gt;&gt;</code> in the previous example.</li><li>We still display the <code>$choice</code> variable not using Javascript, but we could find that HTML block using jQuery(which is built-in in SugarCube scripts), and then set the value of it to <code>$choice</code>, but it&apos;s unnecessary.</li></ol><p>When you use Javascript, you have access to the story format&apos;s APIs, so it&apos;s more customizability. However, you may not encounter such complexity in your game.</p><hr><p>That&apos;s it for now! There are more things to do in a game, of course. But you have the documentation and tools to discover and learn more independently.</p>]]></content:encoded></item><item><title><![CDATA[Next.js vs. React: what should you use?]]></title><description><![CDATA[<p>React is a tool for building a front end. Next.js serves the same purpose. However, both instruments offer a slightly different set of features. More precisely, Next.js gives you more than React. But it doesn&apos;t mean you should choose it every time.</p><p>See also <a href="https://metacognitive.me/why-do-i-use-next-js-in-my-projects/">why I</a></p>]]></description><link>https://metacognitive.me/next-js-vs-react/</link><guid isPermaLink="false">63575081deb7e100014e4ecf</guid><category><![CDATA[javascript]]></category><category><![CDATA[programming]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Tue, 25 Oct 2022 04:19:12 GMT</pubDate><content:encoded><![CDATA[<p>React is a tool for building a front end. Next.js serves the same purpose. However, both instruments offer a slightly different set of features. More precisely, Next.js gives you more than React. But it doesn&apos;t mean you should choose it every time.</p><p>See also <a href="https://metacognitive.me/why-do-i-use-next-js-in-my-projects/">why I use Next.js in my projects</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/10/image-4.png" class="kg-image" alt loading="lazy" width="833" height="394" srcset="https://metacognitive.me/content/images/size/w600/2022/10/image-4.png 600w, https://metacognitive.me/content/images/2022/10/image-4.png 833w" sizes="(min-width: 720px) 720px"><figcaption>A difference between Next.js and React: Next.js gives you more features</figcaption></figure><h1 id="advantages-of-reactjs">Advantages of React.js</h1><p>If you don&apos;t know what React is, it&apos;s an instrument that simplifies the development of web pages. It allows you to build components(thus, separating your pages and UI elements into convenient parts) using an advantageous markup(JSX).</p><p>Angular and Vue do the same job with some implementation differences. However, these tools bring us convenience in developing the web.</p><p>With React, it&apos;s simple to start a project(use <a href="https://reactjs.org/docs/create-a-new-react-app.html?ref=metacognitive.me">create-react-app</a>), and we have a bundler and a compiler. The next step is to run the app with one command. &quot;We got it. It&apos;s simple, fine, fine!&quot;</p><p>To compare React and Next.js, let&apos;s look at what Next allows us to do.</p><h1 id="nextjs-benefits">Next.js benefits</h1><p>A satisfactory <strong>tl;dr</strong> would be: &quot;<strong>Next.js is React but with more features.</strong>&quot; Next is a framework that uses React. React is a library that gives you the pros you read above, but also it gives you freedom of choice. You may use a different compiler or bundler, or you may use it in the react-native platform. Also, you choose your set of tools: a routing system, an SCSS compiler(if you need SCSS over CSS), and so on.</p><p>Next.js gives you React but with an improved developer experience. You don&apos;t need to spend time making the choices. But if you want, you can, of course.</p><p>Let&apos;s look at the specific benefits of Next over React.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/10/image-5.png" class="kg-image" alt loading="lazy" width="781" height="344" srcset="https://metacognitive.me/content/images/size/w600/2022/10/image-5.png 600w, https://metacognitive.me/content/images/2022/10/image-5.png 781w" sizes="(min-width: 720px) 720px"><figcaption>Next.js saves you time, while React gives more choices, which you may not need</figcaption></figure><h2 id="routing">Routing</h2><p><em>Why care: you don&apos;t need to spend time choosing a router. There are many routers for React, and you may not know the best fit for your situation.</em></p><p>Next has the router built-in. You only need to put your pages in the `src/pages` folder. So, the &quot;contact.tsx&quot;(`tsx` is a JSX with Typescript) file will be available as a page at &quot;yourAppAddress/contact&quot;. There is dynamic routes support too.</p><h2 id="static-pages-generation">Static pages generation</h2><p><em>Why care: if you need static pages for your app(e.g., a landing page that leads to the app), and you don&apos;t want to make them dynamic(because of the performance), you&apos;ll need to configure a server that will serve HTML pages in addition to your React app.</em></p><p>You can generate static pages with Next.js because it has a built-in server.</p><h2 id="server-side-rendering">Server-side rendering</h2><p><em>Why care: the same thing as above, except that you want to generate a page upon each request.</em></p><p>Static generation outputs the HTML that <strong>will be reused on each request</strong>. The Server-side rendering method will generate HTML upon each request. The former is recommended because of better performance.</p><h2 id="data-fetching">Data Fetching</h2><p><em>Why care: if you want to fetch data skipping CORS or get data from the database directly from your app or read files, you&apos;ll need a server.</em></p><p>Next.js data-fetching methods allow you to do all of that without configuring a server. For example, you can generate a static page using fetching local files at build time. Or, you can request a third-party server omitting CORS because Next has an intermediary - an API server.</p><h2 id="image-optimization">Image optimization</h2><p><em>Why care: you don&apos;t need to think about image optimization. I.e., how to reduce an image size, what format to choose, and how to lazy-load the images.</em></p><p>There are usually two apparent problems with images:</p><ol><li>Image size. I.e., reducing a 3MB JPG into a 40KB Webp.</li><li>Loading them after a page is rendered to reduce the network load.</li></ol><p>Next solves these problems for a developer, so they can think about the other parts of the app. All the images inside that use `next/image` will be optimized and lazy-loaded. Also, you may set a loading priority for each of them.</p><h2 id="it-uses-swc">It uses <a href="https://swc.rs/?ref=metacognitive.me">SWC</a></h2><p><em>Why care: you need faster build times.</em></p><p>Next uses SWC, which is, according to their claim, &quot;<strong>20x faster than Babel</strong> on a single thread and <strong>70x faster</strong> on four cores&quot;. Such speeds are a good enhancement during build times and &quot;hot&quot; reloading.</p><h2 id="built-in-eslint">Built-in ESlint</h2><p><em>Why care: you spend time configuring ESlint.</em></p><p>Imagine you wrote a few lines of code and already have the lint issues warnings.</p><h2 id="built-in-typescript-support">Built-in TypeScript support</h2><p><em>Why care: you want to write in Typescript, but configuring it takes some time.</em></p><p>This feature is a huge dealbreaker for me because configuring Typescript takes time. Sometimes it&apos;s merely installing the package(`npm install typescript`), and adding the basic `tsconfig.json`. Still, you need to configure it correctly according to your project needs. Since you have various files in a Next.js project(stylesheets, `public` files, JSX, js), imagine going through them to figure out what can be ignored, what rules(configuration) to add, and then to have to break changes with the framework updates.</p><p>Next.js does it for us, yay!</p><h2 id="environment-variables">Environment Variables</h2><p><em>Why care: if you want to store some private information like secrets, API keys, etc., and you don&apos;t want to expose them in an app&apos;s bundle. You may create a server to pull that data from or use some third-party provider, but it takes time and one more place for your code.</em></p><p>The framework supports `.env` files: create a `.env.local`, add the secrets, and nobody will see them. You may also expose some by prefixing them with `NEXT_PUBLIC_`.</p><h2 id="scripts-handling-and-performance">Scripts handling and performance</h2><p><em>Why care: you&apos;re thinking about lazy-loading some Javascript scripts(3rd-party ones, too), loading them first, or setting any other priority.</em></p><p>Next.js can do all of that if you use `&lt;Script&gt;` instead of the standard `&lt;script&gt;`. Also, it can offload the scripts to a web worker using <a href="https://partytown.builder.io/?ref=metacognitive.me">Partytown</a>.</p><h2 id="it-has-a-server">It has a server</h2><p><em>Why care: you need a server environment. E.g., to make database queries.</em></p><p>We talked about it in the Data fetching section, but it&apos;s a good point to highlight one more time because you may need a server for not data fetching only. For example, maybe you need to do some filesystem-heavy logic and then fetch the results via Next.js API server.</p><h1 id="so-why-react-then">So, why React, then?</h1><p>Next.js has more features than I described here(those I like personally and wanted to highlight). So, we come to the question of why we need React when starting a new project.</p><p>Sometimes, you don&apos;t need such a beast for a simple use-case. For example, if you have a single static page and you don&apos;t fetch any data. Also, you don&apos;t have much dynamic logic. Thus, there&apos;s no need to bring all of the mentioned features because you need to learn the framework(though its docs are great) and the resources to support the build overhead. I.e., why configure the Next.js CI process if you can have merely an HTML page?</p><p>Choose Next.js for a better developer experience, so you don&apos;t need to spend time configuring some tools but coding.</p>]]></content:encoded></item><item><title><![CDATA[What profession should I choose?]]></title><description><![CDATA[<p>It was challenging to know what I wanted to work on or for. I had almost no understanding of what people of different professions do <strong>daily</strong>. In general, economists calculate something; doctors treat; mathematicians calculate(after economists?), and lawyers deal with the law somehow.</p><p><em>Hint: you may find actionable advice</em></p>]]></description><link>https://metacognitive.me/what-profession-should-i-choose/</link><guid isPermaLink="false">63359d952e1e2b0001a13cc1</guid><category><![CDATA[thoughts]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Tue, 04 Oct 2022 16:19:38 GMT</pubDate><content:encoded><![CDATA[<p>It was challenging to know what I wanted to work on or for. I had almost no understanding of what people of different professions do <strong>daily</strong>. In general, economists calculate something; doctors treat; mathematicians calculate(after economists?), and lawyers deal with the law somehow.</p><p><em>Hint: you may find actionable advice at the end of this article.</em></p><p>I missed the details: what exactly do economists and mathematicians calculate? How do musicians and actors make money? Is it interesting to be an engineer or designer? How to know the answers to these questions when you don&apos;t have much experience?</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/09/image-6.png" class="kg-image" alt loading="lazy" width="602" height="339" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image-6.png 600w, https://metacognitive.me/content/images/2022/09/image-6.png 602w"></figure><h1 id="lack-of-knowledge">Lack of knowledge</h1><p>Many students don&apos;t know how they want their life to look. And if they do, their plan will probably change in the future. The same applies to adults. Our goals change. The things I enjoyed ten years ago today may not be so enjoyable because I find new things to want <strong>more</strong>.</p><p>The problem(when choosing something <strong>now</strong>) is that our desires change when we change. And the latter happens constantly.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/09/image-7.png" class="kg-image" alt loading="lazy" width="768" height="426" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image-7.png 600w, https://metacognitive.me/content/images/2022/09/image-7.png 768w" sizes="(min-width: 720px) 720px"><figcaption>Merely an approximate visualization</figcaption></figure><p>The students&apos; problem when pondering &quot;what profession should I choose&quot; is that they don&apos;t have much data about how they, society, and the world function. I don&apos;t know many things, but the information I collected through the years, career, communication with people, and books helped me better understand what I want and where I want to be in the next few years.</p><h1 id="it-starts-with-the-most-meaningful-question">It starts with the most meaningful question</h1><p><strong>What do I want to do in life?</strong> &quot;I enjoy eating, playing games, and watching movies, but that won&apos;t make me money&quot; - I thought. So I should get a job somewhen. And for this, I need to go to college or university(do I?). But why do I need money? To live, in general: get food, have a place to live, and if something is left, I may spend the rest on something I enjoy.</p><p>So I have things I enjoy doing, and I should have a job that pays the bills. Maybe I may combine the two? So now I have a plan:</p><ol><li>Get a job that pays the bills.</li><li>Enjoy things I like doing.</li></ol><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/10/image.png" class="kg-image" alt loading="lazy" width="427" height="473"></figure><h2 id="getting-a-job-that-pays-the-bills">Getting a job that pays the bills</h2><p>Many people get this step wrong: they study at a university or college to get a waiter&apos;s-like job. Some of them pay a lot for such an education. Then, they pay the debt by working a waiter&apos;s-like job (while in and) after the university.</p><p>Many jobs on the market require a human&apos;s basics: eyes, mouth, and ability to speak. Then, some jobs require more domain knowledge. But, still, one doesn&apos;t need to study for five years for them. And some jobs require you the fundamentals and domain knowledge - doctors, for example.</p><p>So if I didn&apos;t know what I wanted to do, I&apos;d find some entry-level job that could pay me for rent and food. From there, I might research the market and myself better.</p><p>If I enjoy programming, I can learn it for free and get a job. On the other hand, if I tried this path and didn&apos;t like it, I may try copywriting and see how it goes.</p><p>If I didn&apos;t know what job I might take, I&apos;d go to a jobs aggregator website and scan all the job postings I see there. It gives me an overview of the current market needs. For example, I know that a YouTube blogger will pay me to edit their videos - now I know how much money I may be paid for such a job. Or, I know that a restaurant owner will pay $Y per hour if I bring food from the kitchen to customers&apos; tables.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/10/image-1.png" class="kg-image" alt loading="lazy" width="622" height="206" srcset="https://metacognitive.me/content/images/size/w600/2022/10/image-1.png 600w, https://metacognitive.me/content/images/2022/10/image-1.png 622w"></figure><h2 id="universitycollege-approach">University/college approach</h2><p>When choosing a skills direction first, for example, I want to be a singer, I study first, then look at the market needs and don&apos;t understand what the world may pay me.</p><p>If I did the market research first, it&apos;s an excellent way to go: I know what skills I need and study them.</p><p>If I don&apos;t care about money (because I know I can find any entry-level job anytime) and want to pursue the things I enjoy(e.g., singing), it&apos;s also a good approach - in this case, though, I flip the priorities order. I choose the things I enjoy(singing) over the money to pay rent or food.</p><h1 id="as-a-conclusion">As a conclusion</h1><ol><li>People constantly change as well as their needs, ambitions, and desires.</li><li>If a young person tries to understand what they want to do, it&apos;s more difficult because of a lack of knowledge.</li><li>The world is constantly changing.</li></ol><p>Combining these three facets and the answer to what to do in life becomes even more complicated.</p><p>For young people trying to understand what skills they should learn or what profession they should choose:</p><ol><li>Determine if there&apos;s an activity you enjoy doing and want to be paid for. I.e., if it&apos;s possible to combine a job and the things you enjoy doing.</li><li>Research the [job] market: how much may it pay for this kind of job? What skills does one need to get it? What is the best way to get the skills - university, online courses, books, etc.?</li><li>If you don&apos;t know what you enjoy or at least what you can do for money: find a balance between the money the market gives a person for a particular job and the time one needs to learn the skills for it. For example, if you already know two languages, you may become a translator without learning additional skills. If you want to be paid more than a translator(in this example), and you know that a copywriter may earn 60% more, and you need a month to learn(or improve) your skills, it&apos;s worth switching to the latter if you like doing that of course.</li></ol>]]></content:encoded></item><item><title><![CDATA[Can we program creativity?]]></title><description><![CDATA[<p>The short answer is: why not?</p><p>According to <a href="https://en.wikipedia.org/wiki/Creativity?ref=metacognitive.me">Wikipedia</a>:</p><blockquote>Creativity is a phenomenon whereby something new and valuable is formed</blockquote><p>I&apos;ll describe a few ideas in this article, but they aren&apos;t new. So, is this article a creative work?</p><p>According to the definition - yes, it</p>]]></description><link>https://metacognitive.me/can-we-program-creativity/</link><guid isPermaLink="false">63257568fa350b0001d609e7</guid><category><![CDATA[thoughts]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sat, 17 Sep 2022 09:46:46 GMT</pubDate><content:encoded><![CDATA[<p>The short answer is: why not?</p><p>According to <a href="https://en.wikipedia.org/wiki/Creativity?ref=metacognitive.me">Wikipedia</a>:</p><blockquote>Creativity is a phenomenon whereby something new and valuable is formed</blockquote><p>I&apos;ll describe a few ideas in this article, but they aren&apos;t new. So, is this article a creative work?</p><p>According to the definition - yes, it requires some combination of my current knowledge, thus creating a new way to deliver such a topic. It&apos;s valuable because someone will find new ideas here. However, the very ideas aren&apos;t new, and one may find a different way of delivering them on the Internet.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/09/image.png" class="kg-image" alt loading="lazy" width="709" height="567" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image.png 600w, https://metacognitive.me/content/images/2022/09/image.png 709w"><figcaption>Most of the time, we transform the existing ideas into other ideas in different forms</figcaption></figure><p>Can a natural language generation model create such an article? Not quite like this, but a similar one that will be better and worse, depending on the random selection of many generated texts. So, yes, it can already.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/09/image-1.png" class="kg-image" alt loading="lazy" width="556" height="511"><figcaption>A natural language text model generates some good text</figcaption></figure><p>Can we presume the same for music, movies, and image creation? With a working model and many examples, this is what neural networks do today. The quality of that art is disputable and depends on the patterns and story complexity.</p><h2 id="what-is-new">What is new?</h2><p>The &quot;new&quot; in the creativity definition is significantly relative. This article is original only in terms of deliverability to readers. The hand-drawn images here are authentic only in my unique hand movements, not in the ideas they present. Therefore, re-creating a similar article by the models trained on a lot of data is possible.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/09/image-2.png" class="kg-image" alt loading="lazy" width="1254" height="357" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image-2.png 600w, https://metacognitive.me/content/images/size/w1000/2022/09/image-2.png 1000w, https://metacognitive.me/content/images/2022/09/image-2.png 1254w" sizes="(min-width: 720px) 720px"></figure><p>Let&apos;s assume the originality of my ideas in this article is 0.0001 out of 1. And let&apos;s assume that Einstein&apos;s theory of relativity is 1. The models that generate text may reach a similar to this article, relatively small originality score because they combine the examples given to them by humans. They can&apos;t produce a 0.9 of 1 of the novelty score if they work like pattern distinguishing algorithms.</p><p>Humans are pattern distinguishers too. However, some of us can produce more novelty in our ideas. But we&apos;re entirely different than those programs, aren&apos;t we? Yes, we are because we aren&apos;t merely pattern recognizers. Instead, we can understand the information and create models of how the world works. The neural network models don&apos;t do that.</p><h2 id="a-program-that-creates-models">A program that creates models</h2><p>How can humans do that? We have a model for this, but we don&apos;t know how it works in reality. Our brain is astonishingly complex. The cells there, as in any other tissues in our body, are created by other cells&apos; that have instructions on how to do so. The living organisms&apos; cells know how to encode the instructions and then extract them to make new cells.</p><p>The instructions don&apos;t necessarily tell every brain cell how to think about something; they&apos;re telling cells how to function. And then you have billions of such cells that work together, forming a complex structure. So DNA instructions don&apos;t convey to a brain cell how to think, but they contain a base set of instructions to let it function with other such cells and transmit signals.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/09/image-3.png" class="kg-image" alt loading="lazy" width="644" height="202" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image-3.png 600w, https://metacognitive.me/content/images/2022/09/image-3.png 644w"></figure><p>We&apos;re programmed. But our &quot;codebase&quot; is much more complicated than any other one. We&apos;re programmed to create models, understand, and recognize patterns. Thus, we can produce more novelty in the existing ideas.</p><p>Can we program machines to do so? It&apos;s possible in principle because it&apos;s possible with humans. But, can we, humans, program a machine to think? It requires us to create a model of how we work(we still don&apos;t know many things about how we function). Or to create a model of how a machine may construct models. I.e., a hypothesis, not an exact human &quot;program&quot; reproduction.</p><h2 id="summary">Summary</h2><p>It&apos;s possible to program creativity in machines, in principle. We were programmed(not necessarily <strong>by</strong> something, it might be a random coincidence), so why it&apos;s not possible with other matter? The different question is if humans can do that. And the answer depends on our mental ability to understand how to create a working model that can &quot;think.&quot; In a digital world, it&apos;s called AI. But who knows, maybe we&apos;ll be programming stones.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/09/image-4.png" class="kg-image" alt loading="lazy" width="765" height="193" srcset="https://metacognitive.me/content/images/size/w600/2022/09/image-4.png 600w, https://metacognitive.me/content/images/2022/09/image-4.png 765w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[Temporary space to save ideas quickly]]></title><description><![CDATA[<p>It&apos;s beneficial to write down the thoughts you want to think about more in the future. Then, you can return to them at any convenient moment and continue developing a thought process.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/05/image.png" class="kg-image" alt loading="lazy" width="651" height="311" srcset="https://metacognitive.me/content/images/size/w600/2022/05/image.png 600w, https://metacognitive.me/content/images/2022/05/image.png 651w"></figure><p>I wasn&apos;t used to writing ideas down since I didn&apos;t value them</p>]]></description><link>https://metacognitive.me/temporary-space-to-save-ideas-quickly/</link><guid isPermaLink="false">62888e63cbc2ae00018aacfe</guid><category><![CDATA[productivity]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 22 May 2022 09:13:04 GMT</pubDate><content:encoded><![CDATA[<p>It&apos;s beneficial to write down the thoughts you want to think about more in the future. Then, you can return to them at any convenient moment and continue developing a thought process.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/05/image.png" class="kg-image" alt loading="lazy" width="651" height="311" srcset="https://metacognitive.me/content/images/size/w600/2022/05/image.png 600w, https://metacognitive.me/content/images/2022/05/image.png 651w"></figure><p>I wasn&apos;t used to writing ideas down since I didn&apos;t value them enough(I have a dozen of them every moment, so why care?). However, let&apos;s skip the reasoning on why people write their ideas. Instead, I want to share one concept in this article: having a middle space between a never-ending thoughts waterfall and a notebook.</p><h2 id="problem-you-dont-always-have-your-notebook-near-you">Problem: you don&apos;t always have your notebook near you</h2><p><br>Sometimes, you don&apos;t have access to a notebook or a smartphone with a note-taking app.</p><blockquote>Then make sure you do!</blockquote><p>Yes, you could try, but there are cases when it&apos;s not convenient or possible:</p><ol><li>You drive a car.</li><li>You stand in a crowd.</li><li>You have your smartphone or notebook 50 meters from you.</li><li>You&apos;re on a rollercoaster, on a surgeon&apos;s table, etc.</li></ol><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/05/image-1.png" class="kg-image" alt loading="lazy" width="530" height="491"></figure><p>An obvious solution could be remembering a thought and keeping it in mind. The difficulty is in focusing on that single thought and not getting bombed by dozens of other ideas and distractions.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/05/image-2.png" class="kg-image" alt loading="lazy" width="579" height="298"></figure><h2 id="keeping-ideas-in-mind">Keeping ideas in mind</h2><p><br>I use the apparent solution mentioned above, but with some tricks. I imagine one visual and well-familiar place [1] where I place a thought&apos;s visual representation [2]. You may think of the <a href="https://metacognitive.me/memory-palace/">memory palace technique</a>, and you&apos;re correct.</p><p>If you&apos;re familiar with the mind palace method, you know how and why it works.</p><p><strong>[1] Well-familiar and pre-defined place</strong>. This component allows you to locate where exactly you&apos;ve left the information. Such an approach reduces time and mental effort in finding associations(thoughts) that led to the idea you want to hold.</p><p>How do I usually remember something: what I was thinking about that led me to that thought? What was I doing at that time? Slowly, I build a track of thoughts, and sometimes, I find the one I wanted to remember.</p><p>Since I can&apos;t extract any information by having a memory address like in electronics, the better way is to represent this address visually and virtually in my head.</p><p>A place should be thought out beforehand not to waste time when I need it quickly. Otherwise, I may start to find suitable locations, and my idea will be gone.</p><p>A place should be well-familiar to me. Otherwise, I may start wasting efforts to draw the missing details. Good examples of a suitable location are a room in my house or a garden I visit often.</p><p><br><strong>[2] A visual representation of a thought.</strong> I remember visual information better. Also, I can put it in a virtual place in my mind. Combining that with a place where we can go directly (in thoughts) gives us a great approach to save any information quickly and access it even after a few days.</p><p>But I don&apos;t need to access that idea after a few days. I need to keep it for a few hours at maximum, and then I&apos;ll write it down.</p><blockquote>Why don&apos;t we use our minds to store information if this approach is superior?</blockquote><p>You can try, but our mind isn&apos;t a perfect place to store anything. So I prefer writing everything down. This method is suitable as a temporal place to store ideas until you get access to better storage. However, no one stops you from building huge associations and developing ideas in that semi-temporal space.</p>]]></content:encoded></item><item><title><![CDATA[Why do I use Next.js in my projects]]></title><description><![CDATA[<p>It simplifies development workflow, provides many built-in solutions and optimizations, simply put. Next.js is a React framework that employs the latter to make a developer&apos;s life easier when creating web apps.</p><h1 id="how-did-i-develop-web-appswebsites-before">How did I develop web apps/websites before</h1><p>It&apos;s sort of a retrospective on</p>]]></description><link>https://metacognitive.me/why-do-i-use-next-js-in-my-projects/</link><guid isPermaLink="false">623b2328a173ea000103e0a8</guid><category><![CDATA[programming]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 27 Mar 2022 07:57:34 GMT</pubDate><content:encoded><![CDATA[<p>It simplifies development workflow, provides many built-in solutions and optimizations, simply put. Next.js is a React framework that employs the latter to make a developer&apos;s life easier when creating web apps.</p><h1 id="how-did-i-develop-web-appswebsites-before">How did I develop web apps/websites before</h1><p>It&apos;s sort of a retrospective on how things were before fancy technologies. It&apos;s a short journey on how do we come up with React. Feel free to skip it and read more about Next.js in the next sections.</p><h3 id="pure-html-css-era-simple-websites">Pure HTML, CSS era: simple websites</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/03/image.png" class="kg-image" alt loading="lazy" width="1024" height="640" srcset="https://metacognitive.me/content/images/size/w600/2022/03/image.png 600w, https://metacognitive.me/content/images/size/w1000/2022/03/image.png 1000w, https://metacognitive.me/content/images/2022/03/image.png 1024w" sizes="(min-width: 720px) 720px"><figcaption>An old and simple website written in HTML</figcaption></figure><p>When I was getting started with web development, I put simple <code>&lt;div&gt;</code> blocks into Notepad, adding some CSS styles. It&apos;s straightforward. I don&apos;t need to know any frameworks, additional technologies. A few more <code>&lt;div&gt;</code> blocks, then some text and buttons, and I got a sidebar, a menu, and a content block with text.</p><p>The problem with this approach begins when I want to add more pages: I should copy-paste those sidebar and menu codes into the new page. As a result, I should amend the code on every page if I want to change, say, the color of the button placed on every page in a header.</p><p>Not an ideal method, but it works well for a plain one-page website.</p><h3 id="using-template-engines-to-re-use-components">Using template engines to re-use components<br></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/03/image-1.png" class="kg-image" alt loading="lazy" width="898" height="390" srcset="https://metacognitive.me/content/images/size/w600/2022/03/image-1.png 600w, https://metacognitive.me/content/images/2022/03/image-1.png 898w" sizes="(min-width: 720px) 720px"><figcaption>A template engine like Pug allows creating atomic components to avoid code duplication</figcaption></figure><p>There were(and still are) tools that decreased code duplication. Tools like <a href="https://pugjs.org/?ref=metacognitive.me">Pug</a> and <a href="https://expressjs.com/en/resources/template-engines.html?ref=metacognitive.me">others</a> are Javascript scripts that compile custom HTML syntax into standard HTML. With their help, a developer can create one component(e.g. a header with links) and put it on many pages without duplicating the component code. If I need to change the component style or structure, I alter the code in one place.</p><p>They also provide helpers to format HTML. For example, Javascript functions to capitalize text. Now it&apos;s easier to build a multi-page website. I create multiple fundamental components for my website and I re-use them on almost every page.</p><h3 id="from-websites-to-web-apps-handling-an-apps-state">From websites to web apps: handling an app&apos;s state</h3><p>There was a time when businesses started to replace desktop apps with web apps. The other ones wanted to automate many things for customers. They began creating websites to receive orders, for example. When we create a many-page website with custom logic to handle users&apos; input, sending data to a server, showing errors, etc., it becomes harder to manage the state. State? We need to store, memorize what users want, what did we show/tell them, and so on.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/03/image-2.png" class="kg-image" alt loading="lazy" width="1074" height="592" srcset="https://metacognitive.me/content/images/size/w600/2022/03/image-2.png 600w, https://metacognitive.me/content/images/size/w1000/2022/03/image-2.png 1000w, https://metacognitive.me/content/images/2022/03/image-2.png 1074w" sizes="(min-width: 720px) 720px"><figcaption>Handling a web app&apos;s state</figcaption></figure><p>We may keep state on a server, but in such a way we add more complexity there. Also, it&apos;s not always convenient. For example, I want to store a lot of info about the current user and use it immediately on the next page, then forget about it. Say, it&apos;s transforming a picture into a black-and-white one via Javascript. It&apos;d be more efficient to not load our server and make such a transformation client-side.</p><p>We could store a state, or even many states, in a browser&apos;s local storage, or IndexedDB, right? Correct. However, we then need to have a logic to update our UI if the state changes. We might update everything when anything in our state changes, but then another issue appears. Our website&apos;s responsiveness isn&apos;t fine: performance is bad.</p><h3 id="react-vue-and-similar-tools">React, Vue, and similar tools</h3><p>React, for example, solves the components issue(templating), state management problem. With it, I may create optimized web apps, simplify interactions between many components. Why choose React or Vue? They ease the development of complicated web apps. Handling local(component-level) and global state is simpler. Re-using components is much simpler. These tools are libraries, not opinionated, hence not giving you plain constraints: what you should and shouldn&apos;t do. Instead, they tell you rules of good behavior - what code is better to avoid, for example, when writing components.</p><h1 id="react-pros-and-cons">React: pros and cons</h1><h2 id="pro-reusability-of-components">Pro: reusability of components</h2><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/03/image-3.png" class="kg-image" alt loading="lazy" width="600" height="450" srcset="https://metacognitive.me/content/images/2022/03/image-3.png 600w"></figure><p>We talked about how it was difficult to not duplicate code in other web pages. React allows a developer to create small, large components and re-use them anywhere. We may include small components into bigger ones and include them in larger components. Thus, we diminish repeatable code and we have full control of a local component state. Hence, we optimize a web app(or, we make it worse).</p><h2 id="pro-its-performant-because-of-virtual-dom">Pro: it&apos;s performant because of virtual DOM</h2><p>React creates an additional layer of API of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction?ref=metacognitive.me">DOM</a> to optimize performance. Since the library allows you to create UI consisting of many components, it tries to update an as small number of them as possible to avoid the standard load on a browser&apos;s re-rendering. By standard, I mean not updating the entire web page when we have only a minor state change. Why re-draw all elements in DOM if we can re-draw the ones that depend on the modified data, right?</p><h2 id="pro-a-massive-community">Pro: a massive community</h2><p>Any great technology is backed up by a large community. If it&apos;s not large, then it&apos;s difficult to find answers on weird(or any) issues on Stackoverflow, or, to find a library to draw a simple green circle. In the Javascript world, this community is among the largest. The same applies to React, a part of it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/03/image-4.png" class="kg-image" alt loading="lazy" width="712" height="492" srcset="https://metacognitive.me/content/images/size/w600/2022/03/image-4.png 600w, https://metacognitive.me/content/images/2022/03/image-4.png 712w"><figcaption>A large community provides many already built solutions for a web app</figcaption></figure><p>If I need to make a well-styled table in React, I may find it in a moment on Google. If I have hard times figuring out some peculiar behavior with the library, it&apos;s easy to find an answer.</p><h2 id="cons-not-for-me">Cons: not for me</h2><p>React works well for the problems it solves. It&apos;s easy to instantiate a new project and start coding. For me, it&apos;s not difficult to learn. And, later, it speeds up the development. Then why this article about Next.js?</p><h1 id="nextjs-advantages-after-using-react">Next.js advantages after using React</h1><p>React community created <code><a href="https://reactjs.org/docs/create-a-new-react-app.html?ref=metacognitive.me">create-react-app</a></code> CLI tool to instantiate a new project and see the result immediately. And I liked that for my simple web apps.</p><p>However, my next projects had public pages, a blog. A solution could be to set up a server and render the pages there, to return prepared HTML. Or, to bring other tools: a blog engine, a static site engine.</p><h2 id="built-in-serverstatic-rendering">Built-in server/static rendering</h2><p>Next.js cares about this and lets a developer continue writing code. It&apos;s why I didn&apos;t need to use other tools to build a blog or a regular page optimized for search engines and performance.</p><h3 id="why-care-about-server-rendering">Why care about server rendering?</h3><p>When exposing a web page to search engines, it&apos;s better to provide them HTML page without Javascript. Google, for example, <a href="https://www.practicalecommerce.com/seo-how-google-reads-and-renders-javascript?ref=metacognitive.me">can also understand Javascript</a> there(hence a regular React app can be &quot;understood&quot;), but it sends a website to a rendering queue, which takes more time than processing pages when a Googlebot is reading a website right now.</p><p>Server rendering may come with a complex setup if one tries this for the first time: I need a server, at least, to render those web pages there.</p><p>The other thing intertwined with the previous one is improved performance for users(and search bots). A server renders a page and browsers show it without the necessity to compile Javascript. It comes with an additional load on the server though: it should render a page for every user(especially if the page consists of dynamic data).</p><p>We could cache such pages or make them not so dynamic. Anyway, they will be fetched and shown fast for a user. Consequently, our web vitals become better.</p><p>Next.js allows me to create a page that is <a href="https://nextjs.org/docs/basic-features/pages?ref=metacognitive.me">pre-rendered by default</a>. Either at build time(static generation, pages are reused for every request) or at a compile-time(SSR, hence rendering on every request). Static generation is a preferred way since it generates pages at build time. Even if I have dynamic data on the pages but I can fetch it at build time, it&apos;s an ideal way to optimize performance.</p><h3 id="programmatic-seo">Programmatic SEO</h3><p>Programmatic SEO is a technique to automate creating a lot of web pages that target almost similar keywords. They may have one search intent but it varies in details. Imagine you have an agency that lists realtors in different cities and countries: to help people who look for an apartment to find agents quickly. You make a website with the primary keyword &quot;best realtors&quot;. However, this keyword is popular and a new website won&apos;t gain traction from Google. Hence, we may target long-tail keywords: we save the primary intent(&quot;best realtors&quot;) but specify a location. In this way, &quot;best realtors in Kyiv&quot; isn&apos;t as popular as &quot;best realtors&quot; and we target more specific intent on our web page.</p><p>However, we&apos;d require more time to build such pages one by one, right? Most of the code could be copy-pasted, only the list with realtors differs. If we target &quot;best realtors&quot; in 10,000 various cities, it&apos;s a lot of work. What if we want then to target for &quot;best agents in Kyiv&quot;-like keywords? We alter a word, and we require additional 10,000 web pages.</p><p>Here&apos;s the thing: we have the realtors lists in various cities already, we have a web page template. With Next.js, building a lot of pages for programmatic SEO is simple. Have a list of keywords, have one code(template) and the framework will build a page for every keyword you specified.</p><h2 id="built-in-routing">Built-in routing</h2><p>Remember how do you choose a router for a new React project? They&apos;re almost the same, have some differences, and some libraries are stable. With a Next.js project, I don&apos;t need to think about what router to use this time(maybe some other library?). It has a built-in router. And it&apos;s a simple one: you put a file in the <code><a href="https://nextjs.org/docs/basic-features/pages?ref=metacognitive.me">pages</a></code> folder and it becomes a page.</p><p>For example, I want to make a page with the URL <code>&lt;myapp&gt;/sign-in</code>. I put <code>sign-in.tsx</code> component or <code>sign-in</code> folder with <code>index.tsx</code> component there and it works.</p><p>The router provides all the necessary features: dynamic routes, nested routes, linking pages.</p><h2 id="built-in-api-server">Built-in API server</h2><p>There&apos;s <code>pages/api</code> folder where I may specify API endpoints. Some good use cases are:</p><ol><li>API middlewares. When I want to alter a request(e.g. its headers) to make another one to a different server, for example.</li><li>Request resources on other domains. To avoid the CORS issue(<a href="https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors?ref=metacognitive.me">an example project</a>). Oftentimes, I need to request some 3rd-party resource, but I can&apos;t due to CORS. One solution is to make a server, make the request there, and then redirect it to the 3rd-party. Let&apos;s save time though. For simple requests(and even a bit complicated, Next.js can handle it too), it&apos;d better use <code>pages/api</code>.</li></ol><h2 id="build-in-images-and-fonts-optimization">Build-in images and fonts optimization</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/03/image-5.png" class="kg-image" alt loading="lazy" width="760" height="382" srcset="https://metacognitive.me/content/images/size/w600/2022/03/image-5.png 600w, https://metacognitive.me/content/images/2022/03/image-5.png 760w" sizes="(min-width: 720px) 720px"><figcaption>Next.js built-in image optimization</figcaption></figure><p>I don&apos;t want to optimize such assets on every page I code. At the beginning of some project, it&apos;s usually not a top priority. But it&apos;s great when the framework does the 80%-like(there are other complicated optimization tricks we usually don&apos;t need) job at optimizing assets. You paste an image and it&apos;s automatically smaller, without layout shifts, and it lazy-loads!</p><h2 id="environment-variables">Environment variables</h2><p>There are 2 environments that are available when you code a Next.js app: a browser, a server. Environment variables in a browser are visible if one wants to find them in the bundled code. The server variables are hidden since users don&apos;t have access to remote hosts and their code.</p><p>With Next.js, I can create both env. variables without setting up webpack and installing another library to handle env. vars for a server. The framework has built-in support for them!</p><p>There&apos;s a <code>.env</code> file where I specify server vars, and in the same file I may specify browser vars by adding a prefix to a var - <code>NEXT_PUBLIC_</code>. Incredibly convenient to me.</p><h1 id="summary">Summary</h1><p>Next.js saves me time a lot with current and new projects. I can combine a few apps seamlessly and have one codebase only. The advantages I wrote about may not apply to your use case though. If you use React now, it&apos;s worth trying: the framework adds up useful features on top of the React pros.</p><p>If you have questions or feedback, let <a href="https://twitter.com/sergchr?ref=metacognitive.me">me</a> know.</p><p><br></p><p><br></p>]]></content:encoded></item><item><title><![CDATA[Implementing push notifications with Firebase for Javascript apps]]></title><description><![CDATA[A tutorial on implementing Firebase web push notifications for React, Next.js, Node.js, Javascript apps.]]></description><link>https://metacognitive.me/implementing-push-notifications-with-firebase/</link><guid isPermaLink="false">61ead6f9ae238d00019491f6</guid><category><![CDATA[javascript]]></category><category><![CDATA[programming]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Fri, 21 Jan 2022 18:29:56 GMT</pubDate><content:encoded><![CDATA[<p>These notifications we&apos;re used to on smartphones are available in browser environments too. If you know why are you here exactly, skip this part and jump directly to the solution.</p><p>And these notifications on the web that we hate because every spam site asks our permissions about sending us their spam. However, the technology itself is useful. I didn&apos;t implement web push notifications before. There was no such case, but recently I needed to notify my users about important information as soon as possible. Email is good, but a user should open an email client first. With notifications, you see the popup immediately.</p><p>I decided to write this article because I didn&apos;t find comprehensive information about implementing browser notifications for React, Next.JS, Node apps. We&apos;ll be using Firebase for this purpose, to save time ourselves by not building solutions from scratch.</p><h2 id="overview-of-browser-push-notifications">Overview of browser push notifications</h2><p>So as we said, it&apos;s like those mobile notifications but used in browsers mostly for spamming. It&apos;s worth noting, that you need to send them to a user if that&apos;s really what he subscribed to. Examples:</p><ul><li>new comments under the user&apos;s post;</li><li>new message on some platform;</li><li>important information that should be handled fast;</li></ul><p>The other non-important things may go to email.</p><h3 id="how-does-it-work">How does it work</h3><p>First, you ask a user permission to show the notifications. If you get an acceptance, your website installs a <a href="https://developers.google.com/web/fundamentals/primers/service-workers?ref=metacognitive.me">service worker</a> that&apos;ll be handling the notifications. You also send the request to register this particular user in a messaging server, you&apos;ll be asking it to send a notification to someone.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://metacognitive.me/content/images/2022/01/image-1.png" class="kg-image" alt loading="lazy" width="1000" height="394" srcset="https://metacognitive.me/content/images/size/w600/2022/01/image-1.png 600w, https://metacognitive.me/content/images/2022/01/image-1.png 1000w" sizes="(min-width: 720px) 720px"><figcaption>Push notifications overview</figcaption></figure><p>When a messaging server registers your users, it&apos;ll send you a unique for your user token that you&apos;ll be using as an addressee to send push notifications programmatically.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2022/01/image-2.png" class="kg-image" alt loading="lazy" width="995" height="424" srcset="https://metacognitive.me/content/images/size/w600/2022/01/image-2.png 600w, https://metacognitive.me/content/images/2022/01/image-2.png 995w" sizes="(min-width: 720px) 720px"></figure><p>You save the registration token from a messaging server. When you want to send a notification, you&apos;ll point out this token for the user you want to send a message to, thus the messaging server understands to whom to send the notification. When a user agrees to receive notifications, your website installs a service worker, it&apos;s a background script that&apos;ll be running on the user&apos;s browser. It&apos;s programmed to handle the messages from the messaging server. When it receives one, it&apos;ll assemble a notification to show to this user.</p><p><strong>Messaging server?</strong> This is any server that knows how to communicate with your service worker. You can build it by yourself and code a service worker that will be managing messages from there. But we won&apos;t complicate our life and we&apos;ll be using Firebase.</p><h2 id="firebase-push-notifications">Firebase push notifications</h2><p>If we use Firebase, we don&apos;t care about the proper messaging server setup because we got covered. What we need is to code logic to ask for the notifications permissions, install a service worker and write a logic to send notifications from our app.</p><p>For further setup, you should create a project in the <a href="https://console.firebase.google.com/?ref=metacognitive.me">Firebase Console</a>, and have config from there(a JSON file).</p><h3 id="front-end-set-up">Front-end set up</h3><p>I have a Next.js app, but this algorithm covers any app written in Javascript, it&apos;s a library- and framework-independent.</p><p>Install Firebase to your project so we can leverage simple functions rather than doing requests to FCM(Firebase Cloud Messaging) manually.</p><pre><code class="language-shell">$ npm install firebase
# or
$ yarn add firebase</code></pre><p>Find a place where do you want to ask a user about the notification permission. For example, it can be a button that says &quot;Subscribe to browser notifications&quot;. On this button click, you&apos;ll be calling a function <code>getFCMToken()</code> written below:</p><pre><code class="language-javascript">import { initializeApp } from &apos;firebase/app&apos;;
import { getMessaging, getToken } from &apos;firebase/messaging&apos;;

// Replace these values with your project&apos;s ones
// (you can find such code in the Console)
const firebaseConfig = {
    apiKey: &apos;xxxxx-xxx&apos;,
    authDomain: &apos;xxxx.firebaseapp.com&apos;,
    projectId: &apos;xxxx-xxxx&apos;,
    storageBucket: &apos;xxxx.appspot.com&apos;,
    messagingSenderId: &apos;00000000&apos;,
    appId: &apos;0:00000:00000000&apos;
};

export const app = initializeApp(firebaseConfig);
const messaging = getMessaging();

export async function getFCMToken() {
    try {
        // Don&apos;t forget to paste your VAPID key here
		// (you can find it in the Console too)
        const token = await getToken(messaging, { vapidKey: &lt;YOUR_VAPID_KEY&gt; });
        return token;
    } catch (e) {
        console.log(&apos;getFCMToken error&apos;, e);
        return undefined
    }
}</code></pre><p>With this code, we initialize the Firebase library and write this <code>getFCMToken()</code> function. It retrieves a registration token from FCM, and <strong>it also asks a user for notification permission</strong>. If the permissions are accepted, only then it&apos;ll communicate with FCM to register this user. Otherwise, the code throws an error, which you catch in the <code>catch</code> block.</p><p>Then, you get an FCM token(a user&apos;s unique token in the FCM system), which you&apos;ll be using to send notifications. So you need to <strong>store it</strong> somewhere. Usually, you have a server where you may send the token and it&apos;ll save it in the database for this particular user. Otherwise, you won&apos;t be able to send notifications to users. It&apos;s required to have the Firebase Admin SDK, which is available on server environments.</p><p>There are some exceptions though. In some cases when you want only to subscribe users to your notifications like in a newsletter, you may not store the FCM tokens. Firebase has them and you can send the notifications <strong>manually</strong> from the Console. But it&apos;s not possible to send them automatically(programmatically) because you can&apos;t differentiate users(you don&apos;t have the tokens).</p><p>And the last thing is to have a service worker that will handle the notifications from FCM. Create a file that&apos;ll be available on the root of your web app, the file named <code>firebase-messaging-sw.js</code>. It should be accessible on <code>https://yourwebsite.com/firebase-messaging-sw.js</code>. Its contents:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">// It&apos;s a static script file, so it won&apos;t be covered by a module bundling system
// hence, it uses &quot;importScripts&quot; function to load the other libs
importScripts(&apos;https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js&apos;);
importScripts(&apos;https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js&apos;);

// Replace the values with yours
const firebaseConfig = {
    apiKey: &apos;xxx&apos;,
    authDomain: &apos;xxx&apos;,
    projectId: &apos;xxx&apos;,
    storageBucket: &apos;xxx&apos;,
    messagingSenderId: &apos;xxx&apos;,
    appId: &apos;xxx&apos;
};

firebase.initializeApp(firebaseConfig);

const messaging = firebase.messaging();

// Not necessary, but if you want to handle clicks on notifications
self.addEventListener(&apos;notificationclick&apos;, (event) =&gt; {
    event.notification.close()

    const pathname = event.notification?.data?.FCM_MSG?.notification?.data?.link
    if (!pathname) return
    const url = new URL(pathname, self.location.origin).href

    event.waitUntil(
        self.clients
            .matchAll({ type: &apos;window&apos;, includeUncontrolled: true })
            .then((clientsArr) =&gt; {
                const hadWindowToFocus = clientsArr.some((windowClient) =&gt;
                    windowClient.url === url ? (windowClient.focus(), true) : false
                )

                if (!hadWindowToFocus)
                    self.clients
                        .openWindow(url)
                        .then((windowClient) =&gt;
                            windowClient ? windowClient.focus() : null
                        )
            })
    )
})</code></pre><figcaption>Firebase messaging service worker</figcaption></figure><p>That&apos;s all on the front-end side! You can test your button, on the press, it should ask your permission(a browser asks, to be precise) to send you notifications. When you allow it, you should see an FCM token(console.log it somewhere)</p><h3 id="sending-notifications-from-the-server">Sending notifications from the server</h3><p>In my case, it&apos;s a Node.js server and we&apos;ll be installing the SDK for it, but the general principle is the same for other languages/platforms.</p><pre><code class="language-shell">$ npm install firebase-admin</code></pre><p>You also have a configuration for the backend in the Console. It differs from the client-side one because it has a private key that you need to sign your notification, which will be sent to FCM. Put this <code>firebase.json</code> file(it&apos;s called service account) somewhere to be accessible from code, you may put it as an environment variable.</p><p>Then you should initialize the Firebase library on a server start(or later if you want to control the flow). I&apos;ve put this logic into a separate file:</p><pre><code class="language-javascript">import admin from &apos;firebase-admin&apos;;

import serviceAccount from &apos;./config/firebase.json&apos;;

export function init() {
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
    });
}</code></pre><p>On a server start, call <code>init()</code> and Firebase is ready to serve you.</p><p>I won&apos;t cover storing the FCM tokens, I&apos;m sure you know how to do it and it&apos;s not the purpose of this article. So, given you have an initialized Firebase on the server(from the last paragraph) and you have a user&apos;s FCM token, you&apos;re ready to send push notifications to a user&apos;s browser! It looks like this:</p><pre><code class="language-typescript">import { getMessaging } from &apos;firebase-admin/messaging&apos;;

// I use Typescript, you may not, but types will help you
// to understand what data structures FCM expects.
// It&apos;s an internal structure though, firebase-admin has
// good typings in the library
interface Message {
	title: string;
    body: string;
    requireInteraction?: boolean;
    link?: string;
}

// Use this function to send push notifications to a specific user
export async function sendFCMMessage(fcmToken: string, msg: Message): Promise&lt;string&gt; {
    try {
        const res = await getMessaging().send({
            webpush: {
                notification: {
                    ...msg,
                    icon: &apos;https://your-website.com/favicon.png&apos;,
                    requireInteraction: msg.requireInteraction ?? false,
                    actions: [{
                        title: &apos;Open&apos;,
                        action: &apos;open&apos;,
                    }],
                    data: {
                        link: msg.link,
                    },
                },
            },
            token: fcmToken,
        });
        return res;
    } catch (e) {
        console.error(&apos;sendFCMMessage error&apos;, e);
    }
}</code></pre><p>Now, some details on the notification payload. Firebase supports various platforms, here I use the <code>webpush</code> field for my payload. FCM supports other fields:</p><pre><code class="language-typescript">interface BaseMessage {
    data?: {
        [key: string]: string;
    };
    notification?: Notification;
    android?: AndroidConfig;
    webpush?: WebpushConfig;
    apns?: ApnsConfig;
    fcmOptions?: FcmOptions;
}</code></pre><p>I&apos;ve tried to use <code>notification</code> as a general-purpose one, but I had issues with clicking on notifications, a browser didn&apos;t handle clicks(the service worker had the click handler). Plus, there were problems with showing icons on notifications. It&apos;s better to use <code>webpush</code> if you target desktop users. An FCM token can be for various platforms: Android, iOS, web.</p><p>Inside <code>webpush</code>, there are <code>title</code> and <code>body</code> that correspond to a notification&apos;s title and body. There&apos;s <code>icon</code> if you want your notification to have an icon. Put a publicly accessible image you want to be shown. Set <code>requireInteraction</code> to <code>true</code> if you don&apos;t want the notification to be closed after a few seconds, it should wait for the user&apos;s explicit reaction.<br>There&apos;s a custom <code>link</code> field inside <code>data</code>, it&apos;s aimed for the service worker to be read and handle the click on notifications correctly.</p><p>I don&apos;t know about all browsers, but my browser(Brave) doesn&apos;t handle the default notification click on the whole area, there should be custom buttons. I define them in the <code>actions</code> field. It seems it doesn&apos;t matter what buttons with actions I put, the &quot;Open&quot; button(action) will open the URL from <code>data.link</code> property I send.</p><h2 id="summary">Summary</h2><p>Web push notifications aren&apos;t difficult to implement if you can use Firebase. Also, it&apos;s easy to send messages to various devices on different platforms. Only obtain an FCM token client-side(on a mobile, web, or desktop), and send notifications from a server.</p>]]></content:encoded></item><item><title><![CDATA[2021 updates]]></title><description><![CDATA[<p>It&apos;s one more milestone to write some retrospective. Yet it&apos;s an impetus for me to write updates of what I&apos;ve been working.</p><h2 id="blog">Blog</h2><p>In 2021 I started this blog. I decided to share my learning and thoughts on programming, to write more to clarify</p>]]></description><link>https://metacognitive.me/2021-updates/</link><guid isPermaLink="false">61d1862fae238d00019491c8</guid><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 02 Jan 2022 11:05:33 GMT</pubDate><content:encoded><![CDATA[<p>It&apos;s one more milestone to write some retrospective. Yet it&apos;s an impetus for me to write updates of what I&apos;ve been working.</p><h2 id="blog">Blog</h2><p>In 2021 I started this blog. I decided to share my learning and thoughts on programming, to write more to clarify the thinking process. I wrote 21 articles starting from March 2021. I wrote about non-programming topics too, the most popular article was about a memorizing technique. I posted it on <a href="https://news.ycombinator.com/item?id=28640429&amp;ref=metacognitive.me">HackerNews</a>, got 229 upvotes, and 6k visitors to my website.<br>Writing is great at finding new ideas too, not only understanding the current topic one started pondering about. Sometimes I find myself thinking about new topic ideas when writing the initial article.</p><p>What I like is the low-maintenance cost of this website: a server&apos;s expenses and the thing runs on free Ghost. The people work hard on it, thus I don&apos;t need to create my blog engine(however, I do that for one of my projects, more on it later). It&apos;s convenient - I write an article, publish it, and all of the other things like SEO are getting care of. Hence, I should only produce content and not focus on miscellaneous and not productive stuff.</p><p>In terms of SEO, I got 181 unique visitors for the past 28 days. The engagement time is 46s, which could be more. I expect it to increase when I have more organic search traffic.</p><h2 id="mobile-game">Mobile game</h2><p>In the November of 2020, I started creating a mobile game about playing as an AI that wants to escape from a digital lab. There were such games but I had some new ideas I wanted to play with. An inspiration for me was <a href="http://skynetsimulator.com/?ref=metacognitive.me">this</a> CLI-like game. It took me around 4 months to finish an alpha version, which I published to Google Play.<br>It&apos;s still in beta with ~20-40mins of gameplay time. People liked the game from what I see on Google Play reviews. I wanted to expand the plot, but I took other projects to work on. Maybe in the future, I&apos;ll continue working on it. Or, create a similar game with a different idea. For example, a universe simulation.</p><p>What I&apos;ve learned is that it&apos;s better to create a plot and then design beforehand. The plot was changing during the creation and it took a lot of time to change this or that. Also, it&apos;s better to spend more time on architectural decisions and documentation. Now, when I&apos;m returning to the codebase, I don&apos;t want to disentangle many parts of it. Somewhere it&apos;s difficult to understand why such a decision was made. However, it was a side project and it&apos;s fun to just create things and not think about documentation and long-term support.</p><h2 id="reddit-project">Reddit project</h2><p>Around 6 months ago I started a project that aimed to help me find real problems to solve. The real problem is to find people&apos;s and businesses&apos; problems they face every day(preferably), that are important enough to these people they spend money on a solution. I found Reddit to be a great place for such a purpose.</p><p>The searching process was straightforward using some specific keywords. The issue there was to filter the results. How to automate that? We got natural language processing. I spent some time experimenting with <a href="https://metacognitive.me/how-to-do-text-classification-with-javascript">multiple technologies</a>. The first and the simplest solution could cover some cases, but the overall accuracy was low. Then I went a hard way by creating my NLP models. The accuracy was still low, yet sometimes it could be okay. Though it didn&apos;t classify more difficult texts.<br>The experiments were fun but I needed a working solution. I switched to pre-trained models. TensorFlow has Javascript functionality, and they say you could connect Python pre-trained models to the JS library. In reality, it didn&apos;t work. Hence I outsourced the NLP filtering completely to Python. So, a project was on Javascript(UI and the server), but the filtering workflow was on Python.</p><p>The project was released to the public in November. After some time I thought about pivoting it. &#xA0;So, the tool that will help not only indie makers and me but other people that struggle searching for something on Reddit. After a few months of searching Reddit for various things, I understood that it could be done much better. Also, people may look for not only problems to solve but many various things.</p><p>I spent 2 weeks pivoting and a month plus more to analyze the feedback to enhance it. I currently work on this project, but mostly on the marketing side. Now I spend more time <a href="https://olwi.xyz/articles?ref=metacognitive.me">writing content</a>. By the way, it&apos;s Next.JS that parses markdown. I could employ a ready-made blog engine, but I thought it&apos;d be enough. Well, it is, however, there are some minor issues.</p><p>Olwi now is aiming to help marketers, business owners, indie makers, and other people to find what they need on Reddit. For example, potential problems to solve, what people say about their brand or competitors, search for their potential customers. I plan to collect more feedback. For this, I improve my SEO and write more content to attract more organic visitors.</p><h2 id="twitter">Twitter</h2><p>I registered on Twitter at the start of 2020. Then I started using it more actively in 2021 by building in public, sharing learnings, and so on. I tried to engage with more people to get more visibility of my profile. Eventually, I followed around a thousand profiles and got a feed that has more garbage than interesting thoughts.</p><p>I could follow fewer people, and anyway I would see irrelevant tweets sometimes. My initial goal was to gain an audience for the future exposure of my person and projects. But faking the whole process for the sake of attracting other fake followers isn&apos;t worth it.</p><p><br>Twitter is full of people who are fixated on the idea of gaining more followers to sell info products. Or, gaining more followers to expose their thoughts on something they don&apos;t have real experience. Twitter is a good platform to engage with tweets you&apos;re interested in to spark intriguing conversations. Hence, to even find friends. But it&apos;s difficult to find such conversations without following a bunch of people and scrolling through a thousand irrelevant tweets.</p><h2 id="plans-for-2022">Plans for 2022</h2><p>I&apos;ll continue working on <a href="https://olwi.xyz/?ref=metacognitive.me">Olwi</a>. Creating more content on this blog. But also I want to create some other projects(bad for focus though, so not sure I will). The burnout problem comes closer with more work though. I want to learn how to better handle my mental health. I should do it my first priority.</p>]]></content:encoded></item><item><title><![CDATA[How to do text classification with Javascript]]></title><description><![CDATA[Text classification and machine learning with Javascript: Natural.js, Brain.js, TensorFlow.js.]]></description><link>https://metacognitive.me/how-to-do-text-classification-with-javascript/</link><guid isPermaLink="false">615328d04e990d0001c292ff</guid><category><![CDATA[javascript]]></category><category><![CDATA[programming]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 21 Nov 2021 10:55:35 GMT</pubDate><content:encoded><![CDATA[<p>A few months ago I tried to find information about doing some natural language processing with Javascript. There was not much of it. Most of the time, I stumbled upon tutorials on how to do so in Python. I&apos;m writing this article in the hope to help someone do the same with Javascript. At least, try to. Javascript ecosystem is large, yet machine learning is mostly done in Python. For some custom(complicated) cases, you maybe will decide not to use Javascript. I&apos;ll explain why you may do so.</p><p>I want to point out that I&apos;m not a machine learning engineer. I&apos;ll cover simple cases with no deep explanations of the underlying algorithms.</p><p>There are manageable cases when you may try JS packages that do the classification. In some others, and if you understand ML concepts, you may create custom models using TensorFlow.js.</p><p>My case seemed simple. I wanted to classify potential business problems(opportunities) for my <a href="https://olwi.xyz/?ref=metacognitive.me">Reddit advanced search tool</a>. I&apos;ll tell you soon how it went, once we cover the tools. Let&apos;s start with simple cases.</p><h2 id="naturaljs"><a href="https://naturalnode.github.io/?ref=metacognitive.me">Natural.js</a></h2><p>It&apos;s a package for Node.js that helps deal with natural language. It has many useful built-in helpers. For example, it can do a sentiment analysis from the box and without any setup. Let&apos;s install it:</p><pre><code class="language-sh">$ npm install --save natural</code></pre><blockquote>Easy sentiment analysis, right?</blockquote><pre><code class="language-javascript">const { SentimentAnalyzer, PorterStemmer } = require(&apos;natural&apos;);

const analyzer = new SentimentAnalyzer(&quot;English&quot;, PorterStemmer, &quot;afinn&quot;);
const result = analyzer.getSentiment([&quot;I&quot;, &quot;love&quot;, &quot;cakes&quot;]);

console.log(result); // 0.66
// values greater than 0 indicate a positive sentiment
// values smaller than 0 indicate a negative sentiment</code></pre><p>Yes, it&apos;s easy. <code>PorterStemmer</code> is a transformation function that converts words to theirs <a href="https://searchenterpriseai.techtarget.com/definition/stemming?ref=metacognitive.me#:~:text=Stemming%20is%20the%20process%20of,natural%20language%20processing%20(NLP).&amp;text=When%20a%20new%20word%20is,can%20present%20new%20research%20opportunities.">stems</a>. To their original form, simply put. We pass an array of words to <code>getSentiment</code> function, but we may use built-in <a href="https://naturalnode.github.io/natural/Tokenizers.html?ref=metacognitive.me">tokenizers</a> to do so automatically.</p><blockquote>Where is a promised text classification, <s>Lebowski</s>?</blockquote><p>I wanted to show the simplicity of usage, without even training some complex algorithms. Now let&apos;s see how it deals with text classification.</p><p>The package supports the <a href="http://en.wikipedia.org/wiki/Naive_Bayes_classifier?ref=metacognitive.me">Naive Bayes classifier</a> and <a href="http://en.wikipedia.org/wiki/Logistic_regression?ref=metacognitive.me">logistic regression</a>. They work differently, so try each one and see what fits your case better.</p><pre><code class="language-javascript">const { BayesClassifier } = require(&apos;natural&apos;);

const classifier = new BayesClassifier();

classifier.addDocument(&apos;buy our limited offer&apos;, &apos;spam&apos;);
classifier.addDocument(&apos;grow your audience with us&apos;, &apos;spam&apos;);
classifier.addDocument(&apos;our company provides a great deal&apos;, &apos;spam&apos;);
classifier.addDocument(&apos;I like to read books and watch movies&apos;, &apos;regular&apos;);
classifier.addDocument(&apos;My friend likes to walk near the mall&apos;, &apos;regular&apos;);
classifier.addDocument(&apos;Pizza was awesome yesterday&apos;, &apos;regular&apos;);

classifier.train();

console.log(classifier.classify(&apos;we would like to propose our offer&apos;)); // spam
console.log(classifier.classify(&apos;I\&apos;m feeling tired and want to watch something&apos;)); // regular</code></pre><p>Usually, you need a lot of examples. With a small amount of them, any method you choose(this library or a custom model) will output not the best results. Pay vast attention to your data, it&apos;s a major element in text classification. Maybe Natural.js will cover your case and you can finish the reading. If you need a more custom setup(if you think so, review your data again), read further.</p><h2 id="brainjs"><a href="https://github.com/BrainJS/brain.js?ref=metacognitive.me#brainjs">Brain.js</a></h2><p>This library helps you to build neural networks. Natural works with more simple algorithms. Neural networks are many algorithms that work as one, simply saying. They reflect the behavior of biological neurons that are great at <strong>recognizing patterns</strong>.</p><p>Now you can customize the algorithms. Specifically, you can build your own neural networks architectures - specify how many layers you need, activation functions, learning rate, and other parameters. This is where it gets trickier. There are no &quot;gold rules&quot; at building neural net architectures. The process greatly varies from a use case. We may use the default options in the cases like defining a color from RGB params:</p><pre><code class="language-javascript">const brain = require(&apos;brain.js&apos;);

// Build a default neural net
const net = new brain.NeuralNetwork();

// This is where we specify our data: input and the result(output)
// the data is an array of examples(input and output).
// And then the network trains on them.
net.train([
  // we tell it: if &quot;r&quot; from RGB scheme is 0.03, and &quot;g&quot; is 0.7
  // then the output should be &quot;black&quot;
  { input: { r: 0.03, g: 0.7 }, output: { black: 1 } },
    
  // notice that we skip some values from RGB, in this case we
  // missed &quot;g&quot;
  { input: { r: 0.16, b: 0.2 }, output: { white: 1 } },
    
  // here we point out all the RGB values
  { input: { r: 0.5, g: 0.5, b: 1.0 }, output: { white: 1 } },
]);

// This is how we run the network to get a prediction
const output = net.run({ r: 1, g: 0.4, b: 0 }); // { white: 0.81, black: 0.18 }</code></pre><p>It&apos;s a powerful way to build such a network without understanding the underlying concepts, data normalization. Just point out a few examples and you&apos;re done. However, in reality, you need more examples for better precision.</p><h3 id="transforming-text-to-numeric-vectors">Transforming text to numeric vectors</h3><p>Now we&apos;re talking about data normalization. For text classification, we need to transform the text into numeric values because Brain.js doesn&apos;t have <em>custom</em> data transformation flow for regular neural nets, yet you may try it for <a href="https://github.com/BrainJS/brain.js/blob/master/examples/javascript/childrens-book.js?ref=metacognitive.me">LSTM, for example</a>. Why convert strings to numbers? Neural networks training is a process of many math calculations, which require numbers, not other data types. You might use raw strings, they would be converted to their numeric representations, however, not to the format you(and the algorithms) probably want. What these &quot;algorithms&quot; do is figure out the patterns of the input to build a function that can calculate the output based on the input. So it&apos;s important how you do this transformation.</p><p><strong>The first option</strong>, you may propose, is to convert every character to their numeric order in the alphabet. For instance, &quot;a&quot; is 0, &quot;b&quot; is 1, &quot;c&quot; is 2 and so on. Thus, we will have 26 possible values for every character. It means, the word &quot;car&quot; can be represented as <code>[2, 0, 17]</code>. In this case, if your task is to classify text with many sentences, your input dimensionality becomes 2D, which isn&apos;t fine, because input should be 1D. We might flatten the 2D array, but then it gets delicate. It means, the text like this &quot;I want apples&quot; converts to &quot;iwantapples&quot;(and then to a numeric 1D vector). It may be fine, yet we&apos;re not sure the network recognizes a pattern there to classify correctly.</p><p>The big problem with such an approach is that every character is seen by a net <strong>independently</strong>, not as a word. Thus, &quot;car&quot; is <code>[2, 0, 17]</code>, and the resulting function(a set of functions that process the input) may &quot;think&quot; it&apos;s almost the same as &quot;bar&quot; - <code>[1, 0, 17]</code>. It doesn&apos;t think, of course, but the pattern says so. Thus, it&apos;s difficult to retrieve any context, we just perceive every character independently.</p><p><strong>The second option</strong> is to do the same, but for words. In reality, we retrieve context mainly from words, not by characters separately. Such an approach also simplifies the calculations: we don&apos;t need to convert 2D input into 1D and a neural network gets fewer numbers to process, which is a performance boost. To convert words to a number, we should figure out what numbers to assign to them. You may create examples of text you will be training on, tokenize it into words(omitting punctuation because it doesn&apos;t add context), make a dictionary of these words, where every one of them gets an ordering number. It&apos;s like adding words to a <code>Set</code> and their number is an order in which they appear in it. E.g. if I have a text &quot;I want apples.&quot;, my dictionary is <code>[&quot;i&quot;, &quot;want&quot;, &quot;apples&quot;]</code>, where the word &quot;I&quot; will be assigned to 0, &quot;want&quot; to 1, and &quot;apples&quot; to 2.</p><p>We may optimize this approach by also <a href="https://en.wikipedia.org/wiki/Stemming?ref=metacognitive.me">stemming</a> words to their root form, e.g. &quot;apples&quot; become &quot;apple&quot; because the net doesn&apos;t need to know(except the use cases where your task is to classify singular or plural forms) whether it&apos;s a singular or a plural form, it&apos;s better to have a numeric representation for a word abstraction - apples(&quot;apple&quot;, &quot;apples&quot;).</p><p>It&apos;s the most simple method to vectorize text. Though, it also has problems. In cases, where you need your neural net to &quot;figure out&quot; the context by looking for a set of words, it&apos;s difficult because in the example above, &quot;I&quot; and &quot;want&quot; are placed as neighbors (0 and 1 accordingly), but they aren&apos;t similar, they mean different things. For example, &quot;car&quot; and &quot;automobile&quot; mean the same but can be represented as 14 and 8233 with this approach. Thus, your model may derive different results based on whether your examples have synonyms.</p><p><strong>The third option</strong> is to use pre-generated vectors. The ones that were generated by processing a lot of texts and deriving which words are similar, and which ones are different. Thus, for example, a vector for &quot;car&quot; may be <code>[0.45, 0.78, 0.97, 0.34, 0.87]</code>, and for &quot;automobile&quot; it may be <code>[0.49, 0.73, 0.98, 0.33, 0.88]</code>. As you noticed, they&apos;re not single numbers, but vectors for every word. Thus, you get a 2D array for the whole text. I&apos;d suggest you go with pre-generated vectors such as <a href="https://nlp.stanford.edu/projects/glove/?ref=metacognitive.me">GloVe</a>.</p><h3 id="getting-back-to-brainjs">Getting back to Brain.js</h3><p>Now you know how to convert strings to vectors, you can use the library to help you. It has various types of <a href="https://github.com/BrainJS/brain.js?ref=metacognitive.me#neural-network-types">pre-defined neural networks</a>. The one we saw before is the <a href="https://en.wikipedia.org/wiki/Feedforward_neural_network?ref=metacognitive.me">feedforward neural net</a> with backpropagation. This is where things get delicate too, again - in choosing the right network type. A feedforward net is a simple one that takes an input, does some calculations-transformations, and returns the results. It sees every input independently, it doesn&apos;t have a memory. It means it can&apos;t derive context from multiple words. If your task requires so, you better choose recurring neural nets such as <a href="https://en.wikipedia.org/wiki/Recurrent_neural_network?ref=metacognitive.me">RNN</a> or <a href="https://en.wikipedia.org/wiki/Long_short-term_memory?ref=metacognitive.me">LSTM</a>(<a href="https://github.com/BrainJS/brain.js?ref=metacognitive.me#neural-network-types">see the Brain.js details on them</a>).</p><h2 id="tensorflowjs">TensorFlow.js</h2><p>This is a path where you decided you require more custom setup. This is a Javascript version of a powerful machine learning framework for Python. It allows you to build any models or use already created ones by the community. However, they don&apos;t have much. And their functionality of converting Python models to JS ones and vice versa doesn&apos;t work well enough yet.</p><p>The code may look like this:</p><pre><code class="language-javascript">const tf = require(&apos;@tensorflow/tfjs-node&apos;);

const data = {
    // assume we already have vector representations of the text examples
    inputs: vectorRepresentations,
    // imagine we have such 3 classes
    output: [0, 0, 2, 1, 2, 1, 0, 1],
}

// tensors are TensorFlow vectors to simplify the internal
// processing for the library
const inputTensors = tf.tensor(data.inputs);
const outputTensors = tf.tensor(data.outputs);

const model = tf.sequential();

// 1st layer: a 1d convolutional network
model.add(tf.layers.conv1d({
	filters: 100,
	kernelSize: 3,
	strides: 1,
	activation: &apos;relu&apos;,
	padding: &apos;valid&apos;,
	inputShape: [MAX_WORDS_LENGTH, GLOVE_VECTOR_DIMENSIONS],
}));

// transform 2d input into 1d
model.add(tf.layers.globalMaxPool1d({}));

// the final layer with one neuron
model.add(tf.layers.dense({ units: 1, activation: &apos;sigmoid&apos; }));

// here are some tuning, read in the TF docs for more
model.compile({
    optimizer: tf.train.adam(LEARNING_RATE),
    loss: &apos;binaryCrossentropy&apos;,
    metrics: [&apos;accuracy&apos;],
});

// print the model architecture
model.summary();

// train the model
await model.fit(inputs, answers, {
    // the default size, how many inputs to process per time
    batchSize: 32,
    
    // how many times to &quot;process&quot;, simply put
    epochs: EPOCHS,
    
    // the fraction of the inputs to be in the validation set:
    // the set, which isn&apos;t trained on, but participates in calculating
    // the model&apos;s metrics such as accuracy and loss
    validationSplit: 0.2,
    
    // shuffle inputs randomly to have a different starting seed every time
    shuffle: true,
});

// save the model to load in the future and run classifications
await model.save(&apos;file://./data/models/myFirstModel&apos;);</code></pre><p>Here we built a model to do text classification for 3 pseudo-classes(0, 1, 2). We used a 1d convolutional network for the 1st layer. TensorFlow allows you to specify any amount of layers you want, set training epochs, validation split, choose different ML algorithms, activation functions for every layer, and many other options. Though, we need to know how to build ML models. If we don&apos;t, we may add anything, tune parameters, and won&apos;t receive good results.</p><p>I went to TensorFlow.js for more customizability but spent months on adjusting a lot of stuff and didn&apos;t get great results. I learned many things along the way, but still, I&apos;m not an ML engineer, so it&apos;s better(faster) to use models built by professionals and not create your own wheel. But if it&apos;s for fun, why not! Then, let&apos;s understand the code I wrote.</p><p>I chose this architecture due to its performance: convolutional networks are faster for text processing and also they process input in a kind of context. They&apos;re mainly used in computer vision because they process input matrices, not just 1d arrays of numbers. So, for example, if you get an image, 100x100 px, a convolutional network may process 5x5 pixel window per time. Thus, some noise and details can be classified correctly. For text, it&apos;s almost the same - we need to take multiple words in a batch and don&apos;t process them independently. Thus, simplifying a model&apos;s job in recognizing patterns.</p><p>I chose GloVe vector representations, so my input data was a 2D array of numbers, where every subarray was a word representation. The <code>kernelSize</code> parameter in a convolutional network is responsible for the &quot;sliding window&quot; - those 5x5 pixels to process per time. In my case, I specified <code>kernelSize</code> to <code>3</code>. It means the network processes 3 vectors(3 words) per time. The <code>filters</code> param tells how many neurons you want. <code>strides</code> means how many &quot;steps&quot; to take per once when moving the &quot;sliding window&quot;. For example, for the text &quot;I want to eat apples tomorrow&quot;, the first batch is <code>[&quot;i&quot;, &quot;want&quot;, &quot;to&quot;]</code>, the second batch is <code>[&quot;want&quot;, &quot;to&quot;, &quot;eat&quot;]</code>, the 3rd is <code>[&quot;to&quot;, &quot;eat&quot;, &quot;apples&quot;]</code> , and so on. So, it moves by one word per time to the right.</p><h2 id="general-learnings">General learnings</h2><p>I spent some time with Natural.js, then Brain.js, and TensorFlow. I went to the last one for custom configuration and spent a lot of time building custom models. It&apos;d be better to use an already built model for text classification. However, I didn&apos;t find a good way to transform Python TensorFlow models into Javascript ones, that&apos;s why in the end I switched to a Python setup with HuggingFace. But my task wasn&apos;t so straightforward. I wanted to classify potential people&apos;s problems and pains: where someone hates using something or complaining about things.</p><p>There were some things I learned while building custom models with tensorFlow.js I wish I knew earlier. Write your experiments in a logbook. You&apos;ll be building various models with various hyperparameters and it becomes difficult to recall what worked well for you and what didn&apos;t. Also, don&apos;t forget about the test set(assuming you have a validation one too).</p><p>There is a lot of things to mention about building ML models. Here are some I highlighted in my logbook. I hope it saves someone&apos;s time in narrowing the search when troubleshooting.</p><p><strong>When to stop training</strong>. If a validation loss starts increasing. It should be similar to but slightly higher than a training loss. If it&apos;s lower or almost equal to a training loss, a model requires more training. If training loss is reducing without an increase in validation loss then again keep doing more training.</p><p><strong>You have 1.0 accuracy</strong>. In most cases, if you have 100% train accuracy, you&apos;ve probably greatly overfitted. Or, a model recognized a &quot;false&quot; pattern in your data.</p><p><strong><a href="https://en.wikipedia.org/wiki/Overfitting?ref=metacognitive.me">Overfitting</a></strong>? A big topic. Here&apos;s some reference(not mine, but I can&apos;t find the source):</p><pre><code>If validation loss &gt;&gt; training loss you can call it overfitting.
If validation loss  &gt; training loss you can call it some overfitting.
If validation loss  &lt; training loss you can call it some underfitting.
If validation loss &lt;&lt; training loss you can call it underfitting.</code></pre><p>A higher than training loss validation loss means overfitting, a model learned the patterns that happen to be true in training data, but they&apos;re not in real-world data.</p><p>If you have a too powerful model(the one that has too many parameters and not much training data, see <code>model.summary()</code>), review it again and simplify, because for me some of the models memorized the data, and thus, have greatly overfitted.</p><blockquote>Another evidence of overfitting is that your loss is increasing, Loss is measured more precisely, it&apos;s more sensitive to the noisy prediction if it&apos;s not squashed by sigmoids/thresholds (which seems to be your case for the Loss itself). Intuitively, you can imagine a situation when the network is too sure about output (when it&apos;s wrong), so it gives a value far away from the threshold in case of random misclassification.</blockquote><p><strong>Accuracy or loss fluctuates</strong>.</p><blockquote>some portion of examples is classified <strong>randomly</strong>, which produces fluctuations, as the number of correct random guesses always fluctuates (imagine accuracy when coin should always return &quot;heads&quot;). Basically, sensitivity to noise (when classification produces random results) is a common definition of <strong>overfitting</strong></blockquote><blockquote>The training loss at each epoch is <em>usually</em> computed on <strong>the entire training set</strong>. &#xA0;The validation loss at each epoch is <em>usually</em> computed on <strong>one minibatch of the validation set</strong>, so it is normal for it to be noisier.</blockquote><p>Take care of your batch size. Sometimes it needs to be adjusted:</p><blockquote>Smaller batch sizes give noisy gradients but they converge faster because per epoch you have more updates. If your batch size is 1 you will have N updates per epoch. If it is N, you will only have 1 update per epoch. On the other hand, larger batch sizes give a more informative gradient but they convergence slower and increase computational complexity.</blockquote><p></p>]]></content:encoded></item><item><title><![CDATA[Typescript tutorial for Javascript developers]]></title><description><![CDATA[Learn Typescript to write maintainable code. Javascript is fast to prototype, but that's not all we want. Let's learn how to write type-safe code.]]></description><link>https://metacognitive.me/typescript-tutorial-for-javascript-developers/</link><guid isPermaLink="false">6183ad0d643beb0001e615ce</guid><category><![CDATA[programming]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Thu, 04 Nov 2021 17:36:15 GMT</pubDate><media:content url="https://metacognitive.me/content/images/2021/11/typescript-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://metacognitive.me/content/images/2021/11/typescript-1.png" alt="Typescript tutorial for Javascript developers"><p>I wrote an <a href="https://metacognitive.me/reasons-to-use-typescript/">article</a> on why to use Typescript if you&apos;re still in doubt about whether to use it in your projects. In short, Typescript allows you to write maintainable code. Javascript works well for prototyping but becomes frustrating when you return to a project again. Suddenly, you see blocks of code where you can&apos;t understand what kind of data passes there.</p><p>In this article, I want to introduce you to Typescript while playing with code. Thus, you see it in action and don&apos;t overflow with an unnecessary theory. I recommend playing with the code you&apos;ll meet here in <a href="https://www.typescriptlang.org/play?ref=metacognitive.me">Typescript Playground</a>.</p><p>Imagine you want to count items, which have the field <code>meta</code> that contains the field <code>countable</code> set to <code>true</code>, in an array. If an item doesn&apos;t have <code>meta.countable</code>, we don&apos;t count it.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">function getAmount (arr: any[]) {
    return arr.filter(item =&gt; item.meta.countable === true).length;
}</code></pre><figcaption>Typescript array type with anything in there</figcaption></figure><!--kg-card-begin: html--><details>
    <summary>Why are you using <code>any</code>? It&apos;s not OK!</summary>
    It&apos;s for an example. Don&apos;t use <code>any</code> in such cases. Read more about it later in the article.
</details><!--kg-card-end: html--><p>We see the <code>any</code> keyword near the <code>arr</code> argument, that&apos;s new to us! I guess you already know what it is. This way we tell TS that <code>arr</code> is of <code>any[]</code> type. It literally means any Javascript type in an array. I.e. <code>arr</code> is an array and every item of it is of type <code>any</code>. It safe you from writing such code:</p><pre><code class="language-typescript">// Argument of type &apos;string&apos; is not assignable to parameter of type &apos;any[]&apos;
getAmount(&apos;string&apos;);

// Argument of type &apos;number&apos; is not assignable to parameter of type &apos;any[]&apos;
getAmount(29);</code></pre><p>The compiler ensures you should pass exactly what you&apos;ve pointed out as an <code>arr</code> argument for the <code>getAmount</code> function. What if you need to pass several types, for example, an array and a string? And if <code>arr</code> is a string, then return 0. A weird case, but imagine you work on a legacy system that uses this function in many places, so somewhen you may get a string.</p><pre><code class="language-typescript">function getAmount (arr: any[] | string) {
    if (typeof arr === &apos;string&apos;) {
        return 0;
    }
    return arr.filter(item =&gt; item.meta.countable === true).length;
}

getAmount(&apos;55&apos;); // now it&apos;s possible to pass a string
getAmount([{ meta: {countable: true} }]);</code></pre><p><code>|</code> means &quot;or&quot;. Thus, <code>arr</code> can be an array of anything(<code>any[]</code>) or a string. Refer to <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html?ref=metacognitive.me">this page</a> for more everyday types in Typescript.</p><p>The compiler is smart enough to even infer a return type of <code>getAmount</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">// function getAmount(arr: any[] | string): number
function getAmount (arr: any[] | string) {
    // because we always return a number
    // 0 or arr.length(filtered
}</code></pre><figcaption>Type inferring for a function that always returns a number</figcaption></figure><p>Sometimes, Typescript can&apos;t infer a type because of ambiguity. Usually, it&apos;s a <a href="https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md?ref=metacognitive.me">good practice</a> to explicitly indicate a return type of a function.</p><pre><code class="language-typescript">function getAmount(arr: any[] | string): number {
	// ...
}

// Syntax:            don&apos;t forget this
//							 |
function myFunction(arg: any): boolean {/* function body */}
//								  |
//					a type this function returns</code></pre><p>Now you know how to write functions and point arguments and return types! In most cases, that&apos;s what you need. All other code is still Javascript. With more types. However, let&apos;s dive deeper and highlight more complicated cases and what things to avoid.</p><p>Someone may pass anything in an array:</p><pre><code class="language-typescript">function getAmount(arr: any[]): number {
	// ...
}

getAmount([5, &quot;string&quot;, {}, () =&gt; {}]); // no error</code></pre><p>That&apos;s not what we expect. TS works well in this case, we specified <code>any[]</code>, so what problems? <strong>Don&apos;t use <code>any</code> if there&apos;s no real need for it</strong>. It&apos;s easier to pass <code>any</code> than describing an advanced type, but that&apos;s what Typescript is for. Don&apos;t shoot yourself in a foot in the future. </p><h2 id="typescript-objects">Typescript objects</h2><p>We may want to replace <code>any[]</code> with <code>object[]</code> and it would work as we pass objects there, right? Correct, but an <code>null</code> and a function are also objects. It&apos;s not what we expect either. <strong>Don&apos;t use <code>object</code>, try to narrow types</strong>.</p><pre><code class="language-typescript">interface Item {
    meta?: {
        countable?: boolean;
    }
}

function getAmount (arr: Item[]) {
    return arr.filter(item =&gt; item.meta?.countable === true).length;
}

getAmount([
    {}, {meta: {countable: true}}
]); // 1</code></pre><p>Now it works as expected. We specified a separate <code>interface</code> for a possible array element. Interfaces and types allow you to create your own types using basic Typescript types. Some examples:</p><pre><code class="language-typescript">// is also called &quot;type alias&quot;
type Hash = string;

// interface are &quot;object&quot; types and allow us
// to specify an object immediately
interface Person {
    name: string;
    isOkay: boolean;
};
// it&apos;s the same as using a type alias
type Person = {
    name: string;
    isOkay: boolean;
};</code></pre><h2 id="types-and-interfaces">Types and interfaces</h2><p>Let&apos;s start implementing a booking tickets service to dive deeper into these types and interfaces. We want to have the possibility to book a ticket for a person.</p><pre><code class="language-typescript">type Person = {
    name: string;
}

type Ticket = {
    from: string;
    to: string;
    person: Person;
}

function bookTicket (from: string, to: string, person: Person): Ticket {
    // some procesing
    return {
        from,
        to,
        person,
    };
}

bookTicket(&apos;Paris&apos;, &apos;Mars&apos;, {name: &apos;Joey&apos;});</code></pre><p>The code seems okay. However, we can book a ticket to Mars using the function, but we don&apos;t fly to Mars yet. What we may rectify in our code to adjust to reality? We could add validation for <code>from</code> and <code>to</code> fields inside the function, but we also can do this with TypeScript. For example, we could list possible locations we&apos;re flying to and from.</p><pre><code class="language-typescript">type AvailableLocation = &apos;Paris&apos; | &apos;Moon&apos; | &apos;London&apos;;
type Person = {
    name: string;
}
type Ticket = {
    from: AvailableLocation;
    to: AvailableLocation;
    person: Person;
}

function bookTicket (from: AvailableLocation, to: AvailableLocation, person: Person): Ticket {
    // some procesing
    return {
        from,
        to,
        person,
    };
}

// Error: Argument of type &apos;&quot;Mars&quot;&apos; is not assignable to parameter of type &apos;AvailableLocation&apos;
bookTicket(&apos;Paris&apos;, &apos;Mars&apos;, {name: &apos;Joey&apos;});</code></pre><p>We narrowed possible options for locations. Thus, eliminated cases when we can write code that calls the function with invalid locations like &quot;Mars&quot; or &quot;Andromeda Galaxy&quot;. We listed multiple allowed options via &quot;or&quot; operator - <code>Paris | Moon</code>. We might be using enums for this purpose too:</p><pre><code class="language-typescript">enum Locations {
	Paris,
    Moon,
    London,
}

type Ticket {
	from: Locations;
    to: Locations;
    person: Person;
}

bookTicket(Locations.Paris, Locations.Moon, {name: &apos;Joey&apos;});</code></pre><p>There are differences in using types and enums, I won&apos;t cover them this time, but you may refer to <a href="https://stackoverflow.com/questions/40275832/typescript-has-unions-so-are-enums-redundant?ref=metacognitive.me">this page</a> for the details.</p><p>As you might notice, somewhere I used <code>interface</code> for an object type and then declared another one via <code>type</code>. Use what you like more for such cases or use based on your project code guidelines. For more information about the difference, <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html?ref=metacognitive.me#differences-between-type-aliases-and-interfaces">read here</a>.</p><h2 id="using-record-to-type-objects">Using <code>Record</code> to type objects</h2><p>Sometimes you have generic objects, where a key is always <code>string</code>(and it&apos;s <strong>always</strong> a string, if you want to use other values, use <code>Map</code> instead) and a value is always <code>string</code> too. In this case, you may define its type as follows:</p><pre><code class="language-typescript">type SomeObject = {
	[key: string]: string;
}

const o: SomeObject = {key: &apos;string value&apos;}</code></pre><p>There&apos;s another way to do the same using <code>Record&lt;keyType, valueType&gt;</code>:</p><pre><code class="language-typescript">type SomeObject = Record&lt;string, string&gt;;
// it means an object with string values, e.g. {who: &quot;me&quot;}</code></pre><p>It&apos;s something new here: <a href="https://www.typescriptlang.org/docs/handbook/2/generics.html?ref=metacognitive.me">generics</a>, computed types to re-use the existing ones. Let&apos;s re-create the <code>Record</code> type:</p><pre><code class="language-typescript">type Record&lt;Key, Value&gt; = {
	[key: Key]: Value;
}</code></pre><p>Thus, if we want to create an object, we don&apos;t need to write such signatures every time. So, an object with number values is as simple as:</p><pre><code class="language-typescript">const obj: Record&lt;string, number&gt; = {level: 40, count: 10};</code></pre><p>We may need more complex types, for example, to represent the state of our API requests. Imagine you have a global state where you put all the API data. Thus, you know where to show a loader, when to remove it, and to show relevant data.</p><pre><code class="language-typescript">type StateItem = {
	isLoading: boolean;
    response: Record&lt;string, unknown&gt; | null;
};
type State = Record&lt;string, StateItem&gt;;

const state: State = {
	getInvoices: {
    	isLoading: false,
        response: null,
    },
};</code></pre><p>Do you see the inconveniences here? We might narrow a type for <code>state</code> keys: it&apos;s a string, but we want to be sure we put valid API request names there. The second thing is the <code>unknown</code> I put for the <code>response</code>(an object with <code>unknown</code> values), yet it&apos;s still better than <code>any</code>, because you should determine its type before any processing.</p><pre><code class="language-typescript">type APIRequest = &apos;getInvoices&apos; | &apos;getUsers&apos; | &apos;getActions&apos;;
type BaseResponse = {isOk: boolean};
type GetInvoicesResponse = BaseResponse &amp; {data: string[]};
type GetUsersResponse = BaseResponse &amp; {data: Record&lt;string, string&gt;[]};
type GetActionsResponse = BaseResponse &amp; {data: string[]};
type StateItem = {
	isLoading: boolean;
    response?: GetInvoicesResponse | GetUsersResponse | GetActionsResponse;
};
type State = Record&lt;APIRequest, StateItem&gt;;

// Type is missing the following properties from type &apos;State&apos;: getUsers, getActions
const state: State = {
	getInvoices: {
    	isLoading: false,
        response: {isOk: false, data: [&apos;item&apos;]},
    },
};</code></pre><p>Let&apos;s disassemble some pieces of the above:</p><ol><li><code>APIRequest</code> type is a list of possible requests names. Narrowing types are for the better. See the error comment near the <code>state</code> const? Typescript requires you to specify all the requests.</li><li><code>BaseResponse</code> represents a default and basic response, we always know that we receive <code>{isOk: true | false}</code>. Thus, we may prevent code duplication and re-use the type.</li><li>We made a type for every request possible.</li></ol><p>While it&apos;s better than it was before, but we could do even better. The problem with these types is that <code>response</code> is too generic: we may have &#xA0;<code>GetInvoicesResponse | GetUsersResponse | GetActionsResponse</code>. If there are more requests, there is more ambiguity. Let&apos;s employ generics to reduce duplicate code.</p><pre><code class="language-typescript">type BaseResponse = {isOk: boolean;};
type GetInvoicesResponse = BaseResponse &amp; {data: string[]};
type GetUsersResponse = BaseResponse &amp; {data: Record&lt;string, string&gt;[]};
type GetActionsResponse = BaseResponse &amp; {data: string[]};
type StateItem&lt;Response&gt; = {
	isLoading: boolean;
    response?: Response;
};
type State = {
    getInvoices: StateItem&lt;GetInvoicesResponse&gt;;
    getUsers: StateItem&lt;GetUsersResponse&gt;;
    getActions: StateItem&lt;GetActionsResponse&gt;;
};</code></pre><p>It&apos;s more readable and safe to specify every request separately, thus there&apos;s no need to check <code>state.getInvoices.response</code> on every response type possible.</p><h4 id="summary-of-the-above">Summary of the above</h4><ol><li>Don&apos;t use <code>any</code> type. Prefer <code>unknown</code>. In such a way, you should be checking the type before doing any further operations with it.</li></ol><pre><code class="language-typescript">type Obj = Record&lt;string, unknown&gt;;

const o: Obj = {a: &apos;s&apos;};
o.a.toString(); // Object is of type &apos;unknown&apos;</code></pre><p>2. Prefer <code>Record&lt;string, T&gt;</code> over <code>object</code>, which can be <code>null</code>, any kind of object, a function. &#xA0;<code>T</code> refers to a generic type.</p><p>3. Narrow types where possible. If it&apos;s a few strings you use often, probably they can be combined in one type(see the example about API requests state).</p><pre><code class="language-typescript">type GoogleEmail = `${string}@gmail.com`; // yet it&apos;s still a string

const email1: GoogleEmail = &apos;my@gmail.com&apos;;

// Type &apos;&quot;my@example.com&quot;&apos; is not assignable to type &apos;`${string}@gmail.com`&apos;
const email2: GoogleEmail = &apos;my@example.com&apos;;</code></pre><p>It&apos;s a new thing here: template types. Any email is a string, but if you can narrow a type, then why not(it&apos;s an example, sometimes it&apos;s an overhead).</p><h2 id="other-use-cases-you-may-encounter">Other use cases you may encounter</h2><h4 id="generics-in-functions">Generics in functions</h4><p>You saw generics, it&apos;s a powerful way to re-use the code, the other examples include functions:</p><pre><code class="language-typescript">type Response&lt;T&gt; = {
    isOk: boolean;
    statusCode: number;
    data: T;
}

async function callAPI&lt;T&gt; (route: string, method: string, body: unknown): Response&lt;T&gt; {
	// it&apos;s a pseudo-fetch, the real API differs
    const response = await fetch(route, method, body);
    // some manipulations with data

    return response;
}</code></pre><p>So, the syntax is <code>function &lt;name&gt;:&lt;type&gt; (args) {}</code>. You may use <code>T</code>(or other names for a generic, or, a few of them) inside a function too.</p><h4 id="specifying-types-for-readability">Specifying types for readability</h4><p>Imagine you work a lot with variables that are strings, but it&apos;s hard to understand which is what type exactly. For example, when dealing with OAuth tokens.</p><pre><code class="language-typescript">type AccessToken = string;
type IdToken = string;</code></pre><p>Both tokens are JWT strings, but sometimes it&apos;s useful to understand the context.</p><pre><code class="language-typescript">function callProviderEndpoint (token: AccessToken) {}
function decodeUserInfo (token: IdToken) {}</code></pre><p>However, you could name functions or function arguments well too: <code>token</code> -&gt; <code>accessToken</code>.</p><h4 id="type-assertions">Type assertions</h4><p>There are cases when you need to cast(transform to for the compiler) a type to another one. For example, when a library method returns <code>object</code> and you know it&apos;s not useful, you need a more narrow type. You may write <code>const result = libResult as Record&lt;string, number&gt;</code>. <code><strong>as</strong></code> allows you to transform a type into a desired one(if it&apos;s possible). The easiest cast is for <code>any</code> types: the compiler doesn&apos;t know anything about a value, so it trusts you. There are cases when you&apos;d want to cast something into <code>any</code> for compatibility, but often it&apos;s laziness to write correct types. Invest type into writing good(corresponding to reality) types.</p><p>You may also do casts like follows:</p><pre><code class="language-typescript">const response = &lt;MyCorrectType&gt;libResponse;
// the same as
const result = libResponse as MyCorrectType;</code></pre><h2 id="some-general-questions-one-may-ask">Some general questions one may ask</h2><h4 id="should-i-learn-typescript">Should I learn Typescript?</h4><p>Definitely. I presume you&apos;re already familiar with Javascript, which is simple and fast to prototype. Typescript adds type safety and readability. Your app&apos;s logic becomes more predictable. Read more about <a href="https://metacognitive.me/reasons-to-use-typescript/">reasons to use Typescript</a>.</p><h4 id="how-to-learn-typescript">How to learn Typescript?</h4><p>Read the documentation about the basic types, or this article. Practice the examples by yourself and go code! Install the environment(many frameworks have their already prepared Typescript ecosystem for you to install and use instantly) and make things happen. It&apos;s okay you don&apos;t understand some things or you&apos;re tired of the compiler errors. It&apos;s getting easier.</p><h2 id="summary">Summary</h2><p>I didn&apos;t cover all the things in the article. The mentioned above should be enough to spark your interest and learn the basics that cover most cases you&apos;ll encounter. Learn as you go. The theory might seem to be complicated and boring, it&apos;s okay. Write me on <a href="https://twitter.com/sergchr?ref=metacognitive.me">Twitter</a> if you need more details or help.</p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[How I was learning languages]]></title><description><![CDATA[School language learning classes are boring. To learn a language, one should use it by reading books, talking, listening. Learn by practice.]]></description><link>https://metacognitive.me/how-i-was-learning-languages/</link><guid isPermaLink="false">615be2c94e990d0001c29315</guid><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Wed, 06 Oct 2021 13:49:14 GMT</pubDate><content:encoded><![CDATA[<p>My journey started at school where I was learning English since ... I don&apos;t even remember, I guess since 4th grade? I didn&apos;t have the motivation to learn it. I was finding the lessons boring. We read texts, memorized them, studied grammar. I had a fundamental grasp of the language, but I&apos;d prefer to have more than that after spending so much time on learning.</p><p>At university, I had English lessons for 2 years. No benefits.</p><p>I also was learning Italian for multiple months and reached a basic level. I studied German for 2 months in a free university course. I studied Spanish with Duolingo. I forgot all these languages while having some basic level of understanding.</p><p>A few observations at this moment:</p><ul><li>it&apos;s easy to forget a language you don&apos;t use;</li><li>it&apos;s hard to learn a language if you don&apos;t know its application in real life;</li></ul><p>I started noticing I need English for my first software development job. Software documentation is better written and updated in English. The customers send their requirements in the language as well. I should have googled problems in my native language because I&apos;d get poor answers otherwise. It seemed like decent reasons to start worrying about language learning again. But this time, more productive.</p><h2 id="why-school-language-classes-are-boring">Why school language classes are boring?</h2><p>Reading and memorizing useless information doesn&apos;t make sense, right? That is how it seems to us when we study something at school or university. Without a clear indication of real-world usage, we don&apos;t see a point in learning anything. We could have non-boring classes and teachers, it&apos;d help to encourage interest. Yet I, at least, should understand the real-world application of a thing I try to learn.</p><p>Educational establishments give us the necessary and unnecessary fundamentals. Though they don&apos;t provide information on how, when, and why to use them. They give us many things to memorize, yet they don&apos;t say why we need them.</p><p>Learning a language is difficult and requires a long-term commitment. How to do this effectively when you don&apos;t know the end goal? &quot;It&apos;s important to know a foreign language&quot;. I got this, but where exactly it&apos;s important? Why should I use a foreign language?</p><h2 id="defining-a-goal">Defining a goal</h2><p>So, back to my first IT job. I started using English every day when writing or reading documentation, talking to clients, googling information. I got used to reading content in a foreign language. I started using Reddit, reading books with parallel translation(and without it too), watching movies and series.</p><p>I knew I&apos;ll be using the language more and it&apos;s super applicable to daily life. That&apos;s why learning becomes much easier. Now I&apos;m gonna describe what I&apos;ve tried, what worked for me, and what didn&apos;t - to make this article useful a bit. These tips apply to any language you learn.</p><p><strong>Reading books</strong>. In the language you learn, of course. I was reading mostly programming books at that time. The technical language was simpler to start with. I downloaded English versions of some programming-related books and started reading them. It was unusual at first, I didn&apos;t understand much. Though after reading more and more, it became easier. After some time I tried the same approach with not only technical books. It was more difficult than reading technical information. Fiction books are the hardest because there are many adjectives and phrases people don&apos;t usually use.</p><p>It&apos;s an effective technique to learn how to use and interconnect the words and build sentences. This method also improves your talking(makes words simpler to produce with your mouth) if you read aloud.</p><p><strong>Memorizing words</strong>. When you just started it&apos;s useful to know the fundamental words you can use. It&apos;s worth remembering the top 100 or so of the most used words in the language. Later, the situation becomes complicated. Rote words memorizing doesn&apos;t help much if you don&apos;t use the words you memorize. Don&apos;t forget about the forgetting curve.</p><p>I tried writing words down, making visual associations to every word. It didn&apos;t help in a long-term perspective. The words I remember are the ones I met in some context more than once.</p><p><strong>Talking</strong>. It helps to automate producing phrases in your brain. To improve this skill, you should, guess what, talk. I found multiple language exchange buddies that helped me with English and I helped them with Ukrainian or Russian. Reddit has such subreddits, or you may take a look at various Discord servers.</p><p>This method also means chatting and speaking with people without exchange, just usual talk. Find communities where you can share your opinion and read what other people talk about. Engage in discussions. I used Google Translate when I talked on such platforms at first.</p><p><strong>Listening</strong>. It also means watching videos, listening to podcasts. It helps you get used to how people talk in the language. I tried listening to podcasts, but it doesn&apos;t help much and it&apos;s boring when you don&apos;t understand most parts of it. However, there are podcasts for entry-level practitioners, they may be fun. I tried to watch movies, but it wasn&apos;t a fun experience. It&apos;s active learning, not laying on a bed and enjoying. Yet it&apos;s an effective way to get used to how others pronounce words and connect them into sentences.</p><p><strong>Writing</strong>. It&apos;s an underrated exercise. Join various communities you like and chat with people. And, don&apos;t skip this one, write notes. Create a diary, if you don&apos;t have one. Or, start a blog. Or, a private notes space. Write your thoughts, plans, goals, fairytales somewhere. Writing helps you connect all the aforementioned skills to produce meaningful text. It indicates what words you don&apos;t know, don&apos;t understand, and grammar rules you miss.</p><p><em>If you noticed, I didn&apos;t include a grammar section. You should know its basics, but if you don&apos;t understand some parts, it&apos;s okay. Go practice and you see what are your weak parts in understanding it.</em></p><p>If you don&apos;t know what to write about, I suggest these exercises:</p><ul><li>Write what do you see now, describe everything.</li><li>Pick a random word and write its definition. It can be a noun, adjective, concept, etc. We all know what water, car, and cynism mean, but try to explain their meanings. Then, pick another word from a previous sentence or a random one again and explain it.</li></ul><p>The most important thing to do is to find what interests you and integrate language learning there. You may find watching movies stupid, but you like playing games. Think of how to play games and learn the language. Maybe playing some game with foreign people with whom you can talk? If you like science, you may try watching YouTube videos explaining some aspects of it in the language you learn. Or, find scientific papers and read them. There are many possibilities. Try something and see what do you enjoy.</p>]]></content:encoded></item><item><title><![CDATA[An ultimate guide to memory palaces]]></title><description><![CDATA[<p>Jump to the section <a href="#how-to-create-a-memory-palace">How to create a memory palace</a> if you want to start practicing. Read the <a href="#is-a-memory-palace-for-you">Is a memory palace for you?</a> section to understand whether you need one at all.</p><h2 id="were-bad-at-remembering">We&apos;re bad at remembering</h2><p>The brain isn&apos;t good at storing things but generating</p>]]></description><link>https://metacognitive.me/memory-palace/</link><guid isPermaLink="false">611a8bd3aa639d000182c5e4</guid><category><![CDATA[productivity]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sat, 18 Sep 2021 10:58:26 GMT</pubDate><content:encoded><![CDATA[<p>Jump to the section <a href="#how-to-create-a-memory-palace">How to create a memory palace</a> if you want to start practicing. Read the <a href="#is-a-memory-palace-for-you">Is a memory palace for you?</a> section to understand whether you need one at all.</p><h2 id="were-bad-at-remembering">We&apos;re bad at remembering</h2><p>The brain isn&apos;t good at storing things but generating ideas. It also depends on what sort of things, but we tend to forget them anyway. If something is unique or interesting, it&apos;s simpler to remember, right?</p><p><a href="https://en.wikipedia.org/wiki/Hermann_Ebbinghaus?ref=metacognitive.me">Hermann Ebbinghaus</a> ran memory experiments on himself. He tried to remember nonsense syllables like &quot;ATF&quot;, &quot;UBH&quot;. Then, tested how well he could retain the data he&apos;s learned. Thus, the <a href="https://en.wikipedia.org/wiki/Forgetting_curve?ref=metacognitive.me">forgetting curve</a> appeared.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/forgetting-curve.png" class="kg-image" alt loading="lazy" width="719" height="437" srcset="https://metacognitive.me/content/images/size/w600/2021/09/forgetting-curve.png 600w, https://metacognitive.me/content/images/2021/09/forgetting-curve.png 719w"></figure><p>Some people recollect specific formats of information better. For example, as mentioned, unique or compelling. A well-rhymed poem or a song, which we can&apos;t get rid of sometimes. Maybe you also noticed <strong>it&apos;s simple to remember spatial information</strong>. You know where the nearest shop is and where to find the section with bread. Or, where the things are placed at home. You don&apos;t remember intentionally where your microwave is, do you? Yes, you see it many times and it stuck in your head well. But even the first time you brought it home - you didn&apos;t memorize the place.</p><p>You may try to list formats of information you memorize better. In this article, however, I&apos;ll talk about spatial representation and associations. These two are the building blocks of a memory palace.</p><p>It&apos;s a system to connect information, to memorize and retain it better. It&apos;s not exactly a particular place, because one may have multiple palaces. However, you may have an entry point to access the other places. Without a place, the method downgrades to devising associations. Which is not bad too.</p><p>Simply speaking, it&apos;s a private space in your head where you remember where did you &quot;put&quot; some information. If you have a big palace, you can stroll there looking for what you need or having nostalgia. The good thing is it&apos;s completely yours, no one can see it! Also, it&apos;s not required to be a palace or castle. It can be anything spatial. If you can conceive <a href="https://www.youtube.com/watch?v=zwAD6dRSVyI&amp;ref=metacognitive.me">higher dimensions</a>, you&apos;re welcome to create such a place too.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-4.png" class="kg-image" alt loading="lazy" width="174" height="143"></figure><h2 id="my-story-of-usage">My story of usage</h2><p>I knew about this technique since school while watching The Sherlock series. It showed how neat-looking those palaces are. In university, I ran against the need to pass the tests. I needed to remember completely impractical information, such as names, dates, and terminology. At the time, I didn&apos;t hesitate in my choice of the place to study. I didn&apos;t know what I want to do. So I was down to non-global choices: how to pass the exams.</p><p>The first approach is to cheat by using prepared answers on small papers. There were some exams where students couldn&apos;t use them due to high observability.</p><p>The second approach is rote learning. A few hundred questions and answers on average. Boring and not effective.</p><p>The third approach is learning to understand. It takes more time because I should have to study many related materials to fully understand a topic. And what&apos;s a sense of doing it if I don&apos;t need the information in my life? Impractical.</p><p>The fifth approach was to memorize the exam&apos;s answers but effectively. I love experiments, so I went with this one. I recalled the memory palace method, read more theory and started practicing. It took me a few days to memorize all the answers from one exam. I passed it and got a high grade. Not the highest because I did poor work during the semester, so how can I get it? Though, the exam answers were perfect. But not my knowledge(yet the tests&apos; aim wasn&apos;t to estimate the knowledge).</p><p>I loved the experiment and decided to continue memorizing other than exams information. For example, historical dates, public transportation schedule, information about other people I met(hobbies, sayings, phone numbers), etc.</p><p>6 years later, I don&apos;t use this technique currently. As I know what I want to pursue, I&apos;m more interested in learning rather than storing raw information. It doesn&apos;t mean the method is bad. One should use it either out of curiosity or for specific cases.</p><h2 id="is-a-memory-palace-for-you">Is a memory palace for you?</h2><p>This system has its limitations and use cases. It&apos;s good for memorizing data in a format, which fits you best, in a particular space. Thus, you can &quot;retrieve&quot; the information with ease, mimicking the usual walking in familiar places.</p><p>While the method is prominent to memorize almost anything, <strong>it doesn&apos;t help you understand the data</strong>. You won&apos;t learn by only memorizing. What you do is having raw information. When you retrieve it, you can then explore it better. So, one may store ideas to retrieve them later for further &quot;investigation&quot;. However, you can use usual note-taking for it(as for other raw information too).</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-5.png" class="kg-image" alt loading="lazy" width="869" height="482" srcset="https://metacognitive.me/content/images/size/w600/2021/09/image-5.png 600w, https://metacognitive.me/content/images/2021/09/image-5.png 869w" sizes="(min-width: 720px) 720px"></figure><p>It also isn&apos;t gonna work for you if you don&apos;t want to <strong>spend time every day reviewing what you&apos;ve put in the palace</strong>. The same rules of forgetting apply to memory palaces: you will be forgetting the associations you made. Though, some of them aren&apos;t so easy to forget due to their uniqueness or ridicule. What seems you remember forever, you&apos;re going to forget sooner or later.</p><p>Use cases? If you need to remember any information without its understanding, you can use the approach. When you can courageously use the memory palaces:</p><p>1. Preparing for exams. Teachers still require students to know useless information such as random facts, numbers for the tests. You can courageously use memory palaces.</p><p>2. Speech or presentation. While talking, walk through familiar places to retrieve necessary images to remember what are the next points you want to deliver to the audience. The method is especially good at storing data sequences.</p><p>3. <a href="#numbers">Remembering phone numbers</a>. And other raw information that&apos;s difficult to memorize usually: dates, time, codes.</p><p>And the cases when a memory palace isn&apos;t the best fit:</p><ol><li>You want to understand the information. I.e. <a href="https://metacognitive.me/active-learning/">learning</a>.</li><li>You don&apos;t have time to review the palace regularly. In the beginning, it&apos;ll be every day. We still are humans that forget any kind of information sooner or later.</li><li>You have problems creating visual associations or navigating in space. At least, it&apos;s worth trying to see whether the method works for you. Note that most people don&apos;t have such problems, I&apos;m talking more about such issues as <a href="https://en.wikipedia.org/wiki/Aphantasia?ref=metacognitive.me">aphantasia</a>.</li></ol><h2 id="how-to-create-a-memory-palace">How to create a memory palace</h2><p>One only needs to have a familiar place such as a home to store the associations. It can be even one room, or a road to a shop, work, etc. The most important point is <strong>a place should be familiar to you</strong>. Otherwise, it&apos;s easy to lose stored information due to lost/distorted space.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-7.png" class="kg-image" alt loading="lazy" width="582" height="342"></figure><p>Let me show you a brief example, then we&apos;ll talk about creating palaces for more heavy use.</p><p>Close your eyes and visualize your way to the shop in the head. Now you have storage space. Let&apos;s &quot;put&quot; some information there. For example, we need to memorize a shopping list: bread, milk, batteries, cheese, coca-cola, sugar, 2 carrots, and jelly.</p><p>A regular way would be putting the items as they are in a sequence along your familiar way to a shop. Now you&apos;ll remember you have a shopping list, and maybe even the first few items. However, without linking such raw information, it&apos;s difficult.</p><p>A memory palace way is following. Put a bakery near the beginning of your path to the shop. As soon as you come out home, you see a bakery and a tall guy near it suggesting you free bread. The bread gets a yellow pack of milk out of its pocket and tells you to taste it(yes, it can be absurd, even better). You enjoy milk and feel how its taste becomes so bitter that you drop it. The package broke up into small batteries, which spark. You move away from the bakery and see an enormous piece of cheese. It seems like a building! There is an entrance door. When you open it, you see the small coca-cola-looking creatures that sell sugar on a sugar fair. 2 coca-cola-like creatures swim in 2 sugar pools, where they dissolve. The pools&apos; sugar transforms into carrots! The carrots become bigger and bigger until the moment they&apos;re bigger than the cheese building. Bam! An explosion. All the things became a jelly mass.</p><p>Was it difficult to remember? I presume not. Why? It was <strong>absurd</strong>(see <a href="https://www.sciencedaily.com/releases/2017/06/170619092713.htm?ref=metacognitive.me">Why the peculiar stands out in memory</a>)<strong>, funny, and linked</strong>. The associations you&apos;ve used mean real-world things you wanted to memorize. Plus, all of them were connected with a story. A sequence of visuals is simple to remember.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-8.png" class="kg-image" alt loading="lazy" width="495" height="326"></figure><p>See also:</p><ul><li><a href="http://web.mit.edu/phillipi/www/publications/WhatMakesAnImageMemorable.pdf?ref=metacognitive.me">What makes an image memorable?</a></li></ul><h2 id="associations">Associations</h2><p>You could utilize usual real-world objects without any absurdity. The problem is you get the same representation for an object. If you want to use a &quot;carrot&quot; in multiple stories, you&apos;ll get into a situation of mixing things up. Also, it&apos;s not memorable. You may see carrots every day, but not a talking bread with big pockets.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-9.png" class="kg-image" alt loading="lazy" width="512" height="366"></figure><p><strong>Make ludicrous, absurd associations with the objects you want to remember.</strong></p><p>The second issue you may encounter is it&apos;s simple to have these absurd associations separately, but you forget them in a story. Because of a poor connection. We got a swimming coca-cola, but what&apos;s next? You should devise a story about where it swims, what happens next, how do you see that. It&apos;s even more important to have a <strong>good linkage between images</strong> than an absurd association for an image.</p><p>Summary of what do you need to create the first palace:</p><ul><li>A place to store objects. A road, street, room, other familiar places.</li><li>An <a href="https://en.wikipedia.org/wiki/Associative_memory_(psychology)?ref=metacognitive.me">association</a> with real-world information you want to remember. It may be absurd, but the connection is more important.</li><li>A connection between associations. These should be unique and funny, to better memorize a story.</li></ul><p>I&apos;ll refer to associations with the connections as a <strong>story</strong>.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-10.png" class="kg-image" alt loading="lazy" width="668" height="363" srcset="https://metacognitive.me/content/images/size/w600/2021/09/image-10.png 600w, https://metacognitive.me/content/images/2021/09/image-10.png 668w"></figure><h2 id="palace-of-stories">Palace of stories</h2><p>The palace in &quot;memory palace&quot; stands for many places. A place where you have access to other places and information. So you can have many locations where to put the stories. You may think you need a big location, like a real palace or castle. Thinking about your house, rooms there and all the roads you know, it may seem that it&apos;s not a lot of stories you can place there.</p><p>What you should have is an entrance location where you store all kinds of data: stories or other locations. Otherwise, it&apos;s easy to forget where did you store something. Try to walk through the same path. Entrance point(e.g. your entrance door in a house), then take any direction you want. Later, when you get used to your location, you may walk backward, jump to other places and so.</p><p>What to do with large amounts of data? Some of it can&apos;t be placed inside one familiar space. I used 2 approaches. You may experiment with others and see what works best for you.</p><p><strong>Choose bigger locations.</strong> Thus, you can hold more stories inside one. But still, follow the rule of knowing the location well.</p><p><strong>Resize objects</strong>. If you have to put a house inside a familiar room, you gonna resize either the house or the room. Resizing helps to have fewer locations. However, a new issue appears. It&apos;s harder to have more than &lt;X&gt; objects inside a particular area. Especially, if there are no unique dividers. For example, you decided to store a book summary inside one room on your mouse pad. The mouse pad area is a square where the objects won&apos;t have recognizable transitions. So you need to put more effort into making better associations and their interconnection.</p><p>However, aren&apos;t all the places part of something bigger? A room is in a house, a house is on a street, a street is in a city, and so on. It&apos;s simpler to remember a few objects inside one location. But if you scale a place down to details, you may put more! The difference is in the <strong>place details</strong>. Do you remember a book shelf&apos;s color, size? Your desktop accessories placement? If you don&apos;t, it&apos;s better to not scale things much.</p><h2 id="a-good-memory-palace-properties">A good memory palace properties</h2><p>You can think up a lot of places to accumulate the stories. However, there are preferences I&apos;d suggest taking a look at.</p><ul><li>Good lighting. A place shouldn&apos;t be dark because it eliminates its unique properties. All you see is some more some less dark things. It&apos;s almost the same as using a one-color empty room. Only the strong connections between objects allow you to remember a story. The method though suggests using places as an additional feature to enhance remembering.</li><li>Familiarity. If you don&apos;t remember a space you put things, they can be lost or become distorted.</li><li>No many repeatable objects because you may mix the stories up. Come up with more or less unique features for every object you want to memorize.</li><li>It should be big enough to contain spare stories. In case, you need to alter a story and add or remove objects there.</li><li>It should be categorized. E.g. a separate house for work-related information, a few houses for my personal thoughts, a street with all its shops for book summaries, etc. It&apos;s easy to store everything on the go, but it becomes harder to look for things because they can be everywhere.</li></ul><p>Regarding the last point, you may have a place where you put everything you should remember and categorize it later. It&apos;s useful when you don&apos;t have time or are in doubt where exactly to &quot;put&quot; the objects. Yet don&apos;t forget to clean up the place for temporary stories.</p><h2 id="numbers">Numbers</h2><p>You may be noticed that some data is difficult to memorize. A firm example is numbers. How can you associate numbers? If you&apos;re a football fan, recall the players&apos; numbers on t-shirts. But even then, it becomes hard when players start to repeat.</p><p>Putting a word into a palace is simple because it&apos;s easy to visualize it. Yet it&apos;s more arduous to visualize a definition, concept. Then, one may need a few images. Words are abstracts that represent something you may interact with. Numbers constitute a different concept, they&apos;re more abstract.</p><p>A possible solution is to give every number from 0 to 100 its image association. Thus a phone number becomes a sequence of 5 images that&apos;s easier to memorize. A strategy to pick an association for one number may vary. It&apos;s a topic for another article. You can read about the approaches in the <a href="#further-reading">Further reading</a> section.<br></p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-11.png" class="kg-image" alt loading="lazy" width="258" height="400"></figure><h2 id="advanced-techniques">Advanced techniques</h2><p>When you have many things to store in a palace but struggle to find new places, this may help you. While using ready-made spaces is easier, one may also <strong>create his/her own versions or completely new spaces</strong>.</p><p>There is software that allows people to design a room, a house, or even bigger places. This also allows you to have instant access to a place in case you forget some detail.</p><p>There is <strong><a href="https://en.wikipedia.org/wiki/Minecraft?ref=metacognitive.me">Minecraft</a></strong> also. It&apos;s simple to create places there. I was experimenting with it myself. A good thing is I don&apos;t need to spend a lot of time designing a place because all I have are cubic-like structures. It seems it doesn&apos;t provide a possibility to create details, but it&apos;s not true. There are peculiar blocks I can put to make a place unique and memorable.</p><p>An advantage I may extract from such techniques is the possibility to customize places for my needs. E.g. I can design a large house specifically for book notes. There will be bookshelves, unique doors, and paths.</p><p>If you don&apos;t want to spend time creating places from scratch, you may try to search for Minecraft maps. There are whole cities there! And castles, large houses, etc. There is even the <a href="https://www.youtube.com/watch?v=ZoIXD0Tz6qE&amp;ref=metacognitive.me"><strong>Hogwartz</strong> map</a> from Harry Potter.</p><p>The other alternative is to look for other virtual places. For example, in games, movies. Notice though, the fewer details, the more unique spaces you need.</p><h2 id="summary">Summary</h2><p>Memory palaces are suitable for you if you need to store raw data. They don&apos;t help you learn but memorize much information. The idea is to have a space where you can store the data in a form of visualizations. Along with spatial representation, visualizations are easy for the brain to memorize fast and remember. A good memory palace has 2 key features: organized space to &quot;put&quot; things and unique connections between the things. The space helps you to find the first element in the story. Unique connections help you to recall the other elements.</p><p>Keep in mind <strong>you need to review your palace periodically</strong>: walking there and see what you&apos;ve put. Without it, the images are going to disappear or alter, so the original information becomes distorted.</p><p>Now, you understand the key principles of the technique. Experiment and see what works for you and what doesn&apos;t.</p><p>If you have questions or feedback(I would like to extend the guide to make it more ultimate-like), drop me a message on <a href="https://twitter.com/sergchr?ref=metacognitive.me">Twitter</a>.</p><h2 id="further-reading">Further reading</h2><p>You also may be interested in reading the following:</p><ul><li><a href="https://artofmemory.com/wiki/Mnemonic_Association_System_for_Numbers/?ref=metacognitive.me">Mnemonic Association System for Numbers</a>.</li><li><a href="http://augmentingcognition.com/ltm.html?ref=metacognitive.me">Augmenting Long-term Memory</a> by Michael Nielsen.</li><li><a href="https://en.wikipedia.org/wiki/Moonwalking_with_Einstein?ref=metacognitive.me">Moonwalking with Einstein</a>. The book I highly recommend reading if you want to explore other mnemonics techniques(and memory palaces too).</li><li>What <a href="https://metacognitive.me/active-learning/">active learning</a> is.</li></ul>]]></content:encoded></item><item><title><![CDATA[Why it's important to contemplate thoughts]]></title><description><![CDATA[<p>How much time do you allocate for work? If you do not work, what do you usually do? I surf the Internet, watching YouTube, movies, reading books. What do we do in between? Eating, chores. Have you tried to pause the flow and see what happens?</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image.png" class="kg-image" alt loading="lazy" width="285" height="242"></figure><p>You can try and</p>]]></description><link>https://metacognitive.me/why-its-important-to-contemplate-thoughts/</link><guid isPermaLink="false">613dcf9ab8a7250001e75d2d</guid><category><![CDATA[productivity]]></category><category><![CDATA[thoughts]]></category><dc:creator><![CDATA[Serhii]]></dc:creator><pubDate>Sun, 12 Sep 2021 15:32:39 GMT</pubDate><content:encoded><![CDATA[<p>How much time do you allocate for work? If you do not work, what do you usually do? I surf the Internet, watching YouTube, movies, reading books. What do we do in between? Eating, chores. Have you tried to pause the flow and see what happens?</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image.png" class="kg-image" alt loading="lazy" width="285" height="242"></figure><p>You can try and get bored. It&apos;s normal. Instantly I want to do something useful or enjoyable. Taking a pause and doing nothing isn&apos;t regarded so. We like doing something. Staring at the ceiling, and/or contemplating the thoughts isn&apos;t &quot;useful&quot;. But isn&apos;t it?<br>We like to consume a lot of information. A new video about cosmos, nice. A new book recommendation, gonna read it immediately! If I&apos;m tired, I watch something.</p><p>Consuming feels great. The issue I face is producing new ideas.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-2.png" class="kg-image" alt loading="lazy" width="611" height="401" srcset="https://metacognitive.me/content/images/size/w600/2021/09/image-2.png 600w, https://metacognitive.me/content/images/2021/09/image-2.png 611w"></figure><blockquote>Well, consume relevant information to get ideas from there?</blockquote><p>Yes, but also why not &quot;connecting the dots&quot; by ourselves? We may produce interesting ideas while having only a few. And engaging thoughts about a topic. The brain is so great, it does some thinking in the background. While we sleep, it consolidates the information we consumed that day. While we walk, eat, swim, it creates new neuron connections and &quot;forgets&quot; the others.</p><p>Take a pause and do nothing. Leave the thoughts about a desire to eat. What do you see? Random stuff, but sometimes gems. Write them down. Continue the contemplation.</p><p>I added 15 mins of the &quot;do nothing&quot; time slot in my schedule. I don&apos;t stick to it much, but I try to. It helps to realize I have an intriguing perspective on 10 pages of the book I&apos;ve read recently. Or, a new project idea out of nothing. Another issue is not to forget to write it somewhere. That&apos;s another topic, but I want to mention the importance of note-taking too.</p><p>Isn&apos;t it better to have all the ideas you produced rather than a few you&apos;ve remembered? The brain isn&apos;t a great place to store information, but to produce it. How to understand what to write down? I try to write all ideas, even those I may reject in the future. It&apos;s laziness that doesn&apos;t allow us to write all the notes down. We need to reach a smartphone or laptop, open a note-taking app, find a suitable place to put a note...</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-3.png" class="kg-image" alt loading="lazy" width="404" height="355"></figure><p>Even though we think we should do useful or enjoyable stuff, we also should get bored from time to time. Get bored -&gt; wrote interesting thoughts -&gt; review them later. After consuming content, it&apos;s worth taking a break and ponder about it. Fake busyness pulls out our time. I can&apos;t keep track of the time I lost while being in the &quot;flow&quot;. The flow is any action that the brain automates, or allocates resources to tackle a task. For example, watching a movie, walking, doing a routine. Close the active and pending tasks to see what&apos;s left.</p><p>The fake busyness also consumes a conscious time we&apos;re aware of. That&apos;s where the thoughts about time moving fast come from. Time goes fast when we don&apos;t feel it. The flow does so.</p><figure class="kg-card kg-image-card"><img src="https://metacognitive.me/content/images/2021/09/image-1.png" class="kg-image" alt loading="lazy" width="617" height="353" srcset="https://metacognitive.me/content/images/size/w600/2021/09/image-1.png 600w, https://metacognitive.me/content/images/2021/09/image-1.png 617w"></figure>]]></content:encoded></item></channel></rss>