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
Copy file name to clipboardExpand all lines: build/render_hook_docs/AI_RENDER_HOOK_LESSONS.md
+185Lines changed: 185 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -409,23 +409,208 @@ if ((metaValue.startsWith('"') && metaValue.endsWith('"'))) {
409
409
410
410
---
411
411
412
+
## 21. Server-Side Metadata Extraction for AI Agents
413
+
414
+
**Pattern**: Extract metadata from structured content (YAML, JSON) in the Hugo render hook and embed it as JSON in the HTML output for AI agents that don't execute JavaScript.
415
+
416
+
**Implementation**:
417
+
```html
418
+
{{- /* Extract top-level fields only (no indentation) */ -}}
419
+
{{- $lines := split .Inner "\n" -}}
420
+
{{- $id := "" -}}
421
+
{{- range $lines -}}
422
+
{{- /* Check if line starts without whitespace (32=space, 9=tab) */ -}}
423
+
{{- if and (gt (len .) 0) (ne (index . 0) 32) (ne (index . 0) 9) -}}
-**Indentation detection**: When parsing nested structures, only extract top-level fields by checking if the line starts with whitespace
440
+
-**String manipulation**: Use `strings.Replace` instead of `strings.TrimPrefix` for more reliable extraction
441
+
-**Character codes**: Use ASCII codes (32 for space, 9 for tab) to detect indentation reliably
442
+
-**Metadata format**: Use simple JSON (not JSON-LD) for clarity and ease of parsing
443
+
-**Data attributes**: Use `data-*` attributes to mark metadata elements for AI agents
444
+
445
+
**Why This Matters**:
446
+
- AI agents typically don't execute JavaScript, so metadata must be in static HTML
447
+
- Server-side extraction ensures metadata is available even if JavaScript fails
448
+
- Structured metadata helps AI agents understand the purpose and scope of components
449
+
- Separating metadata from content improves maintainability
450
+
451
+
**Lesson**: Always provide metadata in static HTML for AI agents. Use server-side extraction to ensure accuracy and avoid relying on JavaScript parsing.
452
+
453
+
---
454
+
455
+
## 22. Handling Nested Structures in Hugo Templates
456
+
457
+
**Pattern**: When extracting data from nested YAML/JSON structures, distinguish between top-level and nested fields using indentation detection.
458
+
459
+
**Problem**: If you extract all occurrences of a field (e.g., `id:`), you'll get nested occurrences too, leading to incorrect values.
460
+
461
+
**Solution**: Check indentation before processing:
462
+
```html
463
+
{{- if and (gt (len .) 0) (ne (index . 0) 32) (ne (index . 0) 9) -}}
464
+
{{- /* Process only top-level lines */ -}}
465
+
{{- end -}}
466
+
```
467
+
468
+
**Why This Works**:
469
+
- YAML indentation is significant and indicates nesting level
470
+
- Top-level fields have no leading whitespace
471
+
- Nested fields have leading spaces or tabs
472
+
- Character code 32 = space, 9 = tab
473
+
474
+
**Lesson**: When parsing nested structures in Hugo templates, use indentation detection to distinguish between levels. This prevents extracting nested values when you only want top-level ones.
475
+
476
+
---
477
+
478
+
## 23. Progressive Enhancement with Metadata
479
+
480
+
**Pattern**: Combine progressive enhancement with metadata embedding to serve both humans and AI agents from a single source.
481
+
482
+
**Architecture**:
483
+
1.**Server-side (Hugo)**:
484
+
- Extract metadata from source content
485
+
- Embed metadata as JSON in HTML
486
+
- Preserve raw source in `<pre>` element
487
+
488
+
2.**Client-side (JavaScript)**:
489
+
- Parse raw source for rendering
490
+
- Use metadata for context/identification
491
+
- Enhance with interactivity
492
+
493
+
3.**AI agents**:
494
+
- Read static JSON metadata
495
+
- Parse raw source from `<pre>` element
496
+
- No JavaScript execution needed
497
+
498
+
**Benefits**:
499
+
- Single source of truth (the YAML/JSON in the Markdown)
500
+
- Metadata available to all consumers (humans, AI agents, JavaScript)
501
+
- Graceful degradation if JavaScript fails
502
+
- AI-friendly without extra work
503
+
504
+
**Lesson**: Design render hooks to serve multiple audiences simultaneously. Metadata should be available in static HTML, not just in JavaScript.
505
+
506
+
---
507
+
508
+
## 24. Text Wrapping and Box Sizing in SVG Diagrams
509
+
510
+
**Pattern**: When rendering text in SVG boxes, calculate dimensions based on character width and implement text wrapping to fit within maximum width.
**Lesson**: Calculate SVG dimensions dynamically based on content. Account for all visual elements (padding, margins, decorations) when sizing boxes and containers.
548
+
549
+
---
550
+
551
+
## 25. Scope and Context Metadata for Component Discovery
552
+
553
+
**Pattern**: Add `scope` or `category` metadata to components to help AI agents understand their purpose and applicability.
554
+
555
+
**Implementation**:
556
+
```yaml
557
+
id: documents-tree
558
+
scope: documents
559
+
rootQuestion: root
560
+
questions:
561
+
# ...
562
+
```
563
+
564
+
**Benefits**:
565
+
-**Discoverability**: AI agents can filter components by scope
566
+
-**Context awareness**: Agents know which problem domain each component addresses
567
+
-**Prevents misapplication**: Agents won't use a "collections" tree to recommend document storage
568
+
-**Relationship mapping**: Enables linking related components
569
+
570
+
**Use Cases**:
571
+
- Filtering decision trees by data type category
572
+
- Finding all components related to a specific feature
573
+
- Organizing components hierarchically
574
+
- Providing context in search results
575
+
576
+
**Lesson**: Add semantic metadata (scope, category, type) to components. This helps AI agents understand purpose and applicability, enabling better recommendations and filtering.
577
+
578
+
---
579
+
412
580
## Quick Checklist for Future Render Hooks
413
581
582
+
### Core Patterns
414
583
-[ ] Preserve source content in a `<pre>` or similar element
415
584
-[ ] Use page store pattern to avoid duplicate resource loading
416
585
-[ ] Place static JavaScript in `static/js/`, not `assets/js/`
417
586
-[ ] Avoid `innerHTML` with dynamic content; use safe DOM methods
418
587
-[ ] Use `data-*` attributes to pass server data to JavaScript
588
+
589
+
### Testing & Accessibility
419
590
-[ ] Test with multiple instances on the same page
420
591
-[ ] Consider state persistence if needed
421
592
-[ ] Use semantic HTML and proper accessibility attributes
422
593
-[ ] Document the Markdown format clearly
423
594
-[ ] Provide sensible defaults for optional parameters
595
+
596
+
### Hugo-Specific
424
597
-[ ] Remember Hugo converts attribute names to lowercase
598
+
-[ ] Use indentation detection when parsing nested structures
599
+
-[ ] Extract top-level metadata in render hook (not JavaScript)
600
+
-[ ] Use `strings.Replace` for reliable string manipulation in templates
601
+
602
+
### Advanced Features
425
603
-[ ] Use SVG for complex visual structures
426
604
-[ ] Track processed lines when parsing nested structures
427
605
-[ ] Account for all visual elements in dimension calculations
428
606
-[ ] Use type attributes for conditional features
429
607
-[ ] Handle string unescaping during parsing, not rendering
430
608
-[ ] Create comprehensive format documentation
431
609
610
+
### AI Agent Compatibility
611
+
-[ ] Embed metadata as JSON in static HTML (not just JavaScript)
612
+
-[ ] Add `scope` or `category` metadata for component discovery
613
+
-[ ] Use `data-*` attributes to mark metadata elements
614
+
-[ ] Ensure metadata is available without JavaScript execution
Decision trees are structured YAML documents that guide users through a series of questions to reach a recommendation. They are rendered as interactive SVG diagrams with boxes, connecting lines, and Yes/No branch labels.
6
+
7
+
## Basic Structure
8
+
9
+
```yaml
10
+
```decision-tree {id="documents-tree"}
11
+
id: documents-tree
12
+
scope: documents
13
+
rootQuestion: root
14
+
questions:
15
+
root:
16
+
text: "Your question here?"
17
+
whyAsk: "Explanation of why this question matters"
18
+
answers:
19
+
yes:
20
+
value: "Yes"
21
+
outcome:
22
+
label: "Recommendation"
23
+
id: outcomeId
24
+
no:
25
+
value: "No"
26
+
nextQuestion: nextQuestionId
27
+
nextQuestionId:
28
+
text: "Follow-up question?"
29
+
whyAsk: "Why this matters"
30
+
answers:
31
+
yes:
32
+
value: "Yes"
33
+
outcome:
34
+
label: "Recommendation"
35
+
id: outcomeId
36
+
no:
37
+
value: "No"
38
+
outcome:
39
+
label: "Alternative recommendation"
40
+
id: altOutcomeId
41
+
```
42
+
```
43
+
44
+
## Fields
45
+
46
+
### Top-level
47
+
48
+
-**`id`** (required): Unique identifier for this decision tree (e.g., `documents-tree`, `collections-tree`). Used for discovery and referencing by AI agents.
49
+
-**`scope`** (required): Category or domain this tree applies to (e.g., `documents`, `collections`, `sequences`). Helps AI agents understand the tree's purpose and applicability.
50
+
-**`rootQuestion`** (required): The ID of the starting question
51
+
-**`questions`** (required): Object containing all questions, keyed by ID
52
+
53
+
### Question Object
54
+
55
+
-**`text`** (required): The question text. Can span multiple lines using YAML's `|` literal block syntax
56
+
-**`whyAsk`** (required): Explanation of why this question matters. Helps AI agents understand the decision logic
57
+
-**`answers`** (required): Object with `yes` and `no` keys
58
+
59
+
### Answer Object
60
+
61
+
Each answer (`yes` or `no`) contains:
62
+
63
+
-**`value`** (required): Display text ("Yes" or "No")
Use YAML's literal block syntax (`|`) for multi-line text:
79
+
80
+
```yaml
81
+
text: |
82
+
Do you need nested data structures
83
+
(fields and arrays) or geospatial
84
+
index/query with Redis query engine?
85
+
whyAsk: |
86
+
JSON is the only document type that supports
87
+
deeply nested structures and integrates with
88
+
the query engine for those structures
89
+
```
90
+
91
+
## Code Block Attributes
92
+
93
+
The code block fence supports the following attributes:
94
+
95
+
- **`id`** (optional): Unique identifier for the tree. Should match the `id` field in the YAML. Used by Hugo to pass metadata to the render hook.
96
+
97
+
Example:
98
+
```markdown
99
+
```decision-tree {id="documents-tree"}
100
+
id: documents-tree
101
+
scope: documents
102
+
# ...
103
+
```
104
+
```
105
+
106
+
## Best Practices
107
+
108
+
1. **Use descriptive IDs**: `root`, `hashQuestion`, `jsonOutcome` are clearer than `q1`, `q2`
109
+
2. **Keep questions concise**: Aim for 1-2 lines when possible
110
+
3. **Explain the rationale**: The `whyAsk` field helps users and AI agents understand the decision logic
111
+
4. **Reuse outcomes**: Multiple paths can lead to the same outcome (same `id`)
112
+
5. **Consistent naming**: Use camelCase for IDs, end question IDs with "Question"
113
+
6. **Match fence and YAML IDs**: The `id` in the code block fence should match the `id` field in the YAML for consistency
114
+
7. **Use meaningful scopes**: Choose scope values that clearly indicate the tree's domain (e.g., `documents`, `collections`, `sequences`)
115
+
116
+
## Example: Redis Data Type Selection
117
+
118
+
See `content/develop/data-types/compare-data-types.md` for a complete example.
119
+
120
+
## Rendering
121
+
122
+
Decision trees are rendered as:
123
+
- **SVG diagram** for humans (with boxes, lines, and labels)
124
+
- **Normalized JSON** embedded for AI agents (accessible via `.html.md` URLs)
125
+
- **Raw YAML** preserved in `<pre>` element for accessibility
126
+
127
+
## AI Agent Compatibility
128
+
129
+
The format is designed to be easily parseable by AI agents:
130
+
131
+
### Metadata Embedding
132
+
- **Server-side JSON**: Each tree is embedded with metadata as `<script type="application/json" data-redis-metadata="decision-tree">` containing `id`, `scope`, and `type` fields
133
+
- **No JavaScript required**: Metadata is available in static HTML, accessible to AI agents that don't execute JavaScript
134
+
- **Discoverable**: The `id` and `scope` fields enable AI agents to identify and filter trees
135
+
136
+
### Content Accessibility
137
+
- **Raw YAML preserved**: The original YAML source is preserved in a `<pre class="decision-tree-source">` element for AI parsing
138
+
- **Clear hierarchical structure**: Explicit question IDs and outcome IDs
139
+
- **Reasoning context**: `whyAsk` field explains the decision logic
140
+
- **Normalized JSON**: Available for deterministic processing
141
+
142
+
### Example Metadata
143
+
```json
144
+
{
145
+
"type": "decision-tree",
146
+
"id": "documents-tree",
147
+
"scope": "documents"
148
+
}
149
+
```
150
+
151
+
This metadata helps AI agents:
152
+
- Identify the tree's purpose and domain
153
+
- Filter trees by scope
154
+
- Reference specific trees in recommendations
155
+
- Understand the tree's applicability to different problems
0 commit comments