summaryrefslogtreecommitdiff
path: root/_docs/PROJECT_PLAN.md
blob: 5a8abecdea1bc236c18369a9c7d9061bf80c6584 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
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.