npm package: @solspace/imagiterate-storyblok
Description: Storyblok field-type plugin for AI-powered image iteration using Replicate
Author: Solspace
Latest version: 1.0.0

# Imagiterate for Storyblok

This field plugin mirrors the Imagiterate experience from the Contentful/Dato/Sanity integrations. Editors pick an existing asset from the Storyblok library, describe the change they want, preview the AI-generated iteration, and store the result alongside the source image.

## What you get

- **Choose/replace a Storyblok asset** from the Asset Library.
- **Iterate** using Replicate + the Imagiterate worker.
- **Save** either:
  - to the **field value** (always), and
  - optionally to **Storyblok Assets** (if you configure a Management API token).

## Requirements

- Node.js + npm
- A Storyblok account + a Space
- A Replicate API key (optional; required for generations)
- A Storyblok **Personal Access Token** with **Management API** enabled (optional; required to upload generated images into Storyblok Assets)

## Local development (preview in sandbox)

1. Install dependencies and start the dev server:

```sh
npm install
npm run dev
```

2. Open the Storyblok plugin sandbox while the dev server is running:

- `https://plugin-sandbox.storyblok.com/field-plugin/`

This loads your plugin in an iframe so you can iterate quickly without deploying.

### HTTPS note

This project runs Vite on HTTPS (see `vite.config.ts`). If your browser blocks `https://localhost:8080`, accept the local certificate warning.

## Deploy (publish) the plugin to Storyblok

Deployment registers/updates the Field-type in your Storyblok account (“My Plugins”).

1. Create a Storyblok Personal Access Token:
   - Storyblok → **My account** → **Access tokens**
   - Create a token and enable **Management API**
   - Copy it

2. Set the token as an env var (or use `.env.local`):

```sh
export STORYBLOK_PERSONAL_ACCESS_TOKEN="YOUR_TOKEN"
# or create .env.local with STORYBLOK_PERSONAL_ACCESS_TOKEN=YOUR_TOKEN

npm run build
npm run deploy
```

## Publish to npm (optional)

Publishing to npm is **optional** and does **not** update the plugin inside Storyblok. Think of it as distributing the project/bundle to other developers. To update what editors see in Storyblok, you still run `npm run deploy`.

### Step-by-step

1. Make sure you’re logged in to npm:

```sh
npm login
```

2. Build the package:

```sh
npm run build
```

3. (Recommended) Verify what would be published:

```sh
npm pack --dry-run
```

4. Bump the version:

```sh
npm version patch
# or: npm version minor / npm version major
```

5. Publish (scoped packages usually need `--access public`):

```sh
npm publish --access public
```

### Publish from GitHub (recommended)

This plugin is its **own repo** (there’s a `.git/` inside `imagiterate-storyblok/`), so the workflow lives here:

- `imagiterate-storyblok/.github/workflows/publish-imagiterate-storyblok.yml`

This matches the same workflow style used in `imagiterate-sanity`:

- Publishes on **GitHub Release created**, or
- Publishes via **Actions → Run workflow** (manual)

#### 1) Add the npm token secret

In GitHub: **Repo → Settings → Secrets and variables → Actions → New repository secret**

- **Name**: `NPM_TOKEN`
- **Value**: an npm automation token that can publish `@solspace/imagiterate-storyblok`

#### 2) Publish

- **Recommended**: Create a GitHub Release with tag `vX.Y.Z` (match `package.json`).
- **Manual**: Go to Actions → **Publish to npm** → Run workflow → choose patch/minor/major.

## Install the plugin into your Space

After deploying, you still need to install the Field-type into the Space where you want to use it.

1. Open your Space in Storyblok
2. Go to **My Plugins / Field-types / Apps** (wording varies by UI)
3. Find your field-type (e.g. `imagiterate-storyblok-thejahid`)
4. Click **Install** / **Add to space**

## Add the field to a Component (Content Type)

1. Go to **Block Library** (Components)
2. Open the component you want (e.g. `Page`)
3. Add a new field:
   - Type: **Custom field / Field-type**
   - Select: **Imagiterate** (your deployed field-type)
4. Save the component

Now open a Story that uses that component and you’ll see the Imagiterate field.

## Configure plugin options (recommended)

Options are available at runtime via `useFieldPlugin().data.options`.

`field-plugin.config.json` declares these options:

- `replicateApiKey`
  - **Required** to enable AI generations
  - Get from Replicate
- `managementApiToken`
  - **Optional**, but required if you want “Save to Storyblok & field”
  - Must be a Storyblok **Personal Access Token** with **Management API** enabled
  - Without this, the plugin will still save the generated image URL to the field, but it will not appear in Storyblok’s Asset Library.
- `region`
  - Defaults to `eu`
  - Use `eu`, `us`, or `cn`

Where to set options:

- In Storyblok, edit the field-type/field settings and set these values in the plugin options UI.

## How it works

- The field stores the **selected/generated image URL** as the field value (string). This is the most stable format across save/reload.
- Clicking **Choose asset** uses Storyblok’s asset picker.
- Clicking **Iterate** opens the Imagiterate modal. A prompt triggers generation via the Replicate worker.
- Clicking **Save to Storyblok & field**:
  - uploads the generated image to Storyblok Assets (requires `managementApiToken`)
  - then saves the final Storyblok-hosted URL into the field

## Troubleshooting

- **401 Unauthorized when uploading to Assets**
  - Your `managementApiToken` is not a valid Personal Access Token with Management API enabled
  - Create a new token in **My account → Access tokens**
- **Uploads work but image doesn’t show after refresh**
  - Make sure you clicked Storyblok’s **Save** button in the editor
  - The field value is stored as a URL string; verify the saved Story JSON contains the URL for your field

## License

[MIT](LICENSE) © Solspace