diff options
Diffstat (limited to '_docs/PROJECT_PLAN.md')
| -rw-r--r-- | _docs/PROJECT_PLAN.md | 245 |
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. |
