porcellis.com

commit b16503c3d841fc2d55541766930e1998957b3886

Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>

all: fully compat with latest hugo version, fix diverse issues

 .gitignore | 1 
 config.toml | 16 +++++++--
 content/blog/sobre-software-duravel.en.md | 2 
 content/blog/sobre-software-duravel.md | 2 
  | 12 +++++++
 data/meses.yaml | 12 -------
 data/months.yaml | 12 -------
 i18n/en.toml | 8 +---
 i18n/pt-br.toml | 8 +---
 layouts/_partials/colophon.html | 8 +++++
 layouts/_partials/head.html | 18 +++++++++++
 layouts/_partials/site-title.html | 4 ++
 layouts/_partials/time.html | 3 +
 layouts/baseof.html | 8 +++++
  | 14 +++-----
 layouts/home.html | 37 +++++++++++++++++++++++
 layouts/index.html | 39 ------------------------
 layouts/list.html | 40 +++++++++++++++++++++++++
  | 4 +-
 layouts/partials/basic.html | 20 ------------
  | 0 
  | 0 
  | 0 
  | 0 
 layouts/partials/head.html | 11 ------
 layouts/partials/time.html | 5 ---
  | 2 
 static/robots.txt | 4 ++


diff --git a/.gitignore b/.gitignore
index 73ab8769f93bbbd5c4b69d33c2fa86329d05bc85..1c3fa7397fcb77d73cff8cf465ca2bf8a53dabb7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 public/
 resources/
+.hugo_build.lock




diff --git a/config.toml b/config.toml
index e11b24ee25ce96a6e6f04a014c226d500ca71bf8..d0b2a1d0cb3cdd63aa388d1b7fcdba57b208ceb4 100644
--- a/config.toml
+++ b/config.toml
@@ -1,21 +1,29 @@
 baseURL = "https://porcellis.com/"
 title = "Pedro Lucas Porcellis"
 
+locale = "pt-br"
 defaultContentLanguage = "pt-br"
-languageCode = "pt-br"
 uglyurls = true
-pygmentsUseClasses = true
 disablePathToLower = true
+pluralizeListTitles = false
 
 [permalinks]
 blog = "/:year/:month/:day/:title"
 
+[taxonomies]
+tag = "tags"
+
 [languages]
   [languages.pt-br]
     weight = 1
-    languageName = "Português"
+    label = "Português"
   [languages.en]
     title = "Pedro Lucas Porcellis"
     weight = 2
-    languageName = "English"
+    label = "English"
 
+[markup.highlight]
+noClasses = false
+
+[markup.goldmark.renderer]
+unsafe = true




diff --git a/content/blog/sobre-software-duravel.en.md b/content/blog/sobre-software-duravel.en.md
index 42ae295cc79574a2a37565f17952d68ce31eecc9..ac8295f074f15eb6bb7ddab96973e12b56b5525d 100644
--- a/content/blog/sobre-software-duravel.en.md
+++ b/content/blog/sobre-software-duravel.en.md
@@ -81,7 +81,7 @@ classes, modules and methods. It only does what it must, in the most simplest
 and least intrusive way it can. There's no DSL, there's no huge set of
 assertation matchers.
 
-[My text editor, vim]({{< relref path="/porque-eu-uso-vim.md" lang="pt-br" >}}
+[My text editor, vim]({{< relref path="porque-eu-uso-vim.md" lang="pt-br" >}}
 "Porque eu uso vim, ou uma reflexão sobre complexidade na tecnologia (pt-br)")
 has the same predictable behaviour for over a decade, and it's forks keep the
 same default behaviour, so I know I can hop into some random machine and know it




diff --git a/content/blog/sobre-software-duravel.md b/content/blog/sobre-software-duravel.md
index 842ecdd5f7da089f1f2bcdeb283ebae5adee7dc7..37bdd911f6cd0f5c8eb7489dc4d4d08c1993f33f 100644
--- a/content/blog/sobre-software-duravel.md
+++ b/content/blog/sobre-software-duravel.md
@@ -87,7 +87,7 @@ conceitos básicos da própria linguagem, como classes, metodos e módulos. Ele só
 faz o que ele foi feito pra fazer, da forma mais simples e desobstruente
 possível. Não possui uma DSL, tampouco um ramo diverso de coisas pré-prontas.
 
-[Meu editor de texto, vim]({{< relref "/porque-eu-uso-vim.md" >}} "Porque eu uso
+[Meu editor de texto, vim]({{< relref "porque-eu-uso-vim.md" >}} "Porque eu uso
 vim, ou uma reflexão sobre complexidade na tecnologia") se comporta da mesma
 forma há pelo menos uma década, outras derivações do projeto mantem  o mesmo
 comportamento padrão, o que significa que eu posso entrar em qualquer máquina e




diff --git a/content/new-server.html b/content/new-server.html
deleted file mode 100644
index 2850859d3dbf430ad05a8ca54b23150f03e12876..0000000000000000000000000000000000000000
--- a/content/new-server.html
+++ /dev/null
@@ -1,214 +0,0 @@
-<h1>New Server Checklist</h1>
-<label>
-  <input type="checkbox" /> Set root password
-</label>
-<label>
-  <input type="checkbox" /> Generate fresh sshd host keys
-</label>
-<label>
-  <input type="checkbox" /> Create admin user
-</label>
-<label>
-  <input type="checkbox" /> Add admin to doas group and test doas
-</label>
-<label>
-  <input type="checkbox" /> SSH key added to admin's authorized_keys
-</label>
-<label>
-  <input type="checkbox" /> Disable root login via ssh
-</label>
-<label>
-  <input type="checkbox" /> Disable password login via ssh
-</label>
-<label>
-  <input type="checkbox" /> Set hostname
-</label>
-<label>
-  <input type="checkbox" /> Run system updates
-</label>
-<label>
-  <input type="checkbox" /> Reboot
-</label>
-<label>
-  <input type="checkbox" /> Install &amp; test postfix
-</label>
-
-<style>
-label { display: block; }
-pre { background: #eee; max-width: 720px; padding: 0.5rem; }
-</style>
-
-<h1>doas.conf</h1>
-
-<pre>
-# see doas.conf(5) for configuration details
-
-# Uncomment to allow group "admin" to become root
-# permit :admin
-permit nopass :admin
-permit nopass deploy cmd apk args upgrade -U
-permit nopass deploy cmd service args SERVICE restart
-permit nopass acme cmd nginx args -s reload
-</pre>
-
-<h1>acme setup</h1>
-<p>
-TODO: a package could be made to automate many of these steps
-</p>
-<label>
-	<input type="checkbox" />
-	<code>doas apk add uacme openssl moreutils</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas useradd -md /var/lib/acme -s /sbin/nologin acme</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas mkdir -p /etc/ssl/uacme/private /var/www/.well-known/acme-challenge</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chown acme:acme /etc/ssl/uacme /etc/ssl/uacme/private</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chmod g+rX /etc/ssl/uacme /etc/ssl/uacme/private</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chown acme:acme /var/www/.well-known/acme-challenge</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas touch /var/log/acme.log</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chown acme:acme /var/log/acme.log</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas vim /usr/local/bin/acme-update-certs</code>
-<pre style="margin-left: 1.5rem">#!/bin/sh -eu
-exec &gt;&gt;/var/log/acme.log 2>&1
-date
-
-stats() {
-	cert="/etc/ssl/uacme/$1/cert.pem"
-	if ! [ -e "$cert" ]
-	then
-		return
-	fi
-	expiration=$(date -d"$(openssl x509 -enddate -noout -in "$cert" \
-		| cut -d= -f2)" -D'%b %d %H:%M:%S %Y GMT' +'%s')
-	printf '# TYPE certificate_expiration gauge\n'
-	printf '# HELP certificate_expiration Timestamp when SSL certificate will expire\n'
-	printf 'certificate_expiration{instance="%s"} %s\n' "$1" "$expiration"
-}
-
-acme() {
-	site=$1
-	shift
-	/usr/bin/uacme -v -h /usr/share/uacme/uacme.sh issue $site $* || true
-	stats $site | curl --data-binary @- https://push.metrics.sr.ht/metrics/job/$site
-}
-
-acme DOMAIN SUBDOMAIN...
-doas nginx -s reload</pre>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chmod +x /usr/local/bin/acme-update-certs</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas usermod -aG acme nginx</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas -u acme uacme new sir@cmpwn.com</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas -u acme crontab -e</code>
-<pre style="margin-left: 1.5rem">MAILTO=sir@cmpwn.com
-0 0 * * * chronic /usr/local/bin/acme-update-certs</pre>
-	</code>
-</label>
-
-<label>
-	<input type="checkbox" /> Update nginx configuration
-	(<code>ssl_certificate{,_key}</code> commented)
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas -u acme /usr/local/bin/acme-update-certs</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>cat /var/log/acme.log # verify success</code>
-</label>
-
-<label>
-	<input type="checkbox" /> Update nginx configuration
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas chmod -R g+rX /etc/ssl/uacme /etc/ssl/uacme/private</code>
-</label>
-
-<label>
-	<input type="checkbox" />
-	<code>doas nginx -s reload</code>
-</label>
-
-<label>
-	<input type="checkbox" /> Verify website has working SSL
-</label>
-
-<h2>nginx config</h2>
-
-<pre>
-server {
-	listen 80;
-	listen [::]:80;
-	server_name DOMAIN;
-
-	location / {
-		return 302 https://$server_name$request_uri;
-	}
-
-	location ^~ /.well-known {
-		root /var/www;
-	}
-}
-
-server {
-	listen 443 ssl http2;
-	listen [::]:443 ssl http2;
-	server_name DOMAIN;
-	ssl_certificate /etc/ssl/uacme/DOMAIN/cert.pem;
-	ssl_certificate_key /etc/ssl/uacme/private/DOMAIN/key.pem;
-
-	gzip on;
-	gzip_types text/css text/html;
-
-	# ...
-}
-</pre>




diff --git a/data/meses.yaml b/data/meses.yaml
deleted file mode 100644
index dac340462c58e9acb38f6bad85f8873be541b85a..0000000000000000000000000000000000000000
--- a/data/meses.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-1: "Janeiro"
-2: "Fevereiro"
-3: "Março"
-4: "Abril"
-5: "Maio"
-6: "Junho"
-7: "Julho"
-8: "Agosto"
-9: "Setembro"
-10: "Outubro"
-11: "Novembro"
-12: "Dezembro"




diff --git a/data/months.yaml b/data/months.yaml
deleted file mode 100644
index 14793ecad3b5c74e3f5126a816cc1d53fcc5b641..0000000000000000000000000000000000000000
--- a/data/months.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-1: "January"
-2: "February"
-3: "March"
-4: "April"
-5: "May"
-6: "June"
-7: "July"
-8: "August"
-9: "September"
-10: "October"
-11: "November"
-12: "December"
\ No newline at end of file




diff --git a/i18n/en.toml b/i18n/en.toml
index 2ff35c4bdab7d7205cb30147296d031684272e71..d5e9c417d425277a2ea8725062a5d8da900d2749 100644
--- a/i18n/en.toml
+++ b/i18n/en.toml
@@ -10,16 +10,14 @@ [toc]
 other = "Table of contents"
 [related]
 other = "Related readings"
-[months]
-other = "months"
-[published]
-other = "{{.Month }} {{.Day}}, {{.Year}}"
 [words]
 other = "words"
 [translations]
 other = "Translations available"
 [availableIn]
 other = "Also available in"
+[aboutMe]
+other = "About me"
 [footer]
 other = """
     Comments, questions? Send an email to \
@@ -27,8 +25,6 @@      \
       porcellis@eletrotupi.com \
     </a>. \
     """
-[pt-br]
-other = "Português"
 [copyright]
 other = """
 




diff --git a/i18n/pt-br.toml b/i18n/pt-br.toml
index 75c8b55352ac7139949e943be89d089c997fff34..30b141c97b50c61edbf784c67079770d1e0f33d9 100644
--- a/i18n/pt-br.toml
+++ b/i18n/pt-br.toml
@@ -10,16 +10,14 @@ [toc]
 other = "Tabela de conteúdo"
 [related]
 other = "Leituras relacionadas"
-[months]
-other = "meses"
-[published]
-other = "{{.Day}} de {{.Month}} {{.Year}}"
 [words]
 other = "palavras"
 [translations]
 other = "Traduções disponíveis"
 [availableIn]
 other = "Também disponível em"
+[aboutMe]
+other = "Sobre mim"
 [footer]
 other = """
     Comentários, dúvidas? Envie um email para \
@@ -27,8 +25,6 @@      \
       porcellis@eletrotupi.com \
     </a>. \
     """
-[en]
-other = "Inglês"
 [copyright]
 other = """
 




diff --git a/layouts/_partials/available-lang.html b/layouts/_partials/available-lang.html
new file mode 100644
index 0000000000000000000000000000000000000000..49b3fee66aaac85864a50caf6885f05fa3a52d66
--- /dev/null
+++ b/layouts/_partials/available-lang.html
@@ -0,0 +1,12 @@
+<h3>
+  {{ i18n "availableIn" }}
+</h3>
+<ul>
+  {{ range (where $.Site.Home.AllTranslations "Language.Lang" "!=" .Lang) }}
+    <li>
+      <a href="{{ .Permalink }}">
+        {{ .Language.Label }}
+      </a>
+    </li>
+  {{ end }}
+</ul>




diff --git a/layouts/_partials/bio.html b/layouts/_partials/bio.html
new file mode 100644
index 0000000000000000000000000000000000000000..06b2d35d56e6c400f42a386410f7efb8d9d3376c
--- /dev/null
+++ b/layouts/_partials/bio.html
@@ -0,0 +1,3 @@
+<p class="bio text-small">
+{{ i18n "bio" | safeHTML }}
+</p>




diff --git a/layouts/_partials/colophon.html b/layouts/_partials/colophon.html
new file mode 100644
index 0000000000000000000000000000000000000000..89443a8766ba0f3a69cb45d1f19d48dd59b5571e
--- /dev/null
+++ b/layouts/_partials/colophon.html
@@ -0,0 +1,8 @@
+<footer>
+  <div>
+    {{ i18n "copyright" | safeHTML }} ·
+    <a title="PGP Key" href="{{ "eletrotupi.txt" | absURL }}">pgp</a> ·
+    <a title="RSS for {{ .Lang }}" href="{{ "index.xml" | absLangURL }}">rss</a> ·
+    <a title="Gemini capsule" href="gemini://gemini.eletrotupi.com/~porcellis">gemini</a>
+  </div>
+</footer>




diff --git a/layouts/_partials/css/syntax-dark.css b/layouts/_partials/css/syntax-dark.css
new file mode 100644
index 0000000000000000000000000000000000000000..24168d48a6f1a0f7a3942f60ba539c9bf5bea1a9
--- /dev/null
+++ b/layouts/_partials/css/syntax-dark.css
@@ -0,0 +1,86 @@
+/* Background */ .bg { color: #c9d1d9; background-color: #0d1117; }
+/* PreWrapper */ .chroma { color: #c9d1d9; background-color: #0d1117; }
+/* Other */ .chroma .x {  }
+/* Error */ .chroma .err { color: #f85149 }
+/* CodeLine */ .chroma .cl {  }
+/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
+/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
+/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
+/* LineHighlight */ .chroma .hl { background-color: #ffffcc }
+/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #64686c }
+/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #6e7681 }
+/* Line */ .chroma .line { display: flex; }
+/* Keyword */ .chroma .k { color: #ff7b72 }
+/* KeywordConstant */ .chroma .kc { color: #79c0ff }
+/* KeywordDeclaration */ .chroma .kd { color: #ff7b72 }
+/* KeywordNamespace */ .chroma .kn { color: #ff7b72 }
+/* KeywordPseudo */ .chroma .kp { color: #79c0ff }
+/* KeywordReserved */ .chroma .kr { color: #ff7b72 }
+/* KeywordType */ .chroma .kt { color: #ff7b72 }
+/* Name */ .chroma .n {  }
+/* NameAttribute */ .chroma .na {  }
+/* NameBuiltin */ .chroma .nb {  }
+/* NameBuiltinPseudo */ .chroma .bp {  }
+/* NameClass */ .chroma .nc { color: #f0883e; font-weight: bold }
+/* NameConstant */ .chroma .no { color: #79c0ff; font-weight: bold }
+/* NameDecorator */ .chroma .nd { color: #d2a8ff; font-weight: bold }
+/* NameEntity */ .chroma .ni { color: #ffa657 }
+/* NameException */ .chroma .ne { color: #f0883e; font-weight: bold }
+/* NameFunction */ .chroma .nf { color: #d2a8ff; font-weight: bold }
+/* NameFunctionMagic */ .chroma .fm {  }
+/* NameLabel */ .chroma .nl { color: #79c0ff; font-weight: bold }
+/* NameNamespace */ .chroma .nn { color: #ff7b72 }
+/* NameOther */ .chroma .nx {  }
+/* NameProperty */ .chroma .py { color: #79c0ff }
+/* NameTag */ .chroma .nt { color: #7ee787 }
+/* NameVariable */ .chroma .nv { color: #79c0ff }
+/* NameVariableClass */ .chroma .vc {  }
+/* NameVariableGlobal */ .chroma .vg {  }
+/* NameVariableInstance */ .chroma .vi {  }
+/* NameVariableMagic */ .chroma .vm {  }
+/* Literal */ .chroma .l { color: #a5d6ff }
+/* LiteralDate */ .chroma .ld { color: #79c0ff }
+/* LiteralString */ .chroma .s { color: #a5d6ff }
+/* LiteralStringAffix */ .chroma .sa { color: #79c0ff }
+/* LiteralStringBacktick */ .chroma .sb { color: #a5d6ff }
+/* LiteralStringChar */ .chroma .sc { color: #a5d6ff }
+/* LiteralStringDelimiter */ .chroma .dl { color: #79c0ff }
+/* LiteralStringDoc */ .chroma .sd { color: #a5d6ff }
+/* LiteralStringDouble */ .chroma .s2 { color: #a5d6ff }
+/* LiteralStringEscape */ .chroma .se { color: #79c0ff }
+/* LiteralStringHeredoc */ .chroma .sh { color: #79c0ff }
+/* LiteralStringInterpol */ .chroma .si { color: #a5d6ff }
+/* LiteralStringOther */ .chroma .sx { color: #a5d6ff }
+/* LiteralStringRegex */ .chroma .sr { color: #79c0ff }
+/* LiteralStringSingle */ .chroma .s1 { color: #a5d6ff }
+/* LiteralStringSymbol */ .chroma .ss { color: #a5d6ff }
+/* LiteralNumber */ .chroma .m { color: #a5d6ff }
+/* LiteralNumberBin */ .chroma .mb { color: #a5d6ff }
+/* LiteralNumberFloat */ .chroma .mf { color: #a5d6ff }
+/* LiteralNumberHex */ .chroma .mh { color: #a5d6ff }
+/* LiteralNumberInteger */ .chroma .mi { color: #a5d6ff }
+/* LiteralNumberIntegerLong */ .chroma .il { color: #a5d6ff }
+/* LiteralNumberOct */ .chroma .mo { color: #a5d6ff }
+/* Operator */ .chroma .o { color: #ff7b72; font-weight: bold }
+/* OperatorWord */ .chroma .ow { color: #ff7b72; font-weight: bold }
+/* Punctuation */ .chroma .p {  }
+/* Comment */ .chroma .c { color: #8b949e; font-style: italic }
+/* CommentHashbang */ .chroma .ch { color: #8b949e; font-style: italic }
+/* CommentMultiline */ .chroma .cm { color: #8b949e; font-style: italic }
+/* CommentSingle */ .chroma .c1 { color: #8b949e; font-style: italic }
+/* CommentSpecial */ .chroma .cs { color: #8b949e; font-weight: bold; font-style: italic }
+/* CommentPreproc */ .chroma .cp { color: #8b949e; font-weight: bold; font-style: italic }
+/* CommentPreprocFile */ .chroma .cpf { color: #8b949e; font-weight: bold; font-style: italic }
+/* Generic */ .chroma .g {  }
+/* GenericDeleted */ .chroma .gd { color: #ffa198; background-color: #490202 }
+/* GenericEmph */ .chroma .ge { font-style: italic }
+/* GenericError */ .chroma .gr { color: #ffa198 }
+/* GenericHeading */ .chroma .gh { color: #79c0ff; font-weight: bold }
+/* GenericInserted */ .chroma .gi { color: #56d364; background-color: #0f5323 }
+/* GenericOutput */ .chroma .go { color: #8b949e }
+/* GenericPrompt */ .chroma .gp { color: #8b949e }
+/* GenericStrong */ .chroma .gs { font-weight: bold }
+/* GenericSubheading */ .chroma .gu { color: #79c0ff }
+/* GenericTraceback */ .chroma .gt { color: #ff7b72 }
+/* GenericUnderline */ .chroma .gl { text-decoration: underline }
+/* TextWhitespace */ .chroma .w { color: #6e7681 }




diff --git a/layouts/_partials/css/syntax-light.css b/layouts/_partials/css/syntax-light.css
new file mode 100644
index 0000000000000000000000000000000000000000..9018df907148662fc70a7233a558156255826726
--- /dev/null
+++ b/layouts/_partials/css/syntax-light.css
@@ -0,0 +1,86 @@
+/* Background */ .bg { background-color: #ffffff; }
+/* PreWrapper */ .chroma { background-color: #ffffff; }
+/* Other */ .chroma .x {  }
+/* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 }
+/* CodeLine */ .chroma .cl {  }
+/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
+/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
+/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
+/* LineHighlight */ .chroma .hl { background-color: #ffffcc }
+/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* Line */ .chroma .line { display: flex; }
+/* Keyword */ .chroma .k { color: #000000; font-weight: bold }
+/* KeywordConstant */ .chroma .kc { color: #000000; font-weight: bold }
+/* KeywordDeclaration */ .chroma .kd { color: #000000; font-weight: bold }
+/* KeywordNamespace */ .chroma .kn { color: #000000; font-weight: bold }
+/* KeywordPseudo */ .chroma .kp { color: #000000; font-weight: bold }
+/* KeywordReserved */ .chroma .kr { color: #000000; font-weight: bold }
+/* KeywordType */ .chroma .kt { color: #445588; font-weight: bold }
+/* Name */ .chroma .n {  }
+/* NameAttribute */ .chroma .na { color: #008080 }
+/* NameBuiltin */ .chroma .nb { color: #0086b3 }
+/* NameBuiltinPseudo */ .chroma .bp { color: #999999 }
+/* NameClass */ .chroma .nc { color: #445588; font-weight: bold }
+/* NameConstant */ .chroma .no { color: #008080 }
+/* NameDecorator */ .chroma .nd { color: #3c5d5d; font-weight: bold }
+/* NameEntity */ .chroma .ni { color: #800080 }
+/* NameException */ .chroma .ne { color: #990000; font-weight: bold }
+/* NameFunction */ .chroma .nf { color: #990000; font-weight: bold }
+/* NameFunctionMagic */ .chroma .fm {  }
+/* NameLabel */ .chroma .nl { color: #990000; font-weight: bold }
+/* NameNamespace */ .chroma .nn { color: #555555 }
+/* NameOther */ .chroma .nx {  }
+/* NameProperty */ .chroma .py {  }
+/* NameTag */ .chroma .nt { color: #000080 }
+/* NameVariable */ .chroma .nv { color: #008080 }
+/* NameVariableClass */ .chroma .vc { color: #008080 }
+/* NameVariableGlobal */ .chroma .vg { color: #008080 }
+/* NameVariableInstance */ .chroma .vi { color: #008080 }
+/* NameVariableMagic */ .chroma .vm {  }
+/* Literal */ .chroma .l {  }
+/* LiteralDate */ .chroma .ld {  }
+/* LiteralString */ .chroma .s { color: #dd1144 }
+/* LiteralStringAffix */ .chroma .sa { color: #dd1144 }
+/* LiteralStringBacktick */ .chroma .sb { color: #dd1144 }
+/* LiteralStringChar */ .chroma .sc { color: #dd1144 }
+/* LiteralStringDelimiter */ .chroma .dl { color: #dd1144 }
+/* LiteralStringDoc */ .chroma .sd { color: #dd1144 }
+/* LiteralStringDouble */ .chroma .s2 { color: #dd1144 }
+/* LiteralStringEscape */ .chroma .se { color: #dd1144 }
+/* LiteralStringHeredoc */ .chroma .sh { color: #dd1144 }
+/* LiteralStringInterpol */ .chroma .si { color: #dd1144 }
+/* LiteralStringOther */ .chroma .sx { color: #dd1144 }
+/* LiteralStringRegex */ .chroma .sr { color: #009926 }
+/* LiteralStringSingle */ .chroma .s1 { color: #dd1144 }
+/* LiteralStringSymbol */ .chroma .ss { color: #990073 }
+/* LiteralNumber */ .chroma .m { color: #009999 }
+/* LiteralNumberBin */ .chroma .mb { color: #009999 }
+/* LiteralNumberFloat */ .chroma .mf { color: #009999 }
+/* LiteralNumberHex */ .chroma .mh { color: #009999 }
+/* LiteralNumberInteger */ .chroma .mi { color: #009999 }
+/* LiteralNumberIntegerLong */ .chroma .il { color: #009999 }
+/* LiteralNumberOct */ .chroma .mo { color: #009999 }
+/* Operator */ .chroma .o { color: #000000; font-weight: bold }
+/* OperatorWord */ .chroma .ow { color: #000000; font-weight: bold }
+/* Punctuation */ .chroma .p {  }
+/* Comment */ .chroma .c { color: #999988; font-style: italic }
+/* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic }
+/* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic }
+/* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic }
+/* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic }
+/* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold; font-style: italic }
+/* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold; font-style: italic }
+/* Generic */ .chroma .g {  }
+/* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd }
+/* GenericEmph */ .chroma .ge { color: #000000; font-style: italic }
+/* GenericError */ .chroma .gr { color: #aa0000 }
+/* GenericHeading */ .chroma .gh { color: #999999 }
+/* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd }
+/* GenericOutput */ .chroma .go { color: #888888 }
+/* GenericPrompt */ .chroma .gp { color: #555555 }
+/* GenericStrong */ .chroma .gs { font-weight: bold }
+/* GenericSubheading */ .chroma .gu { color: #aaaaaa }
+/* GenericTraceback */ .chroma .gt { color: #aa0000 }
+/* GenericUnderline */ .chroma .gl { text-decoration: underline }
+/* TextWhitespace */ .chroma .w { color: #bbbbbb }




diff --git a/layouts/_partials/footer.html b/layouts/_partials/footer.html
new file mode 100644
index 0000000000000000000000000000000000000000..733d4b63bd59b2233984cd5d4af518c27237fe33
--- /dev/null
+++ b/layouts/_partials/footer.html
@@ -0,0 +1,5 @@
+<footer>
+  <div>
+    {{ i18n "footer" | safeHTML }}
+  </div>
+</footer>




diff --git a/layouts/_partials/head.html b/layouts/_partials/head.html
new file mode 100644
index 0000000000000000000000000000000000000000..3a451408f015836d0f6dc0e657ef283ec4e82128
--- /dev/null
+++ b/layouts/_partials/head.html
@@ -0,0 +1,18 @@
+<head>
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <title>{{ .Title }}</title>
+  <link rel="alternate" type="application/rss+xml" title="RSS for {{ .Lang }}" href="{{ "index.xml" | absLangURL }}">
+  <link rel="icon" type="image/jpeg" href="/avatar.jpg">
+  {{ $style := resources.Get "style.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
+  <link rel="stylesheet" href="{{ $style.RelPermalink }}" />
+
+  <style type="text/css" media="screen">
+    @media (prefers-color-scheme: dark) {
+      {{ partial "css/syntax-dark.css" . | safeCSS }}
+    }
+    @media (prefers-color-scheme: light) {
+      {{ partial "css/syntax-light.css" . | safeCSS }}
+    }
+  </style>
+</head>




diff --git a/layouts/_partials/site-title.html b/layouts/_partials/site-title.html
new file mode 100644
index 0000000000000000000000000000000000000000..199ec46c144647738a1c5b13fc042a8db617e3cf
--- /dev/null
+++ b/layouts/_partials/site-title.html
@@ -0,0 +1,4 @@
+<a href="{{ .Site.BaseURL }}" class="header-text text-subtle">
+  <img class="avatar" src="/avatar.jpg" alt="{{ .Site.Title }}">
+  <p class="text-small text-uppercase text-spaced">{{ .Site.Title }}</p>
+</a>




diff --git a/layouts/_partials/time.html b/layouts/_partials/time.html
new file mode 100644
index 0000000000000000000000000000000000000000..86612c1b44bb1f0c7de178513bae3e9a4b347109
--- /dev/null
+++ b/layouts/_partials/time.html
@@ -0,0 +1,3 @@
+<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" | safeHTMLAttr }}">
+  {{ .Date | time.Format ":date_long" }}
+</time>




diff --git a/layouts/_partials/translations.html b/layouts/_partials/translations.html
new file mode 100644
index 0000000000000000000000000000000000000000..f07954433b4a27fae3a02d0bb5dbd361490b8d31
--- /dev/null
+++ b/layouts/_partials/translations.html
@@ -0,0 +1,12 @@
+<div class="translations">
+  {{ if .IsTranslated }}
+  <h4>{{ i18n "translations" }}:</h4>
+  <ul>
+    {{ range .Translations }}
+    <li>
+      <a href="{{ .Permalink }}">{{ .Language.Label }}: {{ .Title }}</a>
+    </li>
+    {{ end }}
+  </ul>
+  {{ end }}
+</div>




diff --git a/layouts/baseof.html b/layouts/baseof.html
new file mode 100644
index 0000000000000000000000000000000000000000..551f513d5d076945892509fb4f2d9b65c5ee4549
--- /dev/null
+++ b/layouts/baseof.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<html lang="{{ .Lang }}">
+  {{ partial "head.html" . }}
+
+  <body>
+    {{ block "main" . }}{{ end }}
+  </body>
+</html>




diff --git a/layouts/blog/single.html b/layouts/blog/single.html
deleted file mode 100644
index 01e8ae37250e7ec1ee72e3f165a109028b4545a0..0000000000000000000000000000000000000000
--- a/layouts/blog/single.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{{ partial "basic.html" . }}
-
-<main>
-  <div class="page-content">
-    <div class="index-header text-center">
-      <a href="{{.Site.BaseURL}}" class="header-text text-subtle">
-        <img class="avatar" src="/avatar.jpg" size="50x50">
-        <p class="text-small text-uppercase text-spaced">{{.Site.Title}}</p>
-      </a>
-
-      <div class="divisor"></div>
-    </div>
-
-    <div class="inner-article-title text-center">
-      <div class="inner-article-date text-x-small text-subtle">
-        {{ partial "time.html" . }}
-        · {{ .FuzzyWordCount }} {{ i18n "words" }}
-      </div>
-      <h1>
-        {{ $.Title }}
-      </h1>
-    </div>
-
-    {{ partial "translations.html" . }}
-
-    <article>
-      {{ .Content }}
-    </article>
-
-    <div class="article-footer text-center">
-      <div class="divisor"></div>
-
-      <p class="pt-2 text-small text-spaced text-uppercase">About me</p>
-
-      {{ partial "bio.html" . }}
-
-      <div class="divisor mb-3"></div>
-
-      {{ partial "footer.html" . }}
-    </div>
-  </div>
-</main>




diff --git a/layouts/home.html b/layouts/home.html
new file mode 100644
index 0000000000000000000000000000000000000000..f73ca973c160ea2a6fd09df2afcd4b1bcb606710
--- /dev/null
+++ b/layouts/home.html
@@ -0,0 +1,37 @@
+{{ define "main" }}
+<main class="index">
+  <div class="page-content">
+    <div class="index-header text-center">
+      {{ partial "site-title.html" . }}
+      {{ partial "bio.html" . }}
+      <div class="divisor"></div>
+    </div>
+
+    <div class="languages">
+      {{ partial "available-lang.html" . }}
+    </div>
+
+    <section class="article-list">
+      {{ range (where .Site.RegularPages "Section" "blog") }}
+      <div class="article">
+        <div class="article-title">
+          <div class="article-date text-small text-subtle">
+            {{ partial "time.html" . }}
+          </div>
+
+          <a href="{{ .Permalink }}">
+            <h2>{{ .Title }}</h2>
+          </a>
+        </div>
+
+        <div class="article-snippet">
+          {{ .Summary }}
+        </div>
+      </div>
+      {{ end }}
+    </section>
+
+    {{ partial "colophon.html" . }}
+  </div>
+</main>
+{{ end }}




diff --git a/layouts/index.html b/layouts/index.html
deleted file mode 100644
index 2c2bc86ff3c6bb8d9667de26687de180d44a876b..0000000000000000000000000000000000000000
--- a/layouts/index.html
+++ /dev/null
@@ -1,39 +0,0 @@
-{{ partial "basic.html" . }}
-<main class="index">
-  <div class="page-content">
-    {{ partial "head.html" . }}
-
-    <div class="languages">
-      {{ partial "available-lang.html" . }}
-    </div>
-
-    <section class="article-list">
-      {{ range (where (where (where .Site.RegularPages "Section" "blog") "Params.nohtml" "!=" "true") "draft" "!=" "true" ) }}
-      <div class="article">
-        <div class="article-title">
-          <div class="article-date text-small text-subtle">
-            {{ partial "time.html" . }}
-          </div>
-
-          <a href="{{.Permalink}}">
-            <h2>{{.Title}}</h2>
-          </a>
-        </div>
-
-        <div class="article-snippet">
-          {{ .Summary }}
-        </div>
-      </div>
-      {{ end }}
-    </section>
-
-    <footer>
-      <div>
-        {{ i18n "copyright" | safeHTML }} ·
-        <a title="PGP Key" href="{{ "eletrotupi.txt" | absURL }}">pgp</a> ·
-        <a title="RSS for {{ .Lang }}" href="{{ "index.xml" | absLangURL }}">rss</a> ·
-        <a title="Gemini capsule" href="gemini://gemini.eletrotupi.com/~porcellis">gemini</a>
-      </div>
-    </footer>
-  </div>
-</main>




diff --git a/layouts/list.html b/layouts/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..eaffc0bfb737d11c865bedaf04d45ff740e91433
--- /dev/null
+++ b/layouts/list.html
@@ -0,0 +1,40 @@
+{{ define "main" }}
+<main class="index">
+  <div class="page-content">
+    <div class="index-header text-center">
+      {{ partial "site-title.html" . }}
+      <div class="divisor"></div>
+    </div>
+
+    <div class="inner-article-title text-center">
+      <h1>{{ .Title }}</h1>
+    </div>
+
+    <section class="article-list">
+      {{ range .Pages }}
+      <div class="article">
+        <div class="article-title">
+          {{ if not .Date.IsZero }}
+          <div class="article-date text-small text-subtle">
+            {{ partial "time.html" . }}
+          </div>
+          {{ end }}
+
+          <a href="{{ .Permalink }}">
+            <h2>{{ .Title }}</h2>
+          </a>
+        </div>
+
+        {{ with .Summary }}
+        <div class="article-snippet">
+          {{ . }}
+        </div>
+        {{ end }}
+      </div>
+      {{ end }}
+    </section>
+
+    {{ partial "colophon.html" . }}
+  </div>
+</main>
+{{ end }}




diff --git a/layouts/partials/available-lang.html b/layouts/partials/available-lang.html
deleted file mode 100644
index e6a4872bf91fb1e4f2d561c26dd0eeec7388127d..0000000000000000000000000000000000000000
--- a/layouts/partials/available-lang.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<h3>
-  {{ i18n "availableIn" }}
-</h3>
-<ul>
-  {{ range (where $.Site.Home.AllTranslations "Language.Lang" "!=" .Lang ) }}
-    <li>
-      <a href="{{ .Permalink }}">
-        {{ .Language.LanguageName }}
-      </a>
-    </li>
-  {{ end }}
-</ul>




diff --git a/layouts/partials/basic.html b/layouts/partials/basic.html
deleted file mode 100644
index ff1d683706b9dd8412a03484ffca2eb6c4d99ea2..0000000000000000000000000000000000000000
--- a/layouts/partials/basic.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-<html lang="{{ .Lang }}">
-  <head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <title>{{$.Title}}</title>
-    <link rel="alternate" type="application/rss+xml" title="RSS for {{ .Lang }}" href="{{ "index.xml" | absLangURL }}">
-    <link rel="icon" type="image/jpeg" href="/avatar.jpg">
-    {{ $style := resources.Get "style.scss" | resources.ToCSS | resources.Minify | resources.Fingerprint }}
-    <link rel="stylesheet" href="{{ $style.RelPermalink }}" />
-
-    <style type="text/css" media="screen">
-      @media (prefers-color-scheme: dark) {
-        {{ partial "css/syntax-dark.css" . | safeCSS }}
-      }
-      @media (prefers-color-scheme: light) {
-        {{ partial "css/syntax-light.css" . | safeCSS }}
-      }
-    </style>
-  </head>




diff --git a/layouts/partials/bio.html b/layouts/partials/bio.html
deleted file mode 100644
index 06b2d35d56e6c400f42a386410f7efb8d9d3376c..0000000000000000000000000000000000000000
--- a/layouts/partials/bio.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<p class="bio text-small">
-{{ i18n "bio" | safeHTML }}
-</p>




diff --git a/layouts/partials/css/syntax-dark.css b/layouts/partials/css/syntax-dark.css
deleted file mode 100644
index 24168d48a6f1a0f7a3942f60ba539c9bf5bea1a9..0000000000000000000000000000000000000000
--- a/layouts/partials/css/syntax-dark.css
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Background */ .bg { color: #c9d1d9; background-color: #0d1117; }
-/* PreWrapper */ .chroma { color: #c9d1d9; background-color: #0d1117; }
-/* Other */ .chroma .x {  }
-/* Error */ .chroma .err { color: #f85149 }
-/* CodeLine */ .chroma .cl {  }
-/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
-/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
-/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
-/* LineHighlight */ .chroma .hl { background-color: #ffffcc }
-/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #64686c }
-/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #6e7681 }
-/* Line */ .chroma .line { display: flex; }
-/* Keyword */ .chroma .k { color: #ff7b72 }
-/* KeywordConstant */ .chroma .kc { color: #79c0ff }
-/* KeywordDeclaration */ .chroma .kd { color: #ff7b72 }
-/* KeywordNamespace */ .chroma .kn { color: #ff7b72 }
-/* KeywordPseudo */ .chroma .kp { color: #79c0ff }
-/* KeywordReserved */ .chroma .kr { color: #ff7b72 }
-/* KeywordType */ .chroma .kt { color: #ff7b72 }
-/* Name */ .chroma .n {  }
-/* NameAttribute */ .chroma .na {  }
-/* NameBuiltin */ .chroma .nb {  }
-/* NameBuiltinPseudo */ .chroma .bp {  }
-/* NameClass */ .chroma .nc { color: #f0883e; font-weight: bold }
-/* NameConstant */ .chroma .no { color: #79c0ff; font-weight: bold }
-/* NameDecorator */ .chroma .nd { color: #d2a8ff; font-weight: bold }
-/* NameEntity */ .chroma .ni { color: #ffa657 }
-/* NameException */ .chroma .ne { color: #f0883e; font-weight: bold }
-/* NameFunction */ .chroma .nf { color: #d2a8ff; font-weight: bold }
-/* NameFunctionMagic */ .chroma .fm {  }
-/* NameLabel */ .chroma .nl { color: #79c0ff; font-weight: bold }
-/* NameNamespace */ .chroma .nn { color: #ff7b72 }
-/* NameOther */ .chroma .nx {  }
-/* NameProperty */ .chroma .py { color: #79c0ff }
-/* NameTag */ .chroma .nt { color: #7ee787 }
-/* NameVariable */ .chroma .nv { color: #79c0ff }
-/* NameVariableClass */ .chroma .vc {  }
-/* NameVariableGlobal */ .chroma .vg {  }
-/* NameVariableInstance */ .chroma .vi {  }
-/* NameVariableMagic */ .chroma .vm {  }
-/* Literal */ .chroma .l { color: #a5d6ff }
-/* LiteralDate */ .chroma .ld { color: #79c0ff }
-/* LiteralString */ .chroma .s { color: #a5d6ff }
-/* LiteralStringAffix */ .chroma .sa { color: #79c0ff }
-/* LiteralStringBacktick */ .chroma .sb { color: #a5d6ff }
-/* LiteralStringChar */ .chroma .sc { color: #a5d6ff }
-/* LiteralStringDelimiter */ .chroma .dl { color: #79c0ff }
-/* LiteralStringDoc */ .chroma .sd { color: #a5d6ff }
-/* LiteralStringDouble */ .chroma .s2 { color: #a5d6ff }
-/* LiteralStringEscape */ .chroma .se { color: #79c0ff }
-/* LiteralStringHeredoc */ .chroma .sh { color: #79c0ff }
-/* LiteralStringInterpol */ .chroma .si { color: #a5d6ff }
-/* LiteralStringOther */ .chroma .sx { color: #a5d6ff }
-/* LiteralStringRegex */ .chroma .sr { color: #79c0ff }
-/* LiteralStringSingle */ .chroma .s1 { color: #a5d6ff }
-/* LiteralStringSymbol */ .chroma .ss { color: #a5d6ff }
-/* LiteralNumber */ .chroma .m { color: #a5d6ff }
-/* LiteralNumberBin */ .chroma .mb { color: #a5d6ff }
-/* LiteralNumberFloat */ .chroma .mf { color: #a5d6ff }
-/* LiteralNumberHex */ .chroma .mh { color: #a5d6ff }
-/* LiteralNumberInteger */ .chroma .mi { color: #a5d6ff }
-/* LiteralNumberIntegerLong */ .chroma .il { color: #a5d6ff }
-/* LiteralNumberOct */ .chroma .mo { color: #a5d6ff }
-/* Operator */ .chroma .o { color: #ff7b72; font-weight: bold }
-/* OperatorWord */ .chroma .ow { color: #ff7b72; font-weight: bold }
-/* Punctuation */ .chroma .p {  }
-/* Comment */ .chroma .c { color: #8b949e; font-style: italic }
-/* CommentHashbang */ .chroma .ch { color: #8b949e; font-style: italic }
-/* CommentMultiline */ .chroma .cm { color: #8b949e; font-style: italic }
-/* CommentSingle */ .chroma .c1 { color: #8b949e; font-style: italic }
-/* CommentSpecial */ .chroma .cs { color: #8b949e; font-weight: bold; font-style: italic }
-/* CommentPreproc */ .chroma .cp { color: #8b949e; font-weight: bold; font-style: italic }
-/* CommentPreprocFile */ .chroma .cpf { color: #8b949e; font-weight: bold; font-style: italic }
-/* Generic */ .chroma .g {  }
-/* GenericDeleted */ .chroma .gd { color: #ffa198; background-color: #490202 }
-/* GenericEmph */ .chroma .ge { font-style: italic }
-/* GenericError */ .chroma .gr { color: #ffa198 }
-/* GenericHeading */ .chroma .gh { color: #79c0ff; font-weight: bold }
-/* GenericInserted */ .chroma .gi { color: #56d364; background-color: #0f5323 }
-/* GenericOutput */ .chroma .go { color: #8b949e }
-/* GenericPrompt */ .chroma .gp { color: #8b949e }
-/* GenericStrong */ .chroma .gs { font-weight: bold }
-/* GenericSubheading */ .chroma .gu { color: #79c0ff }
-/* GenericTraceback */ .chroma .gt { color: #ff7b72 }
-/* GenericUnderline */ .chroma .gl { text-decoration: underline }
-/* TextWhitespace */ .chroma .w { color: #6e7681 }




diff --git a/layouts/partials/css/syntax-light.css b/layouts/partials/css/syntax-light.css
deleted file mode 100644
index 9018df907148662fc70a7233a558156255826726..0000000000000000000000000000000000000000
--- a/layouts/partials/css/syntax-light.css
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Background */ .bg { background-color: #ffffff; }
-/* PreWrapper */ .chroma { background-color: #ffffff; }
-/* Other */ .chroma .x {  }
-/* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 }
-/* CodeLine */ .chroma .cl {  }
-/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
-/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
-/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
-/* LineHighlight */ .chroma .hl { background-color: #ffffcc }
-/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
-/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
-/* Line */ .chroma .line { display: flex; }
-/* Keyword */ .chroma .k { color: #000000; font-weight: bold }
-/* KeywordConstant */ .chroma .kc { color: #000000; font-weight: bold }
-/* KeywordDeclaration */ .chroma .kd { color: #000000; font-weight: bold }
-/* KeywordNamespace */ .chroma .kn { color: #000000; font-weight: bold }
-/* KeywordPseudo */ .chroma .kp { color: #000000; font-weight: bold }
-/* KeywordReserved */ .chroma .kr { color: #000000; font-weight: bold }
-/* KeywordType */ .chroma .kt { color: #445588; font-weight: bold }
-/* Name */ .chroma .n {  }
-/* NameAttribute */ .chroma .na { color: #008080 }
-/* NameBuiltin */ .chroma .nb { color: #0086b3 }
-/* NameBuiltinPseudo */ .chroma .bp { color: #999999 }
-/* NameClass */ .chroma .nc { color: #445588; font-weight: bold }
-/* NameConstant */ .chroma .no { color: #008080 }
-/* NameDecorator */ .chroma .nd { color: #3c5d5d; font-weight: bold }
-/* NameEntity */ .chroma .ni { color: #800080 }
-/* NameException */ .chroma .ne { color: #990000; font-weight: bold }
-/* NameFunction */ .chroma .nf { color: #990000; font-weight: bold }
-/* NameFunctionMagic */ .chroma .fm {  }
-/* NameLabel */ .chroma .nl { color: #990000; font-weight: bold }
-/* NameNamespace */ .chroma .nn { color: #555555 }
-/* NameOther */ .chroma .nx {  }
-/* NameProperty */ .chroma .py {  }
-/* NameTag */ .chroma .nt { color: #000080 }
-/* NameVariable */ .chroma .nv { color: #008080 }
-/* NameVariableClass */ .chroma .vc { color: #008080 }
-/* NameVariableGlobal */ .chroma .vg { color: #008080 }
-/* NameVariableInstance */ .chroma .vi { color: #008080 }
-/* NameVariableMagic */ .chroma .vm {  }
-/* Literal */ .chroma .l {  }
-/* LiteralDate */ .chroma .ld {  }
-/* LiteralString */ .chroma .s { color: #dd1144 }
-/* LiteralStringAffix */ .chroma .sa { color: #dd1144 }
-/* LiteralStringBacktick */ .chroma .sb { color: #dd1144 }
-/* LiteralStringChar */ .chroma .sc { color: #dd1144 }
-/* LiteralStringDelimiter */ .chroma .dl { color: #dd1144 }
-/* LiteralStringDoc */ .chroma .sd { color: #dd1144 }
-/* LiteralStringDouble */ .chroma .s2 { color: #dd1144 }
-/* LiteralStringEscape */ .chroma .se { color: #dd1144 }
-/* LiteralStringHeredoc */ .chroma .sh { color: #dd1144 }
-/* LiteralStringInterpol */ .chroma .si { color: #dd1144 }
-/* LiteralStringOther */ .chroma .sx { color: #dd1144 }
-/* LiteralStringRegex */ .chroma .sr { color: #009926 }
-/* LiteralStringSingle */ .chroma .s1 { color: #dd1144 }
-/* LiteralStringSymbol */ .chroma .ss { color: #990073 }
-/* LiteralNumber */ .chroma .m { color: #009999 }
-/* LiteralNumberBin */ .chroma .mb { color: #009999 }
-/* LiteralNumberFloat */ .chroma .mf { color: #009999 }
-/* LiteralNumberHex */ .chroma .mh { color: #009999 }
-/* LiteralNumberInteger */ .chroma .mi { color: #009999 }
-/* LiteralNumberIntegerLong */ .chroma .il { color: #009999 }
-/* LiteralNumberOct */ .chroma .mo { color: #009999 }
-/* Operator */ .chroma .o { color: #000000; font-weight: bold }
-/* OperatorWord */ .chroma .ow { color: #000000; font-weight: bold }
-/* Punctuation */ .chroma .p {  }
-/* Comment */ .chroma .c { color: #999988; font-style: italic }
-/* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic }
-/* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic }
-/* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic }
-/* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic }
-/* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold; font-style: italic }
-/* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold; font-style: italic }
-/* Generic */ .chroma .g {  }
-/* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd }
-/* GenericEmph */ .chroma .ge { color: #000000; font-style: italic }
-/* GenericError */ .chroma .gr { color: #aa0000 }
-/* GenericHeading */ .chroma .gh { color: #999999 }
-/* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd }
-/* GenericOutput */ .chroma .go { color: #888888 }
-/* GenericPrompt */ .chroma .gp { color: #555555 }
-/* GenericStrong */ .chroma .gs { font-weight: bold }
-/* GenericSubheading */ .chroma .gu { color: #aaaaaa }
-/* GenericTraceback */ .chroma .gt { color: #aa0000 }
-/* GenericUnderline */ .chroma .gl { text-decoration: underline }
-/* TextWhitespace */ .chroma .w { color: #bbbbbb }




diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html
deleted file mode 100644
index 733d4b63bd59b2233984cd5d4af518c27237fe33..0000000000000000000000000000000000000000
--- a/layouts/partials/footer.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<footer>
-  <div>
-    {{ i18n "footer" | safeHTML }}
-  </div>
-</footer>




diff --git a/layouts/partials/head.html b/layouts/partials/head.html
deleted file mode 100644
index 8face7032ab5f65f022bfb1b7173b8c3a2449310..0000000000000000000000000000000000000000
--- a/layouts/partials/head.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{{ partial "basic.html" . }}
-<div class="index-header text-center">
-  <a href="{{.Site.BaseURL}}" class="header-text text-subtle">
-    <img class="avatar" src="/avatar.jpg" size="50x50">
-    <p class="text-small text-uppercase text-spaced">{{.Site.Title}}</p>
-  </a>
-
-  {{ partial "bio.html" . }}
-
-  <div class="divisor"></div>
-</div>




diff --git a/layouts/partials/time.html b/layouts/partials/time.html
deleted file mode 100644
index efb66573bc55137ef9265cb3d69263aace152fd2..0000000000000000000000000000000000000000
--- a/layouts/partials/time.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<time datetime="{{ .Date.Format "2006-01-02T15:04:05" | safeHTMLAttr }}">
-  {{ $months := index .Site.Data (i18n "months") }}
-  {{ $month := index $months (printf "%d" .Date.Month) }}
-  {{ i18n "published" (dict "Day" .Date.Day "Month" $month "Year" .Date.Year) }}
-</time>




diff --git a/layouts/partials/translations.html b/layouts/partials/translations.html
deleted file mode 100644
index b316e31cd5033f055b4b13168234919eb3055306..0000000000000000000000000000000000000000
--- a/layouts/partials/translations.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="translations">
-  {{ if .IsTranslated }}
-  <h4>{{ i18n "translations" }}:</h4>
-  <ul>
-    {{ range .Translations }}
-    <li>
-      <a href="{{ .Permalink }}">{{ i18n .Lang }}: {{ .Title }}</a>
-    </li>
-    {{ end }}
-  </ul>
-  {{ end }}
-</div>




diff --git a/layouts/single.html b/layouts/single.html
new file mode 100644
index 0000000000000000000000000000000000000000..6817deadaa3a84a1bbfe84bd2ae926b92dfcd8a2
--- /dev/null
+++ b/layouts/single.html
@@ -0,0 +1,38 @@
+{{ define "main" }}
+<main>
+  <div class="page-content">
+    <div class="index-header text-center">
+      {{ partial "site-title.html" . }}
+      <div class="divisor"></div>
+    </div>
+
+    <div class="inner-article-title text-center">
+      <div class="inner-article-date text-x-small text-subtle">
+        {{ partial "time.html" . }}
+        · {{ .FuzzyWordCount }} {{ i18n "words" }}
+      </div>
+      <h1>
+        {{ .Title }}
+      </h1>
+    </div>
+
+    {{ partial "translations.html" . }}
+
+    <article>
+      {{ .Content }}
+    </article>
+
+    <div class="article-footer text-center">
+      <div class="divisor"></div>
+
+      <p class="pt-2 text-small text-spaced text-uppercase">{{ i18n "aboutMe" }}</p>
+
+      {{ partial "bio.html" . }}
+
+      <div class="divisor mb-3"></div>
+
+      {{ partial "footer.html" . }}
+    </div>
+  </div>
+</main>
+{{ end }}




diff --git a/static/new-server.html b/static/new-server.html
new file mode 100644
index 0000000000000000000000000000000000000000..5fea6de926631899dbcb10d9f112f77e6b6abb73
--- /dev/null
+++ b/static/new-server.html
@@ -0,0 +1,226 @@
+<!doctype html>
+<html lang="pt-br">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta name="robots" content="noindex, nofollow">
+  <title>New Server Checklist</title>
+</head>
+<body>
+<h1>New Server Checklist</h1>
+<label>
+  <input type="checkbox" /> Set root password
+</label>
+<label>
+  <input type="checkbox" /> Generate fresh sshd host keys
+</label>
+<label>
+  <input type="checkbox" /> Create admin user
+</label>
+<label>
+  <input type="checkbox" /> Add admin to doas group and test doas
+</label>
+<label>
+  <input type="checkbox" /> SSH key added to admin's authorized_keys
+</label>
+<label>
+  <input type="checkbox" /> Disable root login via ssh
+</label>
+<label>
+  <input type="checkbox" /> Disable password login via ssh
+</label>
+<label>
+  <input type="checkbox" /> Set hostname
+</label>
+<label>
+  <input type="checkbox" /> Run system updates
+</label>
+<label>
+  <input type="checkbox" /> Reboot
+</label>
+<label>
+  <input type="checkbox" /> Install &amp; test postfix
+</label>
+
+<style>
+label { display: block; }
+pre { background: #eee; max-width: 720px; padding: 0.5rem; }
+</style>
+
+<h1>doas.conf</h1>
+
+<pre>
+# see doas.conf(5) for configuration details
+
+# Uncomment to allow group "admin" to become root
+# permit :admin
+permit nopass :admin
+permit nopass deploy cmd apk args upgrade -U
+permit nopass deploy cmd service args SERVICE restart
+permit nopass acme cmd nginx args -s reload
+</pre>
+
+<h1>acme setup</h1>
+<p>
+TODO: a package could be made to automate many of these steps
+</p>
+<label>
+	<input type="checkbox" />
+	<code>doas apk add uacme openssl moreutils</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas useradd -md /var/lib/acme -s /sbin/nologin acme</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas mkdir -p /etc/ssl/uacme/private /var/www/.well-known/acme-challenge</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chown acme:acme /etc/ssl/uacme /etc/ssl/uacme/private</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chmod g+rX /etc/ssl/uacme /etc/ssl/uacme/private</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chown acme:acme /var/www/.well-known/acme-challenge</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas touch /var/log/acme.log</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chown acme:acme /var/log/acme.log</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas vim /usr/local/bin/acme-update-certs</code>
+<pre style="margin-left: 1.5rem">#!/bin/sh -eu
+exec &gt;&gt;/var/log/acme.log 2>&1
+date
+
+stats() {
+	cert="/etc/ssl/uacme/$1/cert.pem"
+	if ! [ -e "$cert" ]
+	then
+		return
+	fi
+	expiration=$(date -d"$(openssl x509 -enddate -noout -in "$cert" \
+		| cut -d= -f2)" -D'%b %d %H:%M:%S %Y GMT' +'%s')
+	printf '# TYPE certificate_expiration gauge\n'
+	printf '# HELP certificate_expiration Timestamp when SSL certificate will expire\n'
+	printf 'certificate_expiration{instance="%s"} %s\n' "$1" "$expiration"
+}
+
+acme() {
+	site=$1
+	shift
+	/usr/bin/uacme -v -h /usr/share/uacme/uacme.sh issue $site $* || true
+	stats $site | curl --data-binary @- https://push.metrics.sr.ht/metrics/job/$site
+}
+
+acme DOMAIN SUBDOMAIN...
+doas nginx -s reload</pre>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chmod +x /usr/local/bin/acme-update-certs</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas usermod -aG acme nginx</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas -u acme uacme new sir@cmpwn.com</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas -u acme crontab -e</code>
+<pre style="margin-left: 1.5rem">MAILTO=sir@cmpwn.com
+0 0 * * * chronic /usr/local/bin/acme-update-certs</pre>
+	</code>
+</label>
+
+<label>
+	<input type="checkbox" /> Update nginx configuration
+	(<code>ssl_certificate{,_key}</code> commented)
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas -u acme /usr/local/bin/acme-update-certs</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>cat /var/log/acme.log # verify success</code>
+</label>
+
+<label>
+	<input type="checkbox" /> Update nginx configuration
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas chmod -R g+rX /etc/ssl/uacme /etc/ssl/uacme/private</code>
+</label>
+
+<label>
+	<input type="checkbox" />
+	<code>doas nginx -s reload</code>
+</label>
+
+<label>
+	<input type="checkbox" /> Verify website has working SSL
+</label>
+
+<h2>nginx config</h2>
+
+<pre>
+server {
+	listen 80;
+	listen [::]:80;
+	server_name DOMAIN;
+
+	location / {
+		return 302 https://$server_name$request_uri;
+	}
+
+	location ^~ /.well-known {
+		root /var/www;
+	}
+}
+
+server {
+	listen 443 ssl http2;
+	listen [::]:443 ssl http2;
+	server_name DOMAIN;
+	ssl_certificate /etc/ssl/uacme/DOMAIN/cert.pem;
+	ssl_certificate_key /etc/ssl/uacme/private/DOMAIN/key.pem;
+
+	gzip on;
+	gzip_types text/css text/html;
+
+	# ...
+}
+</pre>
+
+</body>
+</html>




diff --git a/static/robots.txt b/static/robots.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c0218e5055e4aa880650586f035092e8509edee8
--- /dev/null
+++ b/static/robots.txt
@@ -0,0 +1,4 @@
+User-agent: *
+Disallow: /new-server.html
+
+Sitemap: https://porcellis.com/sitemap.xml