You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Models are defined as Python files, not in TOML — see [Content Models](#content-models) below.
63
+
69
64
## Nesting Behavior
70
65
71
66
Collections can nest. Content in a nested collection belongs to all parent collections:
@@ -86,11 +81,34 @@ This gives "NPC extends Character" behavior without explicit inheritance — it
86
81
|`url_pattern`| no | — | URL pattern with `{field}` placeholders |
87
82
|`pages`| no |`true`| Whether to generate pages (requires template + url_pattern) |
88
83
|`nav`| no |`false`| Whether generated pages appear in sidebar nav |
89
-
|`model`| no | — | Name of a model from `[models.*]` config |
84
+
|`model`| no | — | Model name — resolved to a Pydantic BaseModel via cascade (see below) |
85
+
86
+
## Content Models
87
+
88
+
Models are optional Python files containing a Pydantic `BaseModel` subclass. When a collection has `model = "speaker"`, rockgarden looks for a `Speaker` class using this cascade (first match wins):
Class name is the title-cased filename (`speaker.py` → `Speaker`).
94
+
95
+
Example:
96
+
97
+
```python
98
+
# _models/speaker.py
99
+
from pydantic import BaseModel
100
+
101
+
classSpeaker(BaseModel):
102
+
name: str
103
+
bio: str=""
104
+
photo: str|None=None
105
+
```
106
+
107
+
Without a model, collection entries are plain dicts. With a model, entries are validated and coerced on load — missing required fields produce a build error.
90
108
91
109
## Data Layer
92
110
93
-
The `ContentStore` stays in-memory (Python dicts/dataclasses) and becomes collection-aware. No external database required.
111
+
The `ContentStore` stays in-memory and becomes collection-aware. No external database required.
94
112
95
113
```python
96
114
store.list_content() # default collection
@@ -113,22 +131,26 @@ For hook scripts that need access to collected data, content is exported to JSON
A `resolve_model(name, config, theme_dir)` function that walks the cascade and returns the Pydantic BaseModel class (or `None` if no model file is found).
152
+
153
+
### 3. Collection-Aware ContentStore
132
154
133
155
Extend `ContentStore` to track collection membership. Without config, all content is in the default collection. Named collections carve out subsets.
134
156
@@ -142,28 +164,28 @@ class ContentStore:
142
164
"""Export all collections to JSON for hook scripts."""
143
165
```
144
166
145
-
### 3. Collection Loader
167
+
### 4. Collection Loader
146
168
147
169
Load files from collection source directories. Supported formats:
148
170
-`.yaml` / `.yml` — parsed as dict of fields
149
171
-`.json` — parsed as dict of fields
150
172
-`.toml` — parsed as dict of fields
151
173
-`.md` — frontmatter as fields, body rendered as HTML and available as `content`
152
174
153
-
Each entry gets a `slug` derived from filename (or overridden by a `slug` field).
175
+
Each entry gets a `slug` derived from filename (or overridden by a `slug` field). If a model is configured, entries are validated through it on load.
154
176
155
-
### 4. Template Context
177
+
### 5. Template Context
156
178
157
-
All collections available in every template as `collections.<name>` (list of dicts). Jinja2's built-in filters handle querying.
179
+
All collections available in every template as `collections.<name>` (list of dicts or model instances serialized to dict). Jinja2's built-in filters handle querying.
158
180
159
-
### 5. Page Generation
181
+
### 6. Page Generation
160
182
161
183
For collections with `pages = true` and a `template` + `url_pattern`:
162
184
- Generate one page per entry
163
185
- URL from `url_pattern` with `{field}` replaced by entry fields
164
186
- Render using specified template with entry data in context
165
187
166
-
### 6. Nav Integration
188
+
### 7. Nav Integration
167
189
168
190
For collections with `nav = true`:
169
191
- Add generated pages to nav tree
@@ -172,13 +194,14 @@ For collections with `nav = true`:
172
194
## Key Files to Create/Modify
173
195
174
196
-`content/store.py` — Extend with collection awareness and JSON export
175
-
-`content/collection.py` — New module: collection loading, format parsing
Copy file name to clipboardExpand all lines: plans/future.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,6 +20,8 @@ Noted but not currently planned:
20
20
-**Configurable reserved directory names**: The special directories `_templates/`, `_themes/`, and `_static/` (output) are currently hardcoded. These should be configurable via `[build]` config with the current names as documented defaults. Useful for sites where those names conflict with content. (`_site` output is already configurable via `[site] output`.)
21
21
-**Extract icon handling**: Move icon resolution (`rockgarden.icons`) into a standalone generic Jinja icons package. Current implementation is bordering on out-of-scope for a static site generator.
22
22
23
+
-**Theme manifest collection defaults**: A `theme.toml` in a theme directory that declares per-collection defaults (`template`, `url_pattern`, `model`). Sites using the theme would only need to provide `source` in their `[[collections]]` config. Deferred from Phase 2 — currently sites must declare all collection fields explicitly, and themes provide model classes via `_themes/<name>/_models/` cascade.
24
+
23
25
Moved to roadmap:
24
26
-~~Content from other data sources~~ → Feature 14 (Collections) + Feature 15 (Build Hooks)
0 commit comments