Repos / hi.imnhan.com / 94ab6cebb4
commit 94ab6cebb465c7171f9eed9d79875cbd2cc7a135
Author: Nhân <hi@imnhan.com>
Date:   Sat Aug 19 17:09:57 2023 +0700

    WIP s4g transition: generate redirects

diff --git a/.gitignore b/.gitignore
index a764eca..16be8f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1 @@
-output/
-*.pid
-__pycache__/
-cache/
-*.pyc
+/output/
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 3c7855d..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "motherfucking-pelican-theme"]
-	path = motherfucking-pelican-theme
-	url = git@github.com:nhanb/motherfucking-pelican-theme.git
diff --git a/.rgignore b/.rgignore
deleted file mode 100644
index 1f57b97..0000000
--- a/.rgignore
+++ /dev/null
@@ -1 +0,0 @@
-/output
diff --git a/content/extra/404.html b/404.html
similarity index 100%
rename from content/extra/404.html
rename to 404.html
diff --git a/content/extra/CNAME b/CNAME
similarity index 100%
rename from content/extra/CNAME
rename to CNAME
diff --git a/Makefile b/Makefile
deleted file mode 100644
index f55c243..0000000
--- a/Makefile
+++ /dev/null
@@ -1,110 +0,0 @@
-PY?=python3
-PELICAN?=pelican
-PELICANOPTS=
-
-BASEDIR=$(CURDIR)
-INPUTDIR=$(BASEDIR)/content
-OUTPUTDIR=$(BASEDIR)/output
-CONFFILE=$(BASEDIR)/pelicanconf.py
-PUBLISHCONF=$(BASEDIR)/publishconf.py
-
-FTP_HOST=localhost
-FTP_USER=anonymous
-FTP_TARGET_DIR=/
-
-SSH_HOST=localhost
-SSH_PORT=22
-SSH_USER=root
-SSH_TARGET_DIR=/var/www
-
-S3_BUCKET=my_s3_bucket
-
-CLOUDFILES_USERNAME=my_rackspace_username
-CLOUDFILES_API_KEY=my_rackspace_api_key
-CLOUDFILES_CONTAINER=my_cloudfiles_container
-
-DROPBOX_DIR=~/Dropbox/Public/
-
-GITHUB_PAGES_BRANCH=master
-
-DEBUG ?= 0
-ifeq ($(DEBUG), 1)
-	PELICANOPTS += -D
-endif
-
-help:
-	@echo 'Makefile for a pelican Web site                                        '
-	@echo '                                                                       '
-	@echo 'Usage:                                                                 '
-	@echo '   make html                        (re)generate the web site          '
-	@echo '   make clean                       remove the generated files         '
-	@echo '   make regenerate                  regenerate files upon modification '
-	@echo '   make publish                     generate using production settings '
-	@echo '   make serve [PORT=8000]           serve site at http://localhost:8000'
-	@echo '   make devserver [PORT=8000]       start/restart develop_server.sh    '
-	@echo '   make stopserver                  stop local server                  '
-	@echo '   make ssh_upload                  upload the web site via SSH        '
-	@echo '   make rsync_upload                upload the web site via rsync+ssh  '
-	@echo '   make dropbox_upload              upload the web site via Dropbox    '
-	@echo '   make ftp_upload                  upload the web site via FTP        '
-	@echo '   make s3_upload                   upload the web site via S3         '
-	@echo '   make cf_upload                   upload the web site via Cloud Files'
-	@echo '   make github                      upload the web site via gh-pages   '
-	@echo '                                                                       '
-	@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html'
-	@echo '                                                                       '
-
-html:
-	$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
-
-clean:
-	[ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
-
-regenerate:
-	$(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
-
-serve:
-ifdef PORT
-	cd $(OUTPUTDIR) && $(PY) -m pelican.server $(PORT)
-else
-	cd $(OUTPUTDIR) && $(PY) -m pelican.server
-endif
-
-devserver:
-ifdef PORT
-	$(BASEDIR)/develop_server.sh restart $(PORT)
-else
-	$(BASEDIR)/develop_server.sh restart
-endif
-
-stopserver:
-	kill -9 `cat pelican.pid`
-	kill -9 `cat srv.pid`
-	@echo 'Stopped Pelican and SimpleHTTPServer processes running in background.'
-
-publish:
-	$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
-
-ssh_upload: publish
-	scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)
-
-rsync_upload: publish
-	rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --delete $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) --cvs-exclude
-
-dropbox_upload: publish
-	cp -r $(OUTPUTDIR)/* $(DROPBOX_DIR)
-
-ftp_upload: publish
-	lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit"
-
-s3_upload: publish
-        s3cmd sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl-public --delete-removed --guess-mime-type
-
-cf_upload: publish
-	cd $(OUTPUTDIR) && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) .
-
-github: publish
-	ghp-import $(OUTPUTDIR)
-	git push origin gh-pages:gh-pages -f
-
-.PHONY: html help clean regenerate serve devserver publish ssh_upload rsync_upload dropbox_upload ftp_upload s3_upload cf_upload github
diff --git a/README.md b/README.md
deleted file mode 100644
index 40989a0..0000000
--- a/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# My blog
-
-This is the source code for https://hi.imnhan.com using
-[Pelican](http://github.com/getpelican/pelican)
-
-# Dev environment
-
-- `make devserver` / `make stopserver` for local dev at port 8000
-- `make github` to publish to hi.imnhan.com
-
-Alternatively, if you find the `make dev/stopserver` workflow clumsy, manually run `pelican -r` and
-simple python http server to keep everything in the foreground:
-
-```sh
-pelican -r content  # in 1 terminal
-cd output && python3 -m http.server 8000  # in another terminal
-```
-
-
-# License
-
-All code and content within this repository is licensed under the terms of the MIT license:
-
-```
-The MIT License (MIT)
-
-Copyright (c) 2013-2023 Bùi Thành Nhân
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-```
diff --git a/_theme/base.css b/_theme/base.css
new file mode 100644
index 0000000..813e870
--- /dev/null
+++ b/_theme/base.css
@@ -0,0 +1,21 @@
+html {
+  font-family: serif;
+  max-width: 50rem;
+  margin: auto;
+}
+
+p,
+ul,
+ol {
+  line-height: 1.35rem;
+}
+
+main img {
+  max-width: 100%;
+}
+
+footer {
+  margin-top: 2rem;
+  text-align: right;
+  font-size: 0.8rem;
+}
diff --git a/_theme/base.tmpl b/_theme/base.tmpl
new file mode 100644
index 0000000..22971ce
--- /dev/null
+++ b/_theme/base.tmpl
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8" />
+  <title>{{if .Title}}{{.Title}} | {{end}}{{ .Site.Name -}}</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <link rel="alternate" type="application/atom+xml" title="Atom feed" href="{{.Feed}}">
+  <link rel="stylesheet" href="{{.Site.Root}}_theme/base.css">
+  {{- template "head" .}}
+</head>
+
+<body>
+{{template "body" .}}
+
+</body>
+
+</html>
diff --git a/_theme/feed.svg b/_theme/feed.svg
new file mode 100644
index 0000000..1a44b51
--- /dev/null
+++ b/_theme/feed.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="RSSicon" viewBox="0 0 8 8" width="256" height="256">
+
+  <title>RSS feed icon</title>
+
+  <style type="text/css">
+    .button {stroke: none; fill: orange;}
+    .symbol {stroke: none; fill: white;}
+  </style>
+
+  <rect class="button" width="8" height="8" rx="1.5"/>
+  <circle class="symbol" cx="2" cy="6" r="1"/>
+  <path class="symbol" d="m 1,4 a 3,3 0 0 1 3,3 h 1 a 4,4 0 0 0 -4,-4 z"/>
+  <path class="symbol" d="m 1,2 a 5,5 0 0 1 5,5 h 1 a 6,6 0 0 0 -6,-6 z"/>
+
+</svg>
diff --git a/_theme/home.tmpl b/_theme/home.tmpl
new file mode 100644
index 0000000..d85797f
--- /dev/null
+++ b/_theme/home.tmpl
@@ -0,0 +1,91 @@
+{{define "head"}}{{end}}
+
+{{define "body"}}
+<header>
+  <h1 class="site-title">{{.Site.Name}}</h1>
+  <p class="tagline">{{.Site.Tagline}}</p>
+</header>
+
+<hr>
+
+<div class="pages">
+{{- range .ArticlesInNav}}
+  <a href="{{.WebPath}}">{{.Title}}</a>
+{{- end}}
+  <a class="feed-link" href="{{.Feed}}">
+    <img src="{{.Site.Root}}_theme/feed.svg" alt="Atom Feed" title="Atom Feed">
+  </a>
+</div>
+
+<hr>
+
+{{.Content}}
+
+{{if .ArticlesInFeed -}}
+<p>All posts, newest first:</p>
+
+<ul>
+  {{- range .ArticlesInFeed}}
+  {{- if not .IsDraft}}
+  <li>
+    <span class="time-prefix">{{.PostedAt.Local.Format "2006-01-02"}} — </span>
+    <a href="{{.WebPath}}">{{.Title}}</a>
+    <span class="time-suffix">({{.PostedAt.Local.Format "2006-01-02"}})</span>
+  </li>
+  {{- end}}
+  {{- end}}
+</ul>
+{{else}}
+<p>No posts yet.</p>
+{{end}}
+
+<style>
+.site-title {
+  margin-bottom: 0;
+}
+.tagline {
+  margin-top: 0;
+}
+
+.feed-link img {
+  height: 1rem;
+}
+.feed-link {
+  float: right;
+}
+hr {
+  clear: both;
+}
+
+.pages a {
+  margin-right: 0.5rem;
+}
+
+ul {
+  padding: 0;
+  list-style: none;
+  /*font-size: 1.1rem;*/
+}
+
+.time-suffix {
+  display: none;
+}
+
+@media (max-width: 30rem) {
+  .time-suffix {
+    display: inline;
+  }
+  .time-prefix {
+    display: none;
+  }
+  li {
+    margin-bottom: 0.5rem;
+  }
+  li::before {
+    content: '❖';
+  }
+}
+</style>
+
+{{template "footer" .}}
+{{end}}
diff --git a/_theme/includes.tmpl b/_theme/includes.tmpl
new file mode 100644
index 0000000..aa3130b
--- /dev/null
+++ b/_theme/includes.tmpl
@@ -0,0 +1,29 @@
+{{define "navbar"}}
+<link rel="stylesheet" href="{{.Site.Root}}_theme/navbar.css">
+<nav>
+  {{- range .ArticlesInNav}}
+  <a href="{{.WebPath}}">{{.Title}}</a>
+  {{- end}}
+
+  {{- if not .Post.PostedAt.IsZero}}
+  <span class="posted-on">
+    Posted on
+    <time datetime="{{.Post.PostedAt.Local.Format "2006-01-02"}}">
+        {{.Post.PostedAt.Local.Format "Monday, 02 Jan 2006"}}
+    </time>
+  </span>
+  {{- end}}
+
+</nav>
+<hr class="nav-hr">
+{{end}}
+
+
+{{define "footer"}}
+{{- if .Site.ShowFooter -}}
+<footer>
+© {{if eq .StartYear .Now.Year}}{{.StartYear}}{{else}}{{.StartYear}}–{{.Now.Year}}{{end}} {{.Site.AuthorName}}<br>
+Made with <a href="https://github.com/nhanb/s4g">s4g</a>
+</footer>
+{{- end -}}
+{{- end}}
diff --git a/_theme/navbar.css b/_theme/navbar.css
new file mode 100644
index 0000000..3a7107b
--- /dev/null
+++ b/_theme/navbar.css
@@ -0,0 +1,12 @@
+nav > a {
+  margin-right: 0.5rem;
+}
+
+nav > .posted-on {
+  float: right;
+  font-style: italic;
+}
+
+.nav-hr {
+  clear: both;
+}
diff --git a/_theme/post.tmpl b/_theme/post.tmpl
new file mode 100644
index 0000000..6878886
--- /dev/null
+++ b/_theme/post.tmpl
@@ -0,0 +1,13 @@
+{{- define "head"}}{{- end}}
+
+{{define "body"}}
+
+{{- template "navbar" .}}
+
+<main>
+<h1>{{.Post.Title}}</h1>
+{{.Content}}
+</main>
+
+{{template "footer" .}}
+{{- end}}
diff --git a/develop_server.sh b/develop_server.sh
deleted file mode 100755
index e295a8d..0000000
--- a/develop_server.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env bash
-##
-# This section should match your Makefile
-##
-PY=${PY:-python3}
-PELICAN=${PELICAN:-pelican}
-PELICANOPTS=
-
-BASEDIR=$(pwd)
-INPUTDIR=$BASEDIR/content
-OUTPUTDIR=$BASEDIR/output
-CONFFILE=$BASEDIR/pelicanconf.py
-
-###
-# Don't change stuff below here unless you are sure
-###
-
-SRV_PID=$BASEDIR/srv.pid
-PELICAN_PID=$BASEDIR/pelican.pid
-
-function usage(){
-  echo "usage: $0 (stop) (start) (restart) [port]"
-  echo "This starts Pelican in debug and reload mode and then launches"
-  echo "an HTTP server to help site development. It doesn't read"
-  echo "your Pelican settings, so if you edit any paths in your Makefile"
-  echo "you will need to edit your settings as well."
-  exit 3
-}
-
-function alive() {
-  kill -0 $1 >/dev/null 2>&1
-}
-
-function shut_down(){
-  PID=$(cat $SRV_PID)
-  if [[ $? -eq 0 ]]; then
-    if alive $PID; then
-      echo "Stopping HTTP server"
-      kill $PID
-    else
-      echo "Stale PID, deleting"
-    fi
-    rm $SRV_PID
-  else
-    echo "HTTP server PIDFile not found"
-  fi
-
-  PID=$(cat $PELICAN_PID)
-  if [[ $? -eq 0 ]]; then
-    if alive $PID; then
-      echo "Killing Pelican"
-      kill $PID
-    else
-      echo "Stale PID, deleting"
-    fi
-    rm $PELICAN_PID
-  else
-    echo "Pelican PIDFile not found"
-  fi
-}
-
-function start_up(){
-  local port=$1
-  echo "Starting up Pelican and HTTP server"
-  shift
-  $PELICAN --debug --autoreload -r $INPUTDIR -o $OUTPUTDIR -s $CONFFILE $PELICANOPTS &
-  pelican_pid=$!
-  echo $pelican_pid > $PELICAN_PID
-  cd $OUTPUTDIR
-  $PY -m pelican.server $port &
-  srv_pid=$!
-  echo $srv_pid > $SRV_PID
-  cd $BASEDIR
-  sleep 1
-  if ! alive $pelican_pid ; then
-    echo "Pelican didn't start. Is the Pelican package installed?"
-    return 1
-  elif ! alive $srv_pid ; then
-    echo "The HTTP server didn't start. Is there another service using port 8000?"
-    return 1
-  fi
-  echo 'Pelican and HTTP server processes now running in background.'
-}
-
-###
-#  MAIN
-###
-[[ ($# -eq 0) || ($# -gt 2) ]] && usage
-port=''
-[[ $# -eq 2 ]] && port=$2
-
-if [[ $1 == "stop" ]]; then
-  shut_down
-elif [[ $1 == "restart" ]]; then
-  shut_down
-  start_up $port
-elif [[ $1 == "start" ]]; then
-  if ! start_up $port; then
-    shut_down
-  fi
-else
-  usage
-fi
diff --git a/fabfile.py b/fabfile.py
deleted file mode 100644
index 39dd7aa..0000000
--- a/fabfile.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from fabric.api import *
-import fabric.contrib.project as project
-import os
-import sys
-import SimpleHTTPServer
-import SocketServer
-
-# Local path configuration (can be absolute or relative to fabfile)
-env.deploy_path = 'output'
-DEPLOY_PATH = env.deploy_path
-
-# Remote server configuration
-production = 'root@localhost:22'
-dest_path = '/var/www'
-
-# Rackspace Cloud Files configuration settings
-env.cloudfiles_username = 'my_rackspace_username'
-env.cloudfiles_api_key = 'my_rackspace_api_key'
-env.cloudfiles_container = 'my_cloudfiles_container'
-
-
-def clean():
-    if os.path.isdir(DEPLOY_PATH):
-        local('rm -rf {deploy_path}'.format(**env))
-        local('mkdir {deploy_path}'.format(**env))
-
-def build():
-    local('pelican -s pelicanconf.py')
-
-def rebuild():
-    clean()
-    build()
-
-def regenerate():
-    local('pelican -r -s pelicanconf.py')
-
-def serve():
-    os.chdir(env.deploy_path)
-
-    PORT = 8000
-    class AddressReuseTCPServer(SocketServer.TCPServer):
-        allow_reuse_address = True
-
-    server = AddressReuseTCPServer(('', PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
-
-    sys.stderr.write('Serving on port {0} ...\n'.format(PORT))
-    server.serve_forever()
-
-def reserve():
-    build()
-    serve()
-
-def preview():
-    local('pelican -s publishconf.py')
-
-def cf_upload():
-    rebuild()
-    local('cd {deploy_path} && '
-          'swift -v -A https://auth.api.rackspacecloud.com/v1.0 '
-          '-U {cloudfiles_username} '
-          '-K {cloudfiles_api_key} '
-          'upload -c {cloudfiles_container} .'.format(**env))
-
-@hosts(production)
-def publish():
-    local('pelican -s publishconf.py')
-    project.rsync_project(
-        remote_dir=dest_path,
-        exclude=".DS_Store",
-        local_dir=DEPLOY_PATH.rstrip('/') + '/',
-        delete=True,
-        extra_opts='-c',
-    )
diff --git a/content/extra/favicon.ico b/favicon.ico
similarity index 100%
rename from content/extra/favicon.ico
rename to favicon.ico
diff --git a/content/extra/favicon.png b/favicon.png
similarity index 100%
rename from content/extra/favicon.png
rename to favicon.png
diff --git a/index.dj b/index.dj
new file mode 100644
index 0000000..6ce56a8
--- /dev/null
+++ b/index.dj
@@ -0,0 +1,4 @@
+Title: Home
+ShowInFeed: false
+Templates: $_theme/base.tmpl, $_theme/includes.tmpl, $_theme/home.tmpl
+---
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..052cf5f
--- /dev/null
+++ b/index.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8" />
+  <title>Home | Hi, I&#39;m Nhân</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <link rel="alternate" type="application/atom+xml" title="Atom feed" href="/feed.xml">
+  <link rel="stylesheet" href="/_theme/base.css">
+</head>
+
+<body>
+
+<header>
+  <h1 class="site-title">Hi, I&#39;m Nhân</h1>
+  <p class="tagline">and welcome to my humble corner on the interwebs</p>
+</header>
+
+<hr>
+
+<div class="pages">
+  <a href="/">Home</a>
+  <a class="feed-link" href="/feed.xml">
+    <img src="/_theme/feed.svg" alt="Atom Feed" title="Atom Feed">
+  </a>
+</div>
+
+<hr>
+
+
+
+
+<p>No posts yet.</p>
+
+
+<style>
+.site-title {
+  margin-bottom: 0;
+}
+.tagline {
+  margin-top: 0;
+}
+
+.feed-link img {
+  height: 1rem;
+}
+.feed-link {
+  float: right;
+}
+hr {
+  clear: both;
+}
+
+.pages a {
+  margin-right: 0.5rem;
+}
+
+ul {
+  padding: 0;
+  list-style: none;
+   
+}
+
+.time-suffix {
+  display: none;
+}
+
+@media (max-width: 30rem) {
+  .time-suffix {
+    display: inline;
+  }
+  .time-prefix {
+    display: none;
+  }
+  li {
+    margin-bottom: 0.5rem;
+  }
+  li::before {
+    content: '❖';
+  }
+}
+</style>
+
+<footer>
+© 2023 nhanb<br>
+Made with <a href="https://github.com/nhanb/s4g">s4g</a>
+</footer>
+
+
+</body>
+
+</html>
diff --git a/manifest.txt b/manifest.txt
new file mode 100644
index 0000000..6553aff
--- /dev/null
+++ b/manifest.txt
@@ -0,0 +1,28 @@
+index.html
+posts/acer-chromebook-spin/index.html
+posts/enable-italic-text-vim-tmux-gnome-terminal/index.html
+posts/fix-rmit-wifi-issue-in-ubuntu-13-04-and-variants/index.html
+posts/go-postgres-caddy-systemd-stack/index.html
+posts/have-you-built-anything-cool/index.html
+posts/how-i-bypassed-my-university-domain-blocker-to-access-hdviet/index.html
+posts/how-to-install-pyqt5-on-virtualenv-on-ubuntu-14.04/index.html
+posts/i-did-not-sign-that-rmit-sc-petition/index.html
+posts/i-made-my-python-webapp-pip-installable/index.html
+posts/ibus-is-dead-to-me-use-fcitx-instead-vi/index.html
+posts/installing-programs-in-ubuntu/index.html
+posts/introducing-mcross-a-minimal-gemini-browser/index.html
+posts/introducing-pytaku-the-only-online-manga-reader-youll-ever-need/index.html
+posts/look-ma-no-stock-theme/index.html
+posts/modern-vim-plugin-management-pathogen-vs-vundle/index.html
+posts/my-first-diy-fightstick-part-1/index.html
+posts/my-first-diy-fightstick-part-2/index.html
+posts/opening-http-link-under-the-cursor-in-vim/index.html
+posts/setting-up-your-development-environment-for-a-node-webkit-project/index.html
+posts/simplest-possible-stepmania-soft-to-hard-pad-mod/index.html
+posts/streaming-videos-from-google-drive-a-second-attempt/index.html
+posts/the-video-streaming-finale-or-why-putio-is-awesome/index.html
+posts/towards-an-acceptable-video-playing-experience/index.html
+posts/virtualenwrapper-python2-python3/index.html
+posts/what-i-did-after-installing-manjaro-xfce/index.html
+posts/why-i-use-linux-automation/index.html
+posts/working-with-sqlite-in-python-without-an-orm-or-migration-framework/index.html
\ No newline at end of file
diff --git a/pelicanconf.py b/pelicanconf.py
deleted file mode 100644
index e15c691..0000000
--- a/pelicanconf.py
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/env python
-from datetime import date
-
-AUTHOR = "Bùi Thành Nhân"
-SITENAME = "Hi, I'm Nhân"
-SITESUBTITLE = "and this is my humble corner on the intertubes."
-SITEURL = ""
-
-THEME = "./nhanb-theme"
-
-TIMEZONE = "Asia/Ho_Chi_Minh"
-
-DEFAULT_LANG = "en"
-TYPOGRIFY = True
-
-MARKDOWN = {
-    "extension_configs": {
-        "markdown.extensions.codehilite": {"css_class": "highlight"},
-        "markdown.extensions.extra": {},
-        "markdown.extensions.meta": {},
-        "smarty": {},
-        "toc": {"permalink": "#"},
-    },
-    "output_format": "html5",
-}
-
-# Feed generation is usually not desired when developing
-FEED_ALL_ATOM = None
-CATEGORY_FEED_ATOM = None
-TRANSLATION_FEED_ATOM = None
-
-STATIC_PATHS = ["images", "extra"]
-
-EXTRA_PATH_METADATA = {
-    "extra/CNAME": {"path": "CNAME"},
-    "extra/favicon.ico": {"path": "favicon.ico"},
-    "extra/favicon.png": {"path": "favicon.png"},
-    "extra/404.html": {"path": "404.html"},
-    "extra/ping.html": {"path": "ping.html"},
-}
-
-ARTICLE_PATHS = ["posts"]
-ARTICLE_URL = "posts/{slug}/"
-ARTICLE_SAVE_AS = "posts/{slug}/index.html"
-ARTICLE_LANG_URL = "posts/{slug}-{lang}/"
-ARTICLE_LANG_SAVE_AS = "posts/{slug}-{lang}/index.html"
-
-PAGE_PATHS = ["pages"]
-PAGE_URL = "{slug}/"
-PAGE_SAVE_AS = "{slug}/index.html"
-PAGE_LANG_URL = "{slug}-{lang}/"
-PAGE_LANG_SAVE_AS = "{slug}-{lang}/index.html"
-
-AUTHOR_URL = "author/{slug}/"
-AUTHOR_SAVE_AS = "author/{slug}/index.html"
-
-CATEGORY_URL = "category/{slug}/"
-CATEGORY_SAVE_AS = "category/{slug}/index.html"
-
-TAG_URL = "tag/{slug}/"
-TAG_SAVE_AS = "tag/{slug}/index.html"
-
-DEFAULT_PAGINATION = False
-
-AUTHOR_NAME = "Bùi Thành Nhân"
-AUTHOR_SLUG = "nhanb"
-
-THEME_STATIC_PATHS = ["static"]
-
-MENUITEMS = (("Blog", "/"),)
-
-PLUGINS = ["minify"]
-
-MINIFY = {
-    "remove_comments": False,
-    "remove_all_empty_space": False,
-    "remove_optional_attribute_quotes": False,
-}
-
-FEED_DOMAIN = SITEURL
-FEED_ALL_ATOM = "feeds/all.atom.xml"
-FEED_ATOM = "feeds/atom.xml"
-CATEGORY_FEED_ATOM = "feeds/{slug}.atom.xml"
-
-# ========= Theme-specific settings follow =============
-
-MOTHERFUCKING_DEFAULT_THUMB = "images/keyboard-warrior.jpg"
-MOTHERFUCKING_GREETINGS = """
-Why hello there, source viewer. Here's a dragon for no particular reason:
-
-       ^                       ^
-       |\   \        /        /|
-      /  \  |\__  __/|       /  \_
-     / /\ \ \ _ \/ _ /      /    \_
-    / / /\ \ {*}\/{*}      /  / \ \_
-    | | | \ \( (00) )     /  // |\ \_
-    | | | |\ \(V""V)\    /  / | || \|
-    | | | | \ |^--^| \  /  / || || ||
-   / / /  | |( WWWW__ \/  /| || || ||
-  | | | | | |  \______\  / / || || ||
-  | | | / | | )|______\ ) | / | || ||
-  / / /  / /  /______/   /| \ \ || ||
- / / /  / /  /\_____/  |/ /__\ \ \ \ \_
- | | | / /  /\______/    \   \__| \ \ \_
- | | | | | |\______ __    \_    \__|_| \_
- | | ,___ /\______ _  _     \_       \  |
- | |/    /\_____  /    \      \__     \ |    /\_
- |/ |   |\______ |      |        \___  \ |__/  \_
- v  |   |\______ |      |            \___/     |
-    |   |\______ |      |                    __/
-     \   \________\_    _\               ____/
-   __/   /\_____ __/   /   )\_,      _____/
-  /  ___/  \____/  ___/___)    \______/
-  VVV  V        VVV  V
-
-(ripped off from http://www.retrojunkie.com/asciiart/myth/dragons.htm)
-"""
-
-CURRENT_YEAR = date.today().year
-
-FOOTER_TEXT = """
-Built with &#9829; and probably too much
-<a target="_blank" rel="noopener" href="https://www.alambe.vn/products/ca-phe-rang-xay-alambe-sai-gon">cà phê sữa đá</a>.
-"""
diff --git a/content/extra/ping.html b/ping.html
similarity index 100%
rename from content/extra/ping.html
rename to ping.html
diff --git a/poetry.lock b/poetry.lock
deleted file mode 100644
index e0167f7..0000000
--- a/poetry.lock
+++ /dev/null
@@ -1,342 +0,0 @@
-# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
-
-[[package]]
-name = "blinker"
-version = "1.6.2"
-description = "Fast, simple object-to-object and broadcast signaling"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "blinker-1.6.2-py3-none-any.whl", hash = "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0"},
-    {file = "blinker-1.6.2.tar.gz", hash = "sha256:4afd3de66ef3a9f8067559fb7a1cbe555c17dcbe15971b05d1b625c3e7abe213"},
-]
-
-[[package]]
-name = "docutils"
-version = "0.20.1"
-description = "Docutils -- Python Documentation Utilities"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"},
-    {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"},
-]
-
-[[package]]
-name = "feedgenerator"
-version = "2.1.0"
-description = "Standalone version of django.utils.feedgenerator"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "feedgenerator-2.1.0-py3-none-any.whl", hash = "sha256:93b7ce1c5a86195cafd6a8e9baf6a2a863ebd6d9905e840ce5778f73efd9a8d5"},
-    {file = "feedgenerator-2.1.0.tar.gz", hash = "sha256:f075f23f28fd227f097c36b212161c6cf012e1c6caaf7ff53d5d6bb02cd42b9d"},
-]
-
-[package.dependencies]
-pytz = ">=0a"
-
-[[package]]
-name = "ghp-import"
-version = "0.5.5"
-description = "Copy your docs directly to the gh-pages branch."
-optional = false
-python-versions = "*"
-files = [
-    {file = "ghp-import-0.5.5.tar.gz", hash = "sha256:3e924ea720e4e1f82d56753db2154bfb86067472c5830732159c3a4c4fbc75d7"},
-]
-
-[[package]]
-name = "htmlmin"
-version = "0.1.12"
-description = "An HTML Minifier"
-optional = false
-python-versions = "*"
-files = [
-    {file = "htmlmin-0.1.12.tar.gz", hash = "sha256:50c1ef4630374a5d723900096a961cff426dff46b48f34d194a81bbe14eca178"},
-]
-
-[[package]]
-name = "jinja2"
-version = "3.1.2"
-description = "A very fast and expressive template engine."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
-    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=2.0"
-
-[package.extras]
-i18n = ["Babel (>=2.7)"]
-
-[[package]]
-name = "joblib"
-version = "1.3.1"
-description = "Lightweight pipelining with Python functions"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "joblib-1.3.1-py3-none-any.whl", hash = "sha256:89cf0529520e01b3de7ac7b74a8102c90d16d54c64b5dd98cafcd14307fdf915"},
-    {file = "joblib-1.3.1.tar.gz", hash = "sha256:1f937906df65329ba98013dc9692fe22a4c5e4a648112de500508b18a21b41e3"},
-]
-
-[[package]]
-name = "markdown"
-version = "3.4.3"
-description = "Python implementation of John Gruber's Markdown."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"},
-    {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"},
-]
-
-[package.extras]
-testing = ["coverage", "pyyaml"]
-
-[[package]]
-name = "markdown-it-py"
-version = "3.0.0"
-description = "Python port of markdown-it. Markdown parsing, done right!"
-optional = false
-python-versions = ">=3.8"
-files = [
-    {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
-    {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
-]
-
-[package.dependencies]
-mdurl = ">=0.1,<1.0"
-
-[package.extras]
-benchmarking = ["psutil", "pytest", "pytest-benchmark"]
-code-style = ["pre-commit (>=3.0,<4.0)"]
-compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
-linkify = ["linkify-it-py (>=1,<3)"]
-plugins = ["mdit-py-plugins"]
-profiling = ["gprof2dot"]
-rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
-testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
-
-[[package]]
-name = "markupsafe"
-version = "2.1.3"
-description = "Safely add untrusted strings to HTML/XML markup."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
-    {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
-    {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
-    {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
-    {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
-    {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
-    {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
-]
-
-[[package]]
-name = "mdurl"
-version = "0.1.2"
-description = "Markdown URL utilities"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
-    {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
-]
-
-[[package]]
-name = "pelican"
-version = "4.8.0"
-description = "Static site generator supporting Markdown and reStructuredText"
-optional = false
-python-versions = ">=3.6,<4.0"
-files = [
-    {file = "pelican-4.8.0-py3-none-any.whl", hash = "sha256:c80a81930f57f9b1a11c9ab5894ce1465dcda2028c9e4e3993cf9cbf2061a57d"},
-    {file = "pelican-4.8.0.tar.gz", hash = "sha256:6445c00cff2142a30592a2de046e5647b84a36c5a0cfafc0eba75abbabb2b4b1"},
-]
-
-[package.dependencies]
-blinker = ">=1.4"
-docutils = ">=0.16"
-feedgenerator = ">=1.9"
-jinja2 = ">=2.7"
-markdown = {version = ">=3.1", optional = true, markers = "extra == \"markdown\""}
-pygments = ">=2.6"
-python-dateutil = ">=2.8"
-pytz = ">=2020.1"
-rich = ">=10.1"
-unidecode = ">=1.1"
-
-[package.extras]
-markdown = ["markdown (>=3.1)"]
-
-[[package]]
-name = "pelican-minify"
-version = "0.9"
-description = "An HTML minification plugin for Pelican, the static site generator."
-optional = false
-python-versions = "*"
-files = [
-    {file = "pelican-minify-0.9.tar.gz", hash = "sha256:a0ffa9b1f15089bc4aec4692c5feba87356d427a7946ffd8b6222ac4c7758773"},
-    {file = "pelican_minify-0.9-py2.py3-none-any.whl", hash = "sha256:fcefce477d4a24c8972ec8871738100f144e329201ab2b45aab8b5d3b7ba8e65"},
-]
-
-[package.dependencies]
-htmlmin = ">=0.1.5"
-joblib = ">=0.9"
-pelican = ">=3.1.1"
-
-[[package]]
-name = "pygments"
-version = "2.15.1"
-description = "Pygments is a syntax highlighting package written in Python."
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
-    {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
-]
-
-[package.extras]
-plugins = ["importlib-metadata"]
-
-[[package]]
-name = "python-dateutil"
-version = "2.8.2"
-description = "Extensions to the standard Python datetime module"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
-files = [
-    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
-    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
-]
-
-[package.dependencies]
-six = ">=1.5"
-
-[[package]]
-name = "pytz"
-version = "2023.3"
-description = "World timezone definitions, modern and historical"
-optional = false
-python-versions = "*"
-files = [
-    {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
-    {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
-]
-
-[[package]]
-name = "rich"
-version = "13.4.2"
-description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
-optional = false
-python-versions = ">=3.7.0"
-files = [
-    {file = "rich-13.4.2-py3-none-any.whl", hash = "sha256:8f87bc7ee54675732fa66a05ebfe489e27264caeeff3728c945d25971b6485ec"},
-    {file = "rich-13.4.2.tar.gz", hash = "sha256:d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898"},
-]
-
-[package.dependencies]
-markdown-it-py = ">=2.2.0"
-pygments = ">=2.13.0,<3.0.0"
-
-[package.extras]
-jupyter = ["ipywidgets (>=7.5.1,<9)"]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-files = [
-    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
-    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-
-[[package]]
-name = "smartypants"
-version = "2.0.1"
-description = "Python with the SmartyPants"
-optional = false
-python-versions = "*"
-files = [
-    {file = "smartypants-2.0.1-py2.py3-none-any.whl", hash = "sha256:8db97f7cbdf08d15b158a86037cd9e116b4cf37703d24e0419a0d64ca5808f0d"},
-]
-
-[[package]]
-name = "typogrify"
-version = "2.0.7"
-description = "Filters to enhance web typography, including support for Django & Jinja templates"
-optional = false
-python-versions = "*"
-files = [
-    {file = "typogrify-2.0.7.tar.gz", hash = "sha256:8be4668cda434163ce229d87ca273a11922cb1614cb359970b7dc96eed13cb38"},
-]
-
-[package.dependencies]
-smartypants = ">=1.8.3"
-
-[[package]]
-name = "unidecode"
-version = "1.3.6"
-description = "ASCII transliterations of Unicode text"
-optional = false
-python-versions = ">=3.5"
-files = [
-    {file = "Unidecode-1.3.6-py3-none-any.whl", hash = "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be"},
-    {file = "Unidecode-1.3.6.tar.gz", hash = "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"},
-]
-
-[metadata]
-lock-version = "2.0"
-python-versions = "^3.10"
-content-hash = "ddedd6f9d94db8a55cde57c4e3ad6c212dd5370b10fd3ff392558c4850c3cb60"
diff --git a/posts/acer-chromebook-spin/index.html b/posts/acer-chromebook-spin/index.html
new file mode 100644
index 0000000..6887b77
--- /dev/null
+++ b/posts/acer-chromebook-spin/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /chromebook/</title>
+    <meta http-equiv="Refresh" content="0; URL=/chromebook/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/chromebook/">/chromebook/</a>.
+  </body>
+</html>
diff --git a/posts/enable-italic-text-vim-tmux-gnome-terminal/index.html b/posts/enable-italic-text-vim-tmux-gnome-terminal/index.html
new file mode 100644
index 0000000..5747bf5
--- /dev/null
+++ b/posts/enable-italic-text-vim-tmux-gnome-terminal/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /tmux-italics/</title>
+    <meta http-equiv="Refresh" content="0; URL=/tmux-italics/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/tmux-italics/">/tmux-italics/</a>.
+  </body>
+</html>
diff --git a/posts/fix-rmit-wifi-issue-in-ubuntu-13-04-and-variants/index.html b/posts/fix-rmit-wifi-issue-in-ubuntu-13-04-and-variants/index.html
new file mode 100644
index 0000000..c1d908f
--- /dev/null
+++ b/posts/fix-rmit-wifi-issue-in-ubuntu-13-04-and-variants/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /rmit-wifi/</title>
+    <meta http-equiv="Refresh" content="0; URL=/rmit-wifi/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/rmit-wifi/">/rmit-wifi/</a>.
+  </body>
+</html>
diff --git a/posts/go-postgres-caddy-systemd-stack/index.html b/posts/go-postgres-caddy-systemd-stack/index.html
new file mode 100644
index 0000000..4f62062
--- /dev/null
+++ b/posts/go-postgres-caddy-systemd-stack/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /go-stack/</title>
+    <meta http-equiv="Refresh" content="0; URL=/go-stack/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/go-stack/">/go-stack/</a>.
+  </body>
+</html>
diff --git a/posts/have-you-built-anything-cool/index.html b/posts/have-you-built-anything-cool/index.html
new file mode 100644
index 0000000..171e8f1
--- /dev/null
+++ b/posts/have-you-built-anything-cool/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /cool/</title>
+    <meta http-equiv="Refresh" content="0; URL=/cool/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/cool/">/cool/</a>.
+  </body>
+</html>
diff --git a/posts/how-i-bypassed-my-university-domain-blocker-to-access-hdviet/index.html b/posts/how-i-bypassed-my-university-domain-blocker-to-access-hdviet/index.html
new file mode 100644
index 0000000..c156712
--- /dev/null
+++ b/posts/how-i-bypassed-my-university-domain-blocker-to-access-hdviet/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /hdviet/</title>
+    <meta http-equiv="Refresh" content="0; URL=/hdviet/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/hdviet/">/hdviet/</a>.
+  </body>
+</html>
diff --git a/posts/how-to-install-pyqt5-on-virtualenv-on-ubuntu-14.04/index.html b/posts/how-to-install-pyqt5-on-virtualenv-on-ubuntu-14.04/index.html
new file mode 100644
index 0000000..34ecdc4
--- /dev/null
+++ b/posts/how-to-install-pyqt5-on-virtualenv-on-ubuntu-14.04/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /pyqt5/</title>
+    <meta http-equiv="Refresh" content="0; URL=/pyqt5/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/pyqt5/">/pyqt5/</a>.
+  </body>
+</html>
diff --git a/posts/i-did-not-sign-that-rmit-sc-petition/index.html b/posts/i-did-not-sign-that-rmit-sc-petition/index.html
new file mode 100644
index 0000000..f3dcad7
--- /dev/null
+++ b/posts/i-did-not-sign-that-rmit-sc-petition/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /petition-fraud/</title>
+    <meta http-equiv="Refresh" content="0; URL=/petition-fraud/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/petition-fraud/">/petition-fraud/</a>.
+  </body>
+</html>
diff --git a/posts/i-made-my-python-webapp-pip-installable/index.html b/posts/i-made-my-python-webapp-pip-installable/index.html
new file mode 100644
index 0000000..d87727d
--- /dev/null
+++ b/posts/i-made-my-python-webapp-pip-installable/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /pippable-webapp/</title>
+    <meta http-equiv="Refresh" content="0; URL=/pippable-webapp/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/pippable-webapp/">/pippable-webapp/</a>.
+  </body>
+</html>
diff --git a/posts/ibus-is-dead-to-me-use-fcitx-instead-vi/index.html b/posts/ibus-is-dead-to-me-use-fcitx-instead-vi/index.html
new file mode 100644
index 0000000..41089d7
--- /dev/null
+++ b/posts/ibus-is-dead-to-me-use-fcitx-instead-vi/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /fcitx/</title>
+    <meta http-equiv="Refresh" content="0; URL=/fcitx/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/fcitx/">/fcitx/</a>.
+  </body>
+</html>
diff --git a/posts/installing-programs-in-ubuntu/index.html b/posts/installing-programs-in-ubuntu/index.html
new file mode 100644
index 0000000..a5335c0
--- /dev/null
+++ b/posts/installing-programs-in-ubuntu/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /ubuntu-programs/</title>
+    <meta http-equiv="Refresh" content="0; URL=/ubuntu-programs/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/ubuntu-programs/">/ubuntu-programs/</a>.
+  </body>
+</html>
diff --git a/posts/introducing-mcross-a-minimal-gemini-browser/index.html b/posts/introducing-mcross-a-minimal-gemini-browser/index.html
new file mode 100644
index 0000000..614b162
--- /dev/null
+++ b/posts/introducing-mcross-a-minimal-gemini-browser/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /mcross/</title>
+    <meta http-equiv="Refresh" content="0; URL=/mcross/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/mcross/">/mcross/</a>.
+  </body>
+</html>
diff --git a/posts/introducing-pytaku-the-only-online-manga-reader-youll-ever-need/index.html b/posts/introducing-pytaku-the-only-online-manga-reader-youll-ever-need/index.html
new file mode 100644
index 0000000..e18d119
--- /dev/null
+++ b/posts/introducing-pytaku-the-only-online-manga-reader-youll-ever-need/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /pytaku/</title>
+    <meta http-equiv="Refresh" content="0; URL=/pytaku/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/pytaku/">/pytaku/</a>.
+  </body>
+</html>
diff --git a/posts/look-ma-no-stock-theme/index.html b/posts/look-ma-no-stock-theme/index.html
new file mode 100644
index 0000000..4bac5d5
--- /dev/null
+++ b/posts/look-ma-no-stock-theme/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /custom-theme/</title>
+    <meta http-equiv="Refresh" content="0; URL=/custom-theme/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/custom-theme/">/custom-theme/</a>.
+  </body>
+</html>
diff --git a/posts/modern-vim-plugin-management-pathogen-vs-vundle/index.html b/posts/modern-vim-plugin-management-pathogen-vs-vundle/index.html
new file mode 100644
index 0000000..3b704f4
--- /dev/null
+++ b/posts/modern-vim-plugin-management-pathogen-vs-vundle/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /pathogen-vs-vundle/</title>
+    <meta http-equiv="Refresh" content="0; URL=/pathogen-vs-vundle/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/pathogen-vs-vundle/">/pathogen-vs-vundle/</a>.
+  </body>
+</html>
diff --git a/posts/my-first-diy-fightstick-part-1/index.html b/posts/my-first-diy-fightstick-part-1/index.html
new file mode 100644
index 0000000..cbf2a05
--- /dev/null
+++ b/posts/my-first-diy-fightstick-part-1/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /fightstick-1/</title>
+    <meta http-equiv="Refresh" content="0; URL=/fightstick-1/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/fightstick-1/">/fightstick-1/</a>.
+  </body>
+</html>
diff --git a/posts/my-first-diy-fightstick-part-2/index.html b/posts/my-first-diy-fightstick-part-2/index.html
new file mode 100644
index 0000000..9e3aa1a
--- /dev/null
+++ b/posts/my-first-diy-fightstick-part-2/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /fightstick-2/</title>
+    <meta http-equiv="Refresh" content="0; URL=/fightstick-2/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/fightstick-2/">/fightstick-2/</a>.
+  </body>
+</html>
diff --git a/posts/opening-http-link-under-the-cursor-in-vim/index.html b/posts/opening-http-link-under-the-cursor-in-vim/index.html
new file mode 100644
index 0000000..0a3ee92
--- /dev/null
+++ b/posts/opening-http-link-under-the-cursor-in-vim/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /vim-open-link/</title>
+    <meta http-equiv="Refresh" content="0; URL=/vim-open-link/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/vim-open-link/">/vim-open-link/</a>.
+  </body>
+</html>
diff --git a/posts/setting-up-your-development-environment-for-a-node-webkit-project/index.html b/posts/setting-up-your-development-environment-for-a-node-webkit-project/index.html
new file mode 100644
index 0000000..23f01e0
--- /dev/null
+++ b/posts/setting-up-your-development-environment-for-a-node-webkit-project/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /node-webkit/</title>
+    <meta http-equiv="Refresh" content="0; URL=/node-webkit/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/node-webkit/">/node-webkit/</a>.
+  </body>
+</html>
diff --git a/posts/simplest-possible-stepmania-soft-to-hard-pad-mod/index.html b/posts/simplest-possible-stepmania-soft-to-hard-pad-mod/index.html
new file mode 100644
index 0000000..4e9dd35
--- /dev/null
+++ b/posts/simplest-possible-stepmania-soft-to-hard-pad-mod/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /stepmania-pad/</title>
+    <meta http-equiv="Refresh" content="0; URL=/stepmania-pad/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/stepmania-pad/">/stepmania-pad/</a>.
+  </body>
+</html>
diff --git a/posts/streaming-videos-from-google-drive-a-second-attempt/index.html b/posts/streaming-videos-from-google-drive-a-second-attempt/index.html
new file mode 100644
index 0000000..8dfc14a
--- /dev/null
+++ b/posts/streaming-videos-from-google-drive-a-second-attempt/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /video-streaming-2/</title>
+    <meta http-equiv="Refresh" content="0; URL=/video-streaming-2/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/video-streaming-2/">/video-streaming-2/</a>.
+  </body>
+</html>
diff --git a/posts/the-video-streaming-finale-or-why-putio-is-awesome/index.html b/posts/the-video-streaming-finale-or-why-putio-is-awesome/index.html
new file mode 100644
index 0000000..289cabf
--- /dev/null
+++ b/posts/the-video-streaming-finale-or-why-putio-is-awesome/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /video-streaming-3/</title>
+    <meta http-equiv="Refresh" content="0; URL=/video-streaming-3/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/video-streaming-3/">/video-streaming-3/</a>.
+  </body>
+</html>
diff --git a/posts/towards-an-acceptable-video-playing-experience/index.html b/posts/towards-an-acceptable-video-playing-experience/index.html
new file mode 100644
index 0000000..904703c
--- /dev/null
+++ b/posts/towards-an-acceptable-video-playing-experience/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /video-streaming-1/</title>
+    <meta http-equiv="Refresh" content="0; URL=/video-streaming-1/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/video-streaming-1/">/video-streaming-1/</a>.
+  </body>
+</html>
diff --git a/posts/virtualenwrapper-python2-python3/index.html b/posts/virtualenwrapper-python2-python3/index.html
new file mode 100644
index 0000000..986820b
--- /dev/null
+++ b/posts/virtualenwrapper-python2-python3/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /virtualenvwrapper/</title>
+    <meta http-equiv="Refresh" content="0; URL=/virtualenvwrapper/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/virtualenvwrapper/">/virtualenvwrapper/</a>.
+  </body>
+</html>
diff --git a/posts/what-i-did-after-installing-manjaro-xfce/index.html b/posts/what-i-did-after-installing-manjaro-xfce/index.html
new file mode 100644
index 0000000..b8cf232
--- /dev/null
+++ b/posts/what-i-did-after-installing-manjaro-xfce/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /manjaro-xfce/</title>
+    <meta http-equiv="Refresh" content="0; URL=/manjaro-xfce/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/manjaro-xfce/">/manjaro-xfce/</a>.
+  </body>
+</html>
diff --git a/posts/why-i-use-linux-automation/index.html b/posts/why-i-use-linux-automation/index.html
new file mode 100644
index 0000000..5e2e8e9
--- /dev/null
+++ b/posts/why-i-use-linux-automation/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /linux-automation/</title>
+    <meta http-equiv="Refresh" content="0; URL=/linux-automation/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/linux-automation/">/linux-automation/</a>.
+  </body>
+</html>
diff --git a/posts/working-with-sqlite-in-python-without-an-orm-or-migration-framework/index.html b/posts/working-with-sqlite-in-python-without-an-orm-or-migration-framework/index.html
new file mode 100644
index 0000000..ebdf692
--- /dev/null
+++ b/posts/working-with-sqlite-in-python-without-an-orm-or-migration-framework/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Redirecting to /sqlite-python/</title>
+    <meta http-equiv="Refresh" content="0; URL=/sqlite-python/" />
+  </head>
+  <body>
+    The page you're looking for has been moved to <a href="/sqlite-python/">/sqlite-python/</a>.
+  </body>
+</html>
diff --git a/publishconf.py b/publishconf.py
deleted file mode 100644
index fc11395..0000000
--- a/publishconf.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*- #
-import os
-import sys
-
-sys.path.append(os.curdir)
-
-from pelicanconf import *  # noqa
-
-# This file is only used if you use `make publish` or
-# explicitly specify it as your config file.
-
-SITEURL = "https://hi.imnhan.com"
-RELATIVE_URLS = True
-
-DELETE_OUTPUT_DIRECTORY = True
-
-# Following items are often useful when publishing
-
-DISQUS_SITENAME = "nerdyweekly"
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index ee88336..0000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[tool.poetry]
-name = "imnhan.com"
-version = "0.1.0"
-description = ""
-authors = ["nhanb <hi@imnhan.com>"]
-
-[tool.poetry.dependencies]
-python = "^3.10"
-typogrify = "^2.0"
-pelican-minify = "^0.9.0"
-pelican = {extras = ["markdown"], version = "^4.8.0"}
-
-[tool.poetry.dev-dependencies]
-ghp-import = "^0.5.5"
-
-[build-system]
-requires = ["poetry>=0.12"]
-build-backend = "poetry.masonry.api"
diff --git a/redirects.txt b/redirects.txt
new file mode 100644
index 0000000..b5bb930
--- /dev/null
+++ b/redirects.txt
@@ -0,0 +1,27 @@
+posts/acer-chromebook-spin/index.html -> chromebook/
+posts/enable-italic-text-vim-tmux-gnome-terminal/index.html -> tmux-italics/
+posts/fix-rmit-wifi-issue-in-ubuntu-13-04-and-variants/index.html -> rmit-wifi/
+posts/go-postgres-caddy-systemd-stack/index.html -> go-stack/
+posts/have-you-built-anything-cool/index.html -> cool/
+posts/how-i-bypassed-my-university-domain-blocker-to-access-hdviet/index.html -> hdviet/
+posts/how-to-install-pyqt5-on-virtualenv-on-ubuntu-14.04/index.html -> pyqt5/
+posts/ibus-is-dead-to-me-use-fcitx-instead-vi/index.html -> fcitx/
+posts/i-did-not-sign-that-rmit-sc-petition/index.html -> petition-fraud/
+posts/i-made-my-python-webapp-pip-installable/index.html -> pippable-webapp/
+posts/installing-programs-in-ubuntu/index.html -> ubuntu-programs/
+posts/introducing-mcross-a-minimal-gemini-browser/index.html -> mcross/
+posts/introducing-pytaku-the-only-online-manga-reader-youll-ever-need/index.html -> pytaku/
+posts/look-ma-no-stock-theme/index.html -> custom-theme/
+posts/modern-vim-plugin-management-pathogen-vs-vundle/index.html -> pathogen-vs-vundle/
+posts/my-first-diy-fightstick-part-1/index.html -> fightstick-1/
+posts/my-first-diy-fightstick-part-2/index.html -> fightstick-2/
+posts/opening-http-link-under-the-cursor-in-vim/index.html -> vim-open-link/
+posts/setting-up-your-development-environment-for-a-node-webkit-project/index.html -> node-webkit/
+posts/simplest-possible-stepmania-soft-to-hard-pad-mod/index.html -> stepmania-pad/
+posts/streaming-videos-from-google-drive-a-second-attempt/index.html -> video-streaming-2/
+posts/the-video-streaming-finale-or-why-putio-is-awesome/index.html -> video-streaming-3/
+posts/towards-an-acceptable-video-playing-experience/index.html -> video-streaming-1/
+posts/virtualenwrapper-python2-python3/index.html -> virtualenvwrapper/
+posts/what-i-did-after-installing-manjaro-xfce/index.html -> manjaro-xfce/
+posts/why-i-use-linux-automation/index.html -> linux-automation/
+posts/working-with-sqlite-in-python-without-an-orm-or-migration-framework/index.html -> sqlite-python/
diff --git a/website.s4g b/website.s4g
new file mode 100644
index 0000000..9e971de
--- /dev/null
+++ b/website.s4g
@@ -0,0 +1,9 @@
+Address: https://hi.imnhan.com
+Name: Hi, I'm Nhân
+Tagline: and welcome to my humble corner on the interwebs
+Root: /
+ShowFooter: true
+NavbarLinks: index.dj
+AuthorName: nhanb
+AuthorURI: https://hi.imnhan.com
+AuthorEmail: hi@imnhan.com