This is a submission for the Storyblok Challenge
What I Built
AI Blog Studio is a multimedia content generation platform that combines AI technologies with Storyblok's headless CMS. The application generates blog posts with AI-written content, contextual images, and audio narration, then stores and manages this content through Storyblok's API.
The platform automates the creation of multimedia blog posts while providing content creators with control over the generation process. Users can create complete blog experiences including text, images, and audio accessibility features through a single interface.
Demo
Live Application: https://aiblogstudio.chronolove.app/
Admin Access: Visit login page and use password: devtosecurestoryblokpassword123
Storyblok Space:
https://app.storyblok.com/#/me/spaces/285396856923566
This application uses Storyblok as a headless CMS backend for content storage. Content is managed via Storyblok's Management API and displayed through the frontend at https://aiblogstudio.chronolove.app. User when logged in can access the admin page and access all functionalities to generate multimedia blog posts with the help of AI.
Code Repository:
https://github.com/bO-05/aiblogstudio
Screenshots
Login page with password field (Password:
devtosecurestoryblokpassword123
)
Network tab showing Storyblok API calls when publishing blog post
Individual blog post without active audio player (only logged in user can generate audio)
Tech Stack
Frontend & Core
- React 18 with TypeScript
- Vite for development and builds
- React Router DOM for client-side routing
- Tailwind CSS for styling
- Framer Motion for animations
- Lucide React for icons
AI Services
-
Mistral AI (
mistral-large-latest
) for content generation - FAL AI with Imagen4 for image generation
- ElevenLabs for text-to-speech audio
Content Management
- Storyblok CMS as headless backend
- Storyblok JS Client for API integration
- LocalStorage for session management
Deployment
- Netlify for hosting with serverless functions
- Netlify Functions for production audio generation
How I Used Storyblok
Headless CMS Implementation
I implemented Storyblok as a headless CMS backend, using it for content storage while building a custom React frontend. The application uses Storyblok's Management API for content operations and the Delivery API for content retrieval.
Content Type Structure
Created a blog_post
content type in Storyblok with these fields:
-
title
(Text) - Blog post headlines -
content
(Rich Text) - Full markdown content -
excerpt
(Text) - Post summaries -
image
(Asset) - AI-generated images with external URL support -
audio
(Asset) - Text-to-speech audio stored as data URLs -
theme
(Text) - Content categorization -
tone
(Text) - Writing style metadata
API Integration
The application uses environment variables for Storyblok configuration:
// Environment setup
VITE_STORYBLOK_TOKEN=your_storyblok_preview_token
VITE_STORYBLOK_MANAGEMENT_TOKEN=your_storyblok_management_token
VITE_STORYBLOK_SPACE_ID=your_space_id
Content Publishing:
const publishPost = async (post: BlogPost) => {
const spaceId = import.meta.env.VITE_STORYBLOK_SPACE_ID;
const managementToken = import.meta.env.VITE_STORYBLOK_MANAGEMENT_TOKEN;
const storyData = {
story: {
name: post.title,
slug: `blog/${slug}`,
content: {
component: 'blog_post',
title: post.title,
content: post.content,
excerpt: post.excerpt,
image: post.imageUrl,
audio: post.audioUrl,
theme: post.theme,
tone: post.tone
}
}
};
const createResponse = await storyblokManagement.post(
`spaces/${spaceId}/stories`,
storyData
);
await storyblokManagement.get(
`spaces/${spaceId}/stories/${storyId}/publish`
);
};
Content Retrieval:
const getStories = async () => {
const response = await storyblok.get('cdn/stories', {
version: 'published',
content_type: 'blog_post',
starts_with: 'blog/',
per_page: 100,
cv: Date.now() // Cache busting
});
};
Key Storyblok Features Used
- Management API for CRUD operations
- Delivery API for content retrieval
- Folder Management with automatic blog folder creation
- Content Publishing with immediate availability
- Asset Handling for images and audio data URLs
- Slug Generation for SEO-friendly URLs
AI Integration
Content Generation with Mistral AI
Uses Mistral's mistral-large-latest
model for blog content generation:
const generateContent = async (request: GenerationRequest) => {
const response = await axios.post(MISTRAL_API_URL, {
model: 'mistral-large-latest',
messages: [{
role: 'user',
content: prompt
}],
temperature: 0.7,
max_tokens: 4000
}, {
headers: {
'Authorization': `Bearer ${import.meta.env.VITE_MISTRAL_API_KEY}`,
'Content-Type': 'application/json'
}
});
};
Features:
- Configurable word counts (300-2000 words)
- Three tone options (professional, casual, humorous)
- JSON response parsing with fallback handling
- Title and excerpt generation
Image Generation with Imagen4
Uses FAL AI's Imagen4 API for contextual image generation:
const generateImage = async (theme: string) => {
const response = await axios.post(FAL_API_URL, {
prompt: atmosphericPrompt,
aspect_ratio: "16:9",
num_images: 1
}, {
headers: {
'Authorization': `Key ${import.meta.env.VITE_FAL_API_KEY}`,
'Content-Type': 'application/json'
}
});
};
Features:
- Theme-based prompt generation
- Atmospheric scene composition
- 16:9 aspect ratio for blog headers
- Fallback to placeholder images
Text-to-Speech with ElevenLabs
Dual-environment audio generation system:
Production (Netlify Functions):
exports.handler = async (event) => {
const response = await fetch(`${ELEVENLABS_API_URL}/${VOICE_ID}`, {
method: 'POST',
headers: {
'xi-api-key': process.env.ELEVENLABS_API_KEY
},
body: JSON.stringify({
text: cleanText,
model_id: 'eleven_turbo_v2'
})
});
const audioBuffer = await response.arrayBuffer();
const audioBase64 = Buffer.from(audioBuffer).toString('base64');
return {
statusCode: 200,
body: JSON.stringify({
audio: audioBase64,
contentType: 'audio/mpeg'
})
};
};
Development (Client-side):
const generateAudio = async (text: string) => {
const response = await axios.post(
`${ELEVENLABS_API_URL}/${voiceId}`,
{
text: prepareTextForTTS(text),
model_id: 'eleven_turbo_v2',
voice_settings: {
stability: 0.5,
similarity_boost: 0.5
}
},
{
headers: {
'xi-api-key': import.meta.env.VITE_ELEVENLABS_API_KEY
},
responseType: 'blob'
}
);
};
Features:
- Rachel voice model for consistent narration
- Markdown content cleaning for natural speech
- Base64 data URL storage for Storyblok persistence
- Environment-specific implementation
AI Content Warnings
The application includes disclaimers about AI-generated content limitations and potential inaccuracies, encouraging users to review content before publication.
Learnings and Takeaways
Technical Challenges Solved
Audio Storage in Storyblok: The main challenge was storing dynamically generated audio files. I solved this by converting audio to base64 data URLs and storing them directly in Storyblok content fields, eliminating the need for external file hosting.
Cross-Environment Audio Generation: Created a system that automatically detects the environment and uses either client-side APIs (development) or Netlify serverless functions (production) for audio generation.
Multi-Service AI Integration: Coordinating three different AI services with different response formats and rate limits required careful error handling and user feedback systems.
Storyblok Implementation Insights
Headless Architecture Benefits: Using Storyblok as a pure backend provided flexibility in frontend design while maintaining robust content management capabilities.
API Token Management: Implemented secure token handling with separate preview and management tokens, plus proper environment variable configuration.
Content Type Design: Balancing flexibility with structure in the blog_post content type, especially for multimedia content with both traditional assets and data URLs.
Development Experience
Environment Configuration: Managing multiple API keys across development and production environments required careful setup and validation systems.
Rate Limiting: Implemented configurable rate limiting to prevent API cost overruns while maintaining user experience.
Error Handling: Each AI service has different failure modes, requiring specific error handling strategies and meaningful user feedback.
What I Learned
Headless CMS Integration: Gained experience with Storyblok's Management and Delivery APIs, understanding the benefits of headless architecture for custom applications.
AI Service Orchestration: Learned to coordinate multiple AI services effectively, handling different response formats and implementing fallback strategies.
Team
This project was developed by async_dime.
Built using React, TypeScript, Storyblok, and AI technologies
Live Demo: Live demo | Admin: /login with password devtosecurestoryblokpassword123
Top comments (0)