multisite-cms-mcp 1.2.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,325 +2,141 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSchema = getSchema;
4
4
  /**
5
- * Returns the complete CMS schema with all built-in and custom collections
5
+ * Returns the complete CMS schema reference for custom collections
6
6
  */
7
7
  async function getSchema() {
8
8
  return `# CMS Schema Reference
9
9
 
10
- ## Built-in Collections
11
-
12
- ### Blog Posts (\`blogs\`)
13
- Time-stamped articles with optional author reference.
14
-
15
- **Fields:**
16
- - \`{{name}}\` (text, required) - Post title
17
- - \`{{slug}}\` (text, required) - URL slug
18
- - \`{{mainImage}}\` (image) - Hero/cover image URL
19
- - \`{{thumbnailImage}}\` (image) - Smaller preview image
20
- - \`{{postSummary}}\` (text) - Short excerpt/description
21
- - \`{{{postBody}}}\` (richText) - Main content (MUST use triple braces)
22
- - \`{{featured}}\` (boolean) - Featured flag
23
- - \`{{url}}\` (special) - Generated URL to post detail page
24
-
25
- **Date tokens (automatically tracked):**
26
- - \`{{createdAt}}\` - When the post was first created
27
- - \`{{publishedAt}}\` - When the post was published (empty for drafts)
28
- - \`{{updatedAt}}\` - When the post was last updated
29
-
30
- **Author Reference (when assigned):**
31
- - \`{{author.name}}\` - Author's name
32
- - \`{{author.picture}}\` - Author's photo URL
33
- - \`{{{author.bio}}}\` (richText) - Author's biography
34
- - \`{{author.email}}\` - Author's email
35
- - \`{{author.twitterProfileLink}}\` - Twitter URL
36
- - \`{{author.linkedinProfileLink}}\` - LinkedIn URL
37
- - \`{{author.url}}\` - Link to author's page
38
-
39
- **Loop syntax:** \`{{#each blogs}}\` or \`{{#each blogs featured=true limit=3}}\`
10
+ ## Collections Overview
40
11
 
41
- ---
42
-
43
- ### Authors (\`authors\`)
44
- Content creators who can be referenced by blog posts.
45
-
46
- **Fields:**
47
- - \`{{name}}\` (text, required) - Author's name
48
- - \`{{slug}}\` (text, required) - URL slug
49
- - \`{{{bio}}}\` (richText) - Biography (MUST use triple braces)
50
- - \`{{picture}}\` (image) - Author photo URL
51
- - \`{{email}}\` (email) - Email address
52
- - \`{{twitterProfileLink}}\` (url) - Twitter URL
53
- - \`{{linkedinProfileLink}}\` (url) - LinkedIn URL
54
- - \`{{url}}\` (special) - Generated URL to author detail page
12
+ All CMS content is managed through **custom collections**. Collections are content types you define (e.g., Blog Posts, Team Members, Services, Products) with custom fields.
55
13
 
56
- **Loop syntax:** \`{{#each authors}}\`
14
+ **To see the exact collections and fields for a specific project, use the \`get_tenant_schema\` tool.**
57
15
 
58
16
  ---
59
17
 
60
- ### Team Members (\`team\`)
61
- Staff, employees, leadership profiles.
18
+ ## Collection Templates
62
19
 
63
- **Fields:**
64
- - \`{{name}}\` (text, required) - Team member's name
65
- - \`{{slug}}\` (text) - URL slug (if using detail pages)
66
- - \`{{role}}\` (text) - Job title/role
67
- - \`{{{bio}}}\` (richText) - Biography (MUST use triple braces)
68
- - \`{{photo}}\` (image) - Headshot/photo URL
69
- - \`{{email}}\` (email) - Email address
70
- - \`{{order}}\` (number) - Display order
71
-
72
- **Loop syntax:** \`{{#each team sort="order" order="asc"}}\`
73
-
74
- ---
20
+ When creating a new collection, you can start from a **template** that pre-configures common field sets:
75
21
 
76
- ### Downloads (\`downloads\`)
77
- Downloadable files and documents.
22
+ - **Blog Posts** - Articles with images, summary, body, author reference
23
+ - **Authors** - Content creators with bio, photo, social links
24
+ - **Team Members** - Staff profiles with role, photo, bio
25
+ - **Downloads** - Downloadable files with description and category
26
+ - **FAQs** - Question and answer pairs
27
+ - **Products** - Items with price, description, images
78
28
 
79
- **Fields:**
80
- - \`{{title}}\` (text, required) - File title
81
- - \`{{slug}}\` (text) - URL slug
82
- - \`{{description}}\` (text) - Description
83
- - \`{{fileUrl}}\` (url) - Download link
84
- - \`{{category}}\` (select) - File category
85
- - \`{{order}}\` (number) - Display order
86
-
87
- **Loop syntax:** \`{{#each downloads sort="order" order="asc"}}\`
29
+ Templates are just starting points - you can customize fields after creation.
88
30
 
89
31
  ---
90
32
 
91
- ## Custom Collections
92
-
93
- Custom collections are tenant-defined content types created in the CMS dashboard. Each custom collection has its own slug and user-defined fields.
33
+ ## Token Syntax
94
34
 
95
- **Token syntax:** Same as built-in collections
96
- - \`{{fieldSlug}}\` for text, number, boolean, image, url, date, select fields
97
- - \`{{{fieldSlug}}}\` for richText fields (MUST use triple braces)
35
+ ### Basic Tokens
36
+ \`\`\`html
37
+ {{fieldSlug}} <!-- For text, number, boolean, image, url, date, select -->
38
+ {{{fieldSlug}}} <!-- For richText fields (MUST use triple braces) -->
39
+ \`\`\`
98
40
 
99
- **Required built-in tokens for ALL custom collections:**
41
+ ### Built-in Tokens (Available on ALL items)
100
42
  - \`{{name}}\` - Item name/title (REQUIRED - every item has a name)
101
- - \`{{slug}}\` - Item URL slug (if collection has detail pages enabled)
43
+ - \`{{slug}}\` - Item URL slug (if collection has detail pages)
102
44
  - \`{{url}}\` - Full item URL (e.g., /services/my-service)
103
45
 
104
- **Date tokens (automatically tracked - available on all items):**
46
+ ### Date Tokens (Automatically tracked)
105
47
  - \`{{createdAt}}\` - When the item was first created
106
48
  - \`{{publishedAt}}\` - When the item was published (empty for drafts)
107
49
  - \`{{updatedAt}}\` - When the item was last updated
108
50
 
109
- **Example - A "Services" collection with fields: image, description (richText), price:**
110
- \`\`\`html
111
- <section class="services">
112
- {{#each services sort="publishedAt" order="desc"}}
113
- <div class="service-card">
114
- <img src="{{image}}" alt="{{name}}">
115
- <h2><a href="{{url}}">{{name}}</a></h2>
116
- {{{description}}}
117
- <p class="price">\${{price}}</p>
118
- <time>{{publishedAt}}</time>
119
- </div>
120
- {{/each}}
121
- </section>
122
- \`\`\`
123
-
124
- **Example - A "Testimonials" collection with fields: quote (richText), company, rating:**
125
- \`\`\`html
126
- <section class="testimonials">
127
- {{#each testimonials limit=6 sort="publishedAt" order="desc"}}
128
- <blockquote class="testimonial">
129
- {{{quote}}}
130
- <cite>
131
- <strong>{{name}}</strong>
132
- {{#if company}}<span>{{company}}</span>{{/if}}
133
- </cite>
134
- </blockquote>
135
- {{/each}}
136
- </section>
137
- \`\`\`
138
-
139
- **To see exact fields for a tenant's custom collections, use the \`get_tenant_schema\` tool.**
140
-
141
51
  ---
142
52
 
143
- ## Custom Fields on Built-in Collections
144
-
145
- Tenants can add custom fields to Blog Posts, Authors, Team Members, and Downloads. These custom fields work exactly like built-in fields.
53
+ ## Loop Syntax
146
54
 
147
- **Token syntax:**
148
- - \`{{customFieldSlug}}\` for text, number, boolean, image, url, date, select
149
- - \`{{{customFieldSlug}}}\` for richText fields
150
-
151
- **Example - "category" field added to blogs:**
55
+ ### Basic Loop
152
56
  \`\`\`html
153
- {{#each blogs}}
154
- <article class="post-card">
155
- <h2>{{name}}</h2>
156
- {{#if category}}
157
- <span class="category-badge">{{category}}</span>
158
- {{/if}}
159
- <p>{{postSummary}}</p>
160
- </article>
161
- {{/each}}
162
- \`\`\`
163
-
164
- **Example - "department" and "linkedinUrl" fields added to team:**
165
- \`\`\`html
166
- {{#each team sort="order" order="asc"}}
167
- <div class="team-member">
168
- <img src="{{photo}}" alt="{{name}}">
169
- <h3>{{name}}</h3>
170
- <p class="role">{{role}}</p>
171
- {{#if department}}
172
- <p class="department">{{department}}</p>
173
- {{/if}}
174
- {{#if linkedinUrl}}
175
- <a href="{{linkedinUrl}}">LinkedIn</a>
176
- {{/if}}
177
- </div>
57
+ {{#each collectionSlug}}
58
+ <article>
59
+ <h2>{{name}}</h2>
60
+ </article>
178
61
  {{/each}}
179
62
  \`\`\`
180
63
 
181
- **To see exact custom fields for a tenant, use the \`get_tenant_schema\` tool.**
182
-
183
- ---
184
-
185
- ## Relation Fields
186
-
187
- Relation fields allow you to link items from one collection to items in another collection. This is similar to how blog posts can have an author reference.
188
-
189
- ### Creating Relation Fields
190
-
191
- When creating a custom collection field, choose type "Relation" and select the target collection. You can link to:
192
- - Built-in collections: \`blogs\`, \`authors\`, \`team\`, \`downloads\`
193
- - Custom collections: Any collection you've created (e.g., \`tags\`, \`categories\`, \`services\`)
194
-
195
- ### Using Relation Fields in Templates
196
-
197
- When an item has a relation field set, the related item's data is available using dot notation:
64
+ ### Loop Modifiers
65
+ - \`limit=N\` - Limit to N items
66
+ - \`featured=true\` - Only featured items (if collection has a boolean "featured" field)
67
+ - \`sort="fieldName"\` - Sort by field
68
+ - \`order="asc|desc"\` - Sort direction
198
69
 
199
70
  \`\`\`html
200
- <!-- Example: A "Projects" collection with a "category" relation field linking to "Categories" collection -->
201
- {{#each projects}}
202
- <article class="project-card">
203
- <h2>{{name}}</h2>
204
- {{#if category}}
205
- <span class="category-tag">{{category.name}}</span>
206
- <a href="{{category.url}}">View all {{category.name}} projects</a>
207
- {{/if}}
208
- </article>
71
+ {{#each posts limit=6 sort="publishedAt" order="desc"}}
72
+ <article>{{name}}</article>
209
73
  {{/each}}
210
74
  \`\`\`
211
75
 
212
- **Available tokens for related items:**
213
- - \`{{relationField.name}}\` - Related item's name
214
- - \`{{relationField.slug}}\` - Related item's slug
215
- - \`{{relationField.url}}\` - Related item's full URL
216
- - \`{{relationField.anyField}}\` - Any field from the related collection
217
-
218
- ### Common Use Cases
219
-
220
- **Tags on Blog Posts:**
221
- \`\`\`html
222
- {{#each blogs}}
223
- <article>
224
- <h2>{{name}}</h2>
225
- {{#if tag}}
226
- <span class="tag">{{tag.name}}</span>
227
- {{/if}}
228
- </article>
229
- {{/each}}
230
- \`\`\`
76
+ ### Loop Variables
77
+ Inside \`{{#each}}\` blocks:
78
+ - \`{{@first}}\` - true for first item
79
+ - \`{{@last}}\` - true for last item
80
+ - \`{{@index}}\` - zero-based index
231
81
 
232
- **Category Pages - Filtering by Relation:**
233
82
  \`\`\`html
234
- <!-- On a category detail page, show items with this category -->
235
- {{#each projects}}
236
- {{#if (eq category.slug ../slug)}}
237
- <div class="project-card">
238
- <h3>{{name}}</h3>
239
- </div>
240
- {{/if}}
83
+ {{#each services limit=3}}
84
+ <div class="{{#if @first}}featured{{/if}}">
85
+ {{name}}
86
+ </div>
241
87
  {{/each}}
242
88
  \`\`\`
243
89
 
244
- **Related Services on Projects:**
245
- \`\`\`html
246
- {{#if relatedService}}
247
- <div class="related-service">
248
- <h4>Service Used</h4>
249
- <a href="{{relatedService.url}}">{{relatedService.name}}</a>
250
- {{#if relatedService.description}}
251
- <p>{{relatedService.description}}</p>
252
- {{/if}}
253
- </div>
254
- {{/if}}
255
- \`\`\`
256
-
257
90
  ---
258
91
 
259
- ## Template Syntax Reference
92
+ ## Conditionals
260
93
 
261
- ### Loops
94
+ ### Check if field has value
262
95
  \`\`\`html
263
- {{#each blogs}}
264
- <article>
265
- <h2>{{name}}</h2>
266
- </article>
267
- {{/each}}
268
- \`\`\`
269
-
270
- **Loop modifiers:**
271
- - \`limit=N\` - Limit to N items
272
- - \`featured=true\` - Only featured items
273
- - \`sort="fieldName"\` - Sort by field
274
- - \`order="asc|desc"\` - Sort direction
275
-
276
- ### Conditionals
277
- \`\`\`html
278
- <!-- Check if a field has a value -->
279
- {{#if mainImage}}
280
- <img src="{{mainImage}}" alt="{{name}}">
96
+ {{#if image}}
97
+ <img src="{{image}}" alt="{{name}}">
281
98
  {{else}}
282
99
  <div class="placeholder"></div>
283
100
  {{/if}}
284
101
 
285
102
  {{#unless featured}}
286
- <span>Regular post</span>
103
+ <span>Regular item</span>
287
104
  {{/unless}}
288
105
  \`\`\`
289
106
 
290
- ### Collection Empty Checks (Page Level)
291
- Check if a collection has items - useful for "No posts yet" fallbacks:
292
-
107
+ ### Collection Empty Checks
293
108
  \`\`\`html
294
- {{#each blogs}}
109
+ {{#each posts}}
295
110
  <article>{{name}}</article>
296
111
  {{/each}}
297
112
 
298
- {{#unless blogs}}
113
+ {{#unless posts}}
299
114
  <p>No posts yet. Check back soon!</p>
300
115
  {{/unless}}
301
116
  \`\`\`
302
117
 
303
- **Important:** The \`{{#if blogs}}\` and \`{{#unless blogs}}\` syntax checks if the collection has any published items. Use this OUTSIDE of \`{{#each}}\` loops for empty state handling.
118
+ ---
119
+
120
+ ## Equality Comparisons
304
121
 
305
- ### Equality Comparisons in Conditionals
306
- Compare two field values using the \`(eq field1 field2)\` helper:
122
+ Compare field values using the \`(eq field1 field2)\` helper:
307
123
 
308
124
  \`\`\`html
309
125
  <!-- Show content when fields ARE equal -->
310
- {{#if (eq author.slug ../slug)}}
311
- <span>This is your post!</span>
126
+ {{#if (eq category.slug ../slug)}}
127
+ <span>Current category</span>
312
128
  {{/if}}
313
129
 
314
- <!-- Show content when fields are NOT equal -->
130
+ <!-- Show content when fields are NOT equal (exclude current) -->
315
131
  {{#unless (eq slug ../slug)}}
316
132
  <a href="{{url}}">{{name}}</a>
317
133
  {{/unless}}
318
134
  \`\`\`
319
135
 
320
- **Common use case - Related Posts (exclude current):**
136
+ ### Related Items Pattern (Exclude Current)
321
137
  \`\`\`html
322
138
  <h3>Other Posts</h3>
323
- {{#each blogs limit=3}}
139
+ {{#each posts limit=3}}
324
140
  {{#unless (eq slug ../slug)}}
325
141
  <article>
326
142
  <a href="{{url}}">{{name}}</a>
@@ -329,28 +145,15 @@ Compare two field values using the \`(eq field1 field2)\` helper:
329
145
  {{/each}}
330
146
  \`\`\`
331
147
 
332
- This pattern is essential for "Related Posts" sections where you want to show other posts but NOT the current one.
333
-
334
- ### Loop Variables
335
- Inside \`{{#each}}\` blocks:
336
- - \`{{@first}}\` - true for first item
337
- - \`{{@last}}\` - true for last item
338
- - \`{{@index}}\` - zero-based index
148
+ ---
339
149
 
340
- \`\`\`html
341
- {{#each blogs limit=3}}
342
- <article class="{{#if @first}}featured{{/if}}">
343
- {{name}}
344
- </article>
345
- {{/each}}
346
- \`\`\`
150
+ ## Parent Context References
347
151
 
348
- ### Parent Context References (\`../\`)
349
- Inside loops, access the parent scope (page's current item) using \`../\`:
152
+ Inside loops, access the parent scope using \`../\`:
350
153
 
351
154
  \`\`\`html
352
155
  <!-- On author detail page, show only posts by THIS author -->
353
- {{#each blogs}}
156
+ {{#each posts}}
354
157
  {{#if (eq author.name ../name)}}
355
158
  <h3>{{name}}</h3>
356
159
  {{/if}}
@@ -361,186 +164,93 @@ Inside loops, access the parent scope (page's current item) using \`../\`:
361
164
  - \`../slug\` - Parent item's slug
362
165
  - \`../fieldName\` - Any field from the parent scope
363
166
 
364
- **Use cases:**
365
- - Author pages: filter posts by current author
366
- - Category pages: filter items by current category
367
- - Related items: match based on current detail page
167
+ ---
368
168
 
369
- ### Equality Helpers Summary
169
+ ## Relation Fields
370
170
 
371
- | Syntax | When to use | Shows content when... |
372
- |--------|-------------|----------------------|
373
- | \`{{#if (eq field1 field2)}}\` | Compare two fields | Fields ARE equal |
374
- | \`{{#unless (eq field1 field2)}}\` | Exclude matches | Fields are NOT equal |
375
- | \`{{#eq field "value"}}\` | Compare to string | Field equals string |
171
+ Link items from one collection to another. Access related item data using dot notation:
376
172
 
377
- **Examples:**
378
173
  \`\`\`html
379
- <!-- Show only when author matches current page -->
380
- {{#if (eq author.slug ../slug)}}...{{/if}}
174
+ {{#each projects}}
175
+ <article>
176
+ <h2>{{name}}</h2>
177
+ {{#if category}}
178
+ <span class="tag">{{category.name}}</span>
179
+ <a href="{{category.url}}">View all {{category.name}}</a>
180
+ {{/if}}
181
+ </article>
182
+ {{/each}}
183
+ \`\`\`
381
184
 
382
- <!-- Show all EXCEPT current item (Related Posts pattern) -->
383
- {{#unless (eq slug ../slug)}}...{{/unless}}
185
+ **Available tokens for related items:**
186
+ - \`{{relationField.name}}\` - Related item's name
187
+ - \`{{relationField.slug}}\` - Related item's slug
188
+ - \`{{relationField.url}}\` - Related item's full URL
189
+ - \`{{relationField.anyField}}\` - Any field from the related collection
384
190
 
385
- <!-- Compare field to a literal value -->
386
- {{#eq status "published"}}...{{/eq}}
387
- \`\`\`
191
+ ---
192
+
193
+ ## Rich Text (Triple Braces)
388
194
 
389
- ### Rich Text (Triple Braces)
390
195
  For HTML content that should NOT be escaped:
391
196
  \`\`\`html
392
- {{{postBody}}} ✓ Correct - renders HTML
393
- {{postBody}} ✗ Wrong - escapes HTML as text
197
+ {{{description}}} ✓ Correct - renders HTML
198
+ {{description}} ✗ Wrong - escapes HTML as text
394
199
  \`\`\`
395
200
 
396
201
  ---
397
202
 
398
203
  ## Important Rules
399
204
 
400
- 1. **Triple braces for richText fields** - \`{{{postBody}}}\`, \`{{{bio}}}\`
401
- 2. **Double braces for everything else** - \`{{name}}\`, \`{{mainImage}}\`
205
+ 1. **Triple braces for richText fields** - \`{{{body}}}\`, \`{{{bio}}}\`
206
+ 2. **Double braces for everything else** - \`{{name}}\`, \`{{image}}\`
402
207
  3. **Always wrap optional fields in {{#if}}** - Check before rendering
403
208
  4. **Use {{url}} for links** - Generates correct path based on manifest
404
- 5. **Match field names exactly** - \`{{name}}\` not \`{{title}}\`
209
+ 5. **Match field slugs exactly** - Case-sensitive
405
210
 
406
211
  ---
407
212
 
408
- ## Image Handling in Templates
409
-
410
- ### Two Types of Images
411
-
412
- **1. Static/UI Images** - Logos, icons, decorative backgrounds, UI elements
413
- - These are bundled with the site package
414
- - Use \`/public/\` paths
415
- - Keep these as static files
416
-
417
- **2. Content Images** - Blog photos, team headshots, product images, user-uploaded media
418
- - These are managed through the CMS dashboard
419
- - Use CMS tokens like \`{{mainImage}}\`, \`{{photo}}\`
420
- - Never hardcode example/placeholder content images
421
-
422
- ### Static UI Images (Keep as /public/ paths)
423
-
424
- \`\`\`html
425
- <!-- These are CORRECT - static UI elements -->
426
- <img src="/public/images/logo.png" alt="Company Logo">
427
- <img src="/public/images/icons/arrow.svg" alt="">
428
- <div style="background-image: url('/public/images/hero-bg.jpg')">
429
- <link rel="icon" href="/public/images/favicon.ico">
430
- \`\`\`
431
-
432
- ### Content Images (Use CMS Tokens)
213
+ ## Image Handling
433
214
 
215
+ ### Static UI Images (logos, icons)
434
216
  \`\`\`html
435
- <!-- These are CORRECT - CMS-managed content -->
436
- <img src="{{mainImage}}" alt="{{name}}">
437
- <img src="{{thumbnailImage}}" alt="{{name}}">
438
- <img src="{{photo}}" alt="{{name}}">
439
-
440
- <!-- WRONG - Don't hardcode example/placeholder content -->
441
- <img src="/images/sample-blog-post.jpg" alt="Sample Post">
442
- <img src="/images/placeholder-team.jpg" alt="Team Member">
217
+ <img src="/public/images/logo.png" alt="Logo">
443
218
  \`\`\`
444
219
 
445
- ### Image Field Pattern
446
-
447
- Always wrap image fields in conditionals since they may not be set:
448
-
220
+ ### CMS Content Images
449
221
  \`\`\`html
450
- {{#if mainImage}}
451
- <img src="{{mainImage}}" alt="{{name}}" class="hero-image">
222
+ {{#if heroImage}}
223
+ <img src="{{heroImage}}" alt="{{name}}">
452
224
  {{/if}}
453
225
  \`\`\`
454
226
 
455
- ### Custom Collection Image Fields
456
-
457
- For custom collections, the **token name matches the field slug** defined when creating the collection.
458
-
459
- **Example:** A "video" collection with these fields:
460
- - \`videothumbnail\` (type: image)
461
- - \`ogimage\` (type: image)
462
- - \`shortdescription\` (type: text)
463
-
464
- **Template uses the field slugs as tokens:**
465
- \`\`\`html
466
- {{#each video sort="publishedAt" order="desc"}}
467
- <article class="video-card">
468
- {{#if videothumbnail}}
469
- <img src="{{videothumbnail}}" alt="{{name}}">
470
- {{/if}}
471
- <h2><a href="{{url}}">{{name}}</a></h2>
472
- <p>{{shortdescription}}</p>
473
- </article>
474
- {{/each}}
475
- \`\`\`
476
-
477
- **To find exact field slugs for a tenant's custom collections, use the \`get_tenant_schema\` tool.**
478
-
479
- ### Common Mistakes to Avoid
480
-
481
- 1. **Replacing logos/icons with CMS tokens** - Static UI images should stay as \`/public/\` paths
482
- 2. **Hardcoding example blog/product content** - Use \`{{#each}}\` loops with CMS tokens
483
- 3. **Missing \`{{#each}}\` loops** - Dynamic content requires iteration over the collection
484
- 4. **Wrong field names** - Token must match the exact field slug (case-sensitive)
485
-
486
227
  ---
487
228
 
488
229
  ## CMS Template Configuration
489
230
 
490
- Templates are configured in manifest.json using a **flat format** that is the SINGLE SOURCE OF TRUTH for URL paths.
231
+ Configure templates in manifest.json:
491
232
 
492
- ### manifest.json Format
493
233
  \`\`\`json
494
234
  {
495
235
  "cmsTemplates": {
496
- // Built-in: Blog
497
- "blogIndex": "pages/blog.html",
498
- "blogIndexPath": "/blog",
499
- "blogPost": "templates/blog-post.html",
500
- "blogPostPath": "/blog",
501
-
502
- // Built-in: Team, Downloads, Authors
503
- "team": "pages/team.html",
504
- "teamPath": "/team",
505
- "downloads": "pages/downloads.html",
506
- "downloadsPath": "/resources",
507
- "authorsIndex": "pages/authors.html",
508
- "authorsIndexPath": "/authors",
236
+ "postsIndex": "pages/blog.html",
237
+ "postsIndexPath": "/blog",
238
+ "postsDetail": "templates/blog-post.html",
239
+ "postsDetailPath": "/blog",
509
240
 
510
- // Custom Collections: Use {slug}Index, {slug}Detail, {slug}IndexPath, {slug}DetailPath
511
- "videoIndex": "pages/videos.html",
512
- "videoIndexPath": "/videos",
513
- "videoDetail": "templates/video-detail.html",
514
- "videoDetailPath": "/videos",
515
-
516
- "serviceIndex": "pages/services.html",
517
- "serviceIndexPath": "/services",
518
- "serviceDetail": "templates/service-detail.html",
519
- "serviceDetailPath": "/service"
241
+ "servicesIndex": "pages/services.html",
242
+ "servicesIndexPath": "/services",
243
+ "servicesDetail": "templates/service-detail.html",
244
+ "servicesDetailPath": "/services"
520
245
  }
521
246
  }
522
247
  \`\`\`
523
248
 
524
- ### Custom Collection URL Routing
525
-
526
- **IMPORTANT:** The collection's internal slug (set in CMS) is for database only, NOT for URLs.
527
- URL paths come EXCLUSIVELY from the manifest's \`{slug}IndexPath\` and \`{slug}DetailPath\`.
528
-
529
- **Example:** Collection with slug \`video\` but paths \`/videos\` and \`/videos/:itemSlug\`:
530
- - \`videoIndexPath: "/videos"\` → Index page at \`/videos\`
531
- - \`videoDetailPath: "/videos"\` → Detail pages at \`/videos/my-video\`
532
-
533
- **Different paths for index and detail:**
534
- - \`serviceIndexPath: "/services"\` → Index at \`/services\`
535
- - \`serviceDetailPath: "/service"\` → Detail at \`/service/my-service\`
536
-
537
- ### Template Types
538
- - **{slug}Index** - Template file for the index/listing page
539
- - **{slug}IndexPath** - URL path for the index page
540
- - **{slug}Detail** - Template file for the detail page
541
- - **{slug}DetailPath** - URL path base for detail pages (item slug appended)
542
-
543
- **Note:** The CMS settings UI can also configure these, but manifest.json takes precedence for AI conversions.
249
+ ### Template Keys Pattern
250
+ - **{collectionSlug}Index** - Template file for listing page
251
+ - **{collectionSlug}IndexPath** - URL path for listing page
252
+ - **{collectionSlug}Detail** - Template file for detail page
253
+ - **{collectionSlug}DetailPath** - URL base for detail pages
544
254
 
545
255
  ---
546
256
 
@@ -548,10 +258,6 @@ URL paths come EXCLUSIVELY from the manifest's \`{slug}IndexPath\` and \`{slug}D
548
258
 
549
259
  Forms are automatically captured and stored in the CMS.
550
260
 
551
- ### Form Setup
552
- 1. Add \`data-form-name="xxx"\` attribute to the form
553
- 2. Include the form handler script in your JavaScript
554
-
555
261
  \`\`\`html
556
262
  <form data-form-name="contact">
557
263
  <input type="text" name="firstName" required>
@@ -561,7 +267,7 @@ Forms are automatically captured and stored in the CMS.
561
267
  </form>
562
268
  \`\`\`
563
269
 
564
- ### Form Handler Script (add to /public/js/main.js)
270
+ ### Form Handler Script
565
271
  \`\`\`javascript
566
272
  document.querySelectorAll('form[data-form-name]').forEach(form => {
567
273
  form.addEventListener('submit', async (e) => {
@@ -586,55 +292,29 @@ document.querySelectorAll('form[data-form-name]').forEach(form => {
586
292
 
587
293
  **CRITICAL:** Endpoint is \`/_forms/{formName}\` - NOT \`/api/forms/submit\`
588
294
 
589
- ### Common Form Names
590
- - \`contact\` - Contact/inquiry forms
591
- - \`newsletter\` - Email signups
592
- - \`quote-request\` - Quote/consultation requests
593
- - \`appointment\` - Scheduling forms
295
+ ---
296
+
297
+ ## SEO Template Tokens
298
+
299
+ For CMS detail pages, use tokens in SEO templates:
300
+ - \`{{name}}\` - Item name for title
301
+ - \`{{description}}\` or summary field - For meta description
302
+ - \`{{image}}\` field - For OG image
594
303
 
595
- Tenant context is handled automatically by the system.
304
+ SEO templates are configured in the Fast Mode Editor.
596
305
 
597
306
  ---
598
307
 
599
- ## SEO Template Tokens
308
+ ## Next Steps
600
309
 
601
- For CMS detail pages (like blog posts), Fast Mode supports **token-based SEO templates**. These allow dynamic SEO meta tags where tokens are replaced with the actual item data at render time.
602
-
603
- **⚠️ IMPORTANT:** Do NOT include hardcoded SEO tags in templates. Fast Mode strips them and replaces with configured settings.
604
-
605
- ### Available SEO Tokens by Collection
606
-
607
- #### Blog Posts (\`blogs\`)
608
- | Token | Use For | Example Output |
609
- |-------|---------|----------------|
610
- | \`{{name}}\` | Meta Title | "How to Build a Website" |
611
- | \`{{postSummary}}\` | Meta Description | "Learn the fundamentals..." |
612
- | \`{{mainImage}}\` | OG Image | "https://cdn.example.com/hero.jpg" |
613
- | \`{{author.name}}\` | Author Attribution | "Jane Smith" |
614
-
615
- **Example SEO Template for Blog:**
616
- - Meta Title: \`{{name}} | {{author.name}} | My Blog\`
617
- - Meta Description: \`{{postSummary}}\`
618
- - OG Image: \`{{mainImage}}\`
619
-
620
- #### Authors (\`authors\`)
621
- | Token | Use For |
622
- |-------|---------|
623
- | \`{{name}}\` | Meta Title |
624
- | \`{{bio}}\` | Meta Description |
625
- | \`{{picture}}\` | OG Image |
626
-
627
- #### Custom Collections
628
- All custom field tokens are available:
629
- - \`{{name}}\` - Item name
630
- - \`{{slug}}\` - URL slug
631
- - \`{{customFieldSlug}}\` - Any custom field
632
-
633
- Date tokens (automatically tracked):
634
- - \`{{createdAt}}\` - When the item was created
635
- - \`{{publishedAt}}\` - When the item was published
636
- - \`{{updatedAt}}\` - When the item was last updated
310
+ **To see exact collections and fields for a specific project, use:**
311
+ \`\`\`
312
+ get_tenant_schema(projectId: "your-project-name-or-id")
313
+ \`\`\`
637
314
 
638
- SEO templates are configured in the Fast Mode Editor when viewing CMS detail pages (e.g., \`/blog/:slug\`).
315
+ This will show you:
316
+ - All collections with their slugs
317
+ - All fields with their tokens, types, and descriptions
318
+ - Relation field targets
639
319
  `;
640
320
  }