summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-07-11 12:15:04 -0600
committert <t@tjp.lol>2026-07-11 12:18:55 -0600
commitd6c7333d37638447a2a41c762574de8851665934 (patch)
tree577145d845ec954ff812308bc98b2ca30dcf5cc0
parent2ab0e23eca3c5cac82d948e506b3f1cb81bedd18 (diff)
Document deployment and stop tracking generated output
-rw-r--r--_docs/IMPLEMENTATION_STATUS.md30
-rw-r--r--_docs/OPERATIONS.md70
-rw-r--r--about/index.html68
-rw-r--r--feed.xml13
-rw-r--r--index.html59
-rw-r--r--notes/index.html47
-rw-r--r--projects/index.html46
-rw-r--r--weblog/index.html41
8 files changed, 100 insertions, 274 deletions
diff --git a/_docs/IMPLEMENTATION_STATUS.md b/_docs/IMPLEMENTATION_STATUS.md
new file mode 100644
index 0000000..cc34e80
--- /dev/null
+++ b/_docs/IMPLEMENTATION_STATUS.md
@@ -0,0 +1,30 @@
+# Project implementation status
+
+Status as of 2026-07-11.
+
+- [x] Fictional examples are retained only under underscore-prefixed names and
+ are absent from public listings and the feed.
+- [x] The Weft Go generator, template conventions, Markdown parsing, inventory,
+ link rewriting, output collision checks, relative links, Atom generation,
+ safe output ownership, rollback, and stale cleanup are implemented and
+ covered by runnable tests.
+- [x] Existing pages are represented by templates or Markdown sources and build
+ back to in-place HTML/XML outputs; `style.css` is unchanged.
+- [x] Inherited prose is enumerated in `PROSE_AUDIT.md`; no replacement post
+ prose was invented.
+- [x] The generated site has an empty valid Atom feed, no public fictional
+ entries, and a consistent CC BY 4.0 footer and colophon disclosure.
+- [x] `.gitignore` covers generated HTML, `feed.xml`, the ownership manifest,
+ and transaction directories; shared Syncthing rules exclude generated HTML.
+- [x] Generated HTML and `feed.xml` are ignored and absent from version
+ control, so a fresh checkout can build without bypassing output ownership.
+- [x] Caddy protection and the locked, delayed, failure-logged cron invocation
+ are recorded in `OPERATIONS.md`.
+- [ ] External: install and schedule Weft on the server, activate the Caddy
+ rules, and validate them against the deployed host.
+- [ ] External: connect deliberately selected real vault content and verify its
+ Syncthing/privacy behavior.
+- [ ] External: restore Notes links only after those real notes are ready.
+
+Notes navigation and homepage note links intentionally remain commented out;
+there is no selected real vault content to publish yet.
diff --git a/_docs/OPERATIONS.md b/_docs/OPERATIONS.md
new file mode 100644
index 0000000..a4a6d13
--- /dev/null
+++ b/_docs/OPERATIONS.md
@@ -0,0 +1,70 @@
+# Weft operations
+
+## Caddy source protection
+
+Before enabling public notes, place these matchers before `file_server` in the
+site block and reload Caddy:
+
+```caddyfile
+@underscore path_regexp underscore (^|/)_[^/]*
+respond @underscore 404
+
+@templates path *.tmpl
+respond @templates 404
+```
+
+The first matcher denies any URL with an underscore-prefixed path component,
+including an entire `_private/` subtree. The second denies template sources.
+Markdown is intentionally not denied and may remain downloadable. Validate the
+active configuration with `caddy validate --config /etc/caddy/Caddyfile` before
+`systemctl reload caddy`.
+
+## Syncthing
+
+Each device keeps this device-local, non-synchronized `.stignore` at the vault
+root:
+
+```text
+#include .stignore.shared
+```
+
+The synchronized `.stignore.shared` contains:
+
+```text
+*.html
+```
+
+The local include lets every device load one shared rule without trying to
+synchronize `.stignore` itself. The shared rule excludes generated HTML at
+every depth in both directions while leaving Markdown synchronized.
+
+## Scheduled build
+
+Install the Weft binary at `/usr/local/bin/weft`, then use a cron entry like:
+
+```cron
+17 * * * * sleep 60 && flock -n /run/lock/weft.lock /usr/local/bin/weft /srv/tjp.lol >>/var/log/weft.log 2>&1 || logger -t weft 'build failed or lock unavailable'
+```
+
+The 60-second delay gives Syncthing time to settle, `flock -n` prevents
+overlapping builds, build output goes to `/var/log/weft.log`, and failure is
+also recorded in the system log under the `weft` tag. Adjust the delay only
+after observing the server's real sync latency. These paths assume a root
+crontab; for an unprivileged account, use lock and log paths it can write.
+
+## Rollout
+
+- [ ] Install Weft and run one manual build on the server.
+- [ ] Add and validate the Caddy matchers above before serving the source tree.
+- [ ] Put the local `.stignore` on every Syncthing device and synchronize
+ `.stignore.shared`.
+- [ ] Connect only the deliberately selected public vault content.
+- [ ] Verify generated note pages, internal links, and underscore privacy on the
+ deployed host.
+- [ ] Install the locked, delayed cron build and confirm a forced failure is
+ logged.
+- [ ] Restore Notes navigation and homepage links only after real public notes
+ are present and verified.
+
+Notes remains hidden: no real selected vault content exists in this repository,
+so vault connection and server activation are intentionally pending.
diff --git a/about/index.html b/about/index.html
deleted file mode 100644
index 99f9a22..0000000
--- a/about/index.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>About &amp; colophon — tjp.lol</title>
-<meta name="description" content="About tjp and how this site is built.">
-<link rel="stylesheet" href="../style.css">
-</head>
-<body>
-<div class="wrap">
-
- <header class="site">
- <h1 class="brand"><a href="../index.html">~tjp<span class="cur"> $_</span></a></h1>
- <nav class="main">
- <a href="../weblog/index.html">weblog</a>
-
- <a href="../projects/index.html">projects</a>
- <a href="index.html" aria-current="page">about</a>
- <a href="../feed.xml">feed</a>
- </nav>
- </header>
-
- <main>
- <article class="post">
- <div class="post-head">
- <h1>About</h1>
- </div>
- <div class="note-body">
- <p>I'm tjp &mdash; an elder-millennial software engineer living in Salt Lake City, Utah. I write mostly Python, spend too long in the terminal, and care about software that's small, legible, and built to last.</p>
- <p>This site is where I keep my <a href="../weblog/index.html">writing</a>. If you want to reach me, <a href="mailto:t@tjp.lol">t@tjp.lol</a> is the best way.</p>
-
- <h2>Elsewhere</h2>
- <ul>
- <li><span class="mono">email</span> &mdash; <a href="mailto:t@tjp.lol">t@tjp.lol</a></li>
- <li><span class="mono">code</span> &nbsp;&mdash; <a href="https://github.com/teepark">github.com/teepark</a></li>
- <li><span class="mono">fedi</span> &nbsp;&mdash; <a href="https://tilde.zone/@tjpcc" rel="me">@tjpcc@tilde.zone</a></li>
- <li><span class="mono">gemini</span> &mdash; <code>gemini://gemini.ctrl-c.club/~tjp/</code></li>
- </ul>
- </div>
-
- <div class="backlinks">
- <h2>Colophon</h2>
- <div class="note-body">
- <p>This site is generated from Markdown and Go templates by Weft, with a single <a href="../style.css">stylesheet</a>. There is no JavaScript anywhere &mdash; not deferred, not optional, none. It renders identically with scripts disabled because there is nothing to disable.</p>
- <ul>
- <li><strong>Type:</strong> your system's UI font for prose, your system's monospace for headings and code. No web fonts, no network requests for type.</li>
- <li><strong>Colour:</strong> light and dark themes via <code>prefers-color-scheme</code> &mdash; it follows your OS setting, in pure CSS.</li>
- <li><strong>Weblog:</strong> published from Markdown as static HTML.</li>
- <li><strong>Notes:</strong> authored in Obsidian, synced across my devices with Syncthing, published as static pages.</li>
- <li><strong>Build:</strong> Weft recursively renders Markdown and Go templates. AI may assist with coding and batch refactoring, but not with published post prose.</li>
- <li><strong>Hosting:</strong> static files. Nothing to run, nothing to patch.</li>
- <li><strong>Licence:</strong> content is <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless a page says otherwise. Take it, remix it, just credit me.</li>
- </ul>
- </div>
- </div>
- </article>
- </main>
-
- <footer>
-
- <p>&copy;2026 tjp &middot; content <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless noted &middot; <a href="../feed.xml">feed</a></p>
- </footer>
-
-</div>
-</body>
-</html>
-
diff --git a/feed.xml b/feed.xml
deleted file mode 100644
index ebbad13..0000000
--- a/feed.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<feed xmlns="http://www.w3.org/2005/Atom">
- <title>tjp.lol</title>
- <subtitle>Notes, code, and longer thoughts from an elder-millennial software engineer in Salt Lake City.</subtitle>
- <link href="https://tjp.lol/feed.xml" rel="self"/>
- <link href="https://tjp.lol/"/>
- <updated>2026-07-11T00:00:00Z</updated>
- <id>https://tjp.lol/</id>
- <author>
- <name>tjp</name>
- <email>t@tjp.lol</email>
- </author>
-
-</feed>
diff --git a/index.html b/index.html
deleted file mode 100644
index fe7b5ee..0000000
--- a/index.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>tjp.lol</title>
-<meta name="description" content="Personal site of tjp — software engineer in Salt Lake City. Weblog, notes, projects.">
-<link rel="stylesheet" href="style.css">
-<link rel="alternate" type="application/atom+xml" title="tjp.lol" href="feed.xml">
-</head>
-<body>
-<div class="wrap">
-
- <header class="site">
- <h1 class="brand"><a href="index.html">~tjp<span class="cur"> $_</span></a></h1>
- <p class="tag">Elder-millennial software engineer in Salt Lake City, Utah. Writing about code, tools, and the small web.</p>
- <nav class="main">
- <a href="weblog/index.html">weblog</a>
-
- <a href="projects/index.html">projects</a>
- <a href="about/index.html">about</a>
- <a href="feed.xml">feed</a>
- </nav>
- </header>
-
- <main>
- <section class="intro">
- <p>Welcome in. This site is my writing desk: weblog posts moving over from my <span class="mono">gemini://</span> capsule, plus a public cut of the notes I keep in Obsidian and sync across my machines with Syncthing.</p>
- <p>Plain HTML and CSS. No JavaScript, no tracking &mdash; it reads exactly the same with scripts turned off. That's the point.</p>
- </section>
-
- <section>
- <h2 class="sec">recent posts</h2>
- <p style="margin-top:.9rem;font-size:.9rem;"><a href="weblog/index.html">all posts &rarr;</a></p>
- </section>
-
- <div class="cols">
- <section>
- <h2 class="sec">elsewhere</h2>
- <ul class="links">
- <li><span class="k">email</span><a href="mailto:t@tjp.lol">t@tjp.lol</a></li>
- <li><span class="k">code</span><a href="https://github.com/teepark">github.com/teepark</a></li>
- <li><span class="k">fedi</span><a href="https://tilde.zone/@tjpcc" rel="me">@tjpcc@tilde.zone</a></li>
- <li><span class="k">gemini</span><a href="about/index.html">gemini://…/~tjp</a></li>
- </ul>
- </section>
-
- </div>
- </main>
-
- <footer>
-
- <p>&copy;2026 tjp &middot; content <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless noted &middot; <a href="feed.xml">feed</a></p>
- </footer>
-
-</div>
-</body>
-</html>
-
diff --git a/notes/index.html b/notes/index.html
deleted file mode 100644
index ea988cf..0000000
--- a/notes/index.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Notes — tjp.lol</title>
-<meta name="description" content="A public cut of my Obsidian notes — a small digital garden.">
-<link rel="stylesheet" href="../style.css">
-</head>
-<body>
-<div class="wrap">
-
- <header class="site">
- <h1 class="brand"><a href="../index.html">~tjp<span class="cur"> $_</span></a></h1>
- <nav class="main">
- <a href="../weblog/index.html">weblog</a>
-
- <a href="../projects/index.html">projects</a>
- <a href="../about/index.html">about</a>
- <a href="../feed.xml">feed</a>
- </nav>
- </header>
-
- <main>
- <section class="intro">
- <p>This is a digital garden &mdash; a public slice of the notes I keep in Obsidian. Unlike the <a href="../weblog/index.html">weblog</a>, these aren't essays. They're living pages: some are a paragraph, some are years old, most link to each other. Start anywhere and follow the threads.</p>
- </section>
-
- <section>
- <h2 class="sec">start here</h2>
- </section>
-
- <section>
- <h2 class="sec">all notes</h2>
-
- </section>
- </main>
-
- <footer>
-
- <p>&copy;2026 tjp &middot; content <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless noted &middot; <a href="../feed.xml">feed</a></p>
- </footer>
-
-</div>
-</body>
-</html>
-
diff --git a/projects/index.html b/projects/index.html
deleted file mode 100644
index 6bc0dc5..0000000
--- a/projects/index.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Projects — tjp.lol</title>
-<meta name="description" content="Things tjp has built.">
-<link rel="stylesheet" href="../style.css">
-</head>
-<body>
-<div class="wrap">
-
- <header class="site">
- <h1 class="brand"><a href="../index.html">~tjp<span class="cur"> $_</span></a></h1>
- <nav class="main">
- <a href="../weblog/index.html">weblog</a>
-
- <a href="index.html" aria-current="page">projects</a>
- <a href="../about/index.html">about</a>
- <a href="../feed.xml">feed</a>
- </nav>
- </header>
-
- <main>
- <section class="intro">
- <p>Small things I've built and still maintain. Most live on <a href="https://github.com/teepark">GitHub</a>.</p>
- </section>
-
- <section>
- <h2 class="sec">maintained</h2>
- </section>
-
- <section>
- <h2 class="sec">archived / for fun</h2>
- </section>
- </main>
-
- <footer>
-
- <p>&copy;2026 tjp &middot; content <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless noted &middot; <a href="../feed.xml">feed</a></p>
- </footer>
-
-</div>
-</body>
-</html>
-
diff --git a/weblog/index.html b/weblog/index.html
deleted file mode 100644
index f67da6b..0000000
--- a/weblog/index.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Weblog — tjp.lol</title>
-<meta name="description" content="Weblog posts by tjp.">
-<link rel="stylesheet" href="../style.css">
-<link rel="alternate" type="application/atom+xml" title="tjp.lol" href="../feed.xml">
-</head>
-<body>
-<div class="wrap">
-
- <header class="site">
- <h1 class="brand"><a href="../index.html">~tjp<span class="cur"> $_</span></a></h1>
- <nav class="main">
- <a href="index.html" aria-current="page">weblog</a>
-
- <a href="../projects/index.html">projects</a>
- <a href="../about/index.html">about</a>
- <a href="../feed.xml">feed</a>
- </nav>
- </header>
-
- <main>
- <section class="intro">
- <p>Longer-form writing. Most of these are migrating over from my Gemini capsule, so dates reflect the original posting. <a href="../feed.xml">Subscribe via RSS</a>.</p>
- </section>
-
-
- </main>
-
- <footer>
-
- <p>&copy;2026 tjp &middot; content <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> unless noted &middot; <a href="../feed.xml">feed</a></p>
- </footer>
-
-</div>
-</body>
-</html>
-