DEV Community

Adam
Adam Subscriber

Posted on

AI Blog Studio: Multimedia Content Generation with AI & Storyblok

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

  • Homepage showing published blog posts
    Homepage showing published blog posts

  • Login page with password field (Password: devtosecurestoryblokpassword123)
    Login page with password field

  • Admin panel content generation form
    Admin panel content generation form

  • Modal showing blog generated successfully
    Modal showing blog generated successfully

  • Timeline view showing post with no playable audio status
    Timeline view showing post with no playable audio status

  • Timeline view showing post with playable audio status
    Timeline view showing post with playable audio status

  • Network tab showing Storyblok API calls when publishing blog post
    Network tab showing Storyblok API calls when publishing blog post

  • Storyblok content tab with published status of blog post
    Storyblok content tab with published status of blog post

  • List of blog posts in /blog page
    List of blog posts in /blog page

  • Individual blog post without active audio player (only logged in user can generate audio)
    Individual blog post without active audio player

  • Individual blog post with active audio player
    Individual blog post with active audio player

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  raw `blog_post` endraw  content type with title, content, excerpt, image, theme, tone, audio fields

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
Enter fullscreen mode Exit fullscreen mode

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`
  );
};
Enter fullscreen mode Exit fullscreen mode

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
  });
};
Enter fullscreen mode Exit fullscreen mode

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'
    }
  });
};
Enter fullscreen mode Exit fullscreen mode

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'
    }
  });
};
Enter fullscreen mode Exit fullscreen mode

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'
    })
  };
};
Enter fullscreen mode Exit fullscreen mode

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'
    }
  );
};
Enter fullscreen mode Exit fullscreen mode

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)