<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Li</title>
    <description>The latest articles on DEV Community by Michael Li (@wayofnumbers).</description>
    <link>https://dev.to/wayofnumbers</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%2F252120%2Ff364668a-f10a-44dc-8a22-bb6324d647a2.jpeg</url>
      <title>DEV Community: Michael Li</title>
      <link>https://dev.to/wayofnumbers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wayofnumbers"/>
    <language>en</language>
    <item>
      <title>TL;DR CTF Writeups: TryHackMe(Vulnversity)</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Tue, 18 May 2021 00:23:05 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/tl-dr-ctf-writeups-tryhackme-vulnversity-58o6</link>
      <guid>https://dev.to/wayofnumbers/tl-dr-ctf-writeups-tryhackme-vulnversity-58o6</guid>
      <description>&lt;h2&gt;
  
  
  Series Brief
&lt;/h2&gt;

&lt;p&gt;Cybersecurity has always been something I want to get into or at least apply my data science skills to. Not because of the 'Mr. Robot' style Hollywood hacking science though, not that. Rather, I was drawn into it because it embodied curiosity, hunger for knowledge, problem-solving, and the mentality of always be tinkering things. &lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://tryhackme.com/"&gt;TryHackMe&lt;/a&gt;, the popular online platform that lets you learn cybersecurity through many short, gamified labs(VMs spun up with certain purpose and configuration). It is quite beginner-friendly too. You don't have to build your own home lab and deal with those virtual machine configurations. They are already ready-made and ready to be exploited. It gives you access to other people's wisdom (CTF rooms developed by other experts or peers) where you can't have if you are building your own home lab. This series is writeups that will record what I felt about the challenges and things I learned from them with a TLDR-kinda style.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Expect for TLDR CTF Writeups
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Might Be Helpful if You:
&lt;/h3&gt;

&lt;p&gt;✔️ Want a 20,000 ft view of what this room is about&lt;br&gt;
✔️ Want all the leads to help you through the journey but still want to tackle it on your own&lt;br&gt;
✔️ Finish the room but still want to see what is some good takeaways&lt;/p&gt;
&lt;h3&gt;
  
  
  Might Want to Check Other Writeups if you:
&lt;/h3&gt;

&lt;p&gt;🔶 Want a detailed step-to-step writeup to guide you through the challenge&lt;br&gt;
For this purpose, I recommend this &lt;a href="https://0xa94.medium.com/tryhackme-vulnversity-ca0bdcc73386"&gt;writeup&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Overall Feelings
&lt;/h2&gt;

&lt;p&gt;Onto the room that we'll be discussing today: TryHackMe: Vulnversity. It is the first real room if you choose the &lt;a href="https://tryhackme.com/paths"&gt;Offensive Pentesting&lt;/a&gt; path (The first &lt;code&gt;Getting Started&lt;/code&gt; and &lt;code&gt;Tutorial&lt;/code&gt; are too easy to count).  Overall, I felt this room is quite well designed. It requires some Linux command-line knowledge but nothing too fancy. It breaks the whole tasks into bite-size pieces, so no single sub-task is too daunting to tackle. It condensed the typical hacking process of recon, exploit, post-exploit into these simple tasks, introduced you to tools, and guide you through the thought process. Note that you still need to do some research on your own. The room won't spoon-feed you everything. But that's exactly where the fun is, right?&lt;/p&gt;


&lt;h2&gt;
  
  
  Reasons to Try This Room
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Learn basic hacking process (Recon -&amp;gt; Exploit  -&amp;gt; Post-Exploit)&lt;/li&gt;
&lt;li&gt;Get familiar with some very essential hacking tools (&lt;code&gt;nmap&lt;/code&gt;, &lt;code&gt;GoBuster&lt;/code&gt;, &lt;code&gt;BurpSuite&lt;/code&gt;, &lt;code&gt;systemctl&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Get a taste of privilege escalation and reverse shell.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Strategy/Tactics Used
&lt;/h2&gt;

&lt;p&gt;➡️ Use &lt;code&gt;nmap&lt;/code&gt; to gain knowledge of open port and services -&amp;gt; Find 80 port open, website on&lt;br&gt;
➡️ Use &lt;code&gt;GoBuster&lt;/code&gt; to search for folders on web-server -&amp;gt; Find an upload form on &lt;code&gt;internal&lt;/code&gt; folder&lt;br&gt;
➡️ Use &lt;code&gt;BurpSuite&lt;/code&gt; to intercept the request and find out what upload format is supported -&amp;gt; &lt;code&gt;php&lt;/code&gt; : No, &lt;code&gt;phtml&lt;/code&gt;: YES!&lt;br&gt;
➡️ Upload reverse-shell payload with &lt;code&gt;.phtml&lt;/code&gt; extension to bypass filtering: Gain a reverse shell&lt;br&gt;
➡️ Within the reverse shell, use &lt;code&gt;find&lt;/code&gt; to search for SUID files that can be used for privilege escalation -&amp;gt; Find &lt;code&gt;/bin/systemctl&lt;/code&gt;&lt;br&gt;
➡️ Create a &lt;code&gt;SystemD&lt;/code&gt; service file and use &lt;code&gt;/bin/systemctl&lt;/code&gt; to enable and run it, gain root access! WIN!&lt;/p&gt;


&lt;h2&gt;
  
  
  Tools/Command Used
&lt;/h2&gt;
&lt;h3&gt;
  
  
  nmap
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NhaI0_B_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvuclw26dgb4eg46lto0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NhaI0_B_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvuclw26dgb4eg46lto0.png" alt="Nmap"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;nmap&lt;/code&gt; is so essential in the recon process. This task is just scratching the surface. Some options used:&lt;br&gt;
&lt;strong&gt;-sV&lt;/strong&gt;: Attempts to determine the version of the services running&lt;br&gt;
&lt;strong&gt;-p xxx or -p-&lt;/strong&gt;: Portscan for port xxx or scan all ports&lt;br&gt;
&lt;strong&gt;-A&lt;/strong&gt;: Enables OS and version detection, executes in-build scripts for further enumeration&lt;/p&gt;
&lt;h3&gt;
  
  
  GoBuster
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jim6yaA7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmel4mmvidx6p1xze8q3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jim6yaA7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmel4mmvidx6p1xze8q3.png" alt="GoBuster"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/OJ/gobuster"&gt;GoBuster&lt;/a&gt; is a URIs/DNS subdomain brute-force tool. It's developed in Go and will enumerate through the hostname you give it and spit out directory and folders. It will work better with a pre-built word list. The command used in the lab is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    **gobuster dir -u http://&amp;lt;ip&amp;gt;:3333 -w &amp;lt;word list location&amp;gt;**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The word list can easily be under &lt;code&gt;**/usr/share/wordlists**&lt;/code&gt; if you use Kali Linux. Some mentioned that &lt;a href="https://github.com/maurosoria/dirsearch"&gt;dirsearch&lt;/a&gt; is a viable alternative here.&lt;br&gt;
Using the tool, you can find an &lt;code&gt;upload&lt;/code&gt; folder that you can upload file onto the web server.&lt;/p&gt;
&lt;h3&gt;
  
  
  BurpSuite
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XhRnMLIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tpa33l45x365xdvkhmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XhRnMLIt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tpa33l45x365xdvkhmt.png" alt="BurpSuite"&gt;&lt;/a&gt;&lt;br&gt;
Trying to upload some files, and you'll find that most extensions are blocked. How to proceed? Enter &lt;a href="https://portswigger.net/burp"&gt;BurpSuite&lt;/a&gt;, according to &lt;a href="https://wiki.archlinux.org/title/Burp_suite"&gt;Arch Wiki&lt;/a&gt;. It is an &lt;em&gt;'integrated platform for performing security testing of web applications.'&lt;/em&gt; Well, we'll just use it to intercept some web requests and try different file extensions and see which one actually is not blocked. &lt;br&gt;
The gist of it is to try to upload something, intercept it using &lt;code&gt;BurpSuite&lt;/code&gt;, then change the file extension part with a pre-loaded wordlist of all kinds of file extensions(e.g. &lt;code&gt;php&lt;/code&gt;, &lt;code&gt;php5&lt;/code&gt;, &lt;code&gt;phtml&lt;/code&gt;, etc.) to test which one actually can bypass the web-server filter. &lt;br&gt;
Once found (&lt;code&gt;phtml&lt;/code&gt;), just upload a &lt;code&gt;PHP&lt;/code&gt;script of a reverse shell and upload to the webserver, load it on the browser, then your listening &lt;code&gt;nc -lvnp 1234&lt;/code&gt; session will get the reverse shell.&lt;/p&gt;
&lt;h3&gt;
  
  
  systemctl
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14Rh4EPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hf7kq43d8vg5iwdh74td.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14Rh4EPm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hf7kq43d8vg5iwdh74td.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Once we have the reverse shell, the last thing will be to privilege escalation.  One way of doing this is to search for executables with SUID permission. We do that with &lt;code&gt;find&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;find / &lt;span class="nt"&gt;-user&lt;/span&gt; root &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-4000&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ldb&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Out of the results returned, &lt;code&gt;/bin/systemctl&lt;/code&gt; stands out. We can create some service   file (e.g. &lt;code&gt;root.service&lt;/code&gt;) and let &lt;code&gt;systemctl&lt;/code&gt; start to get the previlege:&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="nv"&gt;TF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"root.service"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'[Service]
Type=oneshot
ExecStart=/bin/sh -c "cat /root/root.txt &amp;gt; /tmp/flag.txt"
[Install]
WantedBy=multi-user.target'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$TF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note here you can't use text editor like &lt;code&gt;vim&lt;/code&gt; or &lt;code&gt;nano&lt;/code&gt; in a remote shell, just echo into the file. Not optimum, but get the job done. Once you have the &lt;code&gt;root.service&lt;/code&gt; file, run &lt;code&gt;systemctl&lt;/code&gt; to enable/start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/bin/systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; /tmp/output/root.service
/bin/systemctl start /tmp/output/root.service

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the service is properly started, a simple &lt;code&gt;cat /temp/flag.txt&lt;/code&gt; will give us the flag we want to pass the room.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tryhackme.com/"&gt;TryHackMe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tryhackme.com/room/vulnversity"&gt;TryHackMe: Vulnversity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nmap.org/"&gt;nmap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/OJ/gobuster"&gt;GoBuster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/maurosoria/dirsearch"&gt;dirsearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://portswigger.net/burp"&gt;BurpSuite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php"&gt;php reverse shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gtfobins.github.io/gtfobins/systemctl/#suid"&gt;SUID escalation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>tryhackme</category>
      <category>ctf</category>
      <category>pentesting</category>
    </item>
    <item>
      <title>How I Migrate My Data Science Blog from Pelican to Hugo</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Sun, 02 May 2021 05:18:22 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/how-i-migrate-my-data-science-blog-from-pelican-to-hugo-g63</link>
      <guid>https://dev.to/wayofnumbers/how-i-migrate-my-data-science-blog-from-pelican-to-hugo-g63</guid>
      <description>&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Issues of Pelican
&lt;/h2&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%2Fmtcga1jlnuvky98oyj8q.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%2Fmtcga1jlnuvky98oyj8q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
I've been using Pelican as the framework for my &lt;a href="https://wayofnumbers.com" rel="noopener noreferrer"&gt;data science blog&lt;/a&gt; for a while now. It has worked for me, though there were always some minor glitches that made me feel not settled. It never feels complete and satisfying to me. Here are some of the big ones:&lt;/p&gt;
&lt;h3&gt;
  
  
  Small community and niche position
&lt;/h3&gt;

&lt;p&gt;Pelican has a much smaller community than Hugo. It has 10.4k stars vs. the 51.4k stars on GitHub. On the Static Site Generator community, Pelican is a niche. People already know Python might want to try it out (like me!), but others with better understanding and programming skills might prefer other options. &lt;br&gt;
With a smaller community comes with fewer themes, fewer plugins, and less support if you run into some weird issues. This is precisely my experience. &lt;/p&gt;
&lt;h3&gt;
  
  
  Lack of satisfying themes
&lt;/h3&gt;

&lt;p&gt;It was pretty hard to find my current theme &lt;a href="https://elegant.oncrashreboot.com/" rel="noopener noreferrer"&gt;Elegant&lt;/a&gt; that have both a good look and feel as well as utilities. There are not many options to begin with. &lt;/p&gt;
&lt;h3&gt;
  
  
  Small glitches that are hard to tackle
&lt;/h3&gt;

&lt;p&gt;It took me quite some effort to fully get everything to work. Google Analytics, Disqus, Jupyter Notebook support, Table of Content, Read time, etc. During the process, I barely got any help since there simply weren't many people using it. So I have to dig deep into the source code to fix a minor issue. It's not that the process not worth the time(it was and very challenging and educational for me as a programmer), but why I have to dig out the rocks while I can tend the flowers?&lt;/p&gt;
&lt;h3&gt;
  
  
  Speed, Speed, Speed
&lt;/h3&gt;

&lt;p&gt;When it comes to speed as a programming language, Python sits on the 'slowest' end while Go is at the top(almost). What I can tell you is this: it shows on-site generating speed for sure. Pelican will take a couple of seconds to render all my articles (20+), while Go took a couple of milliseconds. Another big perk for Go is, it updates the site in real-time, while Pelican will lag behind a bit. This is more obvious when you made a small change and need to re-generate the whole site to see the updated version. Our time is too precious to be wasted, even a couple of seconds will add up to much. &lt;/p&gt;


&lt;h2&gt;
  
  
  Why Hugo
&lt;/h2&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%2Fv0yduwtj1t6z4uobzxfh.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%2Fv0yduwtj1t6z4uobzxfh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Concurrency and speed
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; boast itself as "&lt;strong&gt;The world’s fastest framework for building websites&lt;/strong&gt;", and I can definitely see why. &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Golang&lt;/a&gt; is developed by Google to solve their code efficiency problems and is known for its great concurrency prowess.  This transfers to Hugo pretty well. The standard build time for a Hugo site is on 100ms level while another static site generator is on 10 seconds level. If speed is your concern, then you'll definitely love Hugo. &lt;/p&gt;
&lt;h3&gt;
  
  
  Good Community Support
&lt;/h3&gt;

&lt;p&gt;Hugo's open source project on GitHub is currently showing 54.4k Stars. That is a pretty big number. Many people use Hugo as their framework of choice for personal/business blogs. This means it's easier to search for similar questions when in doubt. &lt;br&gt;
Also, the response time for Hugo's official  &lt;a href="https://discourse.gohugo.io/" rel="noopener noreferrer"&gt;forum&lt;/a&gt; is relatively short,  given that you frame your question precisely. &lt;br&gt;
Hugo also has excellent &lt;a href="https://gohugo.io/documentation/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;  you can easily find what you want should you implement a new feature.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exposure to Go
&lt;/h3&gt;

&lt;p&gt;Golang as a server-side language is gaining prevalence over the past couple of years among back-end developers. It's a language worth putting some time into. Working with Hugo will unavoidably expose you to Go, and you might learn a thing or two when building your site and get you started with Go.&lt;/p&gt;
&lt;h3&gt;
  
  
  Themes, a lot of themes
&lt;/h3&gt;

&lt;p&gt;Look no further at the official &lt;a href="https://themes.gohugo.io/" rel="noopener noreferrer"&gt;Hugo theme site&lt;/a&gt;. These are the free ones. There are also some sites that offer paid premium themes, and you can decide whether it's worth it. Free or paid, the Hugo theme community is very vibrant and active, result in many options to choose from. &lt;/p&gt;
&lt;h3&gt;
  
  
  Smooth Learning Curve
&lt;/h3&gt;

&lt;p&gt;Some static site generator like &lt;a href="https://www.gatsbyjs.com/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; You'll need to have a solid understanding of React to use it. For Hugo, you don't really have to learn Go first, though knowing some Go will make it even smoother to speed things up. &lt;/p&gt;


&lt;h1&gt;
  
  
  My First Hugo Site
&lt;/h1&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%2F4avav2msqcw4shruto8g.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%2F4avav2msqcw4shruto8g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Enough of the theory-crafting. Let's get down to the details. I'll organize this part in chronological order to show the flow of how it's usually done and some issues I ran into, and how I tackled them. &lt;/p&gt;
&lt;h2&gt;
  
  
  Start from Quick Start
&lt;/h2&gt;

&lt;p&gt;The simplest and best (to me at least) way to start your migration is to actually build a new site from scratch following the official &lt;a href="https://gohugo.io/getting-started/quick-start/" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt;. It's relatively easy to follow and doesn't even have many steps. It will help if you know a bit command line and Git but not required. Hugo comes with a powerful and intuitive CLI interface, and even if you don't know much about the command line, you can finish the tutorial not sweating. For example, build the site is only:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The quick start will pick a theme for you(&lt;a href="https://themes.gohugo.io/gohugo-theme-ananke/" rel="noopener noreferrer"&gt;ananke&lt;/a&gt;) You can change it to your own choice later easily. The final site will look something like &lt;a href="https://themes.gohugo.io/theme/gohugo-theme-ananke/" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick a Theme
&lt;/h2&gt;

&lt;p&gt;Picking a theme is mostly subjective. Choose anything you want. Something that looks appealing to you and meets all your utility needs will be a good start. Just don't spend too much time nailing down your 'perfect one', with so many choices, you are likely to switch multiple times before settle on one that you really feel comfortable with. Mine is &lt;a href="https://themes.gohugo.io/hugo-theme-stack/" rel="noopener noreferrer"&gt;Stack&lt;/a&gt; . For your first site, make sure to also have a look at the theme documentation cause you'll definitely need to read it multiple times to adjust it to your liking. &lt;/p&gt;




&lt;h1&gt;
  
  
  Configure and Adjust
&lt;/h1&gt;

&lt;p&gt;Now comes the fun part, the &lt;strong&gt;tinkering&lt;/strong&gt;! Tweak a theme to make it work for you for some people is daunting, but for me, it's daunting &lt;em&gt;and&lt;/em&gt; exciting. It feels like puzzle solving. You get leads from theme documentation, Hugo documentation, YouTube videos, and stack overflow and put all the pieces together. When it's done, you'll feel excellent about yourself!&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone, Submodule, and Config
&lt;/h2&gt;

&lt;p&gt;First thing first, git clone the theme to local drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/CaiJimmy/hugo-theme-stack/ themes/hugo-theme-stack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It helps to add the theme as a submodule. It's easier to manage with Git that way. And you'll need that for future deployment if you want to put your site on Netlify. &lt;br&gt;
Once the theme folder sits safely on your local drive, you just need to make some minor tweaks to the config file to make them work. You can do this in two ways. One is simply to change your current &lt;code&gt;config.toml&lt;/code&gt; file:&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;echo &lt;/span&gt;theme &lt;span class="se"&gt;\=&lt;/span&gt; &lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"hugo-theme-stack&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you read the theme documentation, what's suggested is to simply copy the &lt;code&gt;config.yaml&lt;/code&gt; file from the theme example site over, since there are other parts of the config you need to get right, and it's easier to start from the theme default config files. &lt;br&gt;
Once done, your simple site will start to look like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/Theme_Stack_demo.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/Theme_Stack_demo.png" alt="Theme Stack Demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Avatar
&lt;/h2&gt;

&lt;p&gt;Now to the little details you need to iron out to make the theme work for you. The first thing that grabbed my attention is the glaring placeholder '150x150' avatar:&lt;br&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%2Fv8px1b9wnb4ipemjq2ke.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%2Fv8px1b9wnb4ipemjq2ke.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Gotta get rid of it first! Looking at the &lt;a href="https://docs.stack.jimmycai.com/configuration#avatar" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, the avatar needs to be put somewhere (I put it under &lt;code&gt;img&lt;/code&gt; subfolder) under &lt;code&gt;assets&lt;/code&gt; folder under the site root directory. Then change the &lt;code&gt;config.yaml&lt;/code&gt; to tell Hugo where to find it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;sidebar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;emoji&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🍥&lt;/span&gt;
        &lt;span class="na"&gt;subtitle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Data Science for the Rest of Us&lt;/span&gt; 
        &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; 
            &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;img/avatar.png&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The site automatically reloaded, and the avatar got updated to my not-so-pretty photo:&lt;br&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%2Fh90gkpfopk8jf8iukn58.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%2Fh90gkpfopk8jf8iukn58.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  favicon
&lt;/h2&gt;

&lt;p&gt;Favicon is that one little thing that when you have it, you never notice it. But if it's not there, the absence of it will nab you forever. Let's get that straight. &lt;br&gt;
I don't have a favicon for my site yet, so I somehow need to generate one. A quick way of doing this is to use &lt;a href="https://favicon.io/" rel="noopener noreferrer"&gt;favicon.io&lt;/a&gt;. It lets you generate your favicon out of an image, a couple of characters, or emoji of your like. For simplicity's sake, I decided to go with my first-name characters. You can always change them later if not satisfied. The UI looks something like the below:&lt;br&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%2F60wo58tv08q9ni7rkj15.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%2F60wo58tv08q9ni7rkj15.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the favicon resource files downloaded, the next step is to figure out where to put them. Looking at the theme documentation, there's no mention of which folder it should be put under.  What is the best way to find information if official documentation is insufficient? GitHub, of course! Usually, people will complain about the lack of information on an open-source project's GitHub and submit issues. Let's see if we can find any clue there. After some search, the theme's GitHub page can be found &lt;a href="https://github.com/CaiJimmy/hugo-theme-stack" rel="noopener noreferrer"&gt;here&lt;/a&gt; Search for 'favicon' within the repo, aha, we have 12 issues related to it:&lt;br&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%2Fpu9qi61emy6m9u0vnw1t.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%2Fpu9qi61emy6m9u0vnw1t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The circled issue (though in Chinese) is the one we need, and it pointed us to the &lt;code&gt;/static&lt;/code&gt; folder to put the favicon. I put it under &lt;code&gt;/static/img/&lt;/code&gt;. Then update the &lt;code&gt;config.yaml&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;mainSections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;post&lt;/span&gt;
    &lt;span class="na"&gt;featuredImageField&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;image&lt;/span&gt;
    &lt;span class="na"&gt;rssFullContent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;favicon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;img/favicon-32x32.png&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload, it works!&lt;br&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%2Ffzrjsm2yleifdxonplyw.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%2Ffzrjsm2yleifdxonplyw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Front Matter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gohugo.io/content-management/front-matter/" rel="noopener noreferrer"&gt;Front matter&lt;/a&gt; is the meta-data for your posts. It contains various predefined variables you can use, or you can customize your own if you prefer. It's all very flexible. In them, the &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;categories&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;, and &lt;code&gt;image&lt;/code&gt; are the most important. The &lt;code&gt;categories&lt;/code&gt; and &lt;code&gt;tags&lt;/code&gt; also decide how your content will be organized. &lt;/p&gt;
&lt;h2&gt;
  
  
  Content organizing and feature image
&lt;/h2&gt;

&lt;p&gt;The theme allows for two ways to organize your content: categories and tags. To do so, just include them in your front matter, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;9-things-i-learned-from-blogging-on-medium-for-the-first-month.jpeg&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Things&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Learned&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Blogging&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Medium&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;First&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Month&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Why&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Medium&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;good&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;platform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exchange&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ideas"&lt;/span&gt;
&lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;9-things-i-learned-from-blogging-on-medium-for-the-first-month&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2019-10-04T20:56:10.704Z&lt;/span&gt;
&lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Machine Learning&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Machine&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Learning"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blogging"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Medium"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The theme will collect all your categories/tags defined in all your posts and put them together in the relative 'categories' and 'tags' page. You can also give a feature image for each category or tag. Just create &lt;code&gt;categories&lt;/code&gt; and &lt;code&gt;tags&lt;/code&gt; folder under &lt;code&gt;/content/&lt;/code&gt;, and in each folder, create a subfolder for each category or tag, under which put in &lt;code&gt;_index.md&lt;/code&gt; file and an image (say &lt;code&gt;ML.jpg&lt;/code&gt;). Within the &lt;code&gt;_index.md&lt;/code&gt; file, put a front matter variable &lt;code&gt;image&lt;/code&gt; and point to the image &lt;code&gt;ML.jpg&lt;/code&gt;. Like below:&lt;br&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%2Fanwvk6k1nbpn9b3kuk1t.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%2Fanwvk6k1nbpn9b3kuk1t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once configured, it should look like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/category_feature_image.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/category_feature_image.png" alt="category_feature_image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Shortcodes - Image Captions
&lt;/h2&gt;

&lt;p&gt;Usually, images in &lt;strong&gt;Markdown&lt;/strong&gt; files should be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But unfortunately, this doesn't work well with image captions. After a couple of trial and errors, I found that the Hugo shortcode &lt;code&gt;figure&lt;/code&gt; works pretty well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;{ {&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;figure&lt;/span&gt; &lt;span class="na"&gt;caption=&lt;/span&gt;&lt;span class="s"&gt;"It ain’t much …"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn-images-1.medium.com/max/2000/0*e5CJeyB0_LVFRe4a.jpg"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;} }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like this:&lt;br&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%2Fdcxjpepbpmrn4y7ff3lq.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%2Fdcxjpepbpmrn4y7ff3lq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that the essential pieces are down, time to write a script to transfer my Pelican-based Markdown files to Hugo-based ones. &lt;/p&gt;


&lt;h1&gt;
  
  
  Writing the Pelican to Hugo migration script
&lt;/h1&gt;

&lt;p&gt;Having figured out all the details of making the theme work, now it's time to transfer my posts tailored for Pelican to more Hugo-ready. This can be done easily with some Python scripting. I used code from this &lt;a href="https://github.com/anthonynelzin/PelicanToHugo" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; as a base and adapted to my needs. The code is pretty self-explanatory. It reads every line of the old Markdown file, uses regex to search through phrases, and needs updating and modifying each line accordingly, mostly front matter, image, and video links.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
#
# Pelican to Hugo v20180603
#
# Convert Markdown files using the pseudo YAML frontmatter syntax
# from Pelican to files using the strict YAML frontmatter syntax
# that Hugo and other static engines expect.
#
# Anthony Nelzin-Santos
# https://anthony.nelzin.fr
# anthony@nelzin.fr
#
# European Union Public Licence v1.2
# https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rmtree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;copytree&lt;/span&gt;

    &lt;span class="c1"&gt;#  Add the path to your files below
&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path/to/your/hugo/content/folder&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;inpath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path/to/your/Pelican/content/folder&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pre_process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

    &lt;span class="c1"&gt;# Clear files in outpath
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;rmtree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# copy all Markdown files over
&lt;/span&gt;    &lt;span class="n"&gt;cp_cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cp &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;inpath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/*.md &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cp_cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# need 'shell=True' if passing the whole command as a string
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pelicantohugo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;first_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Input files will be left in place,
&lt;/span&gt;        &lt;span class="c1"&gt;# output files will be suffixed with "_hugo".
&lt;/span&gt;        &lt;span class="n"&gt;regexed_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;_hugo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt;

        &lt;span class="c1"&gt;# Only convert visible Markdown files.
&lt;/span&gt;        &lt;span class="c1"&gt;# This precaution is useless… until it is useful,
&lt;/span&gt;        &lt;span class="c1"&gt;# mainly on .DS_Store-ridden macOS folders.
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.md&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;input_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;output_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regexed_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# The files will be edited line by line using regex.
&lt;/span&gt;            &lt;span class="c1"&gt;# The conversion of a thousand files only takes a few seconds.
&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rU&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Frontmost handling
&lt;/span&gt;                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Title:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Tags:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Date:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Category:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;categories:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Slug:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;slug:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Summary:.*$)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(author:.*$)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(Subtitle:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c1"&gt;# Add closing frontmatter delimiter after the tags.
&lt;/span&gt;                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(\[TOC\].*$)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="c1"&gt;# Add opening frontmatter delimiter before the title.
&lt;/span&gt;                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(title:)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;---\n\1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c1"&gt;# Enclose the title in quotes.
&lt;/span&gt;                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c1"&gt;# Change date formatting.
&lt;/span&gt;                    &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(date: \d{4}-\d{2}-\d{2}) (\d{2}:\d{2})&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\1T\2:00Z&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c1"&gt;# Slow but insightful way to edit the tags.
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="c1"&gt;# Split the comma separated list of tags.
&lt;/span&gt;                        &lt;span class="n"&gt;tag_split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;# Output the new list of tags.
&lt;/span&gt;                        &lt;span class="n"&gt;tag_plist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag_split&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;# Insert a newline before the list.
&lt;/span&gt;                        &lt;span class="n"&gt;tag_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags: \n- \1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag_plist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;# And enclose the tags in quotes.
&lt;/span&gt;                        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;- (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c1"&gt;# get proper slug
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;slug: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="n"&gt;slug_match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;slug: (.*)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slug_match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mkdir &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# create subfolder using slug for feature image
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\(https://cdn.*?\)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
                        &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;!\[(.*?)\]\((https://cdn.*?)\)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;img_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;img_caption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;first_img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# for first image which is the feature image, need special handling
&lt;/span&gt;                            &lt;span class="n"&gt;first_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
                            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\.((?:jpg|png|jpeg|gif|svg))&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
                                &lt;span class="n"&gt;img_e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\.((?:jpg|png|jpeg|gif|svg))&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="n"&gt;img_ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img_e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="n"&gt;img_ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
                            &lt;span class="c1"&gt;# download image from Medium and put into the created subfolder
&lt;/span&gt;                            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wget -O &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img_ext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
                        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="c1"&gt;# all other images just extract the image url and put into 'figure' shortcode
&lt;/span&gt;                            &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;figure&lt;/span&gt; &lt;span class="n"&gt;caption&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img_caption&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

                    &lt;span class="c1"&gt;# YouTube shortcode
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/embed/(.*?)&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="n"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/embed/(.*?)&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;video_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;youtube&lt;/span&gt; &lt;span class="n"&gt;video_code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
                    &lt;span class="n"&gt;fo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;# Print a little something about the conversion.
&lt;/span&gt;                &lt;span class="c1"&gt;#print(file_name + ' converted.')
&lt;/span&gt;            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# when all is ready, set the 'image:' front matter correctly so feature image could work
&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;image_meta_added&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Add opening frontmatter delimiter before the title.
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;image_meta_added&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;first_img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(---)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;image: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img_ext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;image_meta_added&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
                    &lt;span class="n"&gt;fo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;first_img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mv &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;outpath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/index.md&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;pre_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;pelicantohugo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Some points worth noticing:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;The script will remove everything in the output folder(Hugo content folder) and regenerate them all from the source folder. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Front matter&lt;/strong&gt;: Heavily use regex to replace meta-data. e.g. from 'Title' to 'title', 'Subtitle' to 'description', date format, etc. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image&lt;/strong&gt;: Extract Medium CDM URL, download the image, and put it under post subfolder so that the feature image could work. Other images were put into a &lt;code&gt;{{figure}}&lt;/code&gt; Hugo shortcode for better captioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YouTube&lt;/strong&gt;: extract the video ID and put it into &lt;code&gt;{{youtube}}&lt;/code&gt; Hugo shortcode. It works like a charm.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Transfer my new Medium posts into Hugo markdown
&lt;/h2&gt;

&lt;p&gt;I have some Medium posts that have not yet been transferred to my Pelican blog, so another script is needed. No need to write it myself. I used a Python script from the &lt;a href="https://github.com/chamilad/medium-to-hugo" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;. You need to use Medium's export service to get all your posts into a zip file and then use the script to turn them into Hugo markdown. Since there weren't many posts, I did some adapting manually to create the subfolders for each article so the feature image could work. &lt;/p&gt;

&lt;h1&gt;
  
  
  Switch repo on Netlify
&lt;/h1&gt;

&lt;p&gt;Finally, we have everything we need, now is the time to toggle the switch on Netlify from Pelican to Hugo. Exciting!&lt;br&gt;
First of all, I created a repo for the Hugo site, &lt;a href="https://github.com/wayofnumbers/wayofnumbers_hugo" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;br&gt;
Then, log into my Netlify account,  go to my site, then hit &lt;code&gt;SIte Settings&lt;/code&gt;:&lt;br&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%2Fbyd92hsw6eziaywje7l8.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%2Fbyd92hsw6eziaywje7l8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;code&gt;Build &amp;amp; Deploy&lt;/code&gt; tab, then hit &lt;code&gt;Edit Settings&lt;/code&gt;, like so:&lt;br&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%2F2azokc9hlyb7vzz9qyr9.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%2F2azokc9hlyb7vzz9qyr9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;code&gt;Link to a different repository-&amp;gt;&lt;/code&gt;,  a wizard screen will show up, where you can pick your Hugo repository. Do that, and do some basic build settings. Among them, notice the build command is simply &lt;code&gt;hugo&lt;/code&gt;.  One thing worth noticing is the Hugo version. The default Hugo version on Netlify is not high enough to properly build my site, and I ran into many weird errors. I found the solution to add a &lt;code&gt;netlify.toml&lt;/code&gt; on my site root directory and assign the Hugo version inside of it. You can find the reference guide &lt;a href="https://docs.netlify.com/configure-builds/common-configurations/hugo/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
Once all settings are done, a new build generates the new site. &lt;/p&gt;




&lt;h1&gt;
  
  
  Overall Feeling
&lt;/h1&gt;

&lt;p&gt;Wow, this is a long post. I appreciate whoever made this far. I hope this long article helps a bit on your journey into the HUGO land. Finally, I want to share my overall feelings of the whole process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's not hard but requires some ironing out quite some wrinkles. (Also the fun part?)&lt;/li&gt;
&lt;li&gt;Theme adopting takes the longest time. The documentation helps but often not complete. Github issues help tremendously. &lt;/li&gt;
&lt;li&gt;There are a lot of very kind people who wrote scripts to automate the migration. Use them, but don't hesitate to modify them to your needs. A little programming goes a long way, especially when you have many articles.&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://youtube.com/playlist?list=PLLAZ4kZ9dFpOnyRlyS-liKL5ReHDcj4G3" rel="noopener noreferrer"&gt;YouTube series&lt;/a&gt; I use to learn Hugo basics, all in bite-size.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>blog</category>
      <category>hugo</category>
      <category>pelican</category>
      <category>datascience</category>
    </item>
    <item>
      <title>How to Extract Knowledge from Wikipedia, Data Science Style</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Sun, 09 Feb 2020 06:07:41 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/how-to-extract-knowledge-from-wikipedia-data-science-style-44h8</link>
      <guid>https://dev.to/wayofnumbers/how-to-extract-knowledge-from-wikipedia-data-science-style-44h8</guid>
      <description>&lt;p&gt;As Data Scientists, people tend to think what they do is developing and experimenting with sophisticated and complicated algorithms, and produce state of the art results. This is largely true. It is what a data scientist is mostly proud of and the most innovative and rewarding part. But what people usually don’t see is the sweat they go through to gather, process, and massage the data that leads to the great results. That’s why you can see SQL appears on most of the data scientist position requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SPARQL?
&lt;/h2&gt;

&lt;p&gt;There is another query language that could prove very useful in acquiring data from multiple sources and databases, Wikipedia the biggest among them. The query language is called &lt;a href="https://en.wikipedia.org/wiki/SPARQL"&gt;SPARQL&lt;/a&gt;. According to Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SPARQL&lt;/strong&gt; (pronounced “&lt;a href="https://en.wiktionary.org/wiki/sparkle"&gt;sparkle&lt;/a&gt;”, a &lt;a href="https://en.wikipedia.org/wiki/Recursive_acronym"&gt;recursive acronym&lt;/a&gt;&lt;a href="https://en.wikipedia.org/wiki/SPARQL#cite_note-2"&gt;[2]&lt;/a&gt; for &lt;strong&gt;SPARQL Protocol and RDF Query Language&lt;/strong&gt;) is an &lt;a href="https://en.wikipedia.org/wiki/RDF_query_language"&gt;RDF query language&lt;/a&gt; — that is, a &lt;a href="https://en.wikipedia.org/wiki/Semantic_Query"&gt;semantic&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Query_language"&gt;query language&lt;/a&gt; for &lt;a href="https://en.wikipedia.org/wiki/Database"&gt;databases&lt;/a&gt; — able to retrieve and manipulate data stored in &lt;a href="https://en.wikipedia.org/wiki/Resource_Description_Framework"&gt;Resource Description Framework (RDF)&lt;/a&gt; format&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, this is not a very good definition. It hardly tells you what it can do. To translate it into human-readable language:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SPARQL is a query language similar to SQL in syntax but works on a knowledge graph database like Wikipedia, that allows you to extract knowledge and information by defining a series of filters and constraints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this is still too abstract to you, look at the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMyMqq3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3678/1%2AETRq9qAH__AxcScjgV3J3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMyMqq3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3678/1%2AETRq9qAH__AxcScjgV3J3g.png" alt="Awarded Chemistry Nobel Prizes"&gt;&lt;/a&gt;&lt;em&gt;Awarded Chemistry Nobel Prizes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is a timeline of awarded chemistry Nobel prizes, generated by the &lt;a href="https://w.wiki/4EU"&gt;WikiData Query Service&lt;/a&gt; website, using the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;Awarded&lt;/span&gt; &lt;span class="n"&gt;Chemistry&lt;/span&gt; &lt;span class="n"&gt;Nobel&lt;/span&gt; &lt;span class="n"&gt;Prizes&lt;/span&gt;
    &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;defaultView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Timeline&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;itemLabel&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;YEAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;when&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;pic&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;P166&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;awardStat&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;awarded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;P166&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;statement&lt;/span&gt;
      &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;awardStat&lt;/span&gt; &lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;P166&lt;/span&gt; &lt;span class="n"&gt;wd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Q44585&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;Nobel&lt;/span&gt; &lt;span class="n"&gt;Prize&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Chemistry&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Q35637&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;awardStat&lt;/span&gt; &lt;span class="n"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;P585&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;did&lt;/span&gt; &lt;span class="n"&gt;he&lt;/span&gt; &lt;span class="n"&gt;receive&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;Nobel&lt;/span&gt; &lt;span class="n"&gt;prize&lt;/span&gt;

    &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;wikibase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="n"&gt;bd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;serviceParam&lt;/span&gt; &lt;span class="n"&gt;wikibase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="nv"&gt;"en"&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;OPTIONAL&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;wdt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;P18&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;pic&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anyone familiar with SQL will find the above code quite intuitive. I’ll use another example to explain basically how to formulate similar queries to achieve the results you interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Point: Wikipedia Page
&lt;/h2&gt;

&lt;p&gt;SPARQL works on multiple knowledge graph databases. To know what knowledge graph is, let’s start with something everyone is familiar with: Wikipedia. Wikipedia is the go-to place for most people when they want to research a topic/subject. If you go to Python creator Guido van Rossum’s page, you’ll see a detailed page with all kinds of good information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0OZ756r5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2006/1%2Agy5Rtamq6tljmSGYi3tkqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0OZ756r5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2006/1%2Agy5Rtamq6tljmSGYi3tkqg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Organized Page: WikiData
&lt;/h2&gt;

&lt;p&gt;The problem with this page is it’s not organized. You can search on keywords, but you cannot easily find out the relationship between the information nodes. That’s where the knowledge graph comes into play. The red rectangle on the above page spells “Wikidata Item”, click it will bring you to the knowledge graph view of the same page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dfsx6Qed--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2022/1%2AuxmaEbK9lTe_R_pztxP_6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dfsx6Qed--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2022/1%2AuxmaEbK9lTe_R_pztxP_6w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start the Query
&lt;/h2&gt;

&lt;p&gt;Here we can see all information about Guido is well organized into categories, each category has multiple items. Use SPARQL, you can easily query this information. To do this, Wikipedia provides another page, a user-friendly query service called &lt;a href="https://query.wikidata.org"&gt;Wikidata Query Service&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2nl4XSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2064/1%2ALLZ7jonrSLTH96uR1HnNSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2nl4XSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2064/1%2ALLZ7jonrSLTH96uR1HnNSA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where we can experiment with SPARQL. On the WikiData page, we observed that Guido is a programmer (obviously!), now what if we want to know other programmers that have an entry on Wikipedia? Let’s see the SPARQL code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ?person

WHERE {

?person wdt:P106 wd:Q5482740 .

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we defined a ?person as the **subject **of interest, this is also what will appear as a column in our query results. Then we specify some constraints with WHERE . The constraints are wdt:P106 need to be wd:Q5482740. What? You say. Let me explain it in more detail. wdt is a prefix of a ‘predicate’ or ‘attribute’ of the subject while wd is the prefix of a value(object in SPARQL terms, but that’s not important) of the attribute. wdt: means I am gonna specify an attribute of the subject here, and wd: means I will specify what the value of this attribute is. So what is P106 and Q5482740 ? These are just a code for the specific attribute and value. P106 stands for ‘occupation’ and Q5482740 stands for ‘programmer’. This line of code means, I want the ?person subject to have an attribute of ‘occupation’ of ‘programmer’. Not that scary anymore, right? You can find these codes easily on the WikiData page mentioned above.&lt;/p&gt;

&lt;p&gt;Run the query and you’ll get the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XoL7AweZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2AlAz6legzUdahHVQDRkIYdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XoL7AweZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2AlAz6legzUdahHVQDRkIYdw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  From Code to Name
&lt;/h2&gt;

&lt;p&gt;We got a bunch of person items with different wd:value . If you look closer at the value, they are actually the code for a different person. For example, the first one wd:Q80 is &lt;a href="https://www.wikidata.org/wiki/Q80"&gt;Tim Berners-Lee&lt;/a&gt;, the inventor of WWW. This is not intuitive, we want to be able to directly see the names. To do that, we add a WikiData ‘label service’ that helps us translate the code to name, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ?person ?personLabel

WHERE {

  ?person wdt:P106 wd:Q5482740 .
  ?person rdfs:label ?personLabel .
  FILTER ( LANGMATCHES ( LANG ( ?personLabel ), "fr" ) ) 

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Similar syntax, we want the person to have a ‘label’ attribute, and we define a personLabel value variable to hold these values so we can display them in the query results. Also, we added the personLabel into our SELECT phrase so it will be displayed. Please be noted that I also added a FILTER below to only display the French language label, otherwise it will show multiple language labels for one person, which is not what we want:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yOmPFiA0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2AYOPEjLCa4cb0J0A8iV7B8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yOmPFiA0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2AYOPEjLCa4cb0J0A8iV7B8g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrowing Down
&lt;/h2&gt;

&lt;p&gt;From the above results, we can see that we have some 790 results. This is way too many. Let’s narrow them down to the ones that are ‘somebody’ in the industry. Someone that has an attribute of ‘notable work’:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ?person ?personLabel ?notableworkLabel

WHERE {

?person wdt:P106 wd:Q5482740 .
  ?person rdfs:label ?personLabel .
  FILTER ( LANGMATCHES ( LANG ( ?personLabel ), "fr" ) ) 

  ?person wdt:P800 ?notablework .
  ?notablework rdfs:label ?notableworkLabel .
  FILTER ( LANGMATCHES ( LANG ( ?notableworkLabel ), "fr" ) ) 

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Again, wdt:P800 means ‘notable work’ attribute, everything else is similar. We then get the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LKocIDpU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2062/1%2Abm_RqgE7k3h1QJL4JlBDew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LKocIDpU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2062/1%2Abm_RqgE7k3h1QJL4JlBDew.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Group Multiple Labels
&lt;/h2&gt;

&lt;p&gt;Now we have only 175 results, with each person’s notable work also listed. But wait, why we have five Richard Stallman? Turns out, Richard has more than one notable work, thus listed multiple times in the results. Let’s fix this by grouping all the notable work into one attribute:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ?person ?personLabel ( GROUP_CONCAT ( DISTINCT ?notableworkLabel; separator="; " ) AS ?works )

WHERE {

?person wdt:P106 wd:Q5482740 .
  ?person rdfs:label ?personLabel .
  FILTER ( LANGMATCHES ( LANG ( ?personLabel ), "fr" ) ) 

  ?person wdt:P800 ?notablework .
  ?notablework rdfs:label ?notableworkLabel .
  FILTER ( LANGMATCHES ( LANG ( ?notableworkLabel ), "fr" ) ) 

}

GROUP BY ?person ?personLabel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here ‘GROUP BY’ is used. Also, GROUP_CONCAT function is used to concatenate multiple notableworkLabel into a new column works (&lt;em&gt;I will not explain how these functions work, just want to quickly show you what SPARQL can do. Please feel free to Google if you want to know more, there are plenty of tutorial articles and videos out there)&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3s_PS31w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2A0mw90V_sdEcAh6iC1GfEYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3s_PS31w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2068/1%2A0mw90V_sdEcAh6iC1GfEYA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Faces
&lt;/h2&gt;

&lt;p&gt;Now we have a 90 results list, with all the ‘who-is-who’ in the software engineering world. But SPARQL can do more. Let’s add some faces to the names:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ?person ?personLabel ( GROUP_CONCAT ( DISTINCT ?notableworkLabel; separator="; " ) AS ?works ) ?image

WHERE {

?person wdt:P106 wd:Q5482740 .
  ?person rdfs:label ?personLabel .
  FILTER ( LANGMATCHES ( LANG ( ?personLabel ), "fr" ) ) 

  ?person wdt:P800 ?notablework .
  ?notablework rdfs:label ?notableworkLabel .
  FILTER ( LANGMATCHES ( LANG ( ?notableworkLabel ), "fr" ) ) 

  OPTIONAL {?person wdt:P18 ?image}

}

GROUP BY ?person ?personLabel ?image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The same pattern, we just added an OPTIONAL keyword prior since we don’t want to exclude someone if he doesn’t have an image in his profile. We also switch the view into ‘Image Grid’ :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dSyWbJqB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2008/1%2ACV1Nh0HXqUcSr3bNyEzbTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dSyWbJqB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2008/1%2ACV1Nh0HXqUcSr3bNyEzbTQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are they?
&lt;/h2&gt;

&lt;p&gt;Wow! This is much better. I saw quite some familiar faces! Maybe you wonder where are these guys located? Let’s find out:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#defaultView:ImageGrid

SELECT ?person ?personLabel ( GROUP_CONCAT ( DISTINCT ?notableworkLabel; separator="; " ) AS ?works ) ?image ?countryLabel ?cood

WHERE {
  ?person wdt:P106 wd:Q5482740 .
  ?person rdfs:label ?personLabel .
  FILTER ( LANGMATCHES ( LANG ( ?personLabel ), "fr" ) ) 

  ?person wdt:P800 ?notablework .
  ?notablework rdfs:label ?notableworkLabel .
  FILTER ( LANGMATCHES ( LANG ( ?notableworkLabel ), "fr" ) ) 


  OPTIONAL {?person wdt:P18 ?image}

  OPTIONAL {?person wdt:P19 ?country .
           ?country rdfs:label ?countryLabel .
            ?country wdt:P625 ?cood .
            FILTER ( LANGMATCHES ( LANG ( ?countryLabel ), "fr" ) )
           }

}

GROUP BY ?person ?personLabel ?image ?countryLabel ?cood
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can decipher the code above yourself maybe. It basically says I want this person to have an attribute of country, put into a variable country, then find out the coordinates of the country and put into a variable cood. With the coordinates, we can activate the ‘map’ view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VQNvIWUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A1DJ6txmZ7n6OCuU0NuPD3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VQNvIWUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A1DJ6txmZ7n6OCuU0NuPD3A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see we have a lot of them in the US, some in Europe and others scattered around other parts of the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Examples
&lt;/h2&gt;

&lt;p&gt;With a few lines of codes, we figured out the big influencers in the software industry, what they are known of, where they are and how they look. As you can see the potential here is limitless.&lt;/p&gt;

&lt;p&gt;You can click the ‘&lt;strong&gt;Example&lt;/strong&gt;’ button on the WikiData page to find out more fun and interesting examples you can do with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ej7LFYpG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A8fzA238U6A1nRtJB1Emx_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ej7LFYpG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A8fzA238U6A1nRtJB1Emx_A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an assignment for this article, can you figure out how to add the ‘date of birth’ attribute and generate a timeline graph like the one at the beginning of this article?&lt;/p&gt;

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

&lt;p&gt;In this article, we used WikiData as a knowledge graph example to introduce SPARQL query language. There are other knowledge graphs out there like &lt;a href="https://en.wikipedia.org/wiki/DBpedia"&gt;DBpedia&lt;/a&gt;, etc. This article is by no means a comprehensive tutorial. I just want to introduce the language to more people, so knowledge and information extraction can be done a bit more efficiently.&lt;/p&gt;

</description>
      <category>sparql</category>
      <category>sql</category>
      <category>wikidata</category>
      <category>ontology</category>
    </item>
    <item>
      <title>5 Things I Learned from Google’s New ML-Powered Recorder App</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Thu, 06 Feb 2020 15:50:14 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/5-things-i-learned-from-google-s-new-ml-powered-recorder-app-5aei</link>
      <guid>https://dev.to/wayofnumbers/5-things-i-learned-from-google-s-new-ml-powered-recorder-app-5aei</guid>
      <description>&lt;p&gt;There are tons of audio recording apps in the app store, but you know things will be a bit different if Google developed a brand new one. Google recently released a new ‘&lt;a href="https://play.google.com/store/apps/details?id=com.google.android.apps.recorder"&gt;Recorder&lt;/a&gt;’ app that is powered by its state-of-the-art Machine Learning algorithm that can transcribe what it hears with impressive precision in real-time. This is not the first time Google tried to bless its product with some AI ‘superpower’. Some of their prior attempts failed (I’m talking to you &lt;a href="https://www.engadget.com/2019/10/16/google-discontinues-clips-camera/"&gt;Google Clips&lt;/a&gt;!) and some had quite formidable success, for example, Google’s Pixel phone camera app. With the camera hardware spec a little below industry mainstream, Google’s Pixel flagship phone managed to pull off as &lt;a href="https://www.androidauthority.com/best-camera-phones-670620/"&gt;one of the best smartphone cameras on the market&lt;/a&gt; thanks to its Machine Learning algorithms for image post-processing. The ‘Recorder’ app is yet another attempt by Google to spice up competition using AI, this time on audio.&lt;/p&gt;

&lt;p&gt;After digging deeper into what the app can do differently and how AI played a core role in it, I found some very interesting insights on how Google handles app, AI and user experience that could shed some light on future app development in the AI-era.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Google Recorder?
&lt;/h2&gt;

&lt;p&gt;You can refer to the following short YouTube video on what Recorder does. In short, you can use it to do real-time transcription, search recorded audio by keywords, automatically generate tags or segment the audio into different categories like music, speech, etc.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/RVMqB4W_EH4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I’ve been using it for more than a week and found it to be useful, slick and pleasant to use. Recording audio is not a complicated task, but the AI part makes it even easier. I can see this little app makes a big difference for students and people attending meetings regularly.&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 Adoption of Edge-First Model Design
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5KFW3Fen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aln5CfxKmWRUMQTsG.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5KFW3Fen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aln5CfxKmWRUMQTsG.jpg" alt="Image from[ WishDesk](https://www.google.com/url?sa=i&amp;amp;source=images&amp;amp;cd=&amp;amp;cad=rja&amp;amp;uact=8&amp;amp;ved=2ahUKEwi8qsaS4c7mAhVFXawKHXf6BSsQjB16BAgBEAM&amp;amp;url=https%3A%2F%2Fwishdesk.com%2Fblog%2Fwhat-mobile-first-design&amp;amp;psig=AOvVaw1Z2T4KkHv8kJl4UFvKoWF-&amp;amp;ust=1577293156997339)"&gt;&lt;/a&gt;&lt;em&gt;Image from&lt;a href="https://www.google.com/url?sa=i&amp;amp;source=images&amp;amp;cd=&amp;amp;cad=rja&amp;amp;uact=8&amp;amp;ved=2ahUKEwi8qsaS4c7mAhVFXawKHXf6BSsQjB16BAgBEAM&amp;amp;url=https%3A%2F%2Fwishdesk.com%2Fblog%2Fwhat-mobile-first-design&amp;amp;psig=AOvVaw1Z2T4KkHv8kJl4UFvKoWF-&amp;amp;ust=1577293156997339"&gt; WishDesk&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We all heard of the term ‘Mobile-First Design’. When companies develop their applications, they will design and optimize their app based on mobile experience first, then to other platforms like desktop or web. I think the same idea can also be applied to AI-powered application design, hence ‘Edge-First Design’.&lt;/p&gt;

&lt;p&gt;Usually, Machine Learning based applications run on the cloud, this is due to the heavy computation requirements for most state-of-the-art ML models. For enterprise applications, this approach is fine since the hardware is hardly a real issue. But if a company wants to build impactful AI-based apps for the consumers, then a cloud-based system often won’t cut it. Running AI-based apps from the cloud is not only slow but also has serious privacy concerns. Also to the normal consumer, they are used to the snappiness modern mobile apps offers. They can care less whether your app is based on some SOTA models or not, if the experience cannot match the high standard they get used to, boosted by many years of modern smartphone hardware/software development. So putting the AI on the ‘Edge’, e.g. user’s phone, tablet, smart home devices will be a better way to success.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6yESXwZs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2400/0%2AqaLMK3_40cM494G1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6yESXwZs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2400/0%2AqaLMK3_40cM494G1.png" alt="Image from Lann"&gt;&lt;/a&gt;&lt;em&gt;Image from Lann&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Google Recorder app did a great job on this. It uses a new model called ‘&lt;a href="https://arxiv.org/pdf/1211.3711.pdf"&gt;**RNN transducer(RNN-T)&lt;/a&gt;**’ that is compact enough to reside on the phone while powerful enough to do real-time transcription. Instead of the traditional ‘pipeline’ approach, the RNN-T model uses a &lt;a href="https://www.youtube.com/watch?v=ImUoubi_t7s"&gt;single neural network, end-to-end approach&lt;/a&gt; which is growingly more popular to solve complicated problems. Until recently, we’ve seen a lot of research progress being made on increasing the prediction performance by using bigger and bigger models, yet the opposite direction is equally important: Using as compact a model as possible to achieve similar performance so the model can be put on the edge. I expect more research to be done in this area when machine learning matures in the coming years.&lt;/p&gt;

&lt;h2&gt;
  
  
  #2 Use Different Technology Stack for Performance
&lt;/h2&gt;

&lt;p&gt;Another interesting development is the introduction of &lt;a href="https://www.tensorflow.org/swift"&gt;Swift for TensorFlow&lt;/a&gt;. Created by the creator of Swift programming language, &lt;a href="https://en.wikipedia.org/wiki/Chris_Lattner"&gt;Chris Lattner&lt;/a&gt;. It uses open-source Swift language with TensorFlow and promises both fast development time like Python and high-level performance like C++. &lt;a href="http://fast.ai"&gt;Fast.ai&lt;/a&gt; has a great &lt;a href="https://blog.tensorflow.org/2019/06/fastais-deep-learning-from-foundations_28.html"&gt;introductory course&lt;/a&gt; on it. With ML moving more and more from research labs to commercial applications, the performance of ML models will play a much bigger role and Swift for TensorFlow has great potential on that. According to the founder of &lt;a href="http://fast.ai"&gt;fast.ai&lt;/a&gt;, Jeremy Howard:&lt;br&gt;
&lt;a href="https://developer.apple.com/videos/play/wwdc2019/209/"&gt;&lt;strong&gt;What's New in Machine Learning - WWDC 2019 - Videos - Apple Developer&lt;/strong&gt;&lt;br&gt;
*Core ML 3 has been greatly expanded to enable even more amazing, on-device machine learning capabilities in your app…*developer.apple.com&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Swift can match the performance of hand-tuned assembly code from numerical library vendors. Swift for TensorFlow is the first serious effort I’ve seen to incorporate differentiable programming deep into the heart of a widely used language that is designed from the ground up for performance”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  #3 Privacy Matters
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PcMcFGj5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/11520/0%2Arw-NMk45j3aa8EF9" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PcMcFGj5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/11520/0%2Arw-NMk45j3aa8EF9" alt="Photo by [Matthew Henry](https://unsplash.com/@matthewhenry?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@matthewhenry?utm_source=medium&amp;amp;utm_medium=referral"&gt;Matthew Henry&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest concerns for AI applications is privacy. For AI to really show value, it has to know a lot about the user, often times their personal life details people don’t feel comfortable sharing. Take audio recording as an example, you might want to record your family meeting discussing your next Christmas plan but don’t want it to be transferred onto the cloud and get 10 Christmas travel agents calling you to sell their products. This gives ‘offline’ ML apps an advantage. Since the model is deployed locally on the edge and no data need to be transferred to the cloud, the user can feel assured that their privacy can be protected. The Recorder app runs all the models on-device and makes it a bit less reluctance for people to adopt it.&lt;/p&gt;

&lt;h2&gt;
  
  
  #4 User Experience Design is Still the Key
&lt;/h2&gt;

&lt;p&gt;The Recorder app has a very slick and elegant UI. It’s a simple app with minimal clutters. You can easily start/pause your recording, toggle between ‘Audio’ or ‘Transcript’ mode to check your recorded content and getting suggestions on tags from the content recorded. All works without friction.&lt;/p&gt;

&lt;p&gt;During recording, the app will automatically categorize sections of audio as ‘Speech’, ‘Music’, ‘Whistling’ … etc. and color code them accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0nRMJhKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/2560/0%2ADxe5mkbWE1L-trgT.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0nRMJhKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/2560/0%2ADxe5mkbWE1L-trgT.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When playback your recorded audio, you can see each word get highlighted when being spoken in the transcript mode and you can search through the transcripts use the keyword you want. Very intuitive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jgSDDyte--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/2560/0%2AnEF5vXInKw71Nf2y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jgSDDyte--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/2560/0%2AnEF5vXInKw71Nf2y.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I’m trying to say is: User experience design will make or break a great AI model. Only when working seamlessly with other parts of the app can an AI feature delivers its value to the end-user. A model that can address the user’s paint-point with high performance is only a start, not the end. AI should serve silently behind the scenes rather take the center stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  #5 Responsiveness Come with a Price
&lt;/h2&gt;

&lt;p&gt;In the mobile world, companies strive to offer more responsiveness. Consumers nowadays are very impatient and the last thing they want is to wait. Snappy experience means the user can focus on the content they want or the tasks at hand. But responsiveness on mobile devices is not easy to come by. Computing power, screen size, system resources are all very limited compare to desktop or cloud. To achieve the best responsiveness, more thoughts and research need to be put into the design and development of the app. This includes better use of CPU/GPU, memory optimization, choose fast programming languages for the implementation and reduce dependence on back-end servers. The Machine Learning industry has made great progress on research for the past few years, yet to have more impact on people’s day-to-day life, more investment and work has to be done on the engineering side. And a switch from research to engineering is a sign of matureness for new technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Right Way of Developing AI Applications?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kqBOuvLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3840/0%2AjIEExvGIlAay-wgq" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kqBOuvLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3840/0%2AjIEExvGIlAay-wgq" alt="Image from Overwatch"&gt;&lt;/a&gt;&lt;em&gt;Image from Overwatch&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;People have this fantasy of scary AI taking over humanity for many years. Movies, novels, TV Shows all painted a very dramatic future of AI for mankind. To counter this public (biased?) impression on AI, special cautions need to be taken. It’s beneficial to adopt an ‘AI exist as a tool to help human’ mentality instead of an ‘AI vs Mankind’ one. AI can do a lot of things, but rather than develop AI apps that can ‘replace’ humans, it’s better to have AI that exists to help humans perform their tasks easier and faster. Like the Recorder app to help taking notes, image recognition systems to help the doctor diagnose better, augment reality app to help people better navigate the neighborhood, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  &lt;em&gt;A quiet, friendly, yet powerful AI diligently working behind the scenes to help people do whatever they do better is so much more comfortable and approachable for people, compare to a robotic killing machine in a SciFi movie.&lt;/em&gt;
&lt;/h1&gt;
&lt;/blockquote&gt;

</description>
      <category>machinelearning</category>
      <category>ux</category>
      <category>nlp</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Two Sides of the Same Coin: Jeremy Howard's fast.ai vs Andrew Ng's deeplearning.ai</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Tue, 04 Feb 2020 02:04:15 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/two-sides-of-the-same-coin-jeremy-howard-s-fast-ai-vs-andrew-ng-s-deeplearning-ai-80p</link>
      <guid>https://dev.to/wayofnumbers/two-sides-of-the-same-coin-jeremy-howard-s-fast-ai-vs-andrew-ng-s-deeplearning-ai-80p</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9hb--Tzd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2Aexk4TRN--2VW9fQT64MhdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9hb--Tzd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2Aexk4TRN--2VW9fQT64MhdA.png" alt="Which One to Take? WHY NOT BOTH!"&gt;&lt;/a&gt;&lt;em&gt;Which One to Take? WHY NOT BOTH!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Data science and artificial intelligence might be the hottest topic in tech right now, and rightfully so. There are tremendous breakthroughs both on application level and research fields. This is a blessing, and a curse, at least for students and enthusiasts that want to break into this area. There are too many algorithms to learn, too many coding/engineering skills to hone, and way too many new papers to keep up with even if you felt you’ve mastered the art.&lt;/p&gt;

&lt;p&gt;The journey is long, the learning curve is steep, the strife is real, yet the potential is so great people still flock into it. The good thing is we also have great educators and instructors working on mitigating the pain and make the process a little less harsh and a bit more fun. We’ll explore two of the greatest among them and share a potentially effective approach to help you swim through the sea of Data Science a bit happier.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Learning ‘Burn-out’
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WcHFkmVk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/6552/0%2AvniRBklRl5-vxXQU" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WcHFkmVk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/6552/0%2AvniRBklRl5-vxXQU" alt="Photo by [Toa Heftiba](https://unsplash.com/@heftiba?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@heftiba?utm_source=medium&amp;amp;utm_medium=referral"&gt;Toa Heftiba&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you list what one needs to learn to become an ‘OK’ data scientist or machine learning engineer, it could be scarily long:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Math:&lt;/strong&gt; Linear Algebra, Calculus, Statistics, Algorithms, …&lt;br&gt;
&lt;strong&gt;Coding:&lt;/strong&gt; Python, R, SQL/NoSQL, Hadoop, Spark, Tensorflow/PyTorch, Keras, Numpy, Pandas, OpenCV, Data Visualization…&lt;br&gt;
**Algorithms: **Linear Regression, Logistic Regression, Support Vector Machine, PCA, Anomaly Detection, Collaborative Filtering, Neural Network, CNN, RNN, K-Means, NLP, Deep Learning, Reinforcement Learning, AutoML, …&lt;br&gt;
**Engineering: **Command Line, Cloud platform(AWS, GCP, Asure), DevOps, Deployment, NGINX/Apache, Docker…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The list can easily make the head spin for a person just entering the filed. Yet, it is still just scratching the surface. Some people make &lt;a href="https://github.com/llSourcell/Learn_Machine_Learning_in_3_Months"&gt;an ambitious plan&lt;/a&gt;(&lt;a href="https://dev.toundefined"&gt;Siraj Raval&lt;/a&gt;’s plan is great btw) and dive right into it. Some lost momentum and felt totally under the water and the exit is nowhere to be seen. What went wrong?&lt;/p&gt;

&lt;h2&gt;
  
  
  You ‘Overfit’ Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SToQPbad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2512/0%2AtAHgUC2bqm0nefpg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SToQPbad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2512/0%2AtAHgUC2bqm0nefpg.PNG" alt="From Andrew Ng’s Machine Learning course"&gt;&lt;/a&gt;&lt;em&gt;From Andrew Ng’s Machine Learning course&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Overfitting is a very familiar idea for anyone that knows a bit of Machine Learning. It basically means your algorithm learned ‘too much’ of the data and buried itself into the little details of the data-set and missing the big picture. Come to think of it, sometimes when we learn something, we dive so deep we forgot why we were learning it and how it will fit into the big picture. It’s something I’d like to call ‘overfitting’ your own learning. This happens especially often for people coming from academia background. A math Ph.D. tends to make sure all the theorems are fully understood before proceeding to the next one. This is great for learning math. Have a profound understanding of theories will give you great intuition and confidence. It will enable you to see patterns and issues people without the training cannot see easily, yet Data Science demands more.&lt;/p&gt;

&lt;p&gt;Theory aside, there is also a practical part to it. A properly applied algorithm coupled with efficient codes, carefully tuned hyper-parameters, and well-designed pipeline will usually achieve decent results, but not algorithm alone. Delve down too deep into theory, and you risk missing the practical side of the learning. It’s equally important to accumulate experiences on how to implement what you learned and handle real-life complexities. How to address this? Entering deeplearning.ai and fast.ai courses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deeplearning.ai and Fast.ai
&lt;/h2&gt;

&lt;p&gt;A lot of courses have been developed to help navigate people through the learning process. Among them, Deeplearning.ai and fast.ai are two unique ones that have their own approaches and can give us some insights into a potentially effective way of learning Data Science.&lt;/p&gt;

&lt;h3&gt;
  
  
  deeplearning.ai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9V5zx7ik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2160/0%2AH0fyjfnf0KgEx91q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9V5zx7ik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2160/0%2AH0fyjfnf0KgEx91q.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.deeplearning.ai/"&gt;deeplearning.ai&lt;/a&gt; is a paid course developed by &lt;a href="https://dev.toundefined"&gt;Andrew Ng&lt;/a&gt;. &lt;a href="https://medium.com/datadriveninvestor/thoughts-on-andrew-ngs-machine-learning-course-7724df76320f"&gt;Like his other courses&lt;/a&gt;, it is known for its well-designed learning curve, calm and smooth teaching style, and challenging while fun assignments. It is well accepted as the Deep Learning course one cannot go wrong with. It starts from the fundamental theories and works its way up on how to put all the pieces together to solve real-life problems. It’s also called a ‘Bottom-up’ approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  fast.ai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aW3JZPSg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5200/0%2AW1zoWbhNPkQk7zar.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aW3JZPSg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5200/0%2AW1zoWbhNPkQk7zar.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;fast.ai is introduced by &lt;a href="https://dev.toundefined"&gt;Jeremy Howard&lt;/a&gt; and &lt;a href="https://dev.toundefined"&gt;Rachel Thomas&lt;/a&gt; as a free course to teach people with basic coding experience state-of-the-art deep learning techniques. Without much explanation of the underlying theories, with very few lines of code, student of fast.ai is capable of achieving astoundingly great results on its own domain quickly into the lessons. (I built a &lt;a href="https://medium.com/datadriveninvestor/deep-learning-models-by-fast-ai-library-c1cccc13e2b3"&gt;Chinese Calligraphy Style Classifier that reaches 96% accuracy&lt;/a&gt; rate and &lt;a href="https://towardsdatascience.com/how-to-deploy-your-machine-learning-web-app-to-digital-ocean-64bd19ce15e2"&gt;deployed it on the cloud&lt;/a&gt; after finishing lesson 1 of fast.ai course.) It teaches you how to tackle the real-world problem first, then digs deeper and deeper into how and why things work. It’s also called a ‘Top-down’ approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which One is the Best Approach? Both!
&lt;/h2&gt;

&lt;p&gt;So ‘Bottom-up’ and ‘Top-down’, which one is better? Which one should we take? The answer is &lt;strong&gt;Both&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ohH_btPO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/9000/0%2A0E2S0M23a9GtlOfI" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ohH_btPO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/9000/0%2A0E2S0M23a9GtlOfI" alt="Photo by [Maarten Deckers](https://unsplash.com/@maartendeckers?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@maartendeckers?utm_source=medium&amp;amp;utm_medium=referral"&gt;Maarten Deckers&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See, these two courses complement each other. Say you start from &lt;a href="https://dev.toundefined"&gt;Andrew Ng&lt;/a&gt;’s deeplearning.ai course, you buried yourself into endless formulas and theories, you gained a lot of intuition, but after weeks of learning, you still have nothing to show to your friends and not quite sure when you can apply your newly gained knowledge. Your study on the machine learning fundamentals is getting diminishing returns. Your brain slows down and you start to feel boring. Now is the perfect time to start taking a lesson or two of the fast.ai course. With the help of the powerful fast.ai library and few lines of code, you’ll be able to build impressive models that solve real-life problems and even beat some state-of-the-art papers and &lt;a href="http://kaggle.com"&gt;Kaggle&lt;/a&gt; competitions. This will give your brain a totally different kind of stimulation and your heart more confidence and passion to delve deeper into why everything works. Once you built a couple of projects and ‘wow’ed your friends, you will be more motivated to learn more about the fundamentals, then you can go back to deeplearning.ai course and keep your study there. These two courses push each other forward, you can just rinse and repeat till you finished both.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This forms a perfect learning circle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DuC-yctx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/9688/0%2AY-6oyPq53_8ppU0o" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DuC-yctx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/9688/0%2AY-6oyPq53_8ppU0o" alt="Photo by [Dan Freeman](https://unsplash.com/@danfreemanphoto?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@danfreemanphoto?utm_source=medium&amp;amp;utm_medium=referral"&gt;Dan Freeman&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The best thing about taking both courses this way is once you finished both, you’ll be fully prepared. You have tons of projects built along the way from fast.ai course to showcase to potential employers and you also have the deep knowledge of how everything works or even published one paper or two to show your findings. You are now a well-rounded Data Scientist. How cool is that?&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>fastai</category>
      <category>education</category>
      <category>deeplearningai</category>
    </item>
    <item>
      <title>Title:“This is CS50”: A Pleasant Way to Kick Off Your Data Science Education</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Tue, 04 Feb 2020 01:49:48 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/title-this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-53b5</link>
      <guid>https://dev.to/wayofnumbers/title-this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-53b5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZdSTECIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2880/1%2Af5zbeedqmaZidMfA_3EGBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZdSTECIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2880/1%2Af5zbeedqmaZidMfA_3EGBA.png" alt="CS50 professor David Malan teaches over 800 students on CS5 — from Youtube"&gt;&lt;/a&gt;&lt;em&gt;CS50 professor David Malan teaches over 800 students on CS5 — from Youtube&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So You Want to Get Into Data Science
&lt;/h2&gt;

&lt;p&gt;Congratulations! Data Science is a career that’s hottest, hardest, most challenging, most rewarding, and full of top-notch minds. Your journey is bound to be full of fun, challenges, enlightenments, and achievements (big or small). New papers are published daily or even hourly. New techniques and experiments are developed regularly. New ways of thinking become the new norm. And what seems magical before, are proven feasible.&lt;/p&gt;

&lt;h2&gt;
  
  
  But You Don’t Know Where to Start
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u8mWiojQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/12032/0%2AU7Yftolo9hzPlkH2" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u8mWiojQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/12032/0%2AU7Yftolo9hzPlkH2" alt="Photo by [Ben White](https://unsplash.com/@benwhitephotography?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@benwhitephotography?utm_source=medium&amp;amp;utm_medium=referral"&gt;Ben White&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But getting into Data Science is not easy. Far from it. The learning curve is brutal. There is so much to learn: Linear Algebra, Calculus, Statistics, Python, SQL, Machine Learning, Algorithm, Optimization, Data Wrangling, Data Visualization, Software Engineering, DevOps, … The list goes on and on.&lt;/p&gt;

&lt;p&gt;Some people may have some background in math or statistics, which will definitely help. Yet you still need a solid foundation for software engineering to be efficient and be successful in your career. But this is not a problem, you say. After all, we live in an era of booming online education. There are plenty of courses paid and free we can choose. &lt;strong&gt;True, but this is precisely where the problem is&lt;/strong&gt;. The biggest challenge for self-education these days is not lack of education resources, but hard to find the best or most relevant ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter CS50. If You are Only Allowed to Take One CS Course, Take CS50.
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LahWdP8Mizw"&gt;
&lt;/iframe&gt;
&lt;br&gt;
What is CS50? It is the introductory course on &lt;a href="https://en.wikipedia.org/wiki/Computer_science"&gt;computer science&lt;/a&gt; taught at &lt;a href="https://en.wikipedia.org/wiki/Harvard_University"&gt;Harvard University&lt;/a&gt; by &lt;a href="https://en.wikipedia.org/wiki/David_J._Malan"&gt;Professor David J. Malan&lt;/a&gt;. It is the largest class at Harvard with 800 students, 102 staff, and a professional production team. It offers both an on-campus and an online course. I’ve taken the online one, but it’s already **THE **best computer science course I came across, period. Let me tell you why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The learning curve is so well designed, and it’s like watching a great suspense movie&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CS50 staff has the capability of knowing precisely what you do and do not know before each lecture (in that they have zero &lt;a href="https://www.warc.com/newsandopinion/opinion/expert_blindness_the_silent_threat_to_success/3082"&gt;expert blindness&lt;/a&gt;). So the speech will not mention anything you are not familiar with. It smoothly guides you through key concepts of computer science and makes it seem obvious. It raises questions from time to time and later addresses them with a more in-depth explanation of the concepts. You’ll have plenty of ‘a-ha’ moments, and it almost felt like watching a suspense movie.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Covers core and essential fundamentals of computer science, and leave plenty of room for you to dig deeper&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The course covers most of the critical computer science elements: C, Python, Data Structures, Algorithms, Software Engineering, Resource Management, Web Development, etc. It delves down deep enough so you can understand all the essential concepts while also know where to look if you want to dig deeper.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Orchestrate variety of ways to teach you challenging/boring concept, never felt boring&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V4seHVdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3000/0%2Au0HtnQsAEZkbfl0_.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V4seHVdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3000/0%2Au0HtnQsAEZkbfl0_.jpg" alt="What is an array? Let’s find out! — thecrimson.com"&gt;&lt;/a&gt;&lt;em&gt;What is an array? Let’s find out! — thecrimson.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;CS50 has many ways to teach and keep you engaged. You’ll play a game to understand different sorting algorithms, receive a rubber duck to experience the famous &lt;a href="https://youtu.be/f5d8pVg3Qtg"&gt;Rubber Duck Debugging&lt;/a&gt;, watch experiments of ‘array of lights 🚥’ to learn data structure, even eat a delicious breakfast 🍞 while exploring the idea of pseudo-code. (One of my favorites is where David J. Malan uses a Yellowpage phonebook to explain binary search and tears down half of the book and throw it away. A definitive moment in CS50 indeed. )&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Interactive, fun and engaging, the time just flew by, and you’ll be amazed what you can do once the course is over&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The learning experience is so fun you’ll feel the time fly by without noticing it. Some of the problem set it gives are quite challenging, yet not impossible. And you’ll feel so proud of yourself once you cracked it. You’ll probably fall in love with the joy of problem-solving. If you are stuck, there is an online community on almost every social network platform (Twitter, Reddit, Stack Exchange, Facebook, etc.) where you can get help.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Out-of-class activities get you familiar with the ‘developer culture,’ which is essential for your future career.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/FaO9yVKKeTc"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Puzzle days, office hours, CS 50 Fairs, the final project ‘All-nighter’ hackathon (free breakfast at IHOP if you stay up all night), lots of activities designed to get you familiar with the ‘developer culture’ and better prepare you for the software engineering world.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;State-of-the-art course software to get you started&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How great is a computer science course if they don’t use the software tools they developed themselves? Over the years, CS50’s staff has developed a series of tools/software to help the students &lt;a href="https://cs50.readthedocs.io/ide/"&gt;write code&lt;/a&gt;, &lt;a href="https://cs50.readthedocs.io/submit50/"&gt;submit homework&lt;/a&gt;, &lt;a href="https://cs50.readthedocs.io/check50/"&gt;check their code quality/syntax&lt;/a&gt;, &lt;a href="https://cs50.readthedocs.io/style50/"&gt;tidy up code styles&lt;/a&gt;, and even &lt;a href="https://cs50.readthedocs.io/render50/"&gt;generate color-coded code documentation in PDF form&lt;/a&gt;! These are all neat and useful ‘&lt;a href="https://www.youtube.com/watch?v=PYJYiBlto5M&amp;amp;t=1889s"&gt;training-wheels&lt;/a&gt;’ as David J. Malan puts it and will help you get up to speed.&lt;/p&gt;

&lt;p&gt;But, please don’t just take my words for it, see what YouTube CEO Susan D. Wojcicki said about her experience:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/y1121-De4o4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  And It Is Great for Data Science Too
&lt;/h2&gt;

&lt;p&gt;Being a great course, CS50 is also very **relevant **to Data Science. It helps you lay a solid foundation of software engineering for your future career:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It teaches you C. More importantly, through C, you understand the fundamentals of computer like how memory works, what is a pointer, data structures, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you can write C, then you can quickly learn to write in C++. C++ is the de facto low-level, high-performance language used for data science libraries like Numpy, Pandas, Sk-Learn, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It teaches Python, which is the primary high-level language for Machine Learning and Data Science.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It teaches SQL, which is the most widely used language in Data Science.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It also teaches web programming, useful when you try to deploy your model to production.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So essentially nothing taught in the course is not somewhat useful to you, and the foundation it helps you build will go a long way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CS50 and Beyond!
&lt;/h2&gt;

&lt;p&gt;Once you finished the course, you’ll be more knowledgable and confident to continue your Data Science journey, and I’ll point you to a couple of possible directions from here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CS50’s Web Programming with Python and JavaScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Teaches you the most relevant and progressive web programming tools like CSS, Javascripts, React, Flask/Django, by the talented TF &lt;a href="https://www.youtube.com/watch?v=HMjaUj59QdQ"&gt;Brian Yu&lt;/a&gt;. Link &lt;a href="https://www.youtube.com/playlist?list=PLhQjrBD2T382hIW-IsOVuXP1uMzEvmcE5"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.toundefined"&gt;**Jeremy Howard&lt;/a&gt;’s Fast.ai course to Start a ‘Top-down’ Approach for ML**&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.fast.ai/"&gt;Fast.ai&lt;/a&gt; is fantastic and unique. It enables you to build state-of-the-art deep learning models within the first lesson with less than ten lines of code. Then it delves down deeper and deeper on the how and why. The only prerequisite is one-year of coding experience, which CS50 would have already prepared you with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.toundefined"&gt;**Andrew Ng&lt;/a&gt;’s Machine Learning Course at Coursera**&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/datadriveninvestor/thoughts-on-andrew-ngs-machine-learning-course-7724df76320f"&gt;Another great Machine Learning course&lt;/a&gt;, but a ‘Bottom-up’ style. It smoothly explains the math fundamentals first and gradually builds up the knowledge to piece together complicated machine learning models from scratch. I have &lt;a href="https://towardsdatascience.com/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133"&gt;an article&lt;/a&gt; that explains the difference between &lt;a href="https://dev.toundefined"&gt;Andrew Ng&lt;/a&gt; and &lt;a href="https://dev.toundefined"&gt;Jeremy Howard&lt;/a&gt;’s different approaches to machine learning education and recommend a potentially efficient way to learn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Corey Schafer’s YouTube channel, Python and OOP Tutorials&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As good as it is, CS50 only covers the generic and basic concepts of Python. You’ll need more in-depth knowledge to code efficiently for your data science projects. For this, I recommend &lt;a href="https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g"&gt;Corey Schafer’s YouTube channel&lt;/a&gt;. He is one of the best Python educators I came across to explain complicated ideas in a crystal clear way. Not one second of his videos is wasted. The content is concise, to the point, and highly condensed. He has playlists for basic &lt;a href="https://www.youtube.com/watch?v=YYXdXT2l-Gg&amp;amp;list=PL-osiE80TeTt2d9bfVyTiXJA-UTHn6WwU"&gt;Python&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=xaWlS9HtWYw&amp;amp;list=PL-osiE80TeTsKOdPrKeSOp4rN3mza8VHN"&gt;SQL&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=UO98lJQ3QGI&amp;amp;list=PL-osiE80TeTvipOqomVEeZ1HRrcEvtZB_"&gt;Matplotlib&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=HVsySz-h9r4&amp;amp;list=PL-osiE80TeTuRUfjRe54Eea17-YfnOOAx"&gt;Git&lt;/a&gt;, and &lt;a href="https://www.youtube.com/watch?v=ZDa-Z5JzLYM&amp;amp;list=PL-osiE80TeTsqhIuOqKhwlXsIBIdSeYtc"&gt;Object-Oriented Programming&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Learning Data Science is never a breeze, and I hope this article will help a little in alleviating the pain and make your journey a bit more efficient and fun. If you know other courses and resources that are also great, please feel free to leave a response so others can also see. Thanks!&lt;/p&gt;

&lt;p&gt;Any feedback or constructive criticism is welcomed. You can either find me on Twitter &lt;a href="https://twitter.com/lymenlee"&gt;@lymenlee&lt;/a&gt; or my blog site &lt;a href="https://wayofnumbers.com"&gt;wayofnumbers.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>computerscience</category>
      <category>cs50</category>
      <category>education</category>
    </item>
    <item>
      <title>How to Port Your Medium Articles to Personal Blog with a Simple Bash Script</title>
      <dc:creator>Michael Li</dc:creator>
      <pubDate>Mon, 03 Feb 2020 23:04:59 +0000</pubDate>
      <link>https://dev.to/wayofnumbers/how-to-port-your-medium-articles-to-personal-blog-with-a-simple-bash-script-2eeh</link>
      <guid>https://dev.to/wayofnumbers/how-to-port-your-medium-articles-to-personal-blog-with-a-simple-bash-script-2eeh</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KHrwNS7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/15904/0%2AlwNGcCCG8j0H_5mz" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KHrwNS7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/15904/0%2AlwNGcCCG8j0H_5mz" alt="Photo by [Annie Spratt](https://unsplash.com/@anniespratt?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@anniespratt?utm_source=medium&amp;amp;utm_medium=referral"&gt;Annie Spratt&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Medium is a great publication platform. It has good exposure, quality content, readers that really appreciate good articles and a neat and easy to use UI. It’s especially great for writers that just start their journey.&lt;/p&gt;

&lt;p&gt;As good as it is, having your own blog outside of Medium is still not a bad idea. It enables you to have another channel you can totally own to communicate with your readers. And who knows, no company can last forever, what if Medium got acquired by some other company or something even worse happen. You can still sleep well at night knowing you won’t lose all your articles.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://wayofnumbers.com/"&gt;my own&lt;/a&gt; using &lt;a href="https://github.com/getpelican/pelican"&gt;Pelican&lt;/a&gt;, a Python-based &lt;a href="https://en.wikipedia.org/wiki/Static_web_page"&gt;static site generator&lt;/a&gt;. I wrote an &lt;a href="https://towardsdatascience.com/my-experience-migrating-my-blog-from-github-pages-to-netlify-92ff6c85fb04"&gt;article&lt;/a&gt; explaining the whole process. For every Medium article, I need to copy the URL, run some command to transfer it into Markdown file, then generate the blog site using Pelican. It is simple, but not as simple as I like it to be. So this is a great opportunity for some quick and dirty Bash script to come for the rescue. Let’s see what we can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure the Script
&lt;/h2&gt;

&lt;p&gt;Before start writing the script, it helps to structure out what we want to accomplish, makes it easier to write quality code. Basically, we need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Put all article URLs into one text file manually(plan to automate this part too in the future, using some scraping framework maybe)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read every line of the file, and for each line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract the title and subtitle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the title and subtitle to create meta-data needed for Pelican to turn the Markdown file into a post.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run Pelican command to generate the static site.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push the site to GitHub and trigger Netlify’s auto-build&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Let’s Write the Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v-tJBrlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/10368/0%2AwZqyc6jNLf1vwg3o" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v-tJBrlF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/10368/0%2AwZqyc6jNLf1vwg3o" alt="Photo by [Shahadat Rahman](https://unsplash.com/@hishahadat?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)"&gt;&lt;/a&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@hishahadat?utm_source=medium&amp;amp;utm_medium=referral"&gt;Shahadat Rahman&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First of all, define our variables:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash 
# Define variables
filename='articles.txt'
n=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The structure the loop to read every line of the text file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;# Read in file and do processing on each one&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;line&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
        &lt;span class="c"&gt;# reading each line&lt;/span&gt;
        &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;n+1&lt;span class="k"&gt;))&lt;/span&gt; 
        &lt;span class="nv"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$line&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/https:\/\/towardsdatascience.com\///'&lt;/span&gt; &lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# get slug from URL &lt;/span&gt;
        &lt;span class="nv"&gt;FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/wayofnumbers.github.io/content/&lt;/span&gt;&lt;span class="nv"&gt;$slug&lt;/span&gt;&lt;span class="s2"&gt;.md"&lt;/span&gt;   &lt;span class="c"&gt;# generate Markdown file name from slug &lt;/span&gt;
        mediumexporter &lt;span class="nv"&gt;$line&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;   &lt;span class="c"&gt;# convert medium article to markdown file    &lt;/span&gt;
        &lt;span class="c"&gt;# some processing ...&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="nv"&gt;$filename&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used the sed command to remove the first part of the URL: &lt;a href="https://towardsdatascience.com/"&gt;https://towardsdatascience.com/&lt;/a&gt; so the rest could be used as our slug. For example, &lt;a href="https://towardsdatascience.com/9-things-i-learned-from-blogging-on-medium-for-the-first-month-2bace214b814"&gt;https://towardsdatascience.com/9-things-i-learned-from-blogging-on-medium-for-the-first-month-2bace214b814&lt;/a&gt; turns into &lt;a href="https://towardsdatascience.com/9-things-i-learned-from-blogging-on-medium-for-the-first-month-2bace214b814"&gt;9-things-i-learned-from-blogging-on-medium-for-the-first-month-2bace214b814&lt;/a&gt;, perfect for a slug. Here we also uses the slug to create the filename for the MarkDown file. Then we use mediumexporter to transfer URL into the Markdown file. You can find out more about mediumexporter &lt;a href="https://medium.com/@macropus/export-your-medium-posts-to-markdown-b5ccc8cb0050"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have the Markdown file, let’s fill in the processing code we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;# Processing the markdown file &lt;/span&gt;
        &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +2 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# remove the first line &lt;/span&gt;
        &lt;span class="nv"&gt;fl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# put first line (title) into fl &lt;/span&gt;
        &lt;span class="nv"&gt;firstline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$fl&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/# //'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# Remove '# ' &lt;/span&gt;
        &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# remove the first line &lt;/span&gt;
        &lt;span class="nv"&gt;subtitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 &lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# put first line (subtitle) into subtitle &lt;/span&gt;
        &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +2 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;.tmp"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# remove the first two line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These lines are rather self-explanatory. Now we have firstline variable as the title and subtitle variable as the subtitle, we are now ready to construct the Markdown file meta-data for Pelican:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;# handle metadata for Pelican  &lt;/span&gt;
    &lt;span class="nv"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"
    Title: &lt;/span&gt;&lt;span class="nv"&gt;$firstline&lt;/span&gt;&lt;span class="s2"&gt;
    Slug: &lt;/span&gt;&lt;span class="nv"&gt;$slug&lt;/span&gt;&lt;span class="s2"&gt;
    Subtitle: &lt;/span&gt;&lt;span class="nv"&gt;$subtitle&lt;/span&gt;&lt;span class="s2"&gt;
    Date: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;
    Category: Machine Learning
    Tags: Machine Learning, Artificial Intelligence
    author: Michael Li
    Summary: &lt;/span&gt;&lt;span class="nv"&gt;$firstline&lt;/span&gt;&lt;span class="s2"&gt;
    [TOC]
    "&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can refer to Pelican’s document &lt;a href="https://docs.getpelican.com/en/stable/content.html#file-metadata"&gt;here&lt;/a&gt; for more information about the meta-data format. Simply put, the Markdown file doesn’t need to specifically write the title and subtitle, as long as we specify the title and subtitle field in our meta-data, Pelican will automatically generate them for you in the post, with specific styles per the theme you choose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GH_0QX5L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2400/0%2AWUqf8uBnOPArexxL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GH_0QX5L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2400/0%2AWUqf8uBnOPArexxL" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the correct meta-data, now we can finally update the Markdown and get it ready for site generation:&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="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$meta&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;.new &lt;span class="c"&gt;# sticth meta-data and article content together &lt;/span&gt;
    &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;.new,&lt;span class="o"&gt;}&lt;/span&gt; 
    &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-8&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;.new &lt;span class="c"&gt;# Remove medium's recommended articles&lt;/span&gt;
    &lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;.new,&lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="nv"&gt;$filename&lt;/span&gt;  &lt;span class="c"&gt;# don't forget to enclose the loop.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All my Medium articles have several recommendations for further readings. I removed those for my blog(the last line of code above). Now that the Markdown file is ready, time to generate the site and push it to the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;# push to server&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/wayofnumbers.github.io
    pelican content &lt;span class="nt"&gt;-s&lt;/span&gt; publishconf.py 
    git add &lt;span class="nb"&gt;.&lt;/span&gt;
    git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix"&lt;/span&gt;
    git push origin dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;So there you go. This script only works on Pelican static site generator, but the gist of it can be applied to any of your blogging platforms. I hope you learned a thing or two. And happy blogging/coding!&lt;/p&gt;

</description>
      <category>medium</category>
      <category>bash</category>
      <category>blogging</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
