bim 0.1.0

A content-first static site generator for blogs, digital gardens, and knowledge bases
Documentation
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# Rust Static Site Generator – System Design

## 1. Philosophy

This static site generator (SSG) is a **content-first, convention-over-configuration** system written in Rust. It intentionally avoids front matter, template DSLs, and external tooling dependencies, favoring:

- Markdown as the primary authoring format
- Filesystem structure as the source of truth
- Rust libraries for all processing
- Lenient behavior with warnings instead of hard errors

The system is designed to support **blogs, digital gardens, code snippets, recipes, talks, and slides** in a single coherent knowledge base.

---

## 2. Repository Layout

All content lives at the **root of the repository**.

```
/
  index.md
  nav.md
  blog/
  notes/
  snippets/
  talks/
  projects/
  recipes/
  slides/
  tags/
  contexts/
  images/
  static/
  layouts/
```

### Ignored Files and Directories

- All **dot-prefixed files and directories** (e.g. `.git`, `.obsidian`, `.DS_Store`) are ignored
- **Exception:** dot-prefixed files inside `static/` are copied and served normally
- Build output directory is ignored

---

## 3. Collections

Each top-level directory represents a **collection** with defined behavior.

| Collection | URL Base | Structure | Notes |
|-----------|---------|----------|------|
| blog | `/blog/` | flat | date-sorted, RSS |
| notes | `/notes/` | hierarchical | digital garden |
| snippets | `/snippets/` | flat | code-first |
| talks | `/talks/` | flat | |
| projects | `/projects/` | flat | |
| recipes | `/recipes/` | flat | |
| slides | `/slides/` | flat | reveal.js, no backlinks |

“Flat” means directories are allowed in source but ignored in output URLs.

---

## 4. Markdown Content Model

### 4.1 Markdown Flavor

- CommonMark + useful extensions
- Tables, footnotes, strikethrough
- Automatic heading IDs

### 4.2 Title

- First level-1 heading (`# Title`)
- Fallback: filename

### 4.3 Dates

Determined in priority order:
1. Filename prefix (`YYYY-MM-DD-`)
2. Git last-modified time
3. File modification time

### 4.4 Drafts

A page is a draft if:
- Filename starts with `_`
- Or it is inside a `_drafts/` directory

Drafts are excluded unless `--drafts` is enabled.

---

## 5. Index Page and Directives

### 5.1 Root Index

`index.md` renders to `/`.

It may contain **directives** controlling generated lists:

```
{{recent blog 5}}
{{recent notes 8}}
```

Directives are parsed and replaced during rendering.

---

## 6. Navigation

### 6.1 nav.md

Navigation is defined in `nav.md` at the repository root.

Example:

```
- [Home]/
- [Blog]/blog/
- [Notes]/notes/
- [Recipes]/recipes/
```

Only Markdown lists are parsed. Order is preserved.

---

## 7. Notes as a Digital Garden

Notes support **hierarchical structure** and directory indexes.

```
notes/
  linux/
    index.md
    networking.md
```

Behavior:
- If a directory contains `index.md`, it is rendered
- Otherwise, an index is auto-generated
- Index pages list subdirectories and pages

Notes fully participate in backlinks.

---

## 8. Code Snippets

### 8.1 Source Format

Snippets are **code files**, not Markdown.

```
snippets/
  rust/vec_dedup.rs
  bash/find_large_files.sh
```

### 8.2 Rendering

- Language inferred from file extension
- Highlighted using `syntect`
- Rendered inside a page layout
- Filename becomes title

### 8.3 URLs

```
/snippets/vec-dedup/
```

Directories are organizational only.

Snippets support backlinks.

---

## 9. Tags and Contexts

### 9.1 Inline Syntax

In Markdown text:

- Tags: `[#rust systems programming]`
- Contexts: `[@linux networking]`

These generate links to:

```
/tags/rust-systems-programming/
/contexts/linux-networking/
```

### 9.2 Markdown Pages

Tags and contexts may have their own Markdown pages:

```
tags/rust.md
contexts/linux.md
```

If present:
- Rendered first
- Followed by auto-generated listing

---

## 10. Backlinks

Backlinks are computed globally for all pages **except slides**.

A backlink exists when:
- Page A links to Page B
- The link is internal

Rendered at the bottom of pages as a list.

---

## 11. Language Detection and RTL

- Content language detected using `whatlang`
- Applied to `<html lang="…">`
- Arabic → `dir="rtl"`

RTL is handled via layout and CSS.

---

## 12. Git Integration

- Implemented using the `git2` crate
- No external git commands
- If repository is not a git repo:
  - Last-modified metadata is omitted

---

## 13. Images

### 13.1 Source and Output

```
images/        →  /images/
```

### 13.2 Processing

Images are processed using Rust libraries:

- Load image
- Strip EXIF metadata
- Resize to maximum dimensions
- Re-encode to target format/quality

Defaults apply if no configuration is provided.

Markdown image links point directly to `/images/...`.

---

## 14. Static Files

```
static/  →  /
```

- Static files are copied verbatim to output root
- Dot-prefixed files inside `static/` are included

---

## 15. Layouts

### 15.1 Directory

```
layouts/
  default.html
  blog.html
  notes.html
  slides.html
```

### 15.2 Selection Rules

1. Layout matching collection name
2. Fallback to `default.html`

### 15.3 Placeholders

Layouts support a fixed set of placeholders:

- `{{title}}`
- `{{content}}`
- `{{nav}}`
- `{{backlinks}}`
- `{{last_modified}}`
- `{{lang}}`
- `{{dir}}`

Layouts contain no logic.

---

## 16. Command-Line Interface (CLI)

The SSG exposes a small, explicit CLI focused on local workflows. All commands operate relative to the repository root.

### 16.1 `build`

```
ssg build [options]
```

Performs a one-shot build of the site.

Behavior:
- Discovers and processes all content
- Processes images
- Generates HTML, RSS, and sitemap
- Writes output to the build directory

Options:
- `--drafts` : include draft content
- `--output <dir>` : override output directory (default: `dist/`)
- `--clean` : remove output directory before building

---

### 16.2 `watch`

```
ssg watch [options]
```

Continuously watches the repository for changes and rebuilds affected content.

Behavior:
- Performs an initial build
- Watches filesystem changes (excluding ignored paths)
- Incrementally rebuilds changed pages

Options:
- `--drafts`
- `--output <dir>`

---

### 16.3 `serve`

```
ssg serve [options]
```

Builds the site and serves it locally via an HTTP server.

Behavior:
- Runs a full build
- Starts a local HTTP server rooted at the output directory
- Intended for development and preview

Options:
- `--port <port>` (default: `3000`)
- `--host <addr>` (default: `127.0.0.1`)
- `--drafts`
- `--watch` : rebuild on changes while serving

---

### 16.4 `prep-images`

```
ssg prep-images [options]
```

Preprocesses images without building the site.

Behavior:
- Loads images from `images/`
- Strips EXIF metadata
- Resizes images to configured maximum dimensions
- Writes processed images to the output `/images/` directory

Options:
- `--force` : reprocess all images, ignoring cache
- `--output <dir>` : override output directory

This command exists to support image-only workflows and CI pipelines.


---

## 17. Rendering Pipeline

1. Discover content
2. Filter ignored dot-prefixed files
3. Load git metadata
4. Process images
5. Parse Markdown and code
6. Extract links, tags, contexts
7. Build backlink graph
8. Render pages
9. Emit static files
10. Generate RSS and sitemap

---

## 18. Output Characteristics

- Pretty URLs (`/path/index.html`)
- Lenient parsing with warnings
- Deterministic output
- No front matter
- No template DSL

---

## 19. Summary

This system is a **Rust-native static knowledge engine**:

- Blog + digital garden + code notebook
- Strong internal linking via backlinks, tags, and contexts
- Image processing built into the pipeline
- Minimal authoring friction
- Maximum structural clarity

It is designed to scale from personal notes to a long-lived public knowledge base without sacrificing simplicity.