DEV Community

Dylan HUANG
Dylan HUANG

Posted on

Building a Free AI Story Generator with Next.js 15: From Zero to Deployment

How to create a multilingual AI writing tool using the latest Next.js 15 and DeepSeek API

🎯 Project Overview

I recently developed a free AI story generator - aistorygenerators.top, supporting various story types like sci-fi and fairy tales, completely free with no registration required. In this article, I'll share the entire development process, including technology selection, architecture design, and deployment strategies.

Project Features:

  • πŸ†“ Completely free, no registration required
  • 🌍 Bilingual support (English & Chinese)
  • 🎯 Topic-specific story generation
  • πŸ“± Responsive design
  • ⚑ Built with Next.js 15 and TypeScript

πŸ› οΈ Technology Stack Selection

Why Choose Next.js 15?

{
  "framework": "Next.js 15.2.3",
  "reasons": [
    "Powerful App Router system",
    "Built-in internationalization support",
    "Excellent SEO performance",
    "Seamless Vercel deployment integration"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Complete Tech Stack

  • Frontend: Next.js 15 + TypeScript + Tailwind CSS
  • UI Components: shadcn/ui
  • Internationalization: next-intl
  • AI Service: DeepSeek API
  • Deployment: Vercel
  • State Management: React Context

πŸ—οΈ Project Architecture

Directory Structure

aistorygenerators/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ [locale]/          # Internationalized routing
β”‚   β”‚   β”œβ”€β”€ (default)/     # Default layout group
β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx   # Homepage
β”‚   β”‚   β”‚   β”œβ”€β”€ [topic]/   # Dynamic topic pages
β”‚   β”‚   β”‚   └── topics/    # Topics overview
β”‚   β”‚   └── layout.tsx     # Main layout
β”‚   └── api/               # API routes
β”œβ”€β”€ components/            # React components
β”œβ”€β”€ i18n/                 # Internationalization config
└── lib/                  # Utility functions
Enter fullscreen mode Exit fullscreen mode

Core Feature Implementation

1. Internationalization Configuration

// i18n/routing.ts
import {defineRouting} from 'next-intl/routing';

export const routing = defineRouting({
  locales: ['en', 'zh'],
  defaultLocale: 'en',
  localePrefix: 'as-needed'
});
Enter fullscreen mode Exit fullscreen mode

2. Dynamic Topic Routing

// app/[locale]/(default)/[topic]/page.tsx
import { getTopicData } from '@/lib/topics-data';

export async function generateStaticParams() {
  return [
    { topic: 'sci-fi-stories' },
    { topic: 'fairy-tales' },
    // More topics...
  ];
}

export default async function TopicPage({ 
  params 
}: { 
  params: Promise<{ locale: string; topic: string }> 
}) {
  const { locale, topic } = await params;
  const topicData = getTopicData(topic, locale);

  return (
    <div className="container mx-auto px-4 py-8">
      <TopicGenerator topicData={topicData} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

3. AI Story Generation API

// app/api/generate-story/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { generateStoryWithDeepSeek } from '@/lib/deepseek';

export async function POST(request: NextRequest) {
  try {
    const { prompt, topic, length, style } = await request.json();

    // Build topic-specific prompts
    const enhancedPrompt = buildTopicPrompt(prompt, topic, style);

    // Call DeepSeek API
    const story = await generateStoryWithDeepSeek({
      prompt: enhancedPrompt,
      maxTokens: getTokensByLength(length),
      temperature: 0.8
    });

    return NextResponse.json({ story });
  } catch (error) {
    return NextResponse.json(
      { error: 'Story generation failed' }, 
      { status: 500 }
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Topic Data Management

// lib/topics-data.ts
export interface TopicData {
  id: string;
  title: string;
  description: string;
  examples: string[];
  prompts: string[];
  seo: {
    title: string;
    description: string;
    keywords: string;
  };
}

export const topicsData: Record<string, TopicData> = {
  'sci-fi-stories': {
    id: 'sci-fi-stories',
    title: 'AI Sci-Fi Story Generator',
    description: 'Create imaginative science fiction stories...',
    examples: [
      'In 2157, artificial intelligence had already...',
      'The interstellar traveler discovered a...'
    ],
    prompts: [
      'Space exploration',
      'AI awakening',
      'Time travel'
    ],
    seo: {
      title: 'Free AI Sci-Fi Story Generator - Create Future World Stories',
      description: 'Generate original sci-fi stories with AI technology, featuring space, robots, future tech elements...',
      keywords: 'AI sci-fi stories,science fiction generator,free writing tool'
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

🎨 User Experience Optimization

1. Responsive Design

Implementing perfect mobile adaptation with Tailwind CSS:

// components/generator/StoryGenerator.tsx
export default function StoryGenerator() {
  return (
    <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
      {/* Input Area */}
      <div className="space-y-6">
        <Card className="p-6">
          <h2 className="text-xl font-semibold mb-4">
            Story Settings
          </h2>
          {/* Form controls */}
        </Card>
      </div>

      {/* Output Area */}
      <div className="space-y-6">
        <Card className="p-6 min-h-[400px]">
          <h2 className="text-xl font-semibold mb-4">
            Generated Story
          </h2>
          {/* Story content */}
        </Card>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

2. Loading State Management

// hooks/useStoryGenerator.ts
export function useStoryGenerator() {
  const [isGenerating, setIsGenerating] = useState(false);
  const [story, setStory] = useState('');

  const generateStory = async (params: GenerateParams) => {
    setIsGenerating(true);
    try {
      const response = await fetch('/api/generate-story', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(params)
      });

      const data = await response.json();
      setStory(data.story);
    } catch (error) {
      console.error('Generation failed:', error);
    } finally {
      setIsGenerating(false);
    }
  };

  return { story, isGenerating, generateStory };
}
Enter fullscreen mode Exit fullscreen mode

🌍 Internationalization Implementation

1. Translation File Structure

// i18n/messages/en.json
{
  "metadata": {
    "title": "Free AI Story Generator",
    "description": "Generate creative stories with AI..."
  },
  "topics": {
    "sci-fi-stories": {
      "title": "Sci-Fi Story Generator",
      "description": "Create imaginative science fiction stories..."
    }
  },
  "generator": {
    "prompt": "Story prompt",
    "generate": "Generate Story",
    "generating": "Generating..."
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Using Translations in Components

// components/generator/GeneratorForm.tsx
import { useTranslations } from 'next-intl';

export default function GeneratorForm() {
  const t = useTranslations('generator');

  return (
    <form>
      <label>{t('prompt')}</label>
      <textarea placeholder={t('promptPlaceholder')} />
      <button disabled={isGenerating}>
        {isGenerating ? t('generating') : t('generate')}
      </button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

πŸš€ Deployment and Optimization

1. Vercel Deployment Configuration

// vercel.json
{
  "buildCommand": "pnpm build",
  "outputDirectory": ".next",
  "framework": "nextjs",
  "functions": {
    "app/api/generate-story/route.ts": {
      "maxDuration": 30
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Environment Variables Setup

# .env.local
DEEPSEEK_API_KEY=your_api_key_here
NEXT_PUBLIC_SITE_URL=https://aistorygenerators.top
NEXT_PUBLIC_SITE_NAME=AI Story Generator
Enter fullscreen mode Exit fullscreen mode

3. SEO Optimization

// app/[locale]/layout.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'metadata' });

  return {
    title: t('title'),
    description: t('description'),
    alternates: {
      canonical: getCanonicalUrl(locale),
      languages: {
        'en': 'https://aistorygenerators.top',
        'zh': 'https://aistorygenerators.top/zh',
        'x-default': 'https://aistorygenerators.top'
      }
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

πŸ“Š Performance Monitoring

1. Core Web Vitals Optimization

  • LCP: Controlled within 2.5 seconds through image optimization and code splitting
  • FID: Using React.lazy() for lazy loading non-critical components
  • CLS: Reserving space for dynamic content to avoid layout shifts

2. Monitoring Tools Integration

// app/layout.tsx
import { GoogleAnalytics } from '@next/third-parties/google';

export default function RootLayout({ children }: Props) {
  return (
    <html>
      <body>
        {children}
        <GoogleAnalytics gaId="G-XXXXXXXXXX" />
      </body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

🎯 Key Learning Points

1. Next.js 15 New Features Application

  • Async params handling: Adapting to new parameter processing methods
  • Improved App Router: Better routing performance and SEO
  • Enhanced internationalization: More concise multilingual implementation

2. AI Integration Best Practices

  • Prompt engineering: Optimizing prompts for different topics
  • Error handling: Gracefully handling API call failures
  • User experience: Real-time feedback and loading states

3. Performance Optimization Strategies

  • Code splitting: Loading components and pages on demand
  • Image optimization: Using Next.js Image component
  • Caching strategy: Proper use of static generation and server-side rendering

πŸ”— Project Resources

  • Live Demo: aistorygenerators.top
  • Technical Documentation: Detailed development docs and API documentation

πŸ’‘ Summary

Through this project, I gained deep experience with Next.js 15's powerful features, especially in internationalization and AI integration. Key takeaways include:

  1. Importance of architecture design: Good directory structure lays the foundation for future expansion
  2. User experience first: Responsive design and loading state management are crucial
  3. SEO optimization: Multilingual websites require special attention to SEO
  4. Performance monitoring: Continuous monitoring and optimization are keys to success

If you're also considering building AI applications, I hope this case study provides some inspiration. Feel free to share your thoughts and questions in the comments!


Tags: #nextjs #typescript #ai #webdev #react

Top comments (0)