@kvasar/openclaw-storyblok-plugin 0.2.3 → 0.2.5

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-storyblok",
3
3
  "name": "Storyblok Integration",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
5
5
  "description": "Provides tools to interact with Storyblok CMS via Management API and Delivery API. Supports stories, components, and space management.",
6
6
  "activation": {
7
7
  "onStartup": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kvasar/openclaw-storyblok-plugin",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "OpenClaw plugin — interact with Storyblok CMS via Management API and Delivery API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,502 +1,114 @@
1
1
  ---
2
2
  name: storyblok
3
- description: Comprehensive skill for interacting with Storyblok CMS: query content, manage stories, generate pages, and sync with frontend repositories.
4
- allowed-tools: storyblok_get_space, storyblok_get_story, storyblok_list_stories, storyblok_get_components, storyblok_get_component, storyblok_create_story, storyblok_update_story, storyblok_publish_story, storyblok_unpublish_story, storyblok_create_asset_folder, storyblok_delete_asset_folder, storyblok_get_asset_folder, storyblok_create_component, storyblok_get_content_folders, storyblok_update_component,storyblok_update_component_folder, sessions_spawn, read, write, edit
5
-
6
- author: Jordi Marti
7
- version: "2.2"
3
+ description: Comprehensive skill for interacting with Storyblok CMS: query content, manage stories, create and update components, generate AI-assisted pages, and sync with frontend repositories. Use when the user mentions Storyblok, CMS content, stories, components, landing pages, or any content management task involving Storyblok.
4
+ license: Proprietary
5
+ metadata:
6
+ author: Jordi Marti
7
+ version: "2.5"
8
+ allowed-tools: storyblok_get_space, storyblok_get_story, storyblok_list_stories, storyblok_get_components, storyblok_get_component, storyblok_create_story, storyblok_update_story, storyblok_publish_story, storyblok_unpublish_story, storyblok_create_asset_folder, storyblok_delete_asset_folder, storyblok_get_asset_folder, storyblok_create_component, storyblok_get_content_folders, storyblok_update_component, storyblok_update_component_folder, sessions_spawn, read, write, edit
8
9
  ---
9
10
 
10
-
11
-
12
11
  # Storyblok Integration Skill
13
12
 
14
- This skill package provides agents with the ability to work with **Storyblok CMS** using the `openclaw-storyblok` plugin. It covers four main workflows:
15
-
16
- 1. **Content Query** – Retrieve spaces, stories, components, and listings.
17
- 2. **Content Management** – Create, update, publish, and unpublish stories.
18
- 3. **Page Generation** – Use AI-assisted reasoning to create new landing pages.
19
- 4. **Sync Workflow** – Synchronize content or schemas between Storyblok and a frontend repository.
20
-
21
- ## Core Concepts
22
-
23
-
24
- ### Storyblok Block Types
25
-
26
- Storyblok components can be organized into three structural categories:
27
-
28
- #### Nestable Block
13
+ ## Gotchas
29
14
 
30
- Reusable blocks that are inserted **inside other blocks or pages**.
15
+ Non-obvious behaviors that cause silent mistakes:
31
16
 
32
- Examples:
33
-
34
- - Hero
35
- - Grid
36
- - Section
37
- - Newsletter Section
38
- - Chapter
39
- - Full Width Image
40
- - Slider
41
- - CTA Banner
42
- - Feature Grid
43
-
44
- Use these when building modular page layouts.
17
+ - **`storyblok_get_story` requires a numeric ID only.** If you have a slug or UUID, first call `storyblok_list_stories` with `with_slug` or `by_uuids` to resolve the numeric ID.
18
+ - **`storyblok_list_stories` does not return `content`.** Use `storyblok_get_story` for full content, or add `with_summary=true` for a lightweight field-type summary.
19
+ - **`publish=false` does NOT unpublish.** It saves as draft. To unpublish a live story, use `storyblok_unpublish_story`.
20
+ - **`component_group_uuid` ≠ `component_group_id`.** When assigning a component to a folder, use the UUID field — not the numeric ID.
21
+ - **Schema updates don't touch existing stories.** After `storyblok_update_component`, stories already using that component keep their old field values.
22
+ - **`content` is a reserved component name.** Component `name` must be snake_case and must not be `content` alone.
23
+ - **`force_update=true` causes a content conflict** if another user has the story open. Use only when necessary.
24
+ - **Never create separate stories per language.** Always use field-level i18n keys inside the same story.
45
25
 
46
26
  ---
47
27
 
48
- #### Content Type Block
49
-
50
- Top-level content models representing an entry/page/document.
51
-
52
- Examples:
53
-
54
- - Landing Page
55
- - Post
56
- - Authors
57
- - Product
58
- - Page
59
- - Team Members
60
- - FAQ Article
61
- - Case Study
62
-
63
- Use these as standalone entries in Storyblok.
64
-
28
+ ## Which tool to use
29
+
30
+ | Goal | Tool |
31
+ |------|------|
32
+ | Space info | `storyblok_get_space` |
33
+ | Single story with full content | `storyblok_get_story` (numeric ID) |
34
+ | Find stories / list / filter | `storyblok_list_stories` |
35
+ | Inspect available block types | `storyblok_get_components` |
36
+ | Full schema of one component | `storyblok_get_component` |
37
+ | Create story | `storyblok_create_story` |
38
+ | Edit story | `storyblok_update_story` |
39
+ | Publish | `storyblok_publish_story` or `publish=true` on create/update |
40
+ | Unpublish | `storyblok_unpublish_story` only |
41
+ | Create Component | `storyblok_create_component` |
42
+ | Update the values of a component. |`storyblok_update_component` |
65
43
  ---
66
44
 
67
- #### Universal Block
68
-
69
- A block that can be used **both as a content type and nested block**.
70
-
71
- Examples:
72
-
73
- - FAQ Section
74
- - Testimonials
75
- - Rich Text Section
76
- - Gallery
77
- - Reusable Promo Page
78
- - Contact Section
79
-
80
- Use when flexibility is needed across multiple content structures.
81
-
82
- ---
83
-
84
- ## Tool Reference
85
-
86
- ### Content Tools
87
-
88
- ### Content Tools
89
-
90
- | Tool | Required params | Optional params |
91
- |------|----------------|-----------------|
92
- | `storyblok_get_space` | — | — |
93
- | `storyblok_get_story` | `identifier` (ID ) |
94
- | `storyblok_list_stories` | — | See parameter reference below |
95
- | `storyblok_get_components` | — | `version`, `language` |
96
- | `storyblok_get_component` | `component_id` | — |
97
-
98
- #### `storyblok_list_stories` — Parameter Reference
99
-
100
- **Pagination**
101
- | Param | Type | Description |
102
- |-------|------|-------------|
103
- | `page` | number | Page number for paginated results |
104
- | `per_page` | number | Number of results per page |
105
-
106
- **Search**
107
- | Param | Type | Description |
108
- |-------|------|-------------|
109
- | `text_search` | string | Full-text search across name, slug, full slug, and all content fields (UIDs, field values, asset filenames, rich text). Same as the search box in the Content UI. |
110
- | `search` | string | Lighter search: name, slug, or full slug only |
111
- | `reference_search` | string | Search referenced stories/assets by UUID, name, or asset URL |
112
- | `contain_component` | string | Filter by nestable block name(s). Comma-separated for multiple |
113
- | `filter_query` | string | Filter by content type fields. Syntax: `filter_query[field][operation]=value`. Supports comma-separated values |
114
-
115
- **Sorting**
116
- | Param | Type | Description |
117
- |-------|------|-------------|
118
- | `sort_by` | string | Sort by story property or content field. Examples: `created_at:desc`, `content.FIELD_NAME:asc`. Append `:int` or `:float` to sort numeric fields |
119
-
120
- **Fetch by ID / UUID / Slug**
121
- | Param | Type | Description |
122
- |-------|------|-------------|
123
- | `by_ids` | string | Comma-separated story IDs to retrieve |
124
- | `excluding_ids` | string | Comma-separated story IDs to exclude |
125
- | `by_uuids` | string | Comma-separated UUIDs to retrieve |
126
- | `by_uuids_ordered` | string | Comma-separated UUIDs; response order matches input order |
127
- | `with_slug` | string | Retrieve stories matching an exact full slug |
128
- | `by_slugs` | string | Comma-separated full slugs. Supports wildcard: `posts/*` |
129
- | `excluding_slugs` | string | Comma-separated full slugs to exclude. Supports wildcard: `posts*` |
130
- | `starts_with` | string | Filter stories whose slug starts with this string |
131
-
132
- **Hierarchy**
133
- | Param | Type | Description |
134
- |-------|------|-------------|
135
- | `with_parent` | number | Filter by parent folder ID |
136
-
137
- **Tags**
138
- | Param | Type | Description |
139
- |-------|------|-------------|
140
- | `with_tag` | string | Filter by tag name(s). Comma-separated for multiple |
141
-
142
- **Type Filters**
143
- | Param | Type | Description |
144
- |-------|------|-------------|
145
- | `folder_only` | boolean | Return only folder-type stories |
146
- | `story_only` | boolean | Return only non-folder stories |
147
- | `in_trash` | boolean | Return only deleted (trashed) stories |
148
- | `is_published` | boolean | `true` = published only · `false` = draft/unpublished only |
149
- | `mine` | boolean | Return only stories assigned to the current user's token |
150
- | `favourite` | boolean | Return only stories marked as favorites in the Content UI |
151
-
152
- **Workflow & Releases**
153
- | Param | Type | Description |
154
- |-------|------|-------------|
155
- | `in_workflow_stages` | string | Comma-separated workflow stage IDs |
156
- | `in_release` | number | Retrieve stories grouped in a release (use release ID) |
157
-
158
- **Scheduling**
159
- | Param | Type | Description |
160
- |-------|------|-------------|
161
- | `scheduled_at_gt` | string | Stories scheduled after this ISO UTC timestamp |
162
- | `scheduled_at_lt` | string | Stories scheduled before this ISO UTC timestamp |
163
-
164
- **Response Shaping**
165
- | Param | Type | Description |
166
- |-------|------|-------------|
167
- | `with_summary` | boolean | Include a `content_summary` object listing field types found in the story content |
168
-
169
- ### Component Tools
170
-
171
- | Tool | Required params | Optional params |
172
- |------|----------------|-----------------|
173
- | `storyblok_create_component` | `name` | `display_name`, `schema`, `is_root`, `is_nestable`, `preview_field`, `preview_tmpl`, `component_group_uuid`, `icon`, `color`, `internal_tag_ids`, `content_type_asset_preview`, `image` |
174
- | `storyblok_update_component` | `component_id` | `name`, `display_name`, `schema`, `is_root`, `is_nestable`, `preview_field`, `preview_tmpl`, `component_group_uuid`, `icon`, `color`, `internal_tag_ids`, `content_type_asset_preview`, `image` |
175
- | `storyblok_get_component` | `component_id` | — |
176
-
177
- > **Note:** Use `component_group_uuid` (not `component_group_id`) — this is the UUID of the component folder.
178
-
179
- ### Component Folder Tools
180
-
181
- | Tool | Required params | Optional params |
182
- |------|----------------|-----------------|
183
- | `storyblok_get_content_folders` | — | `search`, `with_parent` |
184
- | `storyblok_update_component_folder` | `component_group_id` | `name`, `parent_id` (number or null) |
185
-
186
- > **Note:** `parent_id` can be set to `null` to move a folder to the root level.
187
-
188
- ### Management Tools
189
-
190
- | Tool | Required params | Optional params |
191
- |------|----------------|-----------------|
192
- | `storyblok_create_story` | `name` | `slug`, `folder_id`, `parent_id`, `content`, `tag_list`, `is_folder`, `publish`, `release_id` |
193
- | `storyblok_update_story` | `story_id` | `name`, `slug`, `content`, `parent_id`, `tag_list`, `is_folder`, `publish`, `force_update`, `lang`, `release_id`, `group_id` |
194
- | `storyblok_publish_story` | `story_id` | `lang`, `release_id` |
195
- | `storyblok_unpublish_story` | `story_id` | `lang` |
196
-
197
- ### Asset Folder Tools
198
-
199
- | Tool | Required params | Optional params |
200
- |------|----------------|-----------------|
201
- | `storyblok_create_asset_folder` | `name` | `parent_id` |
202
- | `storyblok_delete_asset_folder` | `folder_id` | — |
203
- | `storyblok_get_asset_folder` | `folder_id` | — |
204
-
205
-
206
- ### Parameter Notes
207
-
208
- - Most tools accept optional parameters; only required fields are mandatory.
209
- - For `storyblok_get_story`, you can specify `version` (draft/published) and `language`.
210
- - For `storyblok_list_stories`, you can filter by `folder_id`, `parent_id`, `status`, `tag`, `per_page`, `page`, `sort_by`, `direction`.
211
- - For management tools, `story_id` can be numeric ID or UUID.
212
- - When constructing content objects, pass them as structured objects — never as JSON strings or stringified blobs.
213
-
214
- #### `storyblok_get_story`
215
- - `version`: `draft` or `published`. Defaults to `published`.
216
- - `language`: optional language code to retrieve a specific translation.
217
-
218
- #### `storyblok_list_stories`
219
- - Filter options: `folder_id`, `parent_id`, `status`, `tag`, `per_page`, `page`, `sort_by`, `direction`.
220
- - `story_id` can be a numeric ID or UUID.
221
-
222
- #### `storyblok_update_story`
223
-
224
- - `publish=true` publishes the story. `publish=false` saves as draft — it does **not** unpublish. Use `storyblok_unpublish_story` to unpublish.
225
- - `force_update="true"` forces an update even if the story is locked by another user (causes a content conflict — use with caution). Has no effect if the story is locked as part of a workflow stage.
226
- - `group_id`: UUID shared between stories defined as alternates (used for internationalization/variants).
227
- - `lang`: publishes a specific language version individually (must be enabled in space internationalization settings).
228
- - `content`: must be a structured object — never pass it as a JSON string or serialized value.
229
-
230
- #### `storyblok_update_component`
231
-
232
- - Component updates **do not** automatically update stories that already use this component. Existing story values are preserved.
233
- - Use minimal updates — only change the fields that need modification. Avoid replacing the entire `schema` unless necessary.
234
- - To add translatable fields, set `"translatable": true` in the field definition within the `schema`.
235
- - Read-only fields like `id`, `created_at`, `updated_at`, `all_presets`, `real_name`, `internal_tags_list` cannot be updated.
236
- - See section **3.1 Component Updates** for detailed guidance on schema migration and i18n considerations.
237
-
238
- ## Workflow Guides
239
-
240
- ### 1. Content Query
241
-
242
- Use the query tools to explore and retrieve data.
243
-
244
- **When to use what:**
245
-
246
- - Need space info? → `storyblok_get_space`
247
- - Need a specific story? → `storyblok_get_story` (provide `identifier`)
248
- - Need a list of stories with filters? → `storyblok_list_stories` (set filters)
249
- - Need to know available content block types? → `storyblok_get_components`
250
- - Need full details of a specific component? → `storyblok_get_component` (provide `component_id`)
251
-
252
- **Example: List all published stories in the last week**
253
-
254
- ```sh
255
- storyblok_list_stories status="published" per_page=100
256
- ```
257
-
258
- **Example: Get a story by slug**
259
-
260
- ```sh
261
- storyblok_get_story identifier="my-landing-page" version="published"
262
- ```
263
-
264
- ### 2. Content Management
265
-
266
- Use the management tools to create, modify, and publish content.
267
-
268
- **Workflow:**
45
+ ## Workflows
269
46
 
270
- - To create a new story: `storyblok_create_story` with `name` and optional `content`, `folder_id`, etc.
271
- - Set `publish=true` to publish immediately on creation.
272
- - The content is a JSON object matching your component structure.
273
- - You can use `storyblok_get_components` first to see available block types.
274
- - To edit a story: `storyblok_update_story` with `story_id` and fields to update.
275
- - Set `publish=true` to publish changes immediately.
276
- - Set `force_update=true` only if the story is locked and you need to override (causes content conflict).
277
- - To link alternates (e.g. language variants), set `group_id` to the same UUID across stories.
278
- - To publish: `storyblok_publish_story` with `story_id`.
279
- - To unpublish: `storyblok_unpublish_story` with `story_id`. Never use `update_story` to unpublish.
47
+ ### Content Management
280
48
 
281
- **Example: Create a draft story**
49
+ 1. If content type is unknown, run `storyblok_get_components` first.
50
+ 2. Build `content` as a structured object matching the component schema (JSON string also accepted but object preferred).
51
+ 3. Create or update the story.
52
+ 4. Publish only on explicit user confirmation.
53
+ 5. To unpublish: `storyblok_unpublish_story` — never `update_story`.
282
54
 
283
- ```sh
284
- storyblok_create_story name="New Homepage" content={"title":"Welcome","body":"<p>Hello</p>"}
285
- ```
55
+ ### Component Management
286
56
 
287
- **Example: Create and publish immediately**
57
+ 1. Run `storyblok_get_components` to check if a component with the same name already exists.
58
+ 2. Decide type (`is_root`, `is_nestable`) before creating — restructuring after stories use it can break content.
59
+ 3. To update the entire story content `use storyblok_update_story` (full object required). To update only component schema fields use `storyblok_update_component` (partial, only what you pass changes). Never update partial using `storyblok_update_story`
60
+ 4. Mark user-facing text fields `"translatable": true`; leave technical fields non-translatable.
61
+ 5. Do not create or delete components without user confirmation.
288
62
 
289
- ```sh
290
- storyblok_create_story name="New Homepage" content={...} publish=true
63
+ **Schema field example:**
64
+ ```json
65
+ {
66
+ "headline": { "type": "text", "pos": 0, "translatable": true },
67
+ "image": { "type": "asset", "pos": 1, "filetypes": ["images"] },
68
+ "body": { "type": "richtext", "pos": 2 }
69
+ }
291
70
  ```
292
71
 
293
- **Example: Update and publish**
72
+ ### Page Generation
294
73
 
295
- ```sh
296
- storyblok_update_story story_id="12345" content={...} publish=true
297
- ```
74
+ - [ ] Clarify goal, tone, and key messages with the user
75
+ - [ ] `storyblok_get_components` — identify available blocks
76
+ - [ ] Design content structure, confirm with user before creating
77
+ - [ ] `storyblok_create_story` with the content object
78
+ - [ ] Publish only on explicit user confirmation
298
79
 
299
- **Example: Publish a story**
80
+ For AI-generated copy, spawn a sub-session via `sessions_spawn` with the same tool permissions.
300
81
 
301
- ```sh
302
- storyblok_publish_story story_id="12345" publish_notes="Initial release"
303
- ```
304
- Storyblok i18n & Component Update Rules
305
-
306
- ### 3. Multilingual Story Pattern
82
+ ---
307
83
 
308
- When creating or updating multilingual Storyblok stories:
84
+ ## Multilingual Stories
309
85
 
310
- -Use field-level i18n translations inside the SAME story
311
- -Do NOT create separate stories per language unless explicitly requested
86
+ Always use field-level i18n inside the **same** story — never separate stories per language.
312
87
 
313
- Required behavior
88
+ - Default language: English (unless specified)
314
89
 
315
- -Default/main language must be English unless specified otherwise
316
- -Translate content to requested locales
317
90
  -Store translations using Storyblok i18n field keys:
318
91
  -field_i18n_es
319
92
  -field_i18n_ca
320
93
  -field_i18n_de
321
94
  -etc.
322
- -Keep all translations inside the same story object
323
- -Ensure localized_paths contains all enabled locales
324
- -Use SEO-friendly English slugs for the main version
325
- -Never duplicate stories for translations
326
-
327
- Example
328
-
329
- Correct:
95
+ - Translation keys: `field_i18n_es`, `field_i18n_ca`, `field_i18n_de`, etc.
96
+ - Use SEO-friendly English slugs
97
+ - Ensure `localized_paths` includes all enabled locales
330
98
 
99
+ ```json
331
100
  {
332
101
  "headline": "Why Most Strategies Fail",
333
102
  "headline_i18n_es": "Por qué fracasan la mayoría de las estrategias",
334
- "headline_i18n_ca": "Per què fracassen la majoria destratègies"
335
- }
336
-
337
- Incorrect:
338
-
339
- -Separate stories per language
340
- -Duplicated content entries
341
- -Missing localized_paths
342
-
343
- #### Expected completion reporting
344
-
345
- After multilingual operations, clearly report:
346
-
347
- -Main language used
348
- -Languages added
349
- -That translations were stored using field-level i18n keys
350
- -That no separate stories were created
351
-
352
- ### 3.1.- Component Updates
353
-
354
- Storyblok components can be updated individually without recreating the full schema.
355
-
356
- Use:
357
-
358
- storyblok_update_component
359
-
360
- * Use component updates for:
361
- - Adding translatable fields
362
- - Updating schema definitions
363
- - Marking fields as translatable
364
- - Updating labels/descriptions
365
- - Extending components for i18n
366
- - Updating preview fields
367
-
368
- #### Important behavior
369
-
370
- Updating a component schema does NOT automatically update stories already using that component.
371
-
372
- After schema updates:
373
-
374
- - Existing stories may require updates
375
- - Missing i18n fields may need to be added manually
376
- - Stories may require republishing
377
-
378
- Existing story values are preserved automatically.
379
-
380
- #### i18n Component Schema Rules
381
-
382
- When creating or updating schemas:
383
-
384
- -Mark user-facing text fields with:
385
-
386
- "translatable": true
387
-
388
- -Keep technical/internal fields non-translatable
389
- -Preserve existing schema fields unless explicitly removing them
390
- -Avoid destructive schema replacements
391
-
392
- Example:
393
-
394
- {
395
- "headline": {
396
- "type": "text",
397
- "translatable": true
398
- }
399
- }
400
-
401
- ##### Single Component Update Strategy
402
-
403
- Prefer minimal schema updates instead of recreating full components.
404
-
405
- Good:
406
-
407
- - Add one new translatable field
408
- - Update a single schema property
409
- - Enable translations on existing fields
410
-
411
- Bad:
412
-
413
- - Recreate the full schema unnecessarily
414
- - Accidentally remove existing fields
415
- - Break existing stories
416
- - Important Storyblok Behavior
417
-
418
- Component schema updates do NOT retroactively overwrite story content.
419
-
420
- After schema changes:
421
-
422
- - Existing stories keep current values
423
- - Stories may require migration/update logic
424
- - Translation fields may need manual population
425
-
426
- This matches official Storyblok component update behavior and helps avoid destructive schema operations.
427
-
428
-
429
- ### 4. Page Generation
430
-
431
- This workflow combines AI reasoning with Storyblok tools to produce complete pages.
432
-
433
- **Steps:**
434
-
435
- 1. Clarify the page goal with the user (topic, tone, key messages).
436
- 2. Fetch component schemas via `storyblok_get_components` to understand available block types.
437
- 3. Use reasoning to design a JSON content structure that uses those components.
438
- 4. Create the story with `storyblok_create_story`.
439
- 5. Optionally publish immediately with `storyblok_publish_story`.
440
-
441
- The agent may also spawn a sub-session (using `sessions_spawn`) to generate the content with an AI model if needed.
442
-
443
- ### 5. Component Management
444
-
445
- Components define the content structure of your space. Always design the schema carefully before creating — renaming or restructuring a component after stories use it can break existing content.
446
-
447
- **When creating a component, decide its type first:**
448
-
449
- | Type | `is_root` | `is_nestable` | Use case |
450
- |------|-----------|---------------|----------|
451
- | Content Type | `true` | `false` | Top-level entries (pages, posts) |
452
- | Nestable | `false` | `true` | Reusable blocks inside pages |
453
- | Universal | `true` | `true` | Can be used both ways |
454
-
455
- **Schema field definition example:**
456
-
457
- ```json
458
- {
459
- "headline": {
460
- "type": "text",
461
- "pos": 0,
462
- "translatable": true,
463
- "description": "Main heading text"
464
- },
465
- "image": {
466
- "type": "asset",
467
- "pos": 1,
468
- "filetypes": ["images"]
469
- },
470
- "body": {
471
- "type": "richtext",
472
- "pos": 2
473
- }
103
+ "headline_i18n_ca": "Per què fracassen la majoria d'estratègies"
474
104
  }
475
105
  ```
476
106
 
477
- **Rules:**
478
-
479
- - `name` must be snake_case. Never use `content` alone — it is a reserved keyword.
480
- - Always set at least one of `is_root` or `is_nestable` to `true`.
481
- - Use `component_group_uuid` (not `component_group_id`) when assigning a component to a folder.
482
- - Use `storyblok_get_components` first to check if a component with the same name already exists before creating.
483
- - Use `storyblok_get_component` to inspect a specific component's full schema and presets.
484
- - Do not create components without user confirmation — they affect the entire space.
485
-
486
- ## Session Awareness
487
-
488
- This skill is designed to work in both main and sub-agent sessions. It can be used directly or spawned via `sessions_spawn` for parallel or isolated execution. When spawning, pass the same tool permissions to ensure access to Storyblok tools.
489
-
490
-
491
-
492
-
493
-
494
-
107
+ After completing multilingual work, confirm: languages added, field-level keys used, no separate stories created.
495
108
 
496
109
  ## Notes
497
110
 
498
111
  - Always handle errors gracefully and report to the user.
499
112
  - Avoid publishing without explicit user consent.
500
113
  - For large exports, use pagination (`per_page`, `page`) to stay within response limits.
501
- - Respect rate limits: Storyblok API may have limits; consider adding delays if many requests.
502
-
114
+ - Respect rate limits: Storyblok API may have limits; consider adding delays if many requests.