11 KiB
Codex Obscura
A dark academia pixel Hugo theme with a fall color palette.
Candlelit manuscripts meet cozy stationery. Books, tea, fountain pens, and the quiet rustle of digital marginalia.
██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗
██╔════╝██╔═══██╗██╔══██╗██╔════╝╚██╗██╔╝
██║ ██║ ██║██║ ██║█████╗ ╚███╔╝
██║ ██║ ██║██║ ██║██╔══╝ ██╔██╗
╚██████╗╚██████╔╝██████╔╝███████╗██╔╝ ██╗
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
Features
- Fall color palette — deep ambers, burnt orange, rust, forest green, umber, parchment cream
- Pixel art borders — CSS-only pixel-perfect box shadow borders on all cards and widgets
- Blinking
█cursor in the site title (optional, easily disabled) - Dark academia typography — VT323 (pixel/terminal) for headings + Josefin Sans for body text
- Dust mote ambient animation — soft floating particles that drift across the page like dust in a library
- Sidebar — sys-info widget with live uptime counter, recent posts, tag cloud, and optional marginalia quote
- Year-grouped archive — posts grouped by year in terminal
ls -lastyle - Tag filtering — clickable tag chips at the top of the archive page with active highlighting
- Post subtitles — optional per-post tagline shown on cards and single pages
- Responsive (Mostly) — two-column desktop, stacked mobile
- RSS feed — full RSS out of the box
- SEO-ready — Open Graph, Twitter Card, canonical URLs
- Syntax highlighting — via highlight.js with Common Lisp support, add more lines to layout/partials/head.html for more
- LaTeX rendering — via KaTeX with Hugo passthrough for clean math expressions
- Custom code blocks — shortcode with language label and optional title
- Comments — Comentario integration (self-hosted, privacy-focused)
Installation
As a Git Submodule (recommended)
First run hugo new site <sitename>
cd <sitename>
git submodule add https://git.johnabs.xyz/bs-sensei/codex-obscura-hugo-theme
Manual
Download and place the folder at themes/codex-obscura/ inside your Hugo site, which you should have made using hugo new site <sitename>
Configuration
After creating your site at from above and adding the template, you should first go to the content folder and create an about.md, resume.md, and a donate.md in your content folder or these will redirect to "Not Found". Your posts link will also redirect, unless you make a folder within content called posts and make post1.md inside it and add some text. Examples of each of these are provided below for your convenience.
A full hugo.toml example:
baseURL = "https://yourdomain.com/"
languageCode = "en-us"
title = "Your Site Title"
theme = "codex-obscura"
paginate = 8
summaryLength = 20
[markup.highlight]
codeFences = false # disable Chroma — we use highlight.js instead
[markup.goldmark.renderer]
unsafe = true # you can probably set this to false, try both. False works for me :)
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [["$$", "$$"]]
inline = [["$", "$"]]
[params]
description = "Your site description shown in the hero card."
author = "Your Name"
tagline = "a brief italicized tagline"
sidebarQuote = "A quote you love."
sidebarQuoteAuthor = "The Author"
resumePDF = "/files/resume.pdf"
comentarioURL = "https://comments.yourdomain.com"
[params.social]
github = "yourusername"
mastodon = "https://mastodon.social/@you"
email = "you@example.com"
[[menu.main]]
name = "home"
url = "/"
weight = 1
[[menu.main]]
name = "posts"
url = "/posts/"
weight = 2
[[menu.main]]
name = "tags"
url = "/tags/"
weight = 3
[[menu.main]]
name = "about"
url = "/about/"
weight = 4
[[menu.main]]
name = "resume"
url = "/resume/"
weight = 5
[[menu.main]]
name = "donate"
url = "/donate/"
weight = 6
[taxonomies]
tag = "tags"
category = "categories"
Creating Content
# New blog post
hugo new posts/my-entry.md
# New about page
hugo new about.md
Post front matter
---
title: "My Entry"
date: 2024-10-31
draft: false
description: "A brief description shown in meta tags."
summary: "Optional hand-written summary overriding auto-generation."
subtitle: "a quiet meditation on autumn leaves"
tags: ["autumn", "philosophy", "notes"]
author: "Archivist"
featured: true # pins to homepage
nocomments: true # disables comments on this post
---
The <!--more--> divider can be placed anywhere in the body to manually control where the summary cuts off:
This sentence will appear as the summary.
<!--more-->
The rest of the post continues here.
Special Pages
About
Create content/about.md with any content. Hugo uses _default/single.html.
Resume
Create content/resume.md:
---
title: "Resume"
type: "resume"
layout: "single"
resumeName: "Your Name"
resumeTitle: "Your subtitle"
email: "you@example.com"
location: "somewhere cozy"
website: "https://yoursite.com"
github: "yourusername"
resumePDF: "/files/resume.pdf"
_build:
list: never
---
Use ## for sections, ### for job/entry titles, #### for subtitle/date lines. Place your PDF at static/files/resume.pdf.
Donate
Create content/donate.md:
---
title: "Support"
type: "donate"
layout: "single"
_build:
list: never
kofi: "yourusername"
liberapay: "yourusername"
github_sponsors: "yourusername"
bitcoin: "bc1qyouraddress"
ethereum: "0xyouraddress"
monero: "4youraddress"
litecoin: "ltc1youraddress"
---
Crypto wallet cards include QR codes generated client-side in the site's amber color palette. Remove any platforms you don't use and they won't appear.
Syntax Highlighting
The theme uses highlight.js instead of Hugo's built-in Chroma for better Common Lisp support as it's my preferred language.
This is already added to layouts/partials/head.html, and more can be added as you go as shown below:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/base16/monokai.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.common.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/lisp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/python.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/r.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/julia.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/bash.min.js"></script>
<script>
hljs.highlightAll();
</script>
Custom code block shortcode
Create layouts/shortcodes/code.html in your site root (this one you need to do!! I can't do it for you in advance):
<div class="code-block">
{{- with .Get "lang" }}
<div class="code-block__header">
<span class="code-block__lang">{{ . }}</span>
{{- with $.Get "title" }}
<span class="code-block__title">{{ . }}</span>
{{- end }}
</div>
{{- end }}
<div class="code-block__body">
{{ highlight (trim .Inner "\n") (.Get "lang" | default "text") "" }}
</div>
</div>
Use it in posts:
{{< code lang="python" title="fibonacci.py" >}}
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
{{< /code >}}
LaTeX
I added KaTeX to layouts/partials/head.html for math typesetting:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body, {
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false}
]
});">
</script>
Then write inline math with $x^2$ and display math with $$\int_0^\infty e^{-x}dx$$.
Comments (Comentario)
Install and run a Comentario instance, then add to hugo.toml:
[params]
comentarioURL = "https://comments.yourdomain.com"
Comments appear automatically on all posts. Disable per-post with nocomments: true in front matter.
Color Palette
| Variable | Value | Use |
|---|---|---|
--amber |
#d4a228 |
Primary accent |
--orange |
#c4601c |
Secondary accent |
--rust |
#8a2e08 |
Deep accent |
--forest-light |
#4e7830 |
Terminal prompt green |
--text-parchment |
#e8d5a3 |
Primary text |
--bg-primary |
#130e07 |
Main background |
--bg-secondary |
#1c1509 |
Card backgrounds |
Override any variable by adding a static/css/custom.css and referencing it in hugo.toml:
[params]
customCSS = ["css/custom.css"]
Typography
| Role | Font | Notes |
|---|---|---|
| Terminal | VT323 | Headings, nav, UI elements |
| Body | Josefin Sans | Paragraph text, sans-serif |
| Code | Courier Prime | Code blocks, monospace |
All loaded from Google Fonts.
File Structure
codex-obscura/
├── archetypes/
│ └── default.md
├── exampleSite/
│ ├── hugo.toml
│ └── content/
│ ├── resume.md
│ └── donate.md
├── layouts/
│ ├── index.html # Homepage
│ ├── _default/
│ │ ├── baseof.html
│ │ ├── single.html # Single post
│ │ └── list.html # Archive / tag pages
│ ├── resume/
│ │ └── single.html # Resume page
│ ├── donate/
│ │ └── single.html # Donate page with QR codes
│ ├── tags/
│ │ └── terms.html # Tag index
│ └── partials/
│ ├── head.html
│ ├── header.html
│ ├── footer.html
│ ├── sidebar.html
│ └── comments.html # Comentario integration
├── static/
│ ├── css/main.css
│ ├── js/main.js # Dust mote animation
│ └── favicon.svg
├── theme.toml
└── README.md
License
MIT — Please attribute my work to me!
"The library is infinite and the lights are always low."