# 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.