meowww-storyblok-proxy
v0.0.21
Published
Storyblok Proxy
Readme
meowww-storyblok-proxy
A powerful Nuxt module that provides a comprehensive proxy between your Nuxt app and the Storyblok API. It handles API routes, asset requests, authentication, caching, and webhook processing with Storyblok access tokens.
✨ Features
- 🔄 API Proxy: Seamless proxying of all Storyblok API requests
- 🖼️ Asset Handling: Proxied asset requests with signed URLs and image operations
- ⚡ Smart Caching: Configurable caching strategies with SWR support
- 🔐 Secure: Server-side token handling (never exposed to client)
- 📄 Auto-Pagination: Automatic pagination for large datasets
- 🎣 Webhook Support: Built-in webhook handling for content updates
- 🧩 TypeScript: Full TypeScript support with comprehensive type definitions
- 🎨 Composables: Ready-to-use composables for common operations
Installation
npm install meowww-storyblok-proxy
# or
yarn add meowww-storyblok-proxy
# or
pnpm add meowww-storyblok-proxyAdd the module to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['meowww-storyblok-proxy'],
storyblokProxy: {
accessToken: process.env.STORYBLOK_TOKEN,
assetToken: process.env.STORYBLOK_ASSET_TOKEN,
nuxtBase: 'https://yourdomain.com', // Required: Your app's base URL
version: 'published', // or 'draft'
},
})Configuration
All options can be configured under the storyblokProxy key in nuxt.config.ts.
Default values are shown below.
interface ModuleOptions {
/** Enable debug logging */
debug: boolean
/** Base route for the proxy (default: '/cms') */
routeBase: string
/** Sub-route for assets (default: '/_assets') */
assetBase: string
/** Base URL of the application (including protocol and host) */
nuxtBase: string
/** Storyblok Content Delivery API token */
accessToken: string
/** Storyblok Asset token for secured media */
assetToken: string
/** Webhook URL path for Storyblok webhooks */
webhookUrl: string
/** Secret for webhook verification */
webhookSecret: string
/** Content version ('draft' or 'published') */
version: 'draft' | 'published'
/** Storyblok API region */
region: 'eu' | 'us' | 'ap' | 'ca' | 'cn'
/** Enable automatic pagination for API calls */
autoPaginate: boolean
/** Cache configuration */
cache: {
/** Cache strategy for API routes */
type: 'private' | 'public' | 'client' | 'disabled'
/** Cache duration in seconds */
maxAge: number
/** Enable stale-while-revalidate */
swr: boolean
/** Asset cache configuration */
assets: {
/** Cache strategy for assets */
type: 'private' | 'public' | 'client' | 'disabled'
/** Cache duration in seconds */
maxAge: number
/** Enable stale-while-revalidate */
swr: boolean
}
}
/** Map of storyblok image operations, 'header' => '500x0' */
imageOperations?: Record<string, string>
}General Options
| Option | Type | Default | Description |
| ---------------- | -------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| debug | boolean | false | Enables debug logs for troubleshooting. |
| routeBase | string | '/cms' | Base route for the proxy. All Storyblok API requests are served through this path. |
| assetBase | string | '/_assets' | Sub-route for Storyblok assets (e.g., images). |
| nuxtBase | string | '' | Base URL of the application (including protocol and host). Example: http://localhost:3000. This value is used to build the internal endpoint for the installed @storyblok/nuxt plugin (endpoint: ${options.nuxtBase}${options.routeBase}`). |
| accessToken | string | '' | Storyblok Content Delivery API token. |
| assetToken | string | '' | Storyblok Asset token for secured media. |
| webhookUrl | string | '' | Webhook URL path for Storyblok webhooks (e.g., /webhook). |
| webhookSecret | string | '' | Secret for webhook verification. |
| version | 'draft' \| 'published' | 'draft' | Defines whether draft or published content should be loaded. |
| region | 'eu' \| 'us' \| 'ap' \| 'ca' \| 'cn' | 'eu' | Storyblok API region, depending on your space. |
| autoPaginate | boolean | false | Enable automatic pagination for API calls to fetch all results. |
Cache Options
| Option | Type | Default | Description |
| --------------------- | ----------------------------------------- | ----------- | --------------------------------------- |
| cache.type | 'private' \| 'public' \| 'client' \| 'disabled' | 'private' | Cache strategy for API routes. |
| cache.maxAge | number | 60 | Time in seconds to cache API responses. |
| cache.swr | boolean | true | Enables stale-while-revalidate. |
| cache.assets.type | 'private' \| 'public' \| 'client' \| 'disabled' | 'client' | Cache strategy for assets. |
| cache.assets.maxAge | number | 60 | Time in seconds to cache assets. |
| cache.assets.swr | boolean | true | Enables SWR for assets. |
Cache Strategies
private: Cache on the server only (default for API routes)public: Cache on both server and clientclient: Cache on the client only (default for assets)disabled: No caching
Routes
When enabled, the module registers the following routes:
- Content API:
${routeBase}/**→ Proxied requests to Storyblok Content API - Links API:
${routeBase}/_links→ Proxy for the Storyblok Links API - Assets:
${routeBase}${assetBase}/**→ Proxy for Storyblok assets - Webhooks:
${routeBase}${webhookUrl}→ Webhook endpoint (if configured)
Example Configuration
export default defineNuxtConfig({
modules: ['meowww-storyblok-proxy'],
storyblokProxy: {
debug: true,
routeBase: '/cms',
assetBase: '/_assets',
nuxtBase: 'http://localhost:3000',
accessToken: process.env.STORYBLOK_TOKEN,
assetToken: process.env.STORYBLOK_ASSET_TOKEN,
webhookUrl: '/webhook',
webhookSecret: process.env.STORYBLOK_WEBHOOK_SECRET,
version: 'draft',
region: 'eu',
autoPaginate: true,
cache: {
type: 'private',
maxAge: 120,
swr: true,
assets: {
type: 'public',
maxAge: 300,
swr: true,
},
},
},
})Usage
This module automatically installs @storyblok/nuxt.
You can use the composables it provides to fetch content.
Fetching a Story
<script setup lang="ts">
const story = await useStoryblok('home')
</script>
<template>
<div>
<h1>{{ story.content.title }}</h1>
<p>{{ story.content.intro }}</p>
</div>
</template>Using the Proxy
Because the module rewrites the API endpoint, requests will automatically go through your Nuxt server:
// Instead of calling api.storyblok.com directly
// The request goes through: /cms/...
const story = await useStoryblok('about')Fetching Links
<script setup lang="ts">
const links = await useStoryblokProxyLinks()
</script>
<template>
<nav>
<NuxtLink
v-for="link in links"
:key="link.id"
:to="link.slug"
>
{{ link.name }}
</NuxtLink>
</nav>
</template>Fetching Assets
<template>
<!-- Assets are proxied through /cms/_assets/... -->
<img
:src="useStoryblokProxyAsset(storyblok_image.filename, '0x300')"
alt="Storyblok Asset"
/>
</template>Server-Side API Calls
You can also use the proxy utilities directly in server-side code:
// server/api/custom.ts
import { call, cachedCall, asset, cachedAsset, config } from '#storyblok-proxy'
export default defineEventHandler(async () => {
// Direct API call
const url = new URL('/stories', 'http://localhost')
const stories = await call(url, config.autoPaginate)
// Cached API call
const cachedStories = await cachedCall(url, config.autoPaginate)
// Asset handling
const assetUrl = new URL('/f/123456/image.jpg', 'https://a.storyblok.com')
const assetData = await cachedAsset(assetUrl, '0x300')
return { stories, assetData }
})Notes
- The module automatically installs and configures
@storyblok/nuxt. - Tokens (
accessToken,assetToken) are stored securely and never exposed to the client. - The
versionoption is available through thestoryblok-proxy-config.mjsfile for client-side access. - All API calls are automatically proxied through your Nuxt server for better performance and security.
- Caching is handled by Nitro's built-in caching system with configurable strategies.
- Webhook support allows for real-time content updates and cache invalidation.
- Server-side utilities are available through the
#storyblok-proxyvirtual module.
Development
Building
npm run buildTesting
npm run testDevelopment Mode
npm run devContributing
Contributions are welcome! Please feel free to submit a Pull Request.
Made with ❤️ by [email protected]
