<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Wumi4</title>
    <description>The latest articles on Forem by Wumi4 (@hoangtuan110).</description>
    <link>https://forem.com/hoangtuan110</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F727147%2Faf7928f9-b1fa-47f7-931f-3523e70f09a9.png</url>
      <title>Forem: Wumi4</title>
      <link>https://forem.com/hoangtuan110</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hoangtuan110"/>
    <language>en</language>
    <item>
      <title>Why I listened to radio stations for working</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Tue, 17 Jan 2023 12:40:05 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/why-i-listened-to-radio-stations-for-working-38kb</link>
      <guid>https://forem.com/hoangtuan110/why-i-listened-to-radio-stations-for-working-38kb</guid>
      <description>&lt;p&gt;For the past couple of days or so, I have been listening to music from radio stations around the world on &lt;a href="https://radio.garden/?r=1" rel="noopener noreferrer"&gt;radio.garden&lt;/a&gt;, whenever I'm working or studying.&lt;/p&gt;

&lt;p&gt;The reason why I chose this over Youtube or my offline music collection is broken down into 6 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I listened to songs I know and love&lt;/strong&gt;. When I'm clicking on a radio station, I always know what to expect from the description or station name. Meanwhile if I turned into my Youtube collection, where it's just a bunch of random music, I never know if it's gonna play low-quality Rasputin or a banger phonk song while I'm studying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Radio stations are like subreddits.&lt;/strong&gt; You can find one for just about everything. If you want to listen to music from records that spins at 78 RPM from the late 1800s to the 1950s, &lt;a href="http://radio.garden/listen/jan-s-78rpm-record-warehouse/" rel="noopener noreferrer"&gt;you can&lt;/a&gt;. If you want to listen music from one of the world's northernmost inhabited areas, well, &lt;a href="http://radio.garden/listen/arctic-outpost-am-1270/" rel="noopener noreferrer"&gt;you can too&lt;/a&gt;. The thing is, no matter how obscure what you are looking for, there's almoat always a station just for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I never know what's playing next&lt;/strong&gt;. If I listen to music on my Youtube collection, I can always knew what will be playing next (at least on mobile), and even if I do it on computer, the algorithm isn't exactly random. But on radio stations, it is truly random. I never know what's going to play next, or if I will enjoy it. I just know it's something I will expect from them. Yes, stations still replay music every once in a while, but at least it is not trying to appeal to me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I discovered new songs&lt;/strong&gt;. Every time I'm listening to a song on a certain station and found the song to be great, I often used my trusty Shazam to identify it. Radio stations has helped me discovered new songs that I liked and added them imto my music collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's good for your privacy&lt;/strong&gt;. With services like Spotify and Youtube, you run into the risk of data mining and megacorps selling your data for advertising companies. Meanwhile radio stations doesn't collect your data, and their advertisements only came in form of sponsorships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's easy&lt;/strong&gt;. You don't have to sign up and log in and search to start listening to music. With radio, just tune in on a station you liked and you are set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So yeah, that's why I listened to radio stations, and why you should, too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This post is a cross-post from &lt;a href="https://tsk.bearblog.dev/why-i-listened-to-radio-stations-for-working/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;. Check it out too!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A quick review of the Fresh web framework</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Mon, 04 Jul 2022 08:37:29 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/a-quick-review-of-the-fresh-web-framework-1367</link>
      <guid>https://forem.com/hoangtuan110/a-quick-review-of-the-fresh-web-framework-1367</guid>
      <description>&lt;p&gt;Unless you have been living under a rock, then you probably have heard of &lt;a href="https://fresh.deno.dev/"&gt;Fresh&lt;/a&gt;, the shiny new TypeScript web framework.&lt;/p&gt;

&lt;p&gt;Fresh boasts some impressive features, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No build step&lt;/li&gt;
&lt;li&gt;No config needed&lt;/li&gt;
&lt;li&gt;TypeScript support out of the box&lt;/li&gt;
&lt;li&gt;No JavaScript is shipped to the client by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But how good is Fresh in terms of developer experience?&lt;/p&gt;

&lt;p&gt;To answer that question, I have built a simple file-system based pastebin service, called &lt;a href="https://github.com/HoangTuan110/petunia"&gt;Petunia&lt;/a&gt;, using Fresh and Deno.&lt;/p&gt;

&lt;p&gt;Short answer?&lt;/p&gt;

&lt;p&gt;Fresh is pretty good if you already know React and Tailwind, though it has some quirks that you have to get used to, like handling input.&lt;/p&gt;

&lt;p&gt;The longer answer?&lt;/p&gt;

&lt;p&gt;Fresh relies on &lt;a href="https://preactjs.com/"&gt;Preact&lt;/a&gt;--a lightweight version of React--to display components, so if you are a React developer, then Fresh should feel like home to you.&lt;/p&gt;

&lt;p&gt;When initializing a new project, Fresh will also ask if you want to use &lt;a href="https://twind.dev/"&gt;Twind&lt;/a&gt;, which is a Tailwind-to-JS library. If you choose this option, then you will have the power of Tailwind without creating a config file or using PostCSS, which I thought is pretty cool.&lt;/p&gt;

&lt;p&gt;Here are a few things to notice though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fresh uses &lt;a href="https://nextjs.org/docs/routing/introduction"&gt;NextJS's file-system based routing&lt;/a&gt;, so for example &lt;code&gt;routes/link/[id].ts&lt;/code&gt; becomes &lt;code&gt;/link/:id&lt;/code&gt; in the web app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The way Fresh handles form submission is very different from React. Instead of using states like React, Fresh takes advantage of the HTML &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element, by getting form data from &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; when the user enters the form, then using a custom handler to process that data, and return that data to the front-end.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's &lt;a href="https://fresh.deno.dev/docs/getting-started/form-submissions"&gt;an example&lt;/a&gt; on the Fresh documentation, implementing a search form that filters an array of names server-side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @jsx h */&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$fresh/server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NAMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charlie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Eve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Frank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Handlers&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NAMES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://news.ycombinator.com/item?id=31974795"&gt;Discuss on HN&lt;/a&gt; | &lt;a href="https://ctt.ac/fe25i"&gt;Tweet this post&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;You can also read this post in &lt;a href="https://tsk.bearblog.dev/a-quick-review-of-fresh-web-framework/"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Hosting fonts locally for Subreply CSS</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Fri, 01 Jul 2022 11:53:12 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/hosting-fonts-locally-for-subreply-css-3j16</link>
      <guid>https://forem.com/hoangtuan110/hosting-fonts-locally-for-subreply-css-3j16</guid>
      <description>&lt;p&gt;As promised in the &lt;a href="https://tsk.bearblog.dev/introducing-subreply-css/"&gt;previous post&lt;/a&gt;, today I will show you how you can host the font that &lt;a href="https://github.com/HoangTuan110/subreply-css"&gt;Subreply CSS&lt;/a&gt; used (which is &lt;a href="https://dotcolon.net/font/route159/"&gt;Route 159&lt;/a&gt;) locally for your project, and use them with Subreply.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 1: Download the font
&lt;/h1&gt;

&lt;p&gt;Go to the website of &lt;a href="https://dotcolon.net/font/route159/"&gt;Route 159&lt;/a&gt;, then click on the &lt;code&gt;Download&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C5AltNl6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/z0w3ca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C5AltNl6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/z0w3ca.png" alt="Click on the  raw `Download` endraw  button" width="880" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, the zip file containing the fonts should start installing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 2: Extract the font
&lt;/h1&gt;

&lt;p&gt;After the installation was done, go to the folder containing the font, then unzip the zip file.&lt;/p&gt;

&lt;p&gt;If you are using the terminal, use the command &lt;code&gt;unzip &amp;lt;filename&amp;gt;&lt;/code&gt;, e.g. &lt;code&gt;unzip route159_110.zip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are using Windows, you can read &lt;a href="https://support.microsoft.com/en-us/windows/zip-and-unzip-files-f6dde0a7-0fec-8294-e1d3-703ed85e7ebc"&gt;this article&lt;/a&gt; from Microsoft.&lt;/p&gt;

&lt;p&gt;After unzipping, your fonts folder should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oMi5stR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/55n6yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oMi5stR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/55n6yx.png" alt="Your fonts folder should look like this" width="880" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 3: Move the fonts file to your project
&lt;/h1&gt;

&lt;p&gt;After extracted all the fonts, we need to move them into your project.&lt;/p&gt;

&lt;p&gt;Go to the directory &lt;code&gt;Web Fonts&lt;/code&gt;, then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are using the terminal, move the file &lt;code&gt;Route159-Bold.woff&lt;/code&gt; and &lt;code&gt;Route159-Regular.woff&lt;/code&gt; to your project.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;Route159-Bold.woff &amp;lt;your-project&amp;gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;Route159-Regular.woff &amp;lt;your-project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using Windows, open your project's folder in another window, then drag the file &lt;code&gt;Route159-Bold.woff&lt;/code&gt; and &lt;code&gt;Route159-Regular.woff&lt;/code&gt; from the fonts folder to your project's folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OBvCmZ0h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/wrksgl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OBvCmZ0h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/wrksgl.png" alt="These two files!" width="880" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 4: Modify the CSS
&lt;/h1&gt;

&lt;p&gt;Finally, we need to directly modify the CSS, so that it will work with our local fonts.&lt;/p&gt;

&lt;p&gt;First, opening the CSS file containing Subreply CSS, using your favorite editor.&lt;/p&gt;

&lt;p&gt;Then, using the &lt;code&gt;Find and Replace&lt;/code&gt; feature of your editor, replace the following text with their corresponded text:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https://files.catbox.moe/gt6un3.woff&lt;/code&gt; to &lt;code&gt;Route159-Regular.woff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https://files.catbox.moe/outwck.woff&lt;/code&gt; to &lt;code&gt;Route159-Bold.woff&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save the file, and your fonts should start working!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://news.ycombinator.com/item?id=31943679"&gt;Discuss on HN&lt;/a&gt; | &lt;a href="https://ctt.ac/8R3cd"&gt;Tweet this post&lt;/a&gt; |&lt;br&gt;
Have questions or feedback? &lt;a href="//mailto:mail@dht.anonaddy.me"&gt;Email me&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;If you feel like the screenshot is from 2010 or something, then it's because I don't do image editing that well. This is my very first times using Krita and GIMP, so the quality isn't that good :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>subreply</category>
    </item>
    <item>
      <title>Introducing Subreply CSS - A beautiful classless CSS style</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Fri, 01 Jul 2022 05:55:38 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/introducing-subreply-css-a-beautiful-classless-css-style-55b5</link>
      <guid>https://forem.com/hoangtuan110/introducing-subreply-css-a-beautiful-classless-css-style-55b5</guid>
      <description>&lt;p&gt;Recently, I came across this website called &lt;a href="https://subreply.com/about"&gt;Subreply&lt;/a&gt;, which is an English-only forum with a clean and simplistic design.&lt;/p&gt;

&lt;p&gt;When I first saw it, I immediately fall in love with its design: Simple, yet modern and beautiful. I love it so much that I decided to rip the CSS from the website and turn it into a classless CSS style.&lt;/p&gt;

&lt;p&gt;And after about 2 days of active working, I introduce to you, Subreply CSS!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kEZgleIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/x8juw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kEZgleIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://files.catbox.moe/x8juw2.png" alt="My blog with Subreply CSS applied" width="880" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Subreply CSS is a classless CSS style that is designed to be modern, beautiful, and simple, just like where it came from.&lt;/p&gt;

&lt;p&gt;Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight&lt;/strong&gt; - Only weights 4 kB! &lt;sup id="fnref1"&gt;1&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile responsive&lt;/strong&gt; and &lt;strong&gt;image responsive&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic dark/light theme&lt;/strong&gt; (based on OS preferences)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom emojis&lt;/strong&gt; before &lt;code&gt;mailto:&lt;/code&gt;, &lt;code&gt;sms:&lt;/code&gt;, and &lt;code&gt;tel:&lt;/code&gt; links&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom blockquotes&lt;/strong&gt; and &lt;strong&gt;code blocks&lt;/strong&gt; &lt;sup id="fnref2"&gt;2&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Beautiful font (&lt;a href="https://dotcolon.net/font/route159/"&gt;Route 159&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fixing missing features from the original Subreply, such as &lt;strong&gt;radios and checkboxes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subreply CSS is suitable for both personal blogs and simple websites!&lt;/p&gt;

&lt;h1&gt;
  
  
  Wow! That's exciting! Where can I know more about it?
&lt;/h1&gt;

&lt;p&gt;You can go to the &lt;a href="https://github.com/HoangTuan110/subreply-css"&gt;Github repo&lt;/a&gt;, which contains further information about the project.&lt;/p&gt;

&lt;h1&gt;
  
  
  I'm still skeptical, I want to try it first
&lt;/h1&gt;

&lt;p&gt;You can try this &lt;a href="https://raw.githack.com/HoangTuan110/subreply-css/main/test.html"&gt;demo&lt;/a&gt; &lt;sup id="fnref3"&gt;3&lt;/sup&gt; or just playing around with &lt;a href="https://tsk.bearblog.dev"&gt;my website&lt;/a&gt; (yes, it uses Subreply CSS).&lt;/p&gt;

&lt;h1&gt;
  
  
  Downsides
&lt;/h1&gt;

&lt;p&gt;Even though it has a lot of good points, Subreply CSS also has some downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the fonts are currently hosted on &lt;a href="https://catbox.moe/"&gt;Catbox&lt;/a&gt;, a file hosting service that I am relying on. This means that if Catbox goes down, all the fonts will be rendered unusable. The best solution for this is to host fonts locally, and I am planning on writing a (short) blog post just for that, so stay tuned!&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Questions? Feedback?
&lt;/h1&gt;

&lt;p&gt;If you have any questions or feedback, feel free to &lt;a href="//mailto:mail@dht.anonaddy.me"&gt;email me&lt;/a&gt;!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;For both original and minified version ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;The blockquotes are stolen from &lt;a href="https://css-tricks.com/snippets/css/simple-and-nice-blockquote-styling/"&gt;here&lt;/a&gt; and the code blocks are stolen from &lt;a href="https://adis.ca/entry/2011/pretty-code-block-in-css/"&gt;here&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Note that the demo version can be a bit outdated. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Some of my best programming language that I have designed</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Tue, 15 Mar 2022 13:51:31 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/some-of-my-best-programming-language-that-i-have-designed-24g9</link>
      <guid>https://forem.com/hoangtuan110/some-of-my-best-programming-language-that-i-have-designed-24g9</guid>
      <description>&lt;p&gt;Throughout my years with programming, I have designed 12 programming languages. Some of them I think are pretty interesting and has some potential. But most of them is either straight up copies from the language that it was based on, or not very interesting to talk about. So, in this post, I will select out some of my best designed programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 3xn
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;3xn&lt;/code&gt; is one of my very first programming languages (and the best one). It is a stack-based esolang where you are limited to only have the first three letters on each line as commands. Any character after that is comments. Here is a &lt;code&gt;Hello world!&lt;/code&gt; in &lt;code&gt;3xn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
'He // Add the string 'He' to the stack
'll
'o  // There is a whitespace after the 'o'
'wo
'rl
'd!
$@. // Merge all things in stack together and print
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;Hello world!&lt;/code&gt; string has to be splitted into smaller parts to fit within the rule using &lt;code&gt;'&lt;/code&gt;. And at the final line, we merge all the small strings together (&lt;code&gt;$&lt;/code&gt;) and then print it out (&lt;code&gt;@&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;You may have (not) noticed the &lt;code&gt;.&lt;/code&gt; at the final line, it is basically the no-op operator: It does nothing. It turns out to be pretty useful for single-line comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... This is a line of comment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is another one, the &lt;code&gt;Counter&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:a // Assign a to 1
[.. // Start while loop
^a1 // Load a to stack and push 1
+:a // Plus 2 number on the stack and assign it back to a
^a@ // Outputs a
]0. // Jumps back to the start of the while loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one makes a bit less sense to me. There is a &lt;code&gt;0&lt;/code&gt; after the &lt;code&gt;]&lt;/code&gt;, which I honestly don't know why is it there. The line &lt;code&gt;+:a&lt;/code&gt; should mean 'assign the + operator to a' (as from the assignment at the first line), but here it means 'add a to 1 and assign the result to a'.&lt;/p&gt;

&lt;p&gt;I think the reason why this is interesting to me is because of the design: You are forced to limit to use only 3 commands on each line, which is kinda frustating and dumb. But also, it forces you to come up with solutions to fit within the rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Nook
&lt;/h2&gt;

&lt;p&gt;Nook is a concatenative, interpreted programming language. It is heavily inspired by GNU &lt;code&gt;dc&lt;/code&gt;. Here is a &lt;code&gt;Hello world!&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{Hello world!} w # Print "Hello world!" after push it to the stack
{Hello world!} p # The same as above, but does not pop the string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nook uses the curly brackets to contain strings and functions, similiar to &lt;code&gt;dc&lt;/code&gt;'s square brackets. Nook uses two different operators for priting to output (&lt;code&gt;w&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt;), while &lt;code&gt;dc&lt;/code&gt; uses 1 (&lt;code&gt;p&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here is a more interesting example, the &lt;code&gt;abs&lt;/code&gt; example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;i d { 0 &amp;gt; } { _1 * w } { w } ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example takes an integer input, then prints the absolute value of the number. At here, there are a few other operators to introduce. There is the &lt;code&gt;d&lt;/code&gt; operator, which is short for &lt;code&gt;duplicate&lt;/code&gt;. And the more important one, the &lt;code&gt;?&lt;/code&gt; or (&lt;code&gt;if&lt;/code&gt;) operator.&lt;/p&gt;

&lt;p&gt;In this example, assuming we give the input &lt;code&gt;-50&lt;/code&gt;. The program will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, duplicate the number (So we have &lt;code&gt;[-50, -50]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Then, we will check the condition of the &lt;code&gt;if&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;-50&lt;/code&gt; is lesser than &lt;code&gt;0&lt;/code&gt; (which in this one it is), print out &lt;code&gt;-50 * -1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Else, we just prints out the input back&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our example, the program will print out &lt;code&gt;50&lt;/code&gt;, which is the result of the expression &lt;code&gt;-50 * -1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I think it is interesting because this is the only language that has been actually implemented so far. You can see the repo on &lt;a href="https://github.com/HoangTuan110/Nooklang"&gt;GitHub&lt;/a&gt; and run all the examples by yourself. It is also a language that is practical (compare to other ones) and have sets of examples (in the &lt;code&gt;examples/&lt;/code&gt; directory) and a &lt;code&gt;CHANGELOG&lt;/code&gt; which you can use as a source of documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;So that is the design of Nook and 3xn. They are, in my opinion, two of the best programming languages that I have designed. If you are more interested in other languages that I made, here is a &lt;a href="https://github.com/HoangTuan110/langdesigns"&gt;GitHub repo&lt;/a&gt; containing all of my notes and examples.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I practice typing in Workman today. Here is my experience.</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Mon, 07 Mar 2022 12:00:53 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/i-practice-typing-in-workman-today-here-is-my-experience-46b7</link>
      <guid>https://forem.com/hoangtuan110/i-practice-typing-in-workman-today-here-is-my-experience-46b7</guid>
      <description>&lt;p&gt;Today, I have had an experience to practice typing using a keyboard layout called &lt;code&gt;Workman&lt;/code&gt;. It is supposedly an improvement to other popular keyboard layouts, like Dvorak, Colemak, and of course, QWERTY. To practice it, I decided to go to &lt;a href="https://monkeytype.com"&gt;Monkeytype&lt;/a&gt;, choose the Workman layout, and get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uVpIQF2q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/workman-layout/Workman/blob/master/workman_layout.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uVpIQF2q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/workman-layout/Workman/blob/master/workman_layout.png%3Fraw%3Dtrue" width="869" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, typing on Workman is weird, as with other things. I was only be able to type at about 3-4 WPM, which is pretty terrible. But, as I start to get more comfortable with it, I started to improve my speed. Now, I usually achieved at around 10-18 WPM with simple sentences with &amp;gt;90% accurancy, which I think is pretty good.&lt;/p&gt;

&lt;p&gt;A thing I really like with Workman is that it feels very comfortable to type. So comfortable in fact, I was sometimes be able to get the feeling of typing on QWERTY, which is something I never expected to get so early.&lt;/p&gt;

&lt;p&gt;Another thing I like about this layout is that a lot of common words (such as &lt;code&gt;that&lt;/code&gt;, &lt;code&gt;is&lt;/code&gt;) are already on the home row, so you don't have to move your hands to type it, unlike QWERTY.&lt;/p&gt;

&lt;p&gt;The only thing I don't like about Workman is that &lt;code&gt;V&lt;/code&gt; is placed in a pretty weird place, making it probably the word that I mistyped the most. Also, because Workman shifts one key off on the top row, so often times, I would mistype &lt;code&gt;P&lt;/code&gt; as my muscle memory would say to press on &lt;code&gt;P&lt;/code&gt; on QWERTY, which resulted in &lt;code&gt;;&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Overall, using Workman has been a pretty enjoyable experience, and it has been one of the better decisions I have made in life.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(At the time of typing, I am still using QWERTY, because I will need to restart the computer to start typing in Workman, bruh.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>keyboard</category>
    </item>
    <item>
      <title>Use Ngrok to share a preview of your web project to everyone!</title>
      <dc:creator>Wumi4</dc:creator>
      <pubDate>Sat, 16 Oct 2021 09:04:38 +0000</pubDate>
      <link>https://forem.com/hoangtuan110/use-ngrok-to-share-a-preview-of-your-web-project-to-everyone-1h1a</link>
      <guid>https://forem.com/hoangtuan110/use-ngrok-to-share-a-preview-of-your-web-project-to-everyone-1h1a</guid>
      <description>&lt;h2&gt;
  
  
  Situation
&lt;/h2&gt;

&lt;p&gt;So, you just build a very cool website, but the only problem is that it is only available through your local web server, or &lt;code&gt;localhost&lt;/code&gt;. You can buy a domain, set up a simple web server, get an SSL certificate, and then figure out how to set for the code to work. But what if you just want to share a quick preview of your website to a friend, or test it on mobile devices, without having to deploy or anything?&lt;/p&gt;

&lt;p&gt;That's where tunnels come in! Tunnel allows you to set a secure, but temporary connection between your &lt;code&gt;localhost&lt;/code&gt; and the Internet. In this post, I will show you how you can share a preview of your web project to everyone using Ngrok!&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In here I am assuming you are using Linux or MacOS. If you use Windows or another OS, then this tutorial is maybe not for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;First, we will need to create a Ngrok account. You can sign up using this &lt;a href="https://dashboard.ngrok.com/signup" rel="noopener noreferrer"&gt;link&lt;/a&gt;, or go to &lt;code&gt;ngrok.com&lt;/code&gt;, and then click on &lt;code&gt;Get Started For Free&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After signing up, you should have a dashboard that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoa2k5sfhhjbzlesf0cu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoa2k5sfhhjbzlesf0cu.png" alt="Ngrok Tutorial Image 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, click on &lt;code&gt;Download for Linux&lt;/code&gt;, and a zip file should be installed.&lt;/p&gt;

&lt;p&gt;Go to your default &lt;code&gt;Download&lt;/code&gt; directory, and then unzip the zip file using &lt;code&gt;unzip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After unzipping, you should see an executable called &lt;code&gt;ngrok&lt;/code&gt;. Running this executable should show something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME:
   ngrok - tunnel local ports to public URLs and inspect traffic

DESCRIPTION:
    ngrok exposes local networked services behinds NATs and firewalls to the
    public internet over a secure tunnel. Share local websites, build/test
    webhook consumers and self-host personal services.
    Detailed help for each command is available with 'ngrok help &amp;lt;command&amp;gt;'.
    Open http://localhost:4040 for ngrok's web interface to inspect traffic.

[bla bla bla ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that we have installed Ngrok!&lt;/p&gt;

&lt;h3&gt;
  
  
  Authenticate the Ngrok agent
&lt;/h3&gt;

&lt;p&gt;Now, we will need to authenticate the Ngrok agent that we just installed, this will grant us access to more features and longer session time.&lt;/p&gt;

&lt;p&gt;On the dashboard, in the tab &lt;code&gt;Getting Started&lt;/code&gt;, click on &lt;code&gt;Your Authtoken&lt;/code&gt;. Click on that will lead to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmef4w83qzpo0izdq1fa8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmef4w83qzpo0izdq1fa8.png" alt="Ngrok Tutorial Image 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, click &lt;code&gt;Copy&lt;/code&gt; to copy your authtoken, and then type this on the terminal to authenticate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./ngrok authtoken &amp;lt;YOUR_AUTHTOKEN&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing that, &lt;code&gt;ngrok&lt;/code&gt; will output something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authtoken saved to configuration file: path/to/ngrok/config/file/ngrok.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which means that we have authenticated our &lt;code&gt;ngrok&lt;/code&gt; agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fire it up
&lt;/h3&gt;

&lt;p&gt;Now, we have done setting up our Ngrok, let's fire it up!&lt;/p&gt;

&lt;p&gt;Before we get into it, we will set up &lt;code&gt;ngrok&lt;/code&gt; in our &lt;code&gt;$PATH&lt;/code&gt; to conveniently run &lt;code&gt;ngrok&lt;/code&gt; everywhere in our shell, without having to remember the path.&lt;/p&gt;

&lt;p&gt;Note that this depends on the shell that you are using. On &lt;code&gt;fish&lt;/code&gt; (the shell that I am currently using), I will set up &lt;code&gt;ngrok&lt;/code&gt; in my &lt;code&gt;$PATH&lt;/code&gt; like this in &lt;code&gt;.config/fish/config.fish&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/ngrok/:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, restart your terminal, and you should be able to run &lt;code&gt;ngrok&lt;/code&gt; using &lt;code&gt;ngrok&lt;/code&gt; command in the shell.&lt;/p&gt;

&lt;p&gt;Now, we will start using &lt;code&gt;Ngrok&lt;/code&gt; in our web project. For the purpose of this tutorial, I have set up a simple web server using &lt;a href="http://bottlepy.org/docs/dev/index.html" rel="noopener noreferrer"&gt;Bottle Framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;cd&lt;/code&gt; to your web project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your/project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, start the local web server. This depends on your project. For my project, since I only use a single file for my project (which is &lt;code&gt;main.py&lt;/code&gt;), I can start the local web server of my project like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;π python3 main.py
Bottle v0.12.19 server starting up &lt;span class="o"&gt;(&lt;/span&gt;using WSGIRefServer&lt;span class="o"&gt;())&lt;/span&gt;...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After start the web server, open another terminal and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;π ngrok http &amp;lt;PORT&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;&amp;lt;PORT&amp;gt;&lt;/code&gt; is the port of your local web server. In my case, it is &lt;code&gt;8080&lt;/code&gt;, so I will type in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;π ngrok http 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After press Enter, you should see an interface that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok by @inconshreveable                                                                                                                                (Ctrl+C to quit)

Session Status                online
Account                       Wumi4 (Plan: Free)
Version                       2.3.40
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://b0be-2001-ee0-4bab-5020-5343-d3ed-89bc-e519.ngrok.io -&amp;gt; http://localhost:8080
Forwarding                    https://b0be-2001-ee0-4bab-5020-5343-d3ed-89bc-e519.ngrok.io -&amp;gt; http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              2       0       0.01    0.00    0.01    0.01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there are two different links in the &lt;code&gt;Forwarding&lt;/code&gt; part: One is &lt;code&gt;http&lt;/code&gt; and one is &lt;code&gt;https&lt;/code&gt;. Click on any of these links will lead to your website.&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;So that's it! You have just learned how to use Ngrok to set up a temporary link that you can use to share it as a preview to everyone!&lt;/p&gt;

&lt;p&gt;I hope you enjoy this tutorial! This is my first blog post since July, so the post may have some errors.&lt;/p&gt;

&lt;p&gt;Ok, that's for all! Goodbye! 😄&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ngrok</category>
    </item>
  </channel>
</rss>
