commit 9ffa35a78ef830d58730cae8ce4510b858241724
parent e081dc4cd0b83050a007dd1f01984ce61304455d
Author: Nathaniel Chappelle <nathaniel@chappelle.dev>
Date: Wed, 4 Feb 2026 19:12:09 -0800
This is ready for prod????
Diffstat:
15 files changed, 537 insertions(+), 116 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1 @@
-content/
dist/
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-# Makefile for framework
+# Makefile for verso_2
.POSIX:
diff --git a/README b/README
@@ -0,0 +1,15 @@
+██╗ ██╗███████╗██████╗ ███████╗ ██████╗ ██████╗
+██║ ██║██╔════╝██╔══██╗██╔════╝██╔═══██╗ ╚════██╗
+██║ ██║█████╗ ██████╔╝███████╗██║ ██║ █████╔╝
+╚██╗ ██╔╝██╔══╝ ██╔══██╗╚════██║██║ ██║ ██╔═══╝
+ ╚████╔╝ ███████╗██║ ██║███████║╚██████╔╝███████╗███████╗
+ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝
+
+Verso_2
+======
+
+After creating Verso which aimed for a spa-style site with heavy utilization of javascript, I have come here to reform my ways and offer up a simpler solution.
+
+Introducing verso_2. It should be self explanatory on how to use it based on the example here (which is also my personal site).
+
+Dependent on the lowdown markdown parser.
diff --git a/build.sh b/build.sh
@@ -1,15 +1,41 @@
#!/bin/sh
-# verso2 - suckless web framework
-# A minimal static site generator
+# ============================================================================
+# ██╗ ██╗███████╗██████╗ ███████╗ ██████╗ ██████╗
+# ██║ ██║██╔════╝██╔══██╗██╔════╝██╔═══██╗ ╚════██╗
+# ██║ ██║█████╗ ██████╔╝███████╗██║ ██║ █████╔╝
+# ╚██╗ ██╔╝██╔══╝ ██╔══██╗╚════██║██║ ██║ ██╔═══╝
+# ╚████╔╝ ███████╗██║ ██║███████║╚██████╔╝███████╗███████╗
+# ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝
+# verso_2 - web framework?
+# ============================================================================
+#
+# Copyright (C) 2026 Binkd.
+#
+# This file is part of verso_2.
+#
+# verso_2 is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# verso_2 is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License
+# along with verso_2. If not, see <https://www.gnu.org/licenses/>.
+#
+# =============================================================================
set -e
# Load configuration
-if [ ! -f "./web.conf" ]; then
- echo "Error: web.conf not found in current directory"
+if [ ! -f "./verso.conf" ]; then
+ echo "Error: verso.conf not found in current directory"
exit 1
fi
-. ./web.conf
+. ./verso.conf
# Helper functions
log() {
@@ -83,7 +109,8 @@ substitute_vars() {
local date="$4"
local nav="$5"
local author="$6"
-
+ local show_meta="$7"
+
# First pass: substitute simple variables
sed -e "s|{{TITLE}}|${title}|g" \
-e "s|{{SITE_TITLE}}|${SITE_TITLE}|g" \
@@ -92,16 +119,23 @@ substitute_vars() {
-e "s|{{AUTHOR}}|${author}|g" \
-e "s|{{DATE}}|${date}|g" \
"$template" | while IFS= read -r line; do
- # Handle {{NAV}} substitution
- if echo "$line" | grep -q '{{NAV}}'; then
- echo "$nav"
- # Handle {{CONTENT}} substitution
- elif echo "$line" | grep -q '{{CONTENT}}'; then
- cat "$content"
- else
- echo "$line"
+
+ # 1. Handle metadata toggle
+ if echo "$line" | grep -q '{{META_LINE}}'; then
+ if [ "$show_meta" != "no" ]; then
+ echo "<p class=\"meta\">$author --- $date</p>"
fi
- done
+ # 2. Handle {{NAV}} substitution
+ elif echo "$line" | grep -q '{{NAV}}'; then
+ echo "$nav"
+ # 3. Handle {{CONTENT}} substitution
+ elif echo "$line" | grep -q '{{CONTENT}}'; then
+ cat "$content"
+ # 4. Otherwise, print the line as is
+ else
+ echo "$line"
+ fi
+ done
}
# Calculate relative path back to root
@@ -127,12 +161,14 @@ build_page() {
local nav
local tmpfile
local author
+ local show_meta
rel_src=$(echo "$src" | sed "s|^${INPUT_DIR}/||")
title=$(extract_title "$src")
date=$(extract_date "$src")
nav=$(generate_nav)
author=$(extract_author "$src")
+ show_meta=$(extract_meta "$src" "show_meta")
[ -z "$author" ] && author="$AUTHOR"
@@ -156,7 +192,7 @@ build_page() {
' "$src" | $MD_PROCESSOR $MD_FLAGS > "$tmpfile"
# Substitute and write output
- substitute_vars "$TEMPLATE_DIR/header.html" "$title" "$tmpfile" "$date" "$nav" "$author" > "$dst"
+ substitute_vars "$TEMPLATE_DIR/header.html" "$title" "$tmpfile" "$date" "$nav" "$author" "$show_meta"> "$dst"
# Add footer with substitution
sed -e "s|{{AUTHOR}}|${AUTHOR}|g" \
@@ -171,9 +207,6 @@ build_page() {
generate_nav() {
local nav_html=""
- # Add home link
- nav_html="$nav_html <a href=\"/\">Home</a>"
-
# Find all items in root of INPUT_DIR (both files and directories)
(
# List markdown files (excluding index.md)
@@ -208,62 +241,67 @@ generate_nav() {
nav_html="$nav_html <a href=\"/$slug.html\">$title</a>"
fi
fi
+
echo "$nav_html"
nav_html=""
done
+
+ echo " <a href=\"/feed.xml\">RSS Feed</a>"
+ echo " <a href=\"${AUTHOR_GIT_HOST}\">Git</a>"
}
-# Generate automatic directory index
generate_directory_index() {
local dir="$1"
local output="$2"
local dirname=$(basename "$dir")
local title
local index_md
-
+
# Convert dirname to title
title=$(echo "$dirname" | sed 's/[-_]/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
-
+
log "Auto-generating index for $dirname..."
-
+
index_md=$(mktemp)
-
- echo "# $title" > "$index_md"
+
+ # ADD THIS BLOCK HERE:
+ cat << EOF > "$index_md"
+---
+title: $title
+show_meta: no
+---
+EOF
+ # Note: Use >> for the rest so we don't overwrite the frontmatter!
+
echo "" >> "$index_md"
-
- # Find all markdown files in this directory (excluding index.md)
- find "$dir" -maxdepth 1 -name "*.md" ! -name "index.md" -type f | sort | while read f; do
+
+ # Find all markdown files, extract date, sort, then format into markdown
+ find "$dir" -maxdepth 1 -name "*.md" ! -name "index.md" -type f | while read f; do
file_title=$(extract_title "$f")
date=$(extract_date "$f")
slug=$(basename "$f" .md)
-
+ # Output: date|title|slug for sorting
+ echo "${date}|${file_title}|${slug}"
+ done | sort -r | while IFS='|' read date title slug; do
if [ -n "$date" ]; then
- echo "* $date [$file_title]($slug/)" >> "$index_md"
- else
- echo "* [$file_title]($slug/)" >> "$index_md"
- fi
- done
-
- # Find subdirectories
- find "$dir" -maxdepth 1 -type d ! -path "$dir" | sort | while read subdir; do
- subdirname=$(basename "$subdir")
- # Try to get title from subdir's index.md
- if [ -f "$subdir/index.md" ]; then
- subdir_title=$(extract_title "$subdir/index.md")
+ echo "* $date [$title]($slug/)" >> "$index_md"
else
- subdir_title=$(echo "$subdirname" | sed 's/[-_]/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
+ echo "* [$title]($slug/)" >> "$index_md"
fi
- echo "* [$subdir_title]($subdirname/)" >> "$index_md"
done
-
+
+ # ... (rest of the subdirectory finding logic)
+
# Build the page
build_page "$index_md" "$output"
-
rm "$index_md"
}
extract_article_html() {
- sed -n '/<article>/,/<\/article>/p' "$1"
+ sed -n '/<article>/,/<\/article>/ {
+ /<header class="post-meta">/,/<\/header>/d
+ p
+ }' "$1"
}
# Generate blog index
@@ -271,25 +309,29 @@ generate_blog_index() {
local blog_src="$INPUT_DIR/$BLOG_DIR"
local blog_dst="$OUTPUT_DIR/$BLOG_DIR"
local index_md
-
+
[ ! -d "$blog_src" ] && return
-
+
log "Generating blog index..."
-
+
index_md=$(mktemp)
-
- echo "# Blog" > "$index_md"
+
+ # Use > for the first line to create/clear, then >> for everything else
+ echo "---" > "$index_md"
+ echo "show_meta: no" >> "$index_md"
+ echo "title: Blog" >> "$index_md"
+ echo "---" >> "$index_md"
echo "" >> "$index_md"
- echo "[RSS Feed](feed.xml)" >> "$index_md"
+ echo "# Blog" >> "$index_md"
echo "" >> "$index_md"
-
+ echo "[RSS Feed](../feed.xml)" >> "$index_md"
+ echo "" >> "$index_md"
+
# Find all blog posts, sort by date descending
find "$blog_src" -name "*.md" ! -name "index.md" | while read f; do
date=$(extract_date "$f")
title=$(extract_title "$f")
slug=$(basename "$f" .md)
-
- # Output: date|title|slug for sorting
echo "${date}|${title}|${slug}"
done | sort -r | while IFS='|' read date title slug; do
if [ "$CLEAN_URLS" = "yes" ]; then
@@ -298,20 +340,20 @@ generate_blog_index() {
echo "* $date [$title]($slug.html)" >> "$index_md"
fi
done
-
+
# Build the index page
if [ "$CLEAN_URLS" = "yes" ]; then
build_page "$index_md" "$blog_dst/index.html"
else
build_page "$index_md" "$blog_dst.html"
fi
-
+
rm "$index_md"
}
# Generate RSS feed
generate_rss() {
- local rss_file="$OUTPUT_DIR/$BLOG_DIR/feed.xml"
+ local rss_file="$OUTPUT_DIR/feed.xml"
local blog_src="$INPUT_DIR/$BLOG_DIR"
[ ! -d "$blog_src" ] && return
@@ -336,9 +378,10 @@ EOF
date=$(extract_date "$f")
title=$(extract_title "$f")
slug=$(basename "$f" .md)
- author=$(extra_author "$file")
+ author=$(extract_author "$f")
[ -z "$author" ] && author="$AUTHOR"
+
echo "${date}|${title}|${slug}|${f}"
done | sort -r | head -n 20 | while IFS='|' read date title slug file; do
if [ "$CLEAN_URLS" = "yes" ]; then
@@ -356,7 +399,7 @@ done | sort -r | head -n 20 | while IFS='|' read date title slug file; do
<link>${url}</link>
<guid>${url}</guid>
<pubDate>${date}</pubDate>
-<dc:creator>${author}</dc:creator>
+<author>${SITE_AUTHOR_EMAIL} (${AUTHOR})</author>
<description><![CDATA[
${body_html}
]]></description>
@@ -478,7 +521,7 @@ build_all() {
main() {
# Check for markdown processor
if ! command -v "$MD_PROCESSOR" > /dev/null 2>&1; then
- error "Markdown processor '$MD_PROCESSOR' not found. Install it or change MD_PROCESSOR in web.conf"
+ error "Markdown processor '$MD_PROCESSOR' not found. Install it or change MD_PROCESSOR in verso.conf"
fi
# Check templates exist
diff --git a/content/assets/logo.png b/content/assets/logo.png
Binary files differ.
diff --git a/content/assets/style.css b/content/assets/style.css
@@ -0,0 +1,68 @@
+/* Layout & Typography */
+html {
+ margin: 1em auto;
+ max-width: 42em;
+ font-family: sans-serif;
+ line-height: 1.5;
+}
+body {
+ margin: auto 8px 20px 8px;
+ background: #fff;
+ color: #000;
+}
+
+/* Header and Navigation (Table-based) */
+header nav table { width: 100%; border-collapse: collapse; border}
+.logo img { max-width: 3em; margin: 0; }
+.logo pre { background-color: transparent; border: none; padding: 0; margin: 0;
+ overflow: hidden; height: auto; width: auto; line-height: 1; letter-spacing: 0;
+ font-family: monospace; display: inline-block; vertical-align: middle; }
+.logo a { color: #000 !important; text-decoration: none; display: inline-block; }
+.logo a:hover { color: #000; background-color: yellow; text-decoration: none; }
+.links { text-align: right; font-weight: bold; }
+.links a { font-weight: bold; color: black; margin-left: 10px; }
+
+
+/* Content Headers */
+h1 { font-size: 1.8em; text-align: center; margin: 1em 0; }
+h2 { font-size: 1.6em; margin-top: 1.5em; }
+h3 { font-size: 1.05em; }
+
+/* Metadata line */
+.meta {
+ text-align: center;
+ font-style: italic;
+ color: #555;
+ margin-bottom: 2em;
+}
+
+/* Links */
+a { color: #000; text-decoration: underline; }
+a:hover { background-color: yellow; }
+
+/* Code Blocks */
+pre {
+ background-color: #eeeeee;
+ border: 2px solid #000;
+ padding: 6px;
+ overflow-x: auto;
+}
+code { background-color: #eeeeee; padding: 2px; font-family: monospace; }
+pre code { padding: 0px; background: none; }
+
+/* Tables (Post lists/File lists) */
+table { width: 100%; border-collapse: collapse; }
+#log tr:hover td, #files tr:hover td { background-color: #eeeeee; }
+#files td { font-family: monospace; font-size: 1.1em; padding: 4px 0; }
+
+/* Footer */
+footer { margin-top: 2em; border-top: 1px solid #ccc; padding-top: 1em; }
+footer table { font-style: italic; width: 100%; }
+.hosted { text-align: right; }
+
+/* Print settings */
+@media print {
+ .page-break { break-before: always; }
+ img, p { break-inside: avoid; }
+ h1, h2, h3 { break-after: avoid; }
+}
diff --git a/content/contact.md b/content/contact.md
@@ -0,0 +1,20 @@
+---
+title: Contact
+show_meta: no
+---
+
+Feel free to reach out:
+
+- Email: [nathaniel@chappelle.dev](mailto:nathaniel@chappelle.dev)
+ - 37AF 9835 E4CD AC40
+- XMPP: [binkd@xmpp.is](xmpp:binkd@xmpp.is)
+
+I'm always happy to chat about systems programming, performance optimization, or
+interesting technical problems. If you think I could get something done for you,
+let me know!
+
+You can find my projects here:
+
+- Personal Git Mirror: [git.chappelle.dev](https://git.chappelle.dev)
+- GitHub: [github.com/Binkersss](https://github.com/Binkersss)
+- Codeberg: [coderberg.org/binkd](https://codeberg.org/binkd)
diff --git a/content/current.md b/content/current.md
@@ -0,0 +1,51 @@
+---
+title: Current
+show_meta: no
+---
+
+Here's what I'm currently working on:
+
+## [Stamail](https://git.chappelle.dev/stamail/log.html)
+
+A [suckless](https://suckless.org) static site generator for mailing list archives
+
+Current state:
+
+- Parses maildir into s-expression using notmuch
+- Creates abstract syntax tree from s-expression
+- Creates message lists and thread trees from s-expression
+- HTML rendered parses lists and trees into a static webpage
+
+Current bugs:
+
+- ~~Generating empty erraneous message nodes~~
+- Threading HTML is _ugly_
+- Navigation of site, and aesthetic, isn't where it should be
+
+## [Gromacs-LS](https://github.com/vanegasj/gromacs-ls-2025.4)
+
+A fork of [Gromacs](https://www.gromacs.org), a moluecular dynamics simulation engine, with support for local stress and elasticity simulation. The project is authored and maintained by Juan Vanegas, a Biophysics professor and researcher at OSU.
+
+- Focusing on:
+ - Porting Gromacs-LS from v2016.3 of Gromacs to v2025.4
+ - Adivsing team members on:
+ - Implementation of automatic-differentiation into the [MDStress](https://vanegaslab.org/software) library.
+ - Performance profiling of MDStress library, including:
+ - Actual CPU time and memory space
+ - Interpretation of compiler generated assembly
+
+## Computer Architecture
+
+Currently taking High Performance Computer Architectures (CS 570 at OSU) as well as exploring creating a Verilog design of my own out-of-order RISC-V cpu
+
+- Focusing on:
+ - Out-of-order pipelines
+ - Branch prediction optimizations
+
+## Privacy and Security
+
+Currently taking a class on Privacy and Surveillance (CS 577 at OSU)
+
+- Focusing on:
+ - [Privacy in Context](https://www.sup.org/books/law/privacy-context) by Helen Nissebaum
+ - How changing contexts define how we feel about technologies, whether the technology is explicitly for surveillance or not
diff --git a/content/index.md b/content/index.md
@@ -0,0 +1,29 @@
+---
+title: About Me
+show_meta: no
+---
+
+I'm a systems developer and Masters Student at Oregon State University who loves
+thinking about what it takes to build fast, minimal software. I spend most of my
+time working on:
+
+- Philosophy of CS
+- Computing Architectures
+- Distributed systems
+- Performance optimization
+
+When I'm not thinking, designing or programming you'll find me cycling the
+gravel forest roads of the Oregon Coast Range, splitboarding in the Oregon
+Cascades, or riding my skateboard for the British Downhill Skateboarding team.
+
+Checkout [Current](current/) to hear more about my current technical and
+non-technical interests!
+
+Checkout my [blog](blog/) to read more about my thoughts, projects, and
+experiences.
+
+## Background
+
+I've been programming for over 4 years, primarily in C, Go, Python, and Rust. I
+believe in writing simple, maintainable, and composable code that does one thing
+well.
diff --git a/content/projects.md b/content/projects.md
@@ -0,0 +1,18 @@
+---
+title: Projects
+show_meta: no
+---
+
+Here are some things I've built:
+
+## [Feather-Virt](https://github.com/binkersss/feather-virt)
+
+A container runtime and hypervisor for inference at the edge.
+
+## [Verso](https://github.com/binkersss/verso)
+
+A minimal static site generator written in Go. Features:
+
+- Markdown with frontmatter support
+- Live reloading dev server
+- Zero configuration needed
diff --git a/templates/footer.html b/templates/footer.html
@@ -1,6 +1,6 @@
<footer>
<div class="container">
- <p>© 2026 {{AUTHOR}}. Built with <a href="https://git.chappelle.dev/verso2">verso2</a>.</p>
+ <p>© 2026 {{AUTHOR}}. Built with <a href="https://git.chappelle.dev/verso2">verso_2</a>.</p>
</div>
</footer>
</body>
diff --git a/templates/header.html b/templates/header.html
@@ -10,24 +10,35 @@
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/blog/feed.xml">
</head>
<body>
- <header>
- <div class="container">
- <h1 class="site-title"><a href="/">{{SITE_TITLE}}</a></h1>
- <nav>
-{{NAV}}
- </nav>
- </div>
+ <header>
+ <nav>
+ <table>
+ <tr>
+ <td class="logo">
+ <strong><a href="/">
+<pre>
+███████╗
+██╔════╝
+██║
+██║
+╚██████╗
+ ╚═════╝</pre>
+ <a></strong>
+ </td>
+ <td class="links">
+ {{NAV}}
+ </td>
+ </tr>
+ </table>
+ </nav>
+ </header>
+ <hr>
+<main class="container">
+ <article>
+ <header class="post-meta">
+ <h1>{{TITLE}}</h1>
+ {{META_LINE}}
</header>
-
- <main class="container">
- <article>
- <header class="post-meta">
- <h1>{{TITLE}}</h1>
- <p class="meta">
- <time>{{DATE}}</time>
- · <span class="author">{{AUTHOR}}</span>
- </p>
- </header>
- {{CONTENT}}
- </article>
- </main>
+ {{CONTENT}}
+ </article>
+</main>
diff --git a/verso.conf b/verso.conf
@@ -0,0 +1,34 @@
+# web.conf - Configuration for verso_2
+
+# Site metadata
+SITE_TITLE="Chappelle.dev"
+SITE_URL="https://chappelle.dev"
+SITE_DESCRIPTION="A simple website"
+AUTHOR="Nathaniel Chappelle"
+SITE_AUTHOR_EMAIL="nathaniel@chappelle.dev"
+AUTHOR_GIT_HOST="https://git.chappelle.dev"
+
+# Paths
+INPUT_DIR="content"
+OUTPUT_DIR="dist"
+TEMPLATE_DIR="templates"
+
+# Markdown processor (lowdown, cmark, markdown, discount, etc.)
+MD_PROCESSOR="lowdown"
+MD_FLAGS=""
+
+# File handling
+COPY_EXTENSIONS="jpg jpeg png gif svg pdf css js ico webp woff woff2 ttf"
+IGNORE_PATTERNS="^\. .*\.swp$ .*~$"
+
+# Features
+GENERATE_RSS="yes"
+GENERATE_SITEMAP="yes"
+CLEAN_URLS="yes" # page.md -> page/index.html
+
+# Date format
+DATE_FORMAT="%Y-%m-%d"
+
+# Blog settings
+BLOG_DIR="blog/"
+POSTS_PER_PAGE="10"
diff --git a/web.conf b/web.conf
@@ -1,32 +0,0 @@
-# web.conf - Configuration for sw web framework
-
-# Site metadata
-SITE_TITLE="Chappelle.dev"
-SITE_URL="https://chappelle.dev"
-SITE_DESCRIPTION="A simple website"
-AUTHOR="Nathaniel Chappelle"
-
-# Paths
-INPUT_DIR="content"
-OUTPUT_DIR="dist"
-TEMPLATE_DIR="templates"
-
-# Markdown processor (lowdown, cmark, markdown, discount, etc.)
-MD_PROCESSOR="lowdown"
-MD_FLAGS=""
-
-# File handling
-COPY_EXTENSIONS="jpg jpeg png gif svg pdf css js ico webp woff woff2 ttf"
-IGNORE_PATTERNS="^\. .*\.swp$ .*~$"
-
-# Features
-GENERATE_RSS="yes"
-GENERATE_SITEMAP="yes"
-CLEAN_URLS="yes" # page.md -> page/index.html
-
-# Date format
-DATE_FORMAT="%Y-%m-%d"
-
-# Blog settings
-BLOG_DIR="blog"
-POSTS_PER_PAGE="10"