storyloco 1.0.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.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/package.json +77 -0
- package/packages/heading/README.md +68 -0
- package/packages/heading/src/app.svelte +64 -0
- package/packages/mux/README.md +68 -0
- package/packages/mux/src/app.svelte +576 -0
- package/packages/shared/README.md +58 -0
- package/packages/shared/dist/components/ui/input/index.d.ts +2 -0
- package/packages/shared/dist/components/ui/input/index.js +4 -0
- package/packages/shared/dist/components/ui/input/input.svelte +51 -0
- package/packages/shared/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/packages/shared/dist/components/ui/label/index.d.ts +2 -0
- package/packages/shared/dist/components/ui/label/index.js +4 -0
- package/packages/shared/dist/components/ui/label/label.svelte +16 -0
- package/packages/shared/dist/components/ui/label/label.svelte.d.ts +4 -0
- package/packages/shared/dist/components/ui/skeleton/index.d.ts +2 -0
- package/packages/shared/dist/components/ui/skeleton/index.js +4 -0
- package/packages/shared/dist/components/ui/skeleton/skeleton.svelte +17 -0
- package/packages/shared/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
- package/packages/shared/dist/components/ui/switch/index.d.ts +2 -0
- package/packages/shared/dist/components/ui/switch/index.js +4 -0
- package/packages/shared/dist/components/ui/switch/switch.svelte +29 -0
- package/packages/shared/dist/components/ui/switch/switch.svelte.d.ts +4 -0
- package/packages/shared/dist/global.css +161 -0
- package/packages/shared/dist/index.d.ts +5 -0
- package/packages/shared/dist/index.js +7 -0
- package/packages/shared/dist/setup.d.ts +2 -0
- package/packages/shared/dist/setup.js +25 -0
- package/packages/shared/dist/utils.d.ts +12 -0
- package/packages/shared/dist/utils.js +5 -0
- package/packages/theme/README.md +68 -0
- package/packages/theme/src/app.svelte +114 -0
- package/src/index.ts +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Storyloco
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Storyloco
|
|
2
|
+
|
|
3
|
+
A collection of slick Storyblok field plugins built with Svelte 5, TypeScript, and Tailwind CSS. Each plugin is designed to be lightweight, performant, and a joy to use.
|
|
4
|
+
|
|
5
|
+
## 🚀 What's Included
|
|
6
|
+
|
|
7
|
+
### Field Plugins
|
|
8
|
+
|
|
9
|
+
- **🎬 Mux Video** - Upload, manage, and configure videos with Mux integration
|
|
10
|
+
- **📝 Heading** - Simple heading editor with level selection (H1-H6)
|
|
11
|
+
- **🎨 Theme** - Color theme selector with visual previews
|
|
12
|
+
|
|
13
|
+
### Shared Components
|
|
14
|
+
|
|
15
|
+
A comprehensive UI component library built with:
|
|
16
|
+
|
|
17
|
+
- **Svelte 5** - Latest reactive framework
|
|
18
|
+
- **Tailwind CSS** - Utility-first styling
|
|
19
|
+
- **Bits UI** - Headless component primitives
|
|
20
|
+
- **TypeScript** - Full type safety
|
|
21
|
+
|
|
22
|
+
## 📦 Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bun add storyloco
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 🎯 Usage
|
|
29
|
+
|
|
30
|
+
### Import Types
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Import specific plugin types
|
|
34
|
+
import type { Video } from 'storyloco/mux'
|
|
35
|
+
import type { Heading } from 'storyloco/heading'
|
|
36
|
+
|
|
37
|
+
// Or import everything
|
|
38
|
+
import type { Video, Heading } from 'storyloco'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Use Shared Components
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { Input, Label, Switch, Skeleton } from 'storyloco/shared'
|
|
45
|
+
import { cn } from 'storyloco/shared/utils'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 🔧 Development
|
|
49
|
+
|
|
50
|
+
### Prerequisites
|
|
51
|
+
|
|
52
|
+
- **Bun** (recommended) or Node.js 18+
|
|
53
|
+
- **Storyblok** account for field plugin development
|
|
54
|
+
|
|
55
|
+
### Setup
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Clone the repo
|
|
59
|
+
git clone <your-repo-url>
|
|
60
|
+
cd storyloco
|
|
61
|
+
|
|
62
|
+
# Install dependencies
|
|
63
|
+
bun install
|
|
64
|
+
|
|
65
|
+
# Start development
|
|
66
|
+
bun run dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Project Structure
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
storyloco/
|
|
73
|
+
├── packages/
|
|
74
|
+
│ ├── mux/ # Video upload & management plugin
|
|
75
|
+
│ ├── heading/ # Heading editor plugin
|
|
76
|
+
│ ├── theme/ # Theme selector plugin
|
|
77
|
+
│ └── shared/ # UI component library
|
|
78
|
+
├── src/
|
|
79
|
+
│ └── index.ts # Type exports
|
|
80
|
+
└── package.json # Root workspace config
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Adding New Plugins
|
|
84
|
+
|
|
85
|
+
1. **Create plugin package**:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
bun run add-plugin
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
2. **Export types** in your plugin:
|
|
92
|
+
|
|
93
|
+
```svelte
|
|
94
|
+
<script module lang="ts">
|
|
95
|
+
export interface YourType {
|
|
96
|
+
// your interface here
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
3. **Add to root exports** in `package.json`:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"exports": {
|
|
106
|
+
"./your-plugin": {
|
|
107
|
+
"types": "./packages/your-plugin/src/app.svelte",
|
|
108
|
+
"import": "./packages/your-plugin/src/app.svelte"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
4. **Re-export in `src/index.ts`**:
|
|
115
|
+
```typescript
|
|
116
|
+
export type { YourType } from '../packages/your-plugin/src/app.svelte'
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 🎨 Shared Components
|
|
120
|
+
|
|
121
|
+
The shared package provides a comprehensive set of UI components:
|
|
122
|
+
|
|
123
|
+
### Form Components
|
|
124
|
+
|
|
125
|
+
- `Input` - Text input with proper styling
|
|
126
|
+
- `Label` - Accessible form labels
|
|
127
|
+
- `Switch` - Toggle switch component
|
|
128
|
+
|
|
129
|
+
### Display Components
|
|
130
|
+
|
|
131
|
+
- `Skeleton` - Loading skeleton component
|
|
132
|
+
|
|
133
|
+
### Utilities
|
|
134
|
+
|
|
135
|
+
- `cn()` - Class name utility (clsx + tailwind-merge)
|
|
136
|
+
- `setup()` - Global setup function
|
|
137
|
+
|
|
138
|
+
## 🔌 Field Plugin Development
|
|
139
|
+
|
|
140
|
+
Each plugin follows the Storyblok field plugin pattern:
|
|
141
|
+
|
|
142
|
+
```svelte
|
|
143
|
+
<script lang="ts">
|
|
144
|
+
import { createFieldPlugin, type FieldPluginResponse } from '@storyblok/field-plugin'
|
|
145
|
+
|
|
146
|
+
interface YourData {
|
|
147
|
+
// your data structure
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
type Plugin = FieldPluginResponse<YourData | null>
|
|
151
|
+
|
|
152
|
+
let plugin: Plugin | null = $state(null)
|
|
153
|
+
let content: YourData = $state(initial_value)
|
|
154
|
+
|
|
155
|
+
onMount(() => {
|
|
156
|
+
createFieldPlugin({
|
|
157
|
+
enablePortalModal: true,
|
|
158
|
+
validateContent: (c) => {
|
|
159
|
+
// validation logic
|
|
160
|
+
return { content: validated_content }
|
|
161
|
+
},
|
|
162
|
+
onUpdateState: (state) => {
|
|
163
|
+
plugin = state as Plugin
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
</script>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 🚀 Deployment
|
|
171
|
+
|
|
172
|
+
### Deploy Individual Plugins
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# From the plugin directory
|
|
176
|
+
cd packages/mux
|
|
177
|
+
bun run deploy
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Build Shared Package
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
cd packages/shared
|
|
184
|
+
bun run build
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 🛠️ Tech Stack
|
|
188
|
+
|
|
189
|
+
- **Framework**: Svelte 5 with TypeScript
|
|
190
|
+
- **Styling**: Tailwind CSS
|
|
191
|
+
- **Components**: Shadcn Svelte, Bits UI primitives
|
|
192
|
+
- **Build Tool**: Vite
|
|
193
|
+
- **Package Manager**: Bun (recommended)
|
|
194
|
+
- **Linting**: ESLint + Prettier
|
|
195
|
+
|
|
196
|
+
## 📄 License
|
|
197
|
+
|
|
198
|
+
MIT License - feel free to use this however you want, you absolute legend! 🎯
|
|
199
|
+
|
|
200
|
+
## 🤝 Contributing
|
|
201
|
+
|
|
202
|
+
1. Fork the repo
|
|
203
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
204
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
205
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
206
|
+
5. Open a Pull Request
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
Built with ❤️ and a lot of swearing by the Storyloco team
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "storyloco",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A collection of slick Storyblok field plugins built with Svelte 5, TypeScript, and Tailwind CSS",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"storyblok",
|
|
7
|
+
"field-plugin",
|
|
8
|
+
"svelte",
|
|
9
|
+
"typescript",
|
|
10
|
+
"tailwind",
|
|
11
|
+
"cms",
|
|
12
|
+
"headless"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/darbymanning/storyloco.git"
|
|
18
|
+
},
|
|
19
|
+
"main": "./src/index.ts",
|
|
20
|
+
"types": "./src/index.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"packages/mux/src/app.svelte",
|
|
24
|
+
"packages/heading/src/app.svelte",
|
|
25
|
+
"packages/theme/src/app.svelte",
|
|
26
|
+
"packages/shared/dist"
|
|
27
|
+
],
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./src/index.ts",
|
|
31
|
+
"import": "./src/index.ts"
|
|
32
|
+
},
|
|
33
|
+
"./mux": {
|
|
34
|
+
"types": "./packages/mux/src/app.svelte",
|
|
35
|
+
"import": "./packages/mux/src/app.svelte"
|
|
36
|
+
},
|
|
37
|
+
"./heading": {
|
|
38
|
+
"types": "./packages/heading/src/app.svelte",
|
|
39
|
+
"import": "./packages/heading/src/app.svelte"
|
|
40
|
+
},
|
|
41
|
+
"./theme": {
|
|
42
|
+
"types": "./packages/theme/src/app.svelte",
|
|
43
|
+
"import": "./packages/theme/src/app.svelte"
|
|
44
|
+
},
|
|
45
|
+
"./shared": {
|
|
46
|
+
"types": "./packages/shared/dist/index.d.ts",
|
|
47
|
+
"svelte": "./packages/shared/dist/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./shared/utils": {
|
|
50
|
+
"types": "./packages/shared/dist/utils.d.ts",
|
|
51
|
+
"svelte": "./packages/shared/dist/utils.js"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "24.0.0",
|
|
56
|
+
"@typescript-eslint/eslint-plugin": "8.34.0",
|
|
57
|
+
"@typescript-eslint/parser": "8.34.0",
|
|
58
|
+
"eslint": "9.28.0",
|
|
59
|
+
"eslint-plugin-prettier": "5.4.1",
|
|
60
|
+
"kitto": "1.0.0-rc.12",
|
|
61
|
+
"prettier": "3.5.3",
|
|
62
|
+
"typescript": "5.8.3",
|
|
63
|
+
"vite": "6.3.5"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"add-plugin": "npx @storyblok/field-plugin-cli@latest add --dir \"./packages\" --structure monorepo",
|
|
67
|
+
"lint": "eslint --ext .js .",
|
|
68
|
+
"format": "prettier . --write"
|
|
69
|
+
},
|
|
70
|
+
"type": "module",
|
|
71
|
+
"workspaces": [
|
|
72
|
+
"packages/*"
|
|
73
|
+
],
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"color": "5.0.0"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Storyblok Field Plugin with "Vanilla" JavaScript
|
|
2
|
+
|
|
3
|
+
This project was generated with `@storyblok/field-plugin-cli`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
For development, run the application locally with
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
and open the [Sandbox](https://plugin-sandbox.storyblok.com/field-plugin/).
|
|
14
|
+
|
|
15
|
+
To build the project, run
|
|
16
|
+
|
|
17
|
+
```shell
|
|
18
|
+
npm run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Deploy the field plugin with the CLI. Issue a [personal access token](https://app.storyblok.com/#/me/account?tab=token), rename `.env.local.example` to `.env.example`, open the file, set the value `STORYBLOK_PERSONAL_ACCESS_TOKEN`, and run
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
npm run deploy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Manifest File for Field Plugins
|
|
28
|
+
|
|
29
|
+
The manifest file is a configuration that enhances the functionality of your field plugin. This JSON file, named `field-plugin.config.json` and located in your project's root folder, is optional but highly recommended.
|
|
30
|
+
|
|
31
|
+
The manifest file allows you to configure [options](https://www.storyblok.com/docs/plugins/field-plugins/introduction#options) for your field plugin. When developing your field plugin with the [Sandbox](https://plugin-sandbox.storyblok.com/field-plugin/), the options are applied by default. Also, the deploy command automatically applies the options in production. So, you no longer need to configure the options manually.
|
|
32
|
+
|
|
33
|
+
### Configuring a Manifest File
|
|
34
|
+
|
|
35
|
+
The options list within the file `field-plugin.config.json` should consist of key-value objects representing the essential options required for your field plugin to function correctly, along with their corresponding values. This is an example of how it should be structured:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"options": [
|
|
40
|
+
{
|
|
41
|
+
"name": "myPluginInitialValue",
|
|
42
|
+
"value": 100
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Now, you just need to access these options in your code like in the example below:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
console.log(data.options.myPluginInitialValue)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Clean up the boilerplate
|
|
55
|
+
|
|
56
|
+
To start from a blank state, delete the following files:
|
|
57
|
+
|
|
58
|
+
- src/components/components.js
|
|
59
|
+
|
|
60
|
+
And search for comments `DELETE THIS BOILERPLATE` comments and delete the code around them.
|
|
61
|
+
|
|
62
|
+
## Continuous delivery
|
|
63
|
+
|
|
64
|
+
Set up [continuous delivery](https://www.storyblok.com/docs/plugins/field-plugins/continuous-delivery) with the CLI. Define an environmental variable `STORYBLOK_PERSONAL_ACCESS_TOKEN`, and use the `--name` and `--skipPrompts` options as such:
|
|
65
|
+
|
|
66
|
+
```shell
|
|
67
|
+
npm run deploy --name $NAME --skipPrompts
|
|
68
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export interface Heading {
|
|
3
|
+
text: string
|
|
4
|
+
level: 1 | 2 | 3 | 4 | 5 | 6
|
|
5
|
+
}
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
import { createFieldPlugin, type FieldPluginResponse } from '@storyblok/field-plugin'
|
|
10
|
+
import { onMount } from 'svelte'
|
|
11
|
+
import { Input } from 'shared'
|
|
12
|
+
|
|
13
|
+
type Plugin = FieldPluginResponse<Heading | null>
|
|
14
|
+
|
|
15
|
+
let plugin: Plugin | null = $state(null)
|
|
16
|
+
let content: Heading = $state({ text: '', level: 1 })
|
|
17
|
+
|
|
18
|
+
onMount(() => {
|
|
19
|
+
createFieldPlugin({
|
|
20
|
+
enablePortalModal: true,
|
|
21
|
+
validateContent: (content) => {
|
|
22
|
+
if (typeof content !== 'object' || content === null) {
|
|
23
|
+
return { content: { text: '', level: 1 } as Heading }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const validated = content as Heading
|
|
27
|
+
// ensure level is one of the allowed values
|
|
28
|
+
if (![1, 2, 3, 4, 5, 6].includes(validated.level)) {
|
|
29
|
+
validated.level = 1
|
|
30
|
+
}
|
|
31
|
+
// ensure text is a string
|
|
32
|
+
if (typeof validated.text !== 'string') {
|
|
33
|
+
validated.text = ''
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { content: validated }
|
|
37
|
+
},
|
|
38
|
+
onUpdateState: (state) => {
|
|
39
|
+
plugin = state as Plugin
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
function update() {
|
|
45
|
+
if (plugin?.type !== 'loaded') return
|
|
46
|
+
const state = $state.snapshot(content)
|
|
47
|
+
plugin.actions.setContent(state)
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
{#if plugin?.type === 'loaded'}
|
|
52
|
+
<fieldset class="flex gap-2">
|
|
53
|
+
<Input class="flex-1" bind:value={content.text} oninput={update} />
|
|
54
|
+
<select
|
|
55
|
+
class="rounded outline-none focus-visible:border-ring border-input bg-white border dark:bg-input/30"
|
|
56
|
+
bind:value={() => content.level, (v) => (content.level = Number(v) as Heading['level'])}
|
|
57
|
+
onchange={update}
|
|
58
|
+
>
|
|
59
|
+
{#each [1, 2, 3, 4, 5, 6] as level}
|
|
60
|
+
<option value={level}>H{level}</option>
|
|
61
|
+
{/each}
|
|
62
|
+
</select>
|
|
63
|
+
</fieldset>
|
|
64
|
+
{/if}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Storyblok Field Plugin with "Vanilla" JavaScript
|
|
2
|
+
|
|
3
|
+
This project was generated with `@storyblok/field-plugin-cli`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
For development, run the application locally with
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
and open the [Sandbox](https://plugin-sandbox.storyblok.com/field-plugin/).
|
|
14
|
+
|
|
15
|
+
To build the project, run
|
|
16
|
+
|
|
17
|
+
```shell
|
|
18
|
+
npm run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Deploy the field plugin with the CLI. Issue a [personal access token](https://app.storyblok.com/#/me/account?tab=token), rename `.env.local.example` to `.env.example`, open the file, set the value `STORYBLOK_PERSONAL_ACCESS_TOKEN`, and run
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
npm run deploy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Manifest File for Field Plugins
|
|
28
|
+
|
|
29
|
+
The manifest file is a configuration that enhances the functionality of your field plugin. This JSON file, named `field-plugin.config.json` and located in your project's root folder, is optional but highly recommended.
|
|
30
|
+
|
|
31
|
+
The manifest file allows you to configure [options](https://www.storyblok.com/docs/plugins/field-plugins/introduction#options) for your field plugin. When developing your field plugin with the [Sandbox](https://plugin-sandbox.storyblok.com/field-plugin/), the options are applied by default. Also, the deploy command automatically applies the options in production. So, you no longer need to configure the options manually.
|
|
32
|
+
|
|
33
|
+
### Configuring a Manifest File
|
|
34
|
+
|
|
35
|
+
The options list within the file `field-plugin.config.json` should consist of key-value objects representing the essential options required for your field plugin to function correctly, along with their corresponding values. This is an example of how it should be structured:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"options": [
|
|
40
|
+
{
|
|
41
|
+
"name": "myPluginInitialValue",
|
|
42
|
+
"value": 100
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Now, you just need to access these options in your code like in the example below:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
console.log(data.options.myPluginInitialValue)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Clean up the boilerplate
|
|
55
|
+
|
|
56
|
+
To start from a blank state, delete the following files:
|
|
57
|
+
|
|
58
|
+
- src/components/components.js
|
|
59
|
+
|
|
60
|
+
And search for comments `DELETE THIS BOILERPLATE` comments and delete the code around them.
|
|
61
|
+
|
|
62
|
+
## Continuous delivery
|
|
63
|
+
|
|
64
|
+
Set up [continuous delivery](https://www.storyblok.com/docs/plugins/field-plugins/continuous-delivery) with the CLI. Define an environmental variable `STORYBLOK_PERSONAL_ACCESS_TOKEN`, and use the `--name` and `--skipPrompts` options as such:
|
|
65
|
+
|
|
66
|
+
```shell
|
|
67
|
+
npm run deploy --name $NAME --skipPrompts
|
|
68
|
+
```
|