summaryrefslogtreecommitdiff
path: root/_docs
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-07-11 11:42:23 -0600
committert <t@tjp.lol>2026-07-11 11:43:04 -0600
commit5943b3063676d68381545e36a9903e1df278e923 (patch)
tree07fc2abc28182202c5cec0cc79b5a0531ae3e616 /_docs
initial commit: claude-designed site and project doc to staticly generate it going forward
Diffstat (limited to '_docs')
-rw-r--r--_docs/PROJECT_PLAN.md245
1 files changed, 245 insertions, 0 deletions
diff --git a/_docs/PROJECT_PLAN.md b/_docs/PROJECT_PLAN.md
new file mode 100644
index 0000000..5a8abec
--- /dev/null
+++ b/_docs/PROJECT_PLAN.md
@@ -0,0 +1,245 @@
+# tjp.lol project plan
+
+## Goals
+
+- Preserve the existing visual design and `style.css` unchanged.
+- Replace duplicated HTML with a small Go static-site generator.
+- Make Markdown the source format for public content.
+- Support public Obsidian notes without nonstandard Obsidian syntax.
+- Publish an Atom feed at `feed.xml`.
+- Remove fictional public content without replacing it with AI-written prose.
+- Keep all published post prose human-written; disclose AI coding/refactoring assistance in the colophon.
+
+## Content and placeholder cleanup
+
+- Prefix retained fictional example files with `_`.
+ - They remain repository references only.
+ - The generator does not scan, render, list, or otherwise expose underscore-prefixed files.
+ - An underscore-prefixed directory excludes its complete subtree, enabling `_private/` in the vault.
+- Remove links to fictional weblog posts, notes, projects, tags, and feed entries.
+- Remove tags everywhere; there is no tag system.
+- Comment out:
+ - Notes navigation in the shared header.
+ - Homepage “from the notes.”
+ - Webring markup in the shared footer.
+- Keep Notes hidden until real vault content is publishing successfully.
+- Replace the fake feed with a valid, initially empty Atom feed rather than invented entries.
+- During migration, enumerate every existing prose location for manual rewrite:
+ - page body copy;
+ - titles and descriptions;
+ - feed title/subtitle text;
+ - project descriptions;
+ - link labels where applicable;
+ - colophon text;
+ - placeholder entries and summaries.
+- Do not generate replacement prose.
+
+## Licence and colophon
+
+- Site content is licensed **CC BY 4.0 unless noted**.
+- Put a consistent content-licence notice in the shared footer, linking directly to Creative Commons.
+- Use the colophon to explain the default licence and exceptions.
+- No separate prose `LICENSE` file or registration is required.
+- Generator code may receive a separate OSS licence later.
+- Replace outdated colophon claims about hand-written HTML and having no build step.
+- Retain the no-JavaScript claim if it remains true.
+- The human-written colophon should state that AI may be used for coding and batch refactoring, but not to generate published post prose.
+
+## Generator
+
+### Implementation
+
+- A Go command-line binary.
+- Use a maintained CommonMark parser with familiar GFM extensions.
+- Disable raw HTML in Markdown.
+- Use Go template syntax:
+ - `html/template` for HTML outputs;
+ - XML-safe rendering for Atom output.
+- Follow the `sw-convert` model: load a named set of reusable templates/partials, rather than serving literal header/footer files.
+
+### Source and output rules
+
+- Run recursively from one defined site root.
+- Markdown conversion is in place:
+
+ ```text
+ path/page.md → path/page.html
+ ```
+
+- Page-output templates use explicit destination extensions:
+
+ ```text
+ index.html.tmpl → index.html
+ feed.xml.tmpl → feed.xml
+ ```
+
+- Reject collisions, such as both `index.md` and `index.html.tmpl` targeting `index.html`.
+- Static assets such as `style.css` are untouched.
+- Markdown sources may remain downloadable.
+- Template sources should not be publicly served.
+
+### Template structure
+
+- Markdown pages use path-based site layouts rather than requiring layout frontmatter:
+ - weblog pages receive the existing post structure/classes;
+ - notes receive the existing note structure/classes;
+ - ordinary pages receive a general page layout.
+- Complex pages such as the homepage, weblog index, notes index, and feed can be written directly as templates.
+- Templates receive helpers for relative paths, sorting, filtering, slicing, and joining rendered sections.
+- Header/footer templates calculate correct relative links such as `../style.css`, preserving portable relative URLs.
+
+## Markdown parsing and page model
+
+### Links
+
+Rewrite only site-local Markdown link destinations:
+
+```text
+[example](other.md) → [example](other.html)
+[example](other.md#part) → [example](other.html#part)
+```
+
+Leave external URLs, mail links, fragments, asset links, and code blocks unchanged.
+
+### Titles and sections
+
+- The first H1 supplies the title for ordinary Markdown pages.
+- The title is used for document metadata, page headings, listings, and Atom entry titles.
+- The extracted H1 is not duplicated in rendered body content.
+- Title fallback order:
+
+ 1. first H1;
+ 2. optional frontmatter title where unavoidable;
+ 3. filename-derived fallback with a build warning.
+
+- Parsed Markdown body is exposed as rendered top-level sections:
+
+ ```go
+ Sections []template.HTML
+ ```
+
+- This is the primary content abstraction; no separate `Lede` field is needed.
+- Weblog convention: the first section after the opening H1 should be a short paragraph. The weblog layout renders that first section in a wrapper with inline `font-size:1.2em`, then renders the remainder normally.
+- Notes and ordinary pages do not receive special lede treatment.
+
+### Metadata
+
+- YAML frontmatter is supported and exposed as `.Meta`.
+- Frontmatter is optional except where genuine metadata is needed.
+- Weblog posts use `post_date` for chronological listings and Atom dates.
+- An optional updated date may override the original post date.
+- Notes can sort by source file modification time.
+
+## Page inventory and indexes
+
+Before rendering anything:
+
+1. Discover all eligible Markdown and page-template sources.
+2. Parse frontmatter and Markdown.
+3. Derive page paths, titles, metadata, source modification times, and rendered sections.
+4. Build the complete page inventory.
+5. Render all HTML pages and `feed.xml`.
+
+The template data includes:
+
+```go
+Pages map[string][]*Page
+```
+
+Each `*Page` is inserted into every ancestor directory collection. For example:
+
+```text
+notes/recipes/cocktails/old_fashioned.md
+```
+
+is available through:
+
+```text
+Pages["notes"]
+Pages["notes/recipes"]
+Pages["notes/recipes/cocktails"]
+```
+
+All entries point to the same `Page` object, which carries path information, metadata, title, modification time, and rendered sections.
+
+Templates can therefore build lists without special generator features:
+
+- weblog index: weblog pages sorted by `Meta.post_date`;
+- homepage: recent posts;
+- notes index: notes sorted by modification time;
+- future manually authored “good starting points” sections.
+
+Only real pages enter these collections. Underscore-prefixed files, directories, and non-page outputs such as `feed.xml` do not.
+
+## Feed
+
+- Retain Atom 1.0 at `feed.xml`.
+- Label the navigation link “feed.”
+- Include weblog posts only.
+- Sort by post date.
+- Emit full rendered post content in each entry.
+- Use absolute canonical URLs under `https://tjp.lol/`.
+- Emit a valid zero-entry feed until real posts exist.
+
+## Syncthing and notes
+
+- Generated HTML remains beside Markdown on the server.
+- Prevent generated HTML from syncing through the vault with Syncthing ignore rules.
+
+Each device has a local, non-synced `.stignore`:
+
+```text
+#include .stignore.shared
+```
+
+The synchronized `.stignore.shared` contains:
+
+```text
+*.html
+```
+
+This prevents HTML synchronization in either direction at every depth while allowing Markdown synchronization.
+
+Notes rollout:
+
+1. Comment out Notes links and homepage note links.
+2. Connect the synced vault to the site source tree and build note HTML.
+3. Validate generated note pages and privacy behavior.
+4. Restore Notes navigation only when public notes are ready.
+
+## Caddy follow-up
+
+Not part of the generator implementation, but record a server task:
+
+- Deny requests for any path containing an underscore-prefixed component.
+- Deny template-source requests such as `*.tmpl`.
+- This ensures `_private/` Markdown and internal template files cannot be downloaded even though Markdown is otherwise publicly available.
+
+## Reliability and validation
+
+- Do not overwrite non-generated HTML.
+- Track generated outputs so deleted/renamed Markdown does not leave accidental stale public pages; cleanup must only remove tracked generated files.
+- Write output safely so a failed build preserves existing pages.
+- Cron execution should use a lock, log failures, and run after Syncthing has had time to settle.
+- Add tests for:
+ - Markdown/GFM conversion and raw-HTML rejection;
+ - local-link rewriting;
+ - underscore exclusions;
+ - output collisions;
+ - title/section extraction;
+ - recursive page inventory;
+ - relative-path generation;
+ - Atom validity and full-content entries.
+- Validate internal links and feed XML before deployment.
+
+## Delivery sequence
+
+1. Archive fictional examples under underscore-prefixed names and remove public references.
+2. Establish source conventions, templates, and generator tests.
+3. Implement parsing, page inventory, Markdown rendering, relative links, and output writing.
+4. Migrate current HTML structure into Markdown and `.html.tmpl` sources.
+5. Audit all inherited prose for manual replacement.
+6. Generate the Atom feed and validate the public site.
+7. Configure Syncthing ignores and Caddy protection.
+8. Connect and publish the selected notes vault content.
+9. Restore Notes links when the published notes are real and ready.