A simple CLI for scaffolding Storyblok projects and fieldtypes.
We added the region
option upon login. If you are using the CLI, please logout
and login
again providing your user region.
Make sure you have Node >= 18.0.0
installed.
$ npm i storyblok -g
Login to the Storyblok cli
$ storyblok login
email
: your user's email addresspassword
: your user's password
token
: your personal access token
Get your personal access token
- Go to https://app.storyblok.com/#/me/account?tab=token and click on Generate new token.
For Both login options you nedd to pass the region
region
(default:eu
): the region you would like to work in. All the supported regions can be found here.
Note
Please keep in mind that the region must match the region of your space, and also that it will be used for all future commands you may perform.
You can also add the token directly from the login’s command, like the example below:
$ storyblok login --token <PERSONAL_ACCESS_TOKEN> --region eu
Logout from the Storyblok cli
$ storyblok logout
Get the currently logged in user
$ storyblok user
Usage to kickstart a boilerplate, fieldtype or theme
$ storyblok select
Download your space's languages schema as json. This command will download 1 file.
$ storyblok pull-languages --space <SPACE_ID>
space
: your space id
Download your space's components schema as json. By default this command will download 2 files: 1 for the components and 1 for the presets; But if you pass a flag --separate-files or --sf
the command will create file for each component and presets. And also you could pass a path --path or -p
to save your components and presets.
It's highly recommended to use also the --prefix-presets-names
or -ppn
parameter if you use --separate-files
because it will prefix the names of the individual files with the name of the component. This feature solves the issue of multiple presets from different components but with the same name, being written in the same file. In a future major version this will become the default behavior.
If you want to resolve datasources for single/multiple option field from your Storyblok components, you can use --resolve-datasources
or --rd
, it will fill up the options fields with the datasource's options.
$ storyblok pull-components --space <SPACE_ID> # Will save files like components-1234.json
$ storyblok pull-components --space <SPACE_ID> --separate-files --prefix-presets-names --file-name production # Will save files like feature-production.json grid-production.json
$ storyblok pull-components --space <SPACE_ID> --resolve-datasources # Will resolve datasources for single/multiple option field
space
: your space idseparate-files
: boolean flag to save components and presets in single files instead a file with allpath
: the path to save your components and preset filesfile-name
(optional): a custom filename used to generate the component and present files, default is the space id
Push your components file to your/another space
$ storyblok push-components <SOURCE> --space <SPACE_ID> --presets-source <PRESETS_SOURCE>
source
: can be a URL or path to JSON file, the path to a json file could be to a single or multiple files separated by comma, like./pages-1234.json,../User/components/grid-1234.json
Using an URL
$ storyblok push-components https://raw.githubusercontent.com/storyblok/nuxtdoc/master/seed.components.json --space 67819
Using a path to a single file
$ storyblok push-components ./components.json --space 67819
Using a path to a multiple files
$ storyblok push-components ./page.json,../grid.json,./feature.json --space 67819
space
: your space idpresets-source
(optional): it can be a URL or path to JSON file with the presets
Using an URL for presets-source
$ storyblok push-components https://raw.githubusercontent.com/storyblok/nuxtdoc/master/seed.components.json --presets-source https://url-to-your-presets-file.json --space 67819
Using a path to file
$ storyblok push-components ./components.json --presets-source ./presets.json --space 67819
Delete a single component on your space.
storyblok delete-component <component> --space <SPACE_ID>
component
: The name or id of the component
space_id
: the space where the command should be executed.
Delete a component on your space.
storyblok delete-component 111111 --space 67819
storyblok delete-component teaser --space 67819
Delete all components from your Space that occur in your Local JSON.
Or delete those components on your Space that do not appear in the JSON. (--reverse
)
storyblok delete-components <SOURCE> --space <SPACE_ID>
source
: can be a URL or path to JSON file, the path to a json file could be to a single or multiple files separated by comma, like./pages-1234.json,../User/components/grid-1234.json
Using an URL
$ storyblok push-components https://raw.githubusercontent.com/storyblok/nuxtdoc/master/seed.components.json --space 67819
Using a path to a single file
$ storyblok push-components ./components.json --space 67819
Using a path to a multiple files
$ storyblok push-components ./page.json,../grid.json,./feature.json --space 67819
space_id
: the space where the command should be executed.reverse
: When passed as an argument, deletes only those components on your space that do not appear in the JSON.dryrun
: when passed as an argument, does not perform any changes on the given space.
Delete all components on a certain space that occur in your local JSON.
storyblok delete-components ./components.json --space 67819
Delete only those components which do not occur in your local json from your space.
storyblok delete-components ./components.json --space 67819 --reverse
To see the result in your console output but to not perform the command on your space, use the --dryrun
argument.
storyblok delete-components ./components.json --space 67819 --reverse --dryrun
Sync components, folder, roles, datasources or stories between spaces
$ storyblok sync --type <COMMAND> --source <SPACE_ID> --target <SPACE_ID>
type
: describe the command type to execute. Can be:folders
,components
,stories
,datasources
orroles
. It's possible pass multiple types separated by comma (,
).source
: the source space to use to synctarget
: the target space to use to syncstarts-with
: sync only stories that starts with the given stringfilter
: sync stories based on the given filter. Required Options: Required options:--keys
,--operations
,--values
keys
: Multiple keys should be separated by comma. Example:--keys key1,key2
,--keys key1
operations
: Operations to be used for filtering. Can be:is
,in
,not_in
,like
,not_like
,any_in_array
,all_in_array
,gt_date
,lt_date
,gt_int
,lt_int
,gt_float
,lt_float
. Multiple operations should be separated by comma.components-full-sync
: If used, the CLI will override the full component object when synching across spaces.
# Sync components from `00001` space to `00002` space
$ storyblok sync --type components --source 00001 --target 00002
# Sync components and stories from `00001` space to `00002` space
$ storyblok sync --type components,stories --source 00001 --target 00002
# Sync only stories that starts with `myStartsWithString` from `00001` space to `00002` space
$ storyblok sync --type stories --source 00001 --target 00002 --starts-with myStartsWithString
# Sync only stories with a category field like `reference` from `00001` space to `00002` space
$ storyblok sync --type stories --source 00001 --target 00002 --filter --keys category --operations like --values reference
# Sync only stories with a category field like `reference` and a name field not like `demo` from `00001` space to `00002` space
$ storyblok sync --type stories --source 00001 --target 00002 --filter --keys category,name --operations like,not_like --values reference,demo
Create a space in Storyblok and select the boilerplate to use
$ storyblok quickstart
Create a migration file (with the name change_<COMPONENT>_<FIELD>.js
) inside the migrations
folder. Check Migrations section to more details
$ storyblok generate-migration --space <SPACE_ID> --component <COMPONENT_NAME> --field <FIELD>
It's important to note that the component
and field
parameters are required and must be spelled exactly as they are in Storyblok. You can check the exact name by looking at the Block library
inside your space.
space
: space where the component iscomponent
: component name. It needs to be a valid componentfield
: name of field
Execute a specific migration file. Check Migrations section to more details
$ storyblok run-migration --space <SPACE_ID> --component <COMPONENT_NAME> --field <FIELD> --dryrun
Optionally you can provide the publish parameter to publish content after saving. Example:
$ storyblok run-migration --publish published --space 1234 --component article --field image
space
: the space you get from the space settings areacomponent
: component name. It needs to be a valid componentfield
: name of fielddryrun
: when passed as an argument, does not perform the migrationpublish
(optional): publish the content when updateall
: publish all stories, even if they have not yet been publishedpublished
: only publish stories that already are published and don't have unpublished changespublished-with-changes
: publish stories that are published and have unpublished changes
publish-languages
(optional): publish specific languages. You can publish more than one language at a time by separating the languages by,
The rollback-migration
command gives the possibility to undo the changes made from the execution of the last run-migrations
command.
$ storyblok rollback-migration --space 1234 --component Product --field title
Important: The rollback-migrations
command will only work if there where changes done with run-migrations
. Therefore running run-migrations
command with the --dryrun
flag will NOT create a rollback file.
space
: the space you get from the space settings areacomponent
: component name. It needs to be a valid componentfield
: name of field
List all spaces of the logged account
$ storyblok spaces
This command gives you the possibility to import flat content from .csv
, .xml
and .json
files coming from other systems.
The attributes path
and title
are required.
$ storyblok import --file <FILE_NAME> --type <TYPE_OF_CONTENT> --folder <FOLDER_ID> --delimiter <DELIMITER_TO_CSV_FILES> --space <SPACE_ID>
A xml file needs to have following format:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<path>this-is-my-title</path>
<title>This is my title</title>
<text>Lorem ipsum dolor sit amet</text>
<image>https://a.storyblok.com/f/51376/x/1502f01431/corporate-website.svg</image>
<category>press</category>
</row>
</root>
A csv file needs to have following format. The first row is used to identify the attribute names:
path;title;text;image;category
this-is-my-title;This is my title;"Lorem ipsum dolor sit amet";https://a.storyblok.com/f/51376/x/1502f01431/corporate-website.svg;press
A json file need to have following format:
[
{
"path": "this-is-my-title",
"title": "This is my title",
"text": "Lorem ipsum dolor sit amet",
"image": "https://a.storyblok.com/f/51376/x/1502f01431/corporate-website.svg",
"category": "press"
}
]
file
: name of the filetype
: name of the content type you want to use for the importspace
: id of your spacedelimiter
(optional): delimiter of the.cvs
files, only necessary if you are uploading a csv file (Default value is ; )folder
(optional): id of the folder where you want to store the content in Storyblok
For global help
$ storyblok --help
For command help
$ storyblok sync --help
For view the CLI version
$ storyblok -V # or --version
The delete-datasources command enables you to remove all datasources within the designated space. By utilizing the --by-slug
option, you can filter the datasources based on their slugs, selectively deleting specific datasources. Similarly, the --by-name
option functions in the same way, allowing you to filter and delete datasources based on their names.
$ storyblok delete-datasources --space-id <SPACE_ID> # Will delete all datasources
$ storyblok delete-datasources --space-id <SPACE_ID> --by-slug global-translations # Will only delete datasources where the slug starts with global-translations
space-id
: your space idby-slug
: Filter Datasources by slugby-name
: Filter Datasources by name
Content migrations are a convenient way to change fields of your content.
To execute a migration you first need to create a migration file. This file is a pure Javascript function where the content of a specific content type or component gets passed through.
To create a migration file, you need to execute the generate-migration
command:
# creating a migration file to product component to update the price
$ storyblok generate-migration --space 00000 --component product --field price
When you run this command a file called change_product_price.js
will be created inside a folder called migrations
.
The created file will have the following content:
// here, 'subtitle' is the name of the field defined when you execute the generate command
module.exports = function (block) {
// Example to change a string to boolean
// block.subtitle = !!(block.subtitle)
// Example to transfer content from other field
// block.subtitle = block.other_field
}
In the migration function you can manipulate the block variable to add or modify existing fields of the component.
To run the migration function you need to execute the run-migration
command. Pass the --dryrun option to not execute the updates and only show the changes in the terminal:
$ storyblok run-migration --space 00000 --component product --field price --dryrun
After checking the output of the dryrun you can execute the updates:
# you can use the --dryrun option to not execute the updates
$ storyblok run-migration --space 00000 --component product --field price
You can execute the migration and, when update the content, publish it using the --publish
and --publish-languages
options. When you use the publish
option, you need to specific one of these following options: 'all', 'published' or 'published-with-changes':
$ storyblok run-migration --space 00000 --component product --field price --publish all
You can specify the languages to update using --publish-languages=<LANGUAGE>
or update all languages using --publish-languages=ALL_LANGUAGES
:
# to update only one language
$ storyblok run-migration --space 00000 --component product --field price --publish all --publish-languages=de
# to update more than one language
$ storyblok run-migration --space 00000 --component product --field price --publish all --publish-languages=de,pt
Whenever you run a run-migrations
command a json file containing all the content before the change takes place will be generated. Important, this just doesn't apply if you add the --dryrun
flag.
Remembering that, the content that will be saved is always related to the last run-migrations
command, that is, if you run the run-migrations
command twice changing the same component, the content will only be saved before the last update.
Let's create an example to update all occurrences of the image field in product component. In the example we replace the url from //a.storyblok.com
to //my-custom-domain.com
.
First, you need to create the migration function:
$ storyblok generate-migration --space 00000 --component product --field image
Then let's update the default image field:
module.exports = function (block) {
block.image = block.image.replace('a.storyblok.com', 'my-custom-domain.com')
}
Now you can execute the migration file:
$ storyblok run-migration --space 00000 --component product --field image --dryrun
To transform a markdown or html field into a richtext field you first need to install a converter library.
$ npm install storyblok-markdown-richtext -g
Now check the path to the global node modules folder
$ npm root -g
Generate the migration with storyblok generate-migration --space 00000 --component blog --field intro
and apply the transformation:
var richtextConverter = require('/usr/local/lib/node_modules/storyblok-markdown-richtext')
module.exports = function (block) {
if (typeof block.intro == 'string') {
block.intro = richtextConverter.markdownToRichtext(block.intro)
}
}
It is possible to generate Typescript type definitions for your Storyblok components. The type definitions are based on the components' JSON Schema that can be retrieved with the pull-components command.
Generate a file with the type definitions for the specified components' JSON Schemas.
$ storyblok generate-typescript-typedefs
--sourceFilePaths <PATHS>
--destinationFilePath <PATH>
--typeNamesPrefix <STRING>
--typeNamesSuffix <STRING>
--JSONSchemaToTSOptionsPath <PATH>
--customFieldTypesParserPath <PATH>
sourceFilePaths
(aliassource
) : Path(s) to the components JSON file(s) as comma separated valuesdestinationFilePath
(aliastarget
) optional : Path to the Typescript file that will be generated (default:storyblok-component-types.d.ts
)typeNamesPrefix
(aliastitlePrefix
) optional : A prefix that will be prepended to all the names of the generated typestypeNamesSuffix
(aliastitleSuffix
) optional : A suffix that will be appended to all the names of the generated types (default:Storyblok
)JSONSchemaToTSOptionsPath
(aliascompilerOptions
) optional : Path to a JSON file with a list of options supported byjson-schema-to-typescript
customFieldTypesParserPath
(aliascustomTypeParser
) optional : Path to the parser file for Custom Field Types
# Generate typedefs for the components retrieved for the space `12345` via the `storyblok pull-components` command
$ storyblok generate-typescript-typedefs --sourceFilePaths ./components.12345.json
# Generate typedefs for multiple components sources
$ storyblok generate-typescript-typedefs --sourceFilePaths ./fooComponent-12345.json,./barComponent-12345.json
# Custom path for the typedefs file
$ storyblok generate-typescript-typedefs --sourceFilePaths ./components.12345.json --destinationFilePath ./types/my-custom-type-file.d.ts
# Provide customized options for the JSON-schema-to-typescript lib
$ storyblok generate-typescript-typedefs --sourceFilePaths ./components.12345.json --JSONSchemaToTSOptionsPath ./PathToJSONFileWithCustomOptions.json
# Provide a custom field types parser
$ storyblok generate-typescript-typedefs --sourceFilePaths ./components.12345.json --customFieldTypesParserPath ./customFieldTypesParser.js
This script uses the json-schema-to-typescript
library under the hood. Values of the JSON Schema to Typescript options can be customized providing a JSON file to the JSONSchemaToTSOptionsPath
.
The default values used for the storyblok generate-typescript-typedefs
command are the same defaults for the library except for two properties:
bannerComment
- The default value is""
to remove noise from the generated Typedefs fileunknownAny
- The default value isfalse
because it can help a smoother Typescript adoption on a JS project
Example JSONSchemaToTSOptions
JSON file to remove additionalProperties
from the generated type definitions:
{
"additionalProperties": false,
}
Storyblok Custom Field Types do not have inherent JSONSchema definitions. To overcome this issue, you can provide a path to a script exporting a parser function that should render a JSONSchema Node for each of your Custom Field Types. The parser function should be exported as a default export, like in the following example:
export default function (key, obj) {
switch (obj.field_type) {
case 'my-custom-field-type-name':
return {
[key]: {
type: 'object',
properties: {
color: { type: 'string' }
},
required: ['color']
}
}
default:
return {}
}
}
Check out our guides for client side apps (VueJS, Angular, React, ...), static site (Jekyll, NuxtJs, ...), dynamic site examples (Node, PHP, Python, Laravel, ...) on our Getting Started page.