revamp projects, continue editing and add precommit hook for lastmod frontmatter

This commit is contained in:
Nathan Anderson 2026-02-02 23:13:56 -07:00
parent 23a44c1e4f
commit 2fad7c173b
16 changed files with 357 additions and 47 deletions

View File

@ -68,3 +68,4 @@ tok
toks toks
UI UI
Nephi Nephi
lol

View File

@ -5,6 +5,12 @@ NC='\033[0m' # No Color
echo "Running pre-commit checks..." echo "Running pre-commit checks..."
# Auto-update lastmod in content files (non-blocking)
# Runs before other checks so lint/spell run on updated files
if [ -x "$(dirname "$0")/update-lastmod.sh" ]; then
"$(dirname "$0")/update-lastmod.sh" || echo "⚠️ lastmod update script encountered an issue"
fi
# Track overall success/failure # Track overall success/failure
OVERALL_RESULT=0 OVERALL_RESULT=0

37
.githooks/update-lastmod.sh Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Auto-update lastmod field in staged content files
# This script should never block a commit - errors are warnings only
update_lastmod() {
local file="$1"
# Generate RFC3339 timestamp with timezone (e.g., 2025-11-08T16:19:07-06:00)
local tz_offset=$(date +%z)
local tz_formatted="${tz_offset:0:3}:${tz_offset:3:2}" # Insert colon: -0600 -> -06:00
local now=$(date +%Y-%m-%dT%H:%M:%S)${tz_formatted}
# Only update if file has lastmod field
if grep -q "^lastmod:" "$file"; then
# Cross-platform sed -i (macOS vs Linux)
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s/^lastmod:.*$/lastmod: $now/" "$file"
else
sed -i "s/^lastmod:.*$/lastmod: $now/" "$file"
fi
git add "$file"
echo " Updated lastmod in $file"
fi
}
# Get staged content files
staged_files=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^content/.*\.md$' || true)
if [ -z "$staged_files" ]; then
exit 0
fi
for file in $staged_files; do
if [ -f "$file" ]; then
update_lastmod "$file" || echo "Warning: Failed to update lastmod in $file"
fi
done

10
archetypes/projects.md Normal file
View File

@ -0,0 +1,10 @@
---
date: {{ .Date }}
description: ""
lastmod: {{ .Date }}
showTableOfContents: true
type: "projects"
title: "{{ replace .Name "-" " " | title }}"
active: true
tags: []
---

View File

@ -29,7 +29,8 @@ togglePreviousAndNextButtons = "true"
avatarUrl = "/images/fosscat_icon.png" avatarUrl = "/images/fosscat_icon.png"
avatarSize = "size-s" avatarSize = "size-s"
numberPostsOnHomePage = 5 numberPostsOnHomePage = 5
showPostsOnHomePage = "recent" # "popular" showPostsOnHomePage = "recent"
numberTilsOnHomePage = 3
[params.meta] [params.meta]
favicon = true favicon = true
@ -48,17 +49,17 @@ name = "Home"
url = "/" url = "/"
weight = 1 weight = 1
[[menu.main]] [[menu.main]]
name = "Posts"
url = "/posts/"
weight = 2
[[menu.main]]
identifier = "tils" identifier = "tils"
name = "TIL's" name = "TIL's"
url = "/tils/" url = "/tils/"
weight = 2 weight = 3
[[menu.main]] [[menu.main]]
name = "Projects" name = "Projects"
url = "/projects/" url = "/projects/"
weight = 3
[[menu.main]]
name = "Posts"
url = "/posts/"
weight = 4 weight = 4
[[menu.main]] [[menu.main]]
name = "Tags" name = "Tags"

View File

@ -16,8 +16,8 @@ I recognize it's important to establish some things before heading out any furth
reaching is extremely broad. So, before I get in to tell my tall tale, lets clear the air so I don't run the risk of reaching is extremely broad. So, before I get in to tell my tall tale, lets clear the air so I don't run the risk of
losing anyone along the way. losing anyone along the way.
- As of the time of writing, it is commonly held preference not say Mormons, and instead say members of the Church of - As of the time of writing, it is a commonly held preference not to say Mormons, and instead say members of the Church
Jesus Christ of Latter Day Saints. of Jesus Christ of Latter Day Saints.
- I'm not writing this to persuade anyone. This is my story. If you feel attacked or validated by my experience, I am - I'm not writing this to persuade anyone. This is my story. If you feel attacked or validated by my experience, I am
going to put that onus on you, the reader, to draw what conclusions you deem appropriate. going to put that onus on you, the reader, to draw what conclusions you deem appropriate.
@ -26,11 +26,11 @@ typically comes from friends and family still a part of the faith, which I alway
whirling a bit when you leave the Church, so hopefully this can clarify things for both of us. whirling a bit when you leave the Church, so hopefully this can clarify things for both of us.
- If you the reader don't know much about the (more commonly recognized) "Mormon" faith, then this post may be hard - If you the reader don't know much about the (more commonly recognized) "Mormon" faith, then this post may be hard
to follow. It will waste no time explaining concepts and assume the reader is familiar with the doctrines, history, to follow. It will waste no time explaining concepts and assume the reader is familiar with the doctrines, history,
and positions of the church. I will do my best to delineate between commonly held **facts** and my _opinions_ cite my and positions of the church. I will do my best to delineate between commonly held **facts** and my _opinions_ and cite
sources. my sources.
- If you the reader take issue with how I've portrayed things, please reach out! I mean it. There's no real way to - If you the reader take issue with how I've portrayed things, please reach out! I mean it. There's no real way to
express this through rendered HTML on your lit array of pixels, but its true. I feel strongly it is important to always express my sincerity through high contrast pixels on your device of choice, but its true. I feel strongly it is
keep these conversations open. important to always keep these conversations open.
_Hopefully_ I haven't lost you, dear reader, and I want to thank you in advance for any of the effort you take to _Hopefully_ I haven't lost you, dear reader, and I want to thank you in advance for any of the effort you take to
understand and empathize with me. You keep my faith in humanity <3 understand and empathize with me. You keep my faith in humanity <3
@ -39,7 +39,11 @@ So, without further ado, lets "begin at the very beginning"
## "Born of goodly parents" ## "Born of goodly parents"
I grew up in a loving home with parents that did their best to give us five kids a great life. I'm the middle kid, the I grew up in a loving home with parents that did their best to give us kids a great life. I'm the middle kid, the
glue you might say *smirk. My involvement in the church informed much of my life. My friends were typically the boys in glue you might say *smirk. My involvement in the church informed much of my life. My friends were typically the boys in
my ward's Sunday school class or in my boy scout troop. My views of the world were most entirely shaped by my religion. my ward's Sunday school class or in my boy scout troop. My views of the world were most entirely shaped by my religion.
I remember feeling immense privilege and dread thinking that I happened to live in the neighborhood of the family that There was some anxiety as a kid knowing whether or not someone was a member because it meant Friends houses that weren't
members of the church felt unsafe.
When I was 8 or 9, I remember feeling immense responsibility, mixed with privilege and dread, thinking that God had
restored His One True Church to my neighborhood! Relief washed over me when I learned that there were actually millions
of us, not just the two hundred in my ward. lol.

View File

@ -1,13 +0,0 @@
---
title: "Projects"
type: "page"
lastmod: 2025-10-03T16:19:07-06:00
---
Worked on frequently, updated on occasion.
- # [Game in Zig & SDL2 ⚡️](/projects/zig-sdl)
<!-- - # [Gaining 15 Pounds in 2025 :muscle:]() -->
<!-- - # [Drones :video_game: :helicopter:]() -->

View File

@ -0,0 +1,8 @@
---
title: "Projects"
---
Worked on frequently, updated on occasion.
As a person with high openness and lower than average follow-thru, this may more just be a catalog of my passing
interests and hobbies!

View File

@ -1,14 +1,15 @@
--- ---
title: "SDL Game in Zig" title: "SDL Game in Zig"
image: "" image: ""
type: "page" type: "projects"
active: false
date: "2025-01-10" date: "2025-01-10"
lastmod: 2025-10-03T16:19:07-06:00 lastmod: 2025-10-03T16:19:07-06:00
--- ---
# Zig Game Dev with SDL2 # Zig Game Dev with SDL2
I'm (was) making a game in Zig! Currently getting back into Zig. I (was) making a game in Zig! Currently getting back into Zig.
Watch me [stream on Twitch](https://twitch.tv/fosscat), or the embed below! Watch me [stream on Twitch](https://twitch.tv/fosscat), or the embed below!

View File

@ -3,8 +3,8 @@ title: "Today I Learned"
type: "til" type: "til"
--- ---
Anyday I learn something cool, I will write up a brief TIL (Today I Learned) post. Any day I learn something cool (and think to write it down), I will write up a brief Today I Learned (TIL) post.
If they help you, great! But I think having a collection of my learnings will be pretty neat just for myself! If they help you, great! But I think having a collection for myself will be pretty neat!
# My TILs # My TILs

View File

@ -1,6 +1,6 @@
--- ---
date: 2025-10-03T16:19:07-06:00 date: 2025-10-03T16:19:07-06:00
description: "" description: "We were made for dogs, and they us."
lastmod: 2025-10-03T16:19:07-06:00 lastmod: 2025-10-03T16:19:07-06:00
showTableOfContents: true showTableOfContents: true
type: "tils" type: "tils"

View File

@ -9,10 +9,10 @@
<h3>{{ .Title }}</h3> <h3>{{ .Title }}</h3>
<p>{{ .Date | time.Format ":date_medium" }}</p> <p>{{ .Date | time.Format ":date_medium" }}</p>
</div> </div>
</br>
<p>{{ .Summary }}</p>
</a> </a>
<p>{{ .Params.Description }}</p>
</div> </div>
</br>
{{ end }} {{ end }}
</div> </div>
{{ end}} {{ end}}

71
layouts/index.html Normal file
View File

@ -0,0 +1,71 @@
{{ define "main" }}
<section class="home-about">
<div class="avatar">
{{ if isset .Site.Params "avatarurl" }}
<img class={{ .Site.Params.AvatarSize | default "size-m" }} src='{{ .Scratch.Get "avatarImgSrc" }}'
alt="{{ .Site.Params.AvatarAltText|default " avatar" }}">
{{ end }}
</div>
<h1>{{ .Site.Title }}</h1>
{{ if isset .Site.Params "description" }}
<h2>{{ .Site.Params.Description }}</h2>
{{ end }}
</section>
<div class="flex-break"></div>
{{ if isset .Site.Params "socialicons" }}
<div class="gk-social-icons">
<ul class="gk-social-icons-list">
{{ range .Site.Params.SocialIcons }}
<li class="gk-social-icon">
<a href="{{ .url }}" {{ if .rel }}rel="{{ .rel }}" {{ end }} aria-label="Learn more on {{ .name }}">
<img class="svg-inject" src="{{ relURL " svg/icons/" }}{{ .name | lower }}.svg" alt="">
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
{{ if os.FileExists "index-about.md" }}
<div class="markdown-content">
{{ readFile "index-about.md" | markdownify }}
</div>
{{ end }}
{{ if isset .Site.Params "showpostsonhomepage" }}
<div class="home-posts list-posts">
<h2>Recent Posts</h2>
{{ $posts := where .Site.Pages "Params.type" "post" }}
{{ if eq .Site.Params.ShowPostsOnHomePage "popular" }}
{{ range $posts.ByWeight | first (or .Site.Params.NumberPostsOnHomePage 4) }}
{{- partial "list-posts.html" . -}}
{{ end }}
{{ else if eq .Site.Params.ShowPostsOnHomePage "recent" }}
{{ range $posts.ByDate.Reverse | first (or .Site.Params.NumberPostsOnHomePage 4) }}
{{- partial "list-posts.html" . -}}
{{ end }}
{{ end }}
</div>
{{ end }}
{{/* TILs Section */}}
{{ $tils := where .Site.Pages "Params.type" "tils" }}
{{ $tilsToShow := $tils.ByDate.Reverse | first (or .Site.Params.NumberTilsOnHomePage 3) }}
{{ if gt (len $tilsToShow) 0 }}
<div class="home-posts list-posts">
<h2>Recent TILs</h2>
{{ range $tilsToShow }}
{{- partial "list-posts.html" . -}}
{{ end }}
</div>
{{ end }}
{{ end }}

View File

@ -0,0 +1,62 @@
{{ define "main" }}
<style>
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 500;
margin-left: 0.5rem;
vertical-align: middle;
}
.status-active {
background-color: rgba(76, 175, 80, 0.15);
color: #4caf50;
border: 1px solid #4caf50;
}
.status-inactive {
background-color: rgba(158, 158, 158, 0.15);
color: #9e9e9e;
border: 1px solid #9e9e9e;
}
.project-date {
font-size: 0.85rem;
color: var(--light-secondary-color);
margin-left: 0.5rem;
}
</style>
<div class="container">
<h1 class="page-title">{{ .Title }}</h1>
{{ .Content }}
<div class="posts-list">
{{ range .Pages }}
<article class="post-entry">
<header class="entry-header">
<h3 class="entry-title">
<a href="{{ .Permalink }}" rel="bookmark">{{ .Title }}</a>
{{ if .Params.active }}
<span class="status-badge status-active">Active</span>
{{ else }}
<span class="status-badge status-inactive">Inactive</span>
{{ end }}
<span class="project-date">Updated {{ .Lastmod.Format "Jan 2, 2006" }}</span>
</h3>
</header>
{{ with .Description }}
<div class="entry-summary">{{ . }}</div>
{{ end }}
</article>
{{ end }}
</div>
{{ if eq (len .Pages) 0 }}
<p>No projects yet.</p>
{{ end }}
</div>
{{ end }}

View File

@ -0,0 +1,122 @@
{{ define "main" }}
<style>
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 500;
margin-left: 0.5rem;
vertical-align: middle;
}
.status-active {
background-color: rgba(76, 175, 80, 0.15);
color: #4caf50;
border: 1px solid #4caf50;
}
.status-inactive {
background-color: rgba(158, 158, 158, 0.15);
color: #9e9e9e;
border: 1px solid #9e9e9e;
}
.post-image {
display: flex;
justify-content: center;
margin: 1.5rem 0;
}
.post-image img {
height: auto;
border-radius: 8px;
border: 1.5px solid var(--light-secondary-color);
box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 8px;
object-fit: cover;
}
.image-caption p {
display: flex;
justify-content: center;
}
@media (max-width: 480px) {
.post-image img {
width: 100%;
max-width: 300px;
}
}
@media (min-width: 481px) and (max-width: 768px) {
.post-image img {
width: 80%;
max-width: 400px;
}
}
@media (min-width: 769px) {
.post-image img {
width: 60%;
max-width: 500px;
}
}
</style>
<div class="post container">
<div class="post-header-section">
<h1>
{{ .Title | markdownify }}
{{ if .Params.active }}
<span class="status-badge status-active">Active</span>
{{ else }}
<span class="status-badge status-inactive">Inactive</span>
{{ end }}
</h1>
{{ with .Description }}
<small role="doc-subtitle">{{ . }}</small>
{{ end }}
<p class="post-date">
Started {{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Date }}
{{ if lt .Date .Lastmod }} | Updated {{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Lastmod }}{{ end }}
</p>
<ul class="post-tags">
{{ range .Params.Tags }}
<li class="post-tag"><a href="{{ "tags/" | absLangURL }}{{ . | urlize }}">{{ . }}</a></li>
{{ end }}
</ul>
</div>
{{ if .Params.image }}
<div class="post-image">
<img src="{{ .Params.image | absURL }}" alt="{{ .Params.image_alt | default .Title }}">
</div>
<div class="image-caption">
<p>{{ .Params.image_caption }}</p>
</div>
{{ end }}
<div class="post-content">
{{ .Content }}
</div>
<div class="prev-next">
{{ if eq .Site.Params.TogglePreviousAndNextButtons "true" }}
{{ if or .PrevInSection .NextInSection }}
{{ partial "prev-next.html" . }}
{{ end }}
{{ end }}
</div>
{{ if .Site.Params.ShowBackToTopButton }}
{{ partial "back-to-top.html" . }}
{{ end }}
</div>
{{- partial "toc.html" . -}}
{{ end }}

0
new
View File