My new post script A developer published a blog post and two shell scripts, new-post and companion-prompt, that automate scaffolding Hugo weblog posts and wiring comment threads on Popsicle Boat. The scripts prompt for front matter, generate RFC3339 dates, and integrate with a commit-time hook to create discussion threads per spec 0006. I asked AI to draft this for me. I've edited it. Any surviving AI smells are my oversight. Well, that did something.Keep going.Nothing is hidden on this page, but some Weblog pages have letters that burn brighter than others.Congratulations Hope you enjoyed the fire πŸ”₯ The fire isn't everything, though. One more click starts it over. When you've found and solved the real puzzle, you'll know. Not a lot to it, just scripts/new-post and follow the prompts to setup the boilerplate. Then write the content. Then to wire up comments on Popsicle Boat, scripts/companion-prompt That’s it Boilerplate, fresh. Kind of like making waffles. Get it? Hehe. New Post bash /usr/bin/env bash new-post β€” scaffold a weblog post interactively. Prompts for the front matter this blog actually uses title, slug, bundle, description, summary, categories, tags , writes the post with a correct RFC3339 date and an empty popsicleboat: line, and leaves the body to you. Committing the post later triggers scripts/companion-prompt, which asks for the thread's space and wires the discussion thread spec 0006 . set -euo pipefail cd "$ git rev-parse --show-toplevel " die { echo "new-post: $1" &2; exit 1; } Quote a YAML scalar: double quotes unless the value has one, then single. yaml quote { case $1 in \" \' | \' \" die "can't hold both quote kinds in front matter: $1" ;; \" printf "'%s'" "$1" ;; printf '"%s"' "$1" ;; esac } Comma-separated answer - YAML list lines "- item" per entry . yaml list { local IFS=',' item for item in $1; do item=$ printf '%s' "$item" | sed -E 's/^ +| +$//g' -n "$item" && printf -- "- %s\n" "$item" done } read -r -p "Title: " title -n "$title" || die "a post needs a title" default slug=$ printf '%s' "$title" | tr ' :upper: ' ' :lower: ' | sed -E "s/'//g; s/ ^a-z0-9 +/-/g; s/^-+//; s/-+$//" read -r -p "Slug $default slug : " slug slug=${slug:-$default slug} -n "$slug" || die "a post needs a slug" read -r -p "Page bundle, for images alongside the post? y/N : " bundle case $bundle in yY post="content/weblog/$slug/index.md" ;; post="content/weblog/$slug.md" ;; esac -e "$post" && die "$post already exists" read -r -p "Description meta/OG line; blank to fill in later : " description read -r -p "Summary list-page line; blank to fill in later : " summary read -r -p "Categories, comma-separated Projects : " categories categories=${categories:-Projects} read -r -p "Tags, comma-separated e.g. popsicleboat, hugo : " tags ts=$ date "+%Y-%m-%dT%H:%M:%S%z" ts="${ts:0:22}:${ts:22}" RFC3339 wants a colon in the offset mkdir -p "$ dirname "$post" " { echo "---" echo "title: $ yaml quote "$title" " echo "description: $ yaml quote "$description" " echo "date: $ts" echo "summary: $ yaml quote "$summary" " echo 'popsicleboat: "" wired at commit by scripts/companion-prompt' echo "categories:" yaml list "$categories" if -n "$tags" ; then echo "tags:" yaml list "$tags" fi echo "---" echo "" } "$post" echo "" echo "Created $post β€” write the essay." echo "Committing it will prompt for its companion thread empty space answer skips ." Companion Prompt bash /usr/bin/env bash companion-prompt β€” wire a new post's companion thread at commit time. For each NEW post staged in this commit content/weblog/ .md or a new bundle's index.md whose popsicleboat: field is empty, prompt for the thread's space and an optional per-post thread title, write the answers into the front matter, run scripts/companion-thread, and re-stage the post β€” so the commit lands with its Discuss thread created and wired. Never blocks a commit. Degraded paths no terminal, no POPSICLEBOAT TOKEN, empty space answer, API failure print how to wire the thread later and let the commit through. Skip the hook with COMPANION PROMPT=0, or --no-verify. set -uo pipefail cd "$ git rev-parse --show-toplevel " "${COMPANION PROMPT:-1}" = "0" && exit 0 new posts=$ git diff --cached --name-only --diff-filter=A -- \ 'content/weblog/ .md' 'content/weblog/ /index.md' | grep -v ' index\.md$' || true -z "$new posts" && exit 0 Posts that already carry a thread URL or no field at all need no prompt. needs thread { grep -qE '^popsicleboat: "" ? . ?$' "$1" } pending= while IFS= read -r post; do -f "$post" && needs thread "$post" && pending+= "$post" done <<< "$new posts" "${ pending @ }" -eq 0 && exit 0 later { how to finish the job after a degraded path echo "companion-prompt: wire it later with: scripts/companion-thread $1 --space