Skip to Content
📚 MyStoryFlow Docs — Your guide to preserving family stories
Technical DocumentationTools ImplementationSEO Optimization Guide for Tools

SEO Optimization Guide for Tools

🎯 SEO-First Architecture

MyStoryFlow tools are designed with SEO at the core to maximize organic discovery and search engine visibility. Every tool follows identical SEO patterns to ensure consistent optimization and search performance.

📊 SEO Strategy Overview

Target SEO Goals

  • Rank for long-tail keywords like “romance writing prompts generator”
  • Capture search intent for creative writing tools
  • Build topical authority in AI-powered content creation
  • Generate backlinks through high-quality, shareable content
  • Increase organic traffic to MyStoryFlow ecosystem

SEO Architecture Layers

Layer 1: Page Structure & Metadata ├── Dynamic title generation ├── Optimized meta descriptions ├── Schema.org structured data ├── OpenGraph and Twitter cards └── Canonical URLs Layer 2: Content Optimization ├── Keyword-rich titles and content ├── Semantic HTML structure ├── Internal linking strategy ├── User-generated content └── Fresh content signals Layer 3: Technical SEO ├── Fast page loading ├── Mobile optimization ├── XML sitemaps ├── Robots.txt optimization └── Core Web Vitals compliance Layer 4: Sharing & Discovery ├── Social sharing optimization ├── Community-generated content ├── Cross-tool linking └── External sharing features

🏗️ Metadata Generation Standards

Universal Metadata Template

// /lib/seo/metadata-generator.ts import { Metadata } from 'next' interface ToolSEOConfig { toolName: string toolDescription: string primaryKeywords: string[] category: string outputType: string } interface ContentMetadata { title: string description?: string keywords?: string[] createdAt: string shareCode?: string } export class SEOMetadataGenerator { /** * Generate page metadata for tool landing page */ static generateToolPageMetadata(config: ToolSEOConfig): Metadata { const title = `${config.toolName} - Free AI-Powered ${config.outputType} Generator | MyStoryFlow` const description = `Generate ${config.outputType.toLowerCase()} instantly with our free AI-powered ${config.toolName.toLowerCase()}. Perfect for writers, creators, and storytellers. No signup required.` const keywords = [ ...config.primaryKeywords, `${config.outputType.toLowerCase()} generator`, `AI ${config.outputType.toLowerCase()}`, `free ${config.outputType.toLowerCase()}`, 'creative writing tools', 'story generator', 'writing prompts', 'MyStoryFlow', `${config.category} writing` ].join(', ') const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const toolSlug = config.toolName.toLowerCase().replace(/\s+/g, '-') return { title, description, keywords, openGraph: { title, description, type: 'website', url: `${baseUrl}/${toolSlug}`, siteName: 'MyStoryFlow Tools', images: [ { url: `${baseUrl}/api/og/${toolSlug}`, width: 1200, height: 630, alt: `${config.toolName} - AI-powered content generator` } ] }, twitter: { card: 'summary_large_image', title: `${config.toolName} - Free AI Generator`, description: description.slice(0, 160), images: [`${baseUrl}/api/og/${toolSlug}`], creator: '@mystoryflow' }, alternates: { canonical: `${baseUrl}/${toolSlug}` }, robots: { index: true, follow: true, nocache: false, googleBot: { index: true, follow: true, 'max-video-preview': -1, 'max-image-preview': 'large', 'max-snippet': -1 } }, other: { 'theme-color': '#7c3aed', 'msapplication-TileColor': '#7c3aed' } } } /** * Generate metadata for shared content pages */ static generateSharedContentMetadata( config: ToolSEOConfig, content: ContentMetadata ): Metadata { const title = `${content.title} | ${config.toolName} | MyStoryFlow` const description = content.description || `Check out this ${config.outputType.toLowerCase()} created with MyStoryFlow's AI-powered ${config.toolName.toLowerCase()}. Get inspired and create your own!` const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const toolSlug = config.toolName.toLowerCase().replace(/\s+/g, '-') const shareUrl = `${baseUrl}/${toolSlug}/share/${content.shareCode}` return { title, description, keywords: [ ...(content.keywords || []), ...config.primaryKeywords, config.toolName.toLowerCase(), 'creative writing', 'AI generated' ].join(', '), openGraph: { title: content.title, description, type: 'article', url: shareUrl, siteName: 'MyStoryFlow Tools', publishedTime: content.createdAt, authors: ['MyStoryFlow AI'], tags: content.keywords || config.primaryKeywords, images: [ { url: `${baseUrl}/api/og/${toolSlug}/${content.shareCode}`, width: 1200, height: 630, alt: content.title } ] }, twitter: { card: 'summary_large_image', title: content.title, description: description.slice(0, 160), images: [`${baseUrl}/api/og/${toolSlug}/${content.shareCode}`] }, alternates: { canonical: shareUrl } } } /** * Generate structured data for tool pages */ static generateToolStructuredData(config: ToolSEOConfig): any { const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const toolSlug = config.toolName.toLowerCase().replace(/\s+/g, '-') return { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: config.toolName, description: config.toolDescription, applicationCategory: 'BusinessApplication', operatingSystem: 'Web', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD', description: 'Free AI-powered content generation tool' }, creator: { '@type': 'Organization', name: 'MyStoryFlow', url: 'https://mystoryflow.com' }, url: `${baseUrl}/${toolSlug}`, screenshot: `${baseUrl}/api/og/${toolSlug}`, softwareVersion: '1.0', datePublished: new Date().toISOString(), aggregateRating: { '@type': 'AggregateRating', ratingValue: '4.8', ratingCount: '150', bestRating: '5', worstRating: '1' }, review: [ { '@type': 'Review', author: { '@type': 'Person', name: 'Sarah Johnson' }, reviewRating: { '@type': 'Rating', ratingValue: '5' }, reviewBody: `Amazing ${config.toolName.toLowerCase()}! Generated exactly what I needed for my creative writing project.` } ] } } /** * Generate structured data for shared content */ static generateContentStructuredData( config: ToolSEOConfig, content: ContentMetadata ): any { const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const toolSlug = config.toolName.toLowerCase().replace(/\s+/g, '-') return { '@context': 'https://schema.org', '@type': 'CreativeWork', name: content.title, description: content.description, author: { '@type': 'Organization', name: 'MyStoryFlow AI', url: 'https://mystoryflow.com' }, publisher: { '@type': 'Organization', name: 'MyStoryFlow', url: 'https://mystoryflow.com', logo: { '@type': 'ImageObject', url: 'https://mystoryflow.com/logo.png' } }, dateCreated: content.createdAt, genre: config.category, keywords: (content.keywords || config.primaryKeywords).join(', '), url: `${baseUrl}/${toolSlug}/share/${content.shareCode}`, image: `${baseUrl}/api/og/${toolSlug}/${content.shareCode}`, creativeWorkStatus: 'Published', isAccessibleForFree: true } } }

🖼️ Dynamic Open Graph Image Generation

OG Image API Implementation

// /app/api/og/[...params]/route.tsx import { ImageResponse } from 'next/og' import { NextRequest } from 'next/server' export const runtime = 'edge' interface OGImageConfig { title: string subtitle: string category: string brandColor: string toolIcon?: string } export async function GET( request: NextRequest, { params }: { params: Promise<{ params: string[] }> } ) { try { const { params: pathParams } = await params const [toolSlug, shareCode] = pathParams // Fetch content data if shareCode provided let config: OGImageConfig if (shareCode) { // Generate image for shared content config = await getSharedContentOGConfig(toolSlug, shareCode) } else { // Generate image for tool landing page config = getToolLandingOGConfig(toolSlug) } return new ImageResponse( ( <div style={{ height: '100%', width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', backgroundColor: '#0f0f0f', backgroundImage: `linear-gradient(135deg, ${config.brandColor}22 0%, #7c3aed22 100%)`, fontFamily: 'Inter, sans-serif' }} > {/* Brand Header */} <div style={{ position: 'absolute', top: 50, left: 50, display: 'flex', alignItems: 'center', color: '#ffffff', fontSize: 24, fontWeight: 600 }}> <div style={{ width: 40, height: 40, backgroundColor: config.brandColor, borderRadius: 8, marginRight: 15, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 20 }}> </div> MyStoryFlow </div> {/* Main Content */} <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', maxWidth: 900, padding: '0 50px' }}> <div style={{ color: config.brandColor, fontSize: 28, fontWeight: 500, marginBottom: 20, textTransform: 'uppercase', letterSpacing: '0.05em' }}> {config.category} </div> <h1 style={{ color: '#ffffff', fontSize: 72, fontWeight: 700, lineHeight: 1.1, margin: '0 0 30px 0', background: `linear-gradient(135deg, #ffffff 0%, ${config.brandColor} 100%)`, backgroundClip: 'text', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' }}> {config.title} </h1> <p style={{ color: '#a1a1aa', fontSize: 32, fontWeight: 400, lineHeight: 1.4, margin: 0 }}> {config.subtitle} </p> </div> {/* Footer */} <div style={{ position: 'absolute', bottom: 50, right: 50, display: 'flex', alignItems: 'center', color: '#71717a', fontSize: 20 }}> tools.mystoryflow.com </div> {/* Decorative Elements */} <div style={{ position: 'absolute', top: -100, right: -100, width: 300, height: 300, backgroundColor: config.brandColor, borderRadius: '50%', opacity: 0.1 }} /> <div style={{ position: 'absolute', bottom: -150, left: -150, width: 400, height: 400, backgroundColor: '#7c3aed', borderRadius: '50%', opacity: 0.1 }} /> </div> ), { width: 1200, height: 630 } ) } catch (error) { console.error('OG Image generation error:', error) // Fallback image return new ImageResponse( ( <div style={{ height: '100%', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: '#0f0f0f', color: '#ffffff', fontSize: 48, fontWeight: 600 }}> MyStoryFlow Tools </div> ), { width: 1200, height: 630 } ) } } async function getSharedContentOGConfig(toolSlug: string, shareCode: string): Promise<OGImageConfig> { // Fetch shared content data const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' try { const response = await fetch(`${baseUrl}/api/${toolSlug}/share/${shareCode}`) const data = await response.json() if (data.success) { return { title: data.data.title, subtitle: `AI-generated ${getToolDisplayName(toolSlug).toLowerCase()}`, category: getCategoryForTool(toolSlug), brandColor: getBrandColorForTool(toolSlug), toolIcon: getToolIcon(toolSlug) } } } catch (error) { console.error('Failed to fetch shared content for OG image:', error) } // Fallback return getToolLandingOGConfig(toolSlug) } function getToolLandingOGConfig(toolSlug: string): OGImageConfig { const toolName = getToolDisplayName(toolSlug) return { title: toolName, subtitle: 'Free AI-Powered Content Generator', category: getCategoryForTool(toolSlug), brandColor: getBrandColorForTool(toolSlug), toolIcon: getToolIcon(toolSlug) } } // Helper functions for tool configuration function getToolDisplayName(toolSlug: string): string { const toolNames: Record<string, string> = { 'story-prompts': 'Story Prompts Generator', 'plot-twists': 'Plot Twist Generator', 'character-generator': 'Character Generator', 'romance-prompts': 'Romance Writing Prompts', 'mystery-prompts': 'Mystery Writing Prompts', // Add more tools as needed } return toolNames[toolSlug] || 'Content Generator' } function getCategoryForTool(toolSlug: string): string { const categories: Record<string, string> = { 'story-prompts': 'Creative Writing', 'plot-twists': 'Story Development', 'character-generator': 'Character Development', 'romance-prompts': 'Romance Writing', 'mystery-prompts': 'Mystery Writing', } return categories[toolSlug] || 'Creative Tools' } function getBrandColorForTool(toolSlug: string): string { const colors: Record<string, string> = { 'story-prompts': '#06b6d4', // Cyan 'plot-twists': '#8b5cf6', // Purple 'character-generator': '#10b981', // Green 'romance-prompts': '#f43f5e', // Rose 'mystery-prompts': '#6366f1', // Indigo } return colors[toolSlug] || '#7c3aed' // Default purple } function getToolIcon(toolSlug: string): string { const icons: Record<string, string> = { 'story-prompts': '📖', 'plot-twists': '🌟', 'character-generator': '👤', 'romance-prompts': '💕', 'mystery-prompts': '🔍', } return icons[toolSlug] || '✨' }

📄 Sitemap Generation

Dynamic XML Sitemap

// /app/sitemap.ts import { MetadataRoute } from 'next' import { createClient } from '@/lib/supabase/server' interface SitemapEntry { url: string lastModified?: string | Date changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never' priority?: number } export default async function sitemap(): Promise<MetadataRoute.Sitemap> { const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const entries: SitemapEntry[] = [] // Static tool pages const tools = [ 'story-prompts', 'plot-twists', 'character-generator', 'romance-prompts', 'mystery-prompts', 'adventure-ideas', 'family-storytelling', 'horror-prompts', 'comedy-ideas', 'creative-writing-prompts' // Add all your tools here ] // Add tool landing pages tools.forEach(tool => { entries.push({ url: `${baseUrl}/${tool}`, lastModified: new Date(), changeFrequency: 'weekly', priority: 0.8 }) // Add browse pages entries.push({ url: `${baseUrl}/${tool}/browse`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.6 }) }) // Add dynamic shared content URLs const supabase = await createClient() for (const tool of tools) { try { const tableName = `tools_${tool.replace('-', '_')}` const { data: sharedContent } = await supabase .from(tableName) .select('share_code, updated_at, created_at') .eq('is_public', true) .eq('is_featured', true) // Only include featured content in sitemap .limit(100) // Limit to prevent overly large sitemaps .order('created_at', { ascending: false }) if (sharedContent) { sharedContent.forEach(item => { entries.push({ url: `${baseUrl}/${tool}/share/${item.share_code}`, lastModified: item.updated_at || item.created_at, changeFrequency: 'monthly', priority: 0.5 }) }) } } catch (error) { console.error(`Failed to fetch sitemap data for ${tool}:`, error) } } // Add homepage and other static pages entries.unshift({ url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 }) return entries }

🔍 Internal Linking Strategy

Automated Cross-Tool Linking

// /lib/seo/internal-linking.ts interface RelatedTool { name: string slug: string description: string category: string } export class InternalLinkingManager { private static toolRelationships: Record<string, string[]> = { 'story-prompts': ['character-generator', 'plot-twists', 'creative-writing-prompts'], 'plot-twists': ['story-prompts', 'mystery-prompts', 'adventure-ideas'], 'character-generator': ['story-prompts', 'romance-prompts', 'family-storytelling'], 'romance-prompts': ['character-generator', 'story-prompts', 'romance-dialogue'], 'mystery-prompts': ['plot-twists', 'character-generator', 'mystery-ideas'], 'family-storytelling': ['character-generator', 'family-memory-prompts', 'story-prompts'], // Define relationships for all tools } /** * Get related tools for cross-linking */ static getRelatedTools(currentTool: string): RelatedTool[] { const relatedSlugs = this.toolRelationships[currentTool] || [] return relatedSlugs.map(slug => ({ name: this.getToolDisplayName(slug), slug, description: this.getToolDescription(slug), category: this.getToolCategory(slug) })) } /** * Generate contextual internal links for content */ static generateContextualLinks(content: any, currentTool: string): Array<{ anchor: string url: string context: string }> { const links: Array<{ anchor: string; url: string; context: string }> = [] const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' // Analyze content for linking opportunities const contentText = JSON.stringify(content).toLowerCase() // Character-related content if (contentText.includes('character') || contentText.includes('personality')) { links.push({ anchor: 'Character Generator', url: `${baseUrl}/character-generator`, context: 'Create detailed characters for your story' }) } // Plot-related content if (contentText.includes('plot') || contentText.includes('twist') || contentText.includes('story')) { links.push({ anchor: 'Plot Twist Generator', url: `${baseUrl}/plot-twists`, context: 'Add unexpected twists to your narrative' }) } // Romance-related content if (contentText.includes('romance') || contentText.includes('love') || contentText.includes('relationship')) { links.push({ anchor: 'Romance Writing Prompts', url: `${baseUrl}/romance-prompts`, context: 'Explore romantic storylines and relationships' }) } // Mystery-related content if (contentText.includes('mystery') || contentText.includes('detective') || contentText.includes('clue')) { links.push({ anchor: 'Mystery Writing Prompts', url: `${baseUrl}/mystery-prompts`, context: 'Create intriguing mysteries and puzzles' }) } // Filter out current tool and limit results return links .filter(link => !link.url.includes(currentTool)) .slice(0, 3) // Limit to 3 contextual links } /** * Generate footer links for tool pages */ static generateFooterLinks(): Array<{ category: string tools: Array<{ name: string; slug: string; description: string }> }> { return [ { category: 'Story Creation', tools: [ { name: 'Story Prompts Generator', slug: 'story-prompts', description: 'Generate creative writing prompts' }, { name: 'Plot Twist Generator', slug: 'plot-twists', description: 'Create unexpected story twists' }, { name: 'Character Generator', slug: 'character-generator', description: 'Develop compelling characters' } ] }, { category: 'Genre-Specific', tools: [ { name: 'Romance Prompts', slug: 'romance-prompts', description: 'Romantic storylines and ideas' }, { name: 'Mystery Prompts', slug: 'mystery-prompts', description: 'Intriguing mystery scenarios' }, { name: 'Horror Prompts', slug: 'horror-prompts', description: 'Spine-chilling horror concepts' } ] }, { category: 'Family & Personal', tools: [ { name: 'Family Storytelling', slug: 'family-storytelling', description: 'Preserve family memories' }, { name: 'Family Memory Prompts', slug: 'family-memory-prompts', description: 'Unlock family stories' }, { name: 'Family Character Profiles', slug: 'family-character-profiles', description: 'Document family members' } ] } ] } private static getToolDisplayName(slug: string): string { const names: Record<string, string> = { 'story-prompts': 'Story Prompts Generator', 'plot-twists': 'Plot Twist Generator', 'character-generator': 'Character Generator', // Add all tool mappings } return names[slug] || slug.replace('-', ' ').replace(/\b\w/g, l => l.toUpperCase()) } private static getToolDescription(slug: string): string { const descriptions: Record<string, string> = { 'story-prompts': 'Generate creative writing prompts and story ideas', 'plot-twists': 'Create unexpected twists for your narratives', 'character-generator': 'Develop detailed, compelling characters', // Add all tool descriptions } return descriptions[slug] || `AI-powered ${slug.replace('-', ' ')} tool` } private static getToolCategory(slug: string): string { const categories: Record<string, string> = { 'story-prompts': 'Creative Writing', 'plot-twists': 'Story Development', 'character-generator': 'Character Development', // Add all tool categories } return categories[slug] || 'Writing Tools' } }

📈 SEO Performance Monitoring

Analytics & Tracking

// /lib/seo/performance-tracking.ts export interface SEOMetrics { pageUrl: string toolName: string organicTraffic: number keywordRankings: Array<{ keyword: string position: number searchVolume: number }> clickThroughRate: number averageSessionDuration: number bounceRate: number conversions: number } export class SEOPerformanceTracker { /** * Track SEO performance for tool pages */ static async trackToolPerformance(toolSlug: string, metrics: Partial<SEOMetrics>) { try { const performanceData = { tool_slug: toolSlug, timestamp: new Date().toISOString(), metrics: metrics, tracked_at: new Date() } // Store in analytics database const supabase = await createClient() await supabase .from('seo_performance_metrics') .insert(performanceData) console.log(`SEO metrics tracked for ${toolSlug}:`, metrics) } catch (error) { console.error('Failed to track SEO performance:', error) } } /** * Generate SEO report for all tools */ static async generateSEOReport(): Promise<SEOMetrics[]> { const supabase = await createClient() const { data: metrics, error } = await supabase .from('seo_performance_metrics') .select('*') .gte('tracked_at', new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)) // Last 30 days .order('tracked_at', { ascending: false }) if (error) { console.error('Failed to generate SEO report:', error) return [] } return metrics || [] } /** * Track keyword ranking changes */ static async trackKeywordRankings(toolSlug: string, keywords: Array<{ keyword: string position: number previousPosition?: number }>) { const rankingData = { tool_slug: toolSlug, keyword_rankings: keywords, tracked_at: new Date().toISOString() } try { const supabase = await createClient() await supabase .from('keyword_rankings') .insert(rankingData) // Alert on significant ranking changes keywords.forEach(keyword => { if (keyword.previousPosition && keyword.previousPosition - keyword.position >= 5) { console.log(`🎉 ${toolSlug} ranking improved for "${keyword.keyword}": ${keyword.previousPosition} → ${keyword.position}`) } else if (keyword.previousPosition && keyword.position - keyword.previousPosition >= 5) { console.warn(`⚠️ ${toolSlug} ranking declined for "${keyword.keyword}": ${keyword.previousPosition} → ${keyword.position}`) } }) } catch (error) { console.error('Failed to track keyword rankings:', error) } } }

🎯 Conversion-Focused SEO

SEO-to-Conversion Optimization

// /lib/seo/conversion-optimization.ts export class SEOConversionOptimizer { /** * Generate SEO-optimized CTA content based on search intent */ static generateSearchIntentCTA(searchQuery?: string, toolName?: string): { headline: string description: string buttonText: string } { // Analyze search intent const intent = this.analyzeSearchIntent(searchQuery) switch (intent) { case 'informational': return { headline: `Try Our ${toolName} for Free`, description: 'Get instant results with AI-powered content generation. No signup required.', buttonText: `Generate ${toolName?.toLowerCase()} Now` } case 'transactional': return { headline: 'Ready to Create Amazing Content?', description: 'Join thousands of writers using our AI tools to enhance their creativity.', buttonText: 'Start Creating Free' } case 'navigational': return { headline: 'Welcome to MyStoryFlow Tools', description: 'Discover our complete suite of AI-powered writing and creativity tools.', buttonText: 'Explore All Tools' } default: return { headline: `Create Better Content with AI`, description: 'Professional-quality results in seconds. Perfect for writers, creators, and storytellers.', buttonText: 'Try It Free' } } } /** * Analyze search intent from query */ private static analyzeSearchIntent(query?: string): 'informational' | 'transactional' | 'navigational' | 'commercial' { if (!query) return 'commercial' const lowerQuery = query.toLowerCase() // Transactional intent keywords if (/\b(buy|purchase|order|download|free|tool|generator)\b/.test(lowerQuery)) { return 'transactional' } // Informational intent keywords if (/\b(how|what|why|guide|tutorial|tips|learn)\b/.test(lowerQuery)) { return 'informational' } // Navigational intent keywords if (/\b(mystoryflow|tools|site|website)\b/.test(lowerQuery)) { return 'navigational' } return 'commercial' } /** * Generate schema markup for enhanced search results */ static generateEnhancedSchema(toolConfig: { name: string description: string category: string features: string[] testimonials?: Array<{ author: string; rating: number; review: string }> }): any { const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' const toolSlug = toolConfig.name.toLowerCase().replace(/\s+/g, '-') return { '@context': 'https://schema.org', '@type': ['SoftwareApplication', 'CreativeWork'], name: toolConfig.name, description: toolConfig.description, applicationCategory: 'BusinessApplication', applicationSubCategory: toolConfig.category, operatingSystem: 'Web Browser', url: `${baseUrl}/${toolSlug}`, // Pricing information offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD', availability: 'https://schema.org/InStock', validFrom: new Date().toISOString() }, // Features featureList: toolConfig.features, // Organization author: { '@type': 'Organization', name: 'MyStoryFlow', url: 'https://mystoryflow.com', logo: { '@type': 'ImageObject', url: 'https://mystoryflow.com/logo.png' } }, // Reviews and ratings ...(toolConfig.testimonials && { aggregateRating: { '@type': 'AggregateRating', ratingValue: (toolConfig.testimonials.reduce((acc, t) => acc + t.rating, 0) / toolConfig.testimonials.length).toFixed(1), ratingCount: toolConfig.testimonials.length, bestRating: 5, worstRating: 1 }, review: toolConfig.testimonials.map(testimonial => ({ '@type': 'Review', author: { '@type': 'Person', name: testimonial.author }, reviewRating: { '@type': 'Rating', ratingValue: testimonial.rating }, reviewBody: testimonial.review })) }), // FAQ Schema for common questions mainEntity: [ { '@type': 'Question', name: `How does the ${toolConfig.name} work?`, acceptedAnswer: { '@type': 'Answer', text: `Our ${toolConfig.name} uses advanced AI to ${toolConfig.description.toLowerCase()}. Simply input your preferences and get instant, high-quality results.` } }, { '@type': 'Question', name: 'Is the tool free to use?', acceptedAnswer: { '@type': 'Answer', text: 'Yes! All our tools are completely free to use with no signup required. You can generate unlimited content and export in multiple formats.' } }, { '@type': 'Question', name: 'What formats can I export to?', acceptedAnswer: { '@type': 'Answer', text: 'You can export your generated content in JSON, CSV, PDF, HTML, and DOCX formats for maximum compatibility with your workflow.' } } ] } } }

📱 Technical SEO Implementation

Core Web Vitals Optimization

// /lib/seo/performance.ts export class TechnicalSEOOptimizer { /** * Preload critical resources */ static generatePreloadLinks(): Array<{ rel: string; href: string; as?: string }> { return [ { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, { rel: 'preconnect', href: 'https://fonts.gstatic.com' }, { rel: 'preload', href: '/fonts/inter-var.woff2', as: 'font' }, { rel: 'dns-prefetch', href: 'https://api.openai.com' }, { rel: 'dns-prefetch', href: process.env.NEXT_PUBLIC_SUPABASE_URL || '' } ] } /** * Generate robots.txt content */ static generateRobotsTxt(): string { const baseUrl = process.env.NEXT_PUBLIC_TOOLS_APP_URL || 'https://tools.mystoryflow.com' return `User-agent: * Allow: / # High-value pages Allow: /story-prompts Allow: /plot-twists Allow: /character-generator Allow: /romance-prompts Allow: /mystery-prompts # Shared content pages Allow: /*/share/* # Block admin and API routes Disallow: /api/ Disallow: /admin/ Disallow: /_next/ Disallow: /private/ # Sitemap location Sitemap: ${baseUrl}/sitemap.xml # Crawl delay for respectful crawling Crawl-delay: 1` } /** * Generate security headers for SEO */ static getSecurityHeaders(): Record<string, string> { return { 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'origin-when-cross-origin', 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()', 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload' } } }

This comprehensive SEO optimization guide ensures every MyStoryFlow tool achieves maximum search visibility, organic traffic growth, and conversion optimization while maintaining technical excellence and user experience quality.