Browse documentation

AI Services

RankFlow AI — Image Generation & Vernacular Content Strategy

Version: 2.0.0

docs/specs/ai/ai-services-05-image-vernacular.md
On this page

Version: 2.0.0 Date: 2026-06-16 Scope: Image generation pipeline, DALL-E/Gemini integration, vernacular translation strategy, cultural adaptation, and multilingual content management Target Audience: AI Engineers, Content Strategists, Designers, Product Team Service Path: src/server/services/ai/images/, src/server/services/ai/vernacular/


1. Image Generation Strategy#

1.1 Philosophy#

Images are not an afterthought — they are a critical part of the content ecosystem. Every GBP post, social post, and landing page benefits from custom-generated imagery that matches the practice's brand identity.

1.2 Image Use Cases#

# Use Case Platform Frequency AI Model Cost/Image
1 GBP Post Images Google Business 2-3x/week DALL-E 3 ~$0.04
2 Social Post Images Instagram, FB, LI 2-4x/week DALL-E 3 ~$0.04
3 Landing Page Hero Website 1x (onboarding) DALL-E 3 ~$0.04
4 Service Illustrations Website 1x (onboarding) DALL-E 3 ~$0.04
5 Blog Post Featured Blog 2-3x/week DALL-E 3 ~$0.04
6 Team/Facility Photos Website 1x (onboarding) Gemini (existing photo enhancement) ~$0.02
7 Promotional Graphics Social 1-2x/month DALL-E 3 ~$0.04
8 Seasonal/Holiday Social, GBP 4-5x/year DALL-E 3 ~$0.04

1.3 Image Budget per Client per Month#

Plan Images/Month Cost/Month ARPU Image Cost %
Starter 12 ~$0.50 $48 ~1.0%
Growth 36 ~$1.50 $144 ~1.0%
Pro 120 ~$5.00 $480 ~1.0%

2. Image Generation Pipeline#

2.1 Pipeline Architecture#

┌─────────────────────────────────────────────────────────────┐
│                    IMAGE GENERATION PIPELINE                │
│                                                              │
│  Step 1: Image Prompt Generation (LLM)                      │
│  ├─ Input: Task type, practice context, image requirements │
│  ├─ Model: Claude Haiku (~$0.002)                           │
│  ├─ Output: Detailed image generation prompt               │
│  └─ Includes: Style, subject, lighting, composition, mood   │
│                                                              │
│  Step 2: Prompt Enhancement (optional)                     │
│  ├─ Add brand color palette                                │
│  ├─ Add cultural context (Indian setting, local landmarks)  │
│  ├─ Add diversity requirements (Indian patients, families)    │
│  └─ Add negative prompt (what to avoid)                    │
│                                                              │
│  Step 3: Image Generation (AI Image Model)                 │
│  ├─ Primary: DALL-E 3 (OpenAI)                             │
│  ├─ Fallback: Gemini Image (Google)                        │
│  ├─ Output: Image URL + metadata                            │
│  └─ Cost: ~$0.04 per image (1024x1024)                    │
│                                                              │
│  Step 4: Quality Check                                      │
│  ├─ Safety filter (NSFW, inappropriate content)            │
│  ├─ Brand alignment check (color, style, subject)          │
│  ├─ Cultural appropriateness check                         │
│  └─ If failed: Regenerate with adjusted prompt               │
│                                                              │
│  Step 5: Storage & CDN                                      │
│  ├─ Upload to S3/R2                                        │
│  ├─ Generate CDN URL                                        │
│  ├─ Generate thumbnail versions                            │
│  └─ Store metadata in database                              │
│                                                              │
│  Step 6: Content Integration                                │
│  ├─ Attach to GBP post, social post, or web page            │
│  ├─ Generate alt text (GPT-4o Mini, ~$0.001)               │
│  └─ Update content with image URL                           │
│                                                              │
│  Step 7: Audit & Logging                                      │
│  ├─ Log image generation cost                               │
│  ├─ Log prompt and result                                   │
│  └─ Track usage per practice                                │
└─────────────────────────────────────────────────────────────┘

2.2 Image Generation Interface#

// src/server/services/ai/images/types.ts

interface ImageGenerateRequest {
  task: ImageTaskType;             // "gbp_post", "social_post", "hero", "blog", etc.
  practiceId: string;
  
  // Image requirements
  subject: string;                 // What the image should depict
  style: ImageStyle;               // "photorealistic", "illustration", "minimalist", "warm"
  aspectRatio: AspectRatio;        // "1:1", "4:5", "16:9", "1.91:1"
  
  // Context
  platform?: Platform;             // "instagram", "facebook", "linkedin", "gbp", "website"
  colorPalette?: string[];         // Brand colors to incorporate
  includePeople?: boolean;         // Whether to include people in the image
  diversityNote?: string;          // "Indian family", "diverse patients", "South Indian setting"
  
  // Optional
  existingImageUrl?: string;       // For image-to-image generation (editing)
  
  requestId: string;
  userId?: string;
}

interface ImageGenerateResponse {
  imageUrl: string;                // CDN URL
  thumbnailUrl: string;            // Smaller version for previews
  metadata: {
    model: "dall-e-3" | "gemini";
    size: string;                  // "1024x1024", "1024x1792", etc.
    costUsd: number;
    latencyMs: number;
    prompt: string;                // The actual prompt used
    negativePrompt?: string;
    revisionPrompt?: string;       // If revised from initial
    safetyCheck: "PASS" | "WARN" | "FAIL";
    brandAlignment: "PASS" | "WARN" | "FAIL";
    culturalCheck: "PASS" | "WARN" | "FAIL";
  };
}

// Aspect ratios by platform:
const PLATFORM_ASPECT_RATIOS: Record<Platform, AspectRatio[]> = {
  "instagram": ["1:1", "4:5"],
  "facebook": ["1:1", "1.91:1"],
  "linkedin": ["1.91:1", "1:1"],
  "twitter": ["16:9", "1:1"],
  "gbp": ["1:1", "4:3"],
  "website": ["16:9", "4:3", "1:1"],
};

3. DALL-E Integration#

3.1 DALL-E 3 Configuration#

// src/server/services/ai/images/providers/dalle.ts

import { createOpenAI } from "@ai-sdk/openai";
import { generateImage } from "ai";

const openai = createOpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export async function generateWithDalle(
  prompt: string,
  options: ImageOptions
): Promise<ImageResult> {
  const startTime = Date.now();
  
  const result = await generateImage({
    model: openai.image("dall-e-3"),
    prompt,
    size: options.aspectRatio === "16:9" ? "1792x1024" 
          : options.aspectRatio === "9:16" ? "1024x1792"
          : "1024x1024",
    quality: "standard", // "standard" or "hd"
    style: options.style === "photorealistic" ? "vivid" : "natural",
  });
  
  return {
    imageUrl: result.url,
    metadata: {
      model: "dall-e-3",
      size: result.size,
      costUsd: 0.04, // Standard quality
      latencyMs: Date.now() - startTime,
      prompt,
    },
  };
}

// DALL-E 3 Pricing (as of 2026):
// Standard quality (1024x1024): $0.04 per image
// Standard quality (1024x1792, 1792x1024): $0.08 per image
// HD quality (1024x1024): $0.08 per image
// HD quality (1024x1792, 1792x1024): $0.12 per image

3.2 DALL-E Prompt Engineering#

DALL-E 3 works best with detailed, descriptive prompts. The prompt generation layer creates these automatically.

// Prompt enhancement for DALL-E 3:
function enhancePromptForDalle(basePrompt: string, context: ImageContext): string {
  const enhancements = [
    // Style enhancement
    context.style === "photorealistic" ? "photorealistic, high-quality photograph, professional photography" : "",
    context.style === "illustration" ? "flat vector illustration, clean lines, modern design" : "",
    context.style === "warm" ? "warm lighting, inviting atmosphere, soft natural light" : "",
    context.style === "minimalist" ? "minimalist design, clean composition, ample white space" : "",
    
    // Cultural context
    context.diversityNote ? `${context.diversityNote}, culturally appropriate setting` : "",
    
    // Quality tags
    "high resolution, detailed, professional",
    
    // Negative space (avoid)
    "no text, no watermark, no logo, no blurry areas",
  ];
  
  return `${basePrompt}. ${enhancements.filter(Boolean).join(", ")}.`;
}

3.3 DALL-E Safety & Moderation#

// DALL-E has built-in safety filters, but we add an additional layer:

const IMAGE_SAFETY_CHECKS = [
  // NSFW detection
  "no_nudity",
  "no_violence",
  "no_gore",
  "no_hate_symbols",
  
  // Medical appropriateness
  "no_medical_gore",          // No graphic medical images
  "no_misleading_medical",    // No images that suggest unproven treatments
  
  // Cultural appropriateness
  "no_stereotypes",
  "no_cultural_appropriation",
  
  // Brand safety
  "no_competitor_logos",
  "no_misleading_imagery",
];

// If DALL-E rejects a prompt (safety violation):
// 1. Log the rejection with prompt and reason
// 2. Adjust the prompt to remove problematic elements
// 3. Retry with revised prompt (max 2 attempts)
// 4. If still failing: Use stock image fallback

4. Gemini Image Integration#

4.1 Gemini Image Configuration#

Gemini is used as a fallback and for specific use cases like image editing and existing photo enhancement.

// src/server/services/ai/images/providers/gemini.ts

import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { generateImage } from "ai";

const google = createGoogleGenerativeAI({
  apiKey: process.env.GOOGLE_API_KEY,
});

export async function generateWithGemini(
  prompt: string,
  options: ImageOptions
): Promise<ImageResult> {
  const startTime = Date.now();
  
  const result = await generateImage({
    model: google.image("gemini-2.5-flash"),
    prompt,
    size: options.aspectRatio === "16:9" ? "1024x576" : "1024x1024",
  });
  
  return {
    imageUrl: result.url,
    metadata: {
      model: "gemini-2.5-flash",
      size: result.size,
      costUsd: 0.02, // Estimated cost
      latencyMs: Date.now() - startTime,
      prompt,
    },
  };
}

4.2 Gemini Use Cases#

Use Case Why Gemini Example
Image Editing Can edit existing images "Add a holiday banner to this clinic photo"
Photo Enhancement Can improve existing photos "Make this photo brighter and more professional"
Long Prompt Understanding Better at complex prompts "A busy dental clinic with 5 Indian patients, a female dentist in white coat, modern equipment, warm lighting, Kochi city view through window"
Fallback When DALL-E is unavailable Same prompt, different model

5. Image Quality & Review#

5.1 Automated Image Review#

// After generation, images are reviewed automatically:

interface ImageReviewResult {
  safety: "PASS" | "WARN" | "FAIL";
  brandAlignment: "PASS" | "WARN" | "FAIL";
  culturalAppropriateness: "PASS" | "WARN" | "FAIL";
  quality: "PASS" | "WARN" | "FAIL";
  
  issues: string[];
  suggestedPromptChanges?: string;
}

// Review checks:
// 1. Safety: Use AWS Rekognition or Google Vision API for NSFW detection
// 2. Brand Alignment: Check if image colors match brand palette (color histogram analysis)
// 3. Cultural Appropriateness: Check for cultural stereotypes or inappropriate depictions
// 4. Quality: Check resolution, blur, artifacts (OpenCV/image processing)

// If any check FAILs:
// - Image is rejected
// - Prompt is adjusted based on issues
// - Regeneration is triggered (max 2 attempts)
// - If still failing: Use stock image from Unsplash/Pexels (free, safe)

5.2 Stock Image Fallback#

If AI image generation fails after 2 attempts, the system falls back to stock images:

// Stock image fallback:
const STOCK_IMAGE_SOURCES = [
  "unsplash",    // Free, high quality, API available
  "pexels",      // Free, high quality, API available
  "pixabay",     // Free, large library
];

// Search query construction:
// "dental clinic interior" + "Kochi" + "India" + "modern" + "professional"

// If no relevant stock image found:
// - Use a generic category image (e.g., "healthcare" or "dental")
// - Log the failure for admin review
// - Alert admin to upload a custom image

6. Vernacular Content Strategy#

6.1 Why Vernacular?#

For Indian practices (especially in Kerala, Tamil Nadu, Karnataka, etc.), a significant portion of the target audience prefers content in their local language. Vernacular content is not just translation — it's cultural adaptation.

6.2 Supported Languages#

Language Code Script Primary Regions Priority
Malayalam ml Malayalam Kerala High
Tamil ta Tamil Tamil Nadu High
Hindi hi Devanagari North India High
Telugu te Telugu Andhra Pradesh, Telangana Medium
Kannada kn Kannada Karnataka Medium
Gujarati gu Gujarati Gujarat Low
Marathi mr Devanagari Maharashtra Low
Bengali bn Bengali West Bengal Low

6.3 Vernacular Content Types#

Content Type Malayalam Tamil Hindi Frequency
Landing Page (Hero) Onboarding
Landing Page (About) Onboarding
Landing Page (Services) Onboarding
Landing Page (FAQ) Onboarding
GBP Posts 1-2x/month
Social Posts 1-2x/month
Blog Posts 1x/month
Citation Descriptions Onboarding
Review Replies As needed
Email Content As needed

7. Translation Pipeline#

7.1 Translation Pipeline Architecture#

┌─────────────────────────────────────────────────────────────┐
│                    TRANSLATION PIPELINE                     │
│                                                              │
│  Step 1: Source Content Preparation                          │
│  ├─ Extract content from source (landing page, post, etc.) │
│  ├─ Identify translatable text (not URLs, phone numbers)   │
│  ├─ Preserve formatting markers ({{variable}}, markdown)   │
│  └─ Segment into translation units (paragraphs, sentences) │
│                                                              │
│  Step 2: Translation (LLM)                                  │
│  ├─ Model: Claude Sonnet (best for nuanced translation)    │
│  ├─ Input: Source text + context + cultural notes            │
│  ├─ Output: Translated text in target language               │
│  └─ Cost: ~$0.008 per 1000 words (~$0.01 per page)         │
│                                                              │
│  Step 3: Post-Translation Processing                         │
│  ├─ Re-insert formatting markers                             │
│  ├─ Verify variable substitution ({{practiceName}} stays)    │
│  ├─ Check for mixed script (ensure all target script)       │
│  └─ Normalize whitespace and punctuation                     │
│                                                              │
│  Step 4: Quality Evaluation                                    │
│  ├─ Back-translation check (translate back to English)       │
│  ├─ Cultural appropriateness check                           │
│  ├─ Readability check (sentence length, complexity)          │
│  └─ Brand voice consistency check                            │
│                                                              │
│  Step 5: Human Review (optional)                             │
│  ├─ For medical content: Mandatory human review            │
│  ├─ For marketing content: Spot-check by native speaker      │
│  └─ For social posts: Admin approval                        │
│                                                              │
│  Step 6: Publishing                                            │
│  ├─ Store translated content in database                    │
│  ├─ Update content record with language variant              │
│  ├─ Generate URL with language prefix (/ml/, /ta/, /hi/)    │
│  └─ Add hreflang tags for SEO                                 │
│                                                              │
│  Step 7: Audit & Logging                                       │
│  ├─ Log translation cost                                      │
│  ├─ Log quality scores                                        │
│  └─ Track per-language usage                                  │
└─────────────────────────────────────────────────────────────┘

7.2 Translation Interface#

// src/server/services/ai/vernacular/types.ts

interface TranslateRequest {
  content: string;                    // Source content (English)
  targetLanguage: LanguageCode;       // "ml", "ta", "hi", etc.
  contentType: ContentType;          // "landing_page", "social_post", "blog", etc.
  practiceId: string;
  
  // Context
  preserveFormatting: boolean;         // Keep markdown, HTML, variables
  includeCulturalNotes: boolean;      // Add cultural context to translation
  
  requestId: string;
}

interface TranslateResponse {
  translatedContent: string;
  sourceLanguage: "en";
  targetLanguage: LanguageCode;
  
  metadata: {
    model: string;                    // "claude-sonnet"
    costUsd: number;
    latencyMs: number;
    wordCount: number;
    characterCount: number;
    
    quality: {
      backTranslationScore: number;   // 0-100 (how close back-translation is to source)
      culturalScore: number;         // 0-100 (cultural appropriateness)
      readabilityScore: number;       // 0-100 (target language readability)
    };
    
    humanReviewRequired: boolean;
    humanReviewStatus?: "pending" | "approved" | "rejected";
  };
}

// Language codes
const LANGUAGE_CODES: Record<LanguageCode, LanguageInfo> = {
  "ml": { name: "Malayalam", script: "Malayalam", regions: ["Kerala"], formalityDefault: "formal" },
  "ta": { name: "Tamil", script: "Tamil", regions: ["Tamil Nadu"], formalityDefault: "formal" },
  "hi": { name: "Hindi", script: "Devanagari", regions: ["North India"], formalityDefault: "formal" },
  "te": { name: "Telugu", script: "Telugu", regions: ["Andhra Pradesh", "Telangana"], formalityDefault: "formal" },
  "kn": { name: "Kannada", script: "Kannada", regions: ["Karnataka"], formalityDefault: "formal" },
};

7.3 Batch Translation#

For bulk content (e.g., onboarding a new client with 5 landing page sections in 3 languages):

// Batch translation saves cost by grouping content:
// Instead of 15 individual API calls (5 sections × 3 languages):
// → 3 batch calls (1 per language, all sections in one prompt)
// Cost savings: ~40% (fewer system prompts, fewer API calls)

interface BatchTranslateRequest {
  items: {
    id: string;
    content: string;
    contentType: ContentType;
  }[];
  targetLanguage: LanguageCode;
  practiceId: string;
}

// Batch prompt:
// "Translate the following 5 sections into Malayalam. 
//  Preserve all formatting and variables. 
//  Section 1: [content] 
//  Section 2: [content] 
//  ..."

8. Cultural Adaptation#

8.1 Cultural Adaptation Framework#

Translation is not enough. Content must be culturally adapted for the target audience.

Aspect English (Default) Malayalam Adaptation Tamil Adaptation Hindi Adaptation
Formality Semi-formal Formal (ningal) Formal (ningal) Formal (aap)
Tone Warm Respectful warmth Respectful warmth Professional warmth
Family Reference "Your family" "Kudumbam" (കുടുംബം) "Kudumbam" (குடும்பம்) "Parivar" (परिवार)
Greetings "Hello" "Namaskaram" (നമസ്കാരം) "Vanakkam" (வணக்கம்) "Namaste" (नमस्ते)
Local Landmarks "MG Road" "MG Road / Lulu Mall" "T Nagar / Marina Beach" "Connaught Place"
Festivals "Holiday" "Onam, Vishu" "Pongal, Tamil New Year" "Diwali, Holi"
Food References "Healthy diet" "Sadya, coconut oil" "Idli, sambar" "Roti, dal"
Medical Terms "Root canal" "Root canal / മൂലദന്തചികിത്സ" "Root canal / மூலக் காரணம்" "Root canal / मूल दांत चिकित्सा"
Trust Building "Since 2015" "2015 മുതൽ Kochi-യിൽ വിശ്വസ്തർ" "2015 முதல் Kochi-யில் நம்பகமானவர்கள்" "2015 से Kochi में विश्वसनीय"

8.2 Cultural Adaptation Rules#

// Cultural adaptation is applied during translation:

const CULTURAL_RULES: Record<LanguageCode, CulturalRule[]> = {
  "ml": [
    { type: "formality", rule: "Use 'നിങ്ങൾ' (ningal) for patients, 'താങ്കൾ' (thangal) for elderly" },
    { type: "reference", rule: "Reference Kerala culture: Onam, Vishu, monsoon season" },
    { type: "tone", rule: "Warm but respectful, family-centric" },
    { type: "medical", rule: "Use Malayalam medical terms where common, English where standard" },
  ],
  "ta": [
    { type: "formality", rule: "Use 'நீங்கள்' (ningal) for formal, 'நீ' (nee) for casual" },
    { type: "reference", rule: "Reference Tamil culture: Pongal, Jallikattu, Tamil New Year" },
    { type: "tone", rule: "Respectful and warm, community-oriented" },
    { type: "medical", rule: "Use Tamil medical terms where common" },
  ],
  "hi": [
    { type: "formality", rule: "Use 'आप' (aap) for formal, 'तुम' (tum) for semi-formal" },
    { type: "reference", rule: "Reference North Indian culture: Diwali, Holi, family values" },
    { type: "tone", rule: "Professional but warm, hierarchical respect" },
    { type: "medical", rule: "Use Hindi medical terms where widely understood" },
  ],
};

9. Multilingual Content Management#

9.1 Content Language Variants#

Every piece of content can exist in multiple language variants:

// Content language variant model:
interface ContentVariant {
  id: string;
  contentId: string;              // Parent content (English = default)
  language: LanguageCode;         // "en", "ml", "ta", "hi"
  
  content: string;                // Translated content
  status: "draft" | "pending_review" | "approved" | "published";
  
  // Translation metadata
  translatedBy: "ai" | "human" | "hybrid";
  translatorId?: string;          // User ID if human-translated
  
  // Quality
  qualityScore: number;
  backTranslationScore: number;
  culturalScore: number;
  
  // Review
  reviewedBy?: string;
  reviewedAt?: Date;
  
  // SEO
  slug: string;                   // Language-specific URL slug
  metaTitle: string;
  metaDescription: string;
  
  createdAt: Date;
  updatedAt: Date;
}

// Default language is always English (en)
// All other languages are variants linked to the English parent

9.2 Language Switching#

// URL structure for multilingual content:
// English (default): /dr-smith-dental/
// Malayalam: /ml/dr-smith-dental/
// Tamil: /ta/dr-smith-dental/
// Hindi: /hi/dr-smith-dental/

// Language switching logic:
// 1. User visits /dr-smith-dental/ (English default)
// 2. If user has language preference cookie → redirect to /{lang}/
// 3. If browser language is Malayalam → show /ml/ version
// 4. If content not available in that language → show English with "Available in English" banner
// 5. User can manually switch language via language selector

// Hreflang tags for SEO:
// <link rel="alternate" hreflang="en" href="https://rankflow.ai/dr-smith-dental/" />
// <link rel="alternate" hreflang="ml" href="https://rankflow.ai/ml/dr-smith-dental/" />
// <link rel="alternate" hreflang="ta" href="https://rankflow.ai/ta/dr-smith-dental/" />
// <link rel="alternate" hreflang="x-default" href="https://rankflow.ai/dr-smith-dental/" />

9.3 Language-Specific GBP#

// Google Business Profile supports multilingual posts:
// - Primary language: English
// - Secondary languages: Malayalam, Tamil, Hindi (if available)

// GBP multilingual strategy:
// 1. Primary GBP listing: English (default)
// 2. Posts: English + 1 vernacular language per week (rotate)
// 3. Description: English + vernacular (if space allows)
// 4. Reviews: Reply in the language the review was written in
// 5. Q&A: Answer in English + vernacular if question is in vernacular

// GBP post rotation:
// Week 1: English + Malayalam
// Week 2: English + Tamil
// Week 3: English + Hindi
// Week 4: English only (if no vernacular for this practice)

10. Vernacular SEO#

10.1 Vernacular Keyword Strategy#

Language Example Keywords Search Volume Difficulty
Malayalam "കൊച്ചിയിലെ മികച്ച ഡെന്റൽ ക്ലിനിക്" Medium Low
Malayalam "ദന്തചികിത്സ കൊച്ചി" Medium Low
Tamil "கோச்சியில் சிறந்த பல் மருத்துவமனை" Medium Low
Tamil "பல் மருத்துவம் கோச்சி" Medium Low
Hindi "कोची में सबसे अच्छा डेंटल क्लिनिक" High Medium
Hindi "दांत का इलाज कोची" High Medium

10.2 Vernacular SEO Implementation#

// Vernacular SEO rules:
// 1. Each language variant gets its own URL (/ml/, /ta/, /hi/)
// 2. Language-specific meta titles and descriptions
// 3. Language-specific hreflang tags
// 4. Language-specific sitemap entries
// 5. Language-specific GBP posts (if applicable)
// 6. Language-specific social media posts (if practice has vernacular pages)

// Vernacular keyword optimization:
// - Translate target keywords into vernacular
// - Use vernacular keywords in:
//   - H1, H2 headings
//   - Meta title and description
//   - First 100 words of content
//   - Alt text for images
//   - GBP post content
//   - Social media captions
//   - Citation descriptions

10.3 Vernacular Content Calendar#

┌─────────────────────────────────────────────────────────────┐
│  VERNACULAR CONTENT CALENDAR (Example: Kerala Practice)    │
│                                                              │
│  Weekly:                                                    │
│  - English GBP post: 2-3x                                   │
│  - Malayalam GBP post: 1x (every Tuesday)                  │
│  - English social post: 2-4x                               │
│  - Malayalam social post: 1x (every Thursday)              │
│                                                              │
│  Monthly:                                                   │
│  - English blog post: 2-3x                                  │
│  - Malayalam blog post: 1x (mid-month)                     │
│                                                              │
│  Quarterly:                                                 │
│  - Landing page content refresh: All languages              │
│  - Citation description updates: All languages              │
│  - FAQ updates: All languages                               │
│                                                              │
│  Special Occasions:                                         │
│  - Onam (Malayalam): Special GBP + social post              │
│  - Vishu (Malayalam): Special GBP + social post             │
│  - Pongal (Tamil): Special GBP + social post (if TN)       │
│  - Diwali (Hindi): Special GBP + social post (if North)   │
│                                                              │
│  Review Replies:                                            │
│  - Reply in the language the review was written in          │
│  - If review is in Malayalam → reply in Malayalam          │
│  - If review is in English → reply in English               │
└─────────────────────────────────────────────────────────────┘

11. Cost & Performance#

11.1 Vernacular Content Cost per Client per Month#

Language Content Type Monthly Volume Cost/Item Monthly Cost
Malayalam GBP Post 4 ~$0.005 ~$0.02
Malayalam Social Post 4 ~$0.005 ~$0.02
Malayalam Blog Post 1 ~$0.012 ~$0.012
Tamil GBP Post 4 ~$0.005 ~$0.02
Tamil Social Post 4 ~$0.005 ~$0.02
Tamil Blog Post 1 ~$0.012 ~$0.012
Hindi GBP Post 4 ~$0.005 ~$0.02
Hindi Social Post 4 ~$0.005 ~$0.02
Hindi Blog Post 1 ~$0.012 ~$0.012
Total (3 languages) ~$0.15

11.2 Image Generation Cost per Client per Month#

Plan Images/Month Cost/Month
Starter 12 ~$0.50
Growth 36 ~$1.50
Pro 120 ~$5.00

11.3 Combined Vernacular + Image Cost#

Plan Text (Vernacular) Images Total ARPU AI Cost %
Starter ~$0.15 ~$0.50 ~$0.65 $48 ~1.4%
Growth ~$0.45 ~$1.50 ~$1.95 $144 ~1.4%
Pro ~$1.50 ~$5.00 ~$6.50 $480 ~1.4%

12. Database Schema#

-- Image Generation Records
CREATE TABLE ai_images (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  task_type VARCHAR(50) NOT NULL, -- "gbp_post", "social_post", "hero", etc.
  
  -- Image details
  prompt TEXT NOT NULL,
  enhanced_prompt TEXT,
  negative_prompt TEXT,
  image_url VARCHAR(500) NOT NULL,
  thumbnail_url VARCHAR(500),
  
  -- Model info
  model VARCHAR(50) NOT NULL,
  size VARCHAR(20) NOT NULL,
  style VARCHAR(50),
  
  -- Quality checks
  safety_check VARCHAR(10) NOT NULL,
  brand_alignment VARCHAR(10) NOT NULL,
  cultural_check VARCHAR(10) NOT NULL,
  quality_check VARCHAR(10) NOT NULL,
  
  -- Cost
  cost_usd DECIMAL(10, 6) NOT NULL,
  latency_ms INTEGER,
  
  -- Usage
  used_in_content_id UUID,
  used_in_content_type VARCHAR(50),
  
  created_at TIMESTAMP DEFAULT NOW(),
  
  INDEX idx_practice_task (practice_id, task_type)
);

-- Content Language Variants
CREATE TABLE content_variants (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  content_id UUID NOT NULL, -- References the parent content
  language VARCHAR(10) NOT NULL, -- "ml", "ta", "hi", etc.
  
  content TEXT NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT "draft",
  
  translated_by VARCHAR(20) NOT NULL DEFAULT "ai", -- "ai", "human", "hybrid"
  translator_id UUID REFERENCES users(id),
  
  -- Quality scores
  quality_score INTEGER,
  back_translation_score INTEGER,
  cultural_score INTEGER,
  
  -- Review
  reviewed_by UUID REFERENCES users(id),
  reviewed_at TIMESTAMP,
  
  -- SEO
  slug VARCHAR(200) NOT NULL,
  meta_title VARCHAR(200),
  meta_description VARCHAR(300),
  
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  
  UNIQUE(content_id, language),
  INDEX idx_content_language (content_id, language)
);

-- Translation Usage Log
CREATE TABLE ai_translation_usage (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  content_id UUID NOT NULL,
  source_language VARCHAR(10) NOT NULL DEFAULT "en",
  target_language VARCHAR(10) NOT NULL,
  
  word_count INTEGER NOT NULL,
  character_count INTEGER NOT NULL,
  
  model VARCHAR(50) NOT NULL,
  cost_usd DECIMAL(10, 6) NOT NULL,
  latency_ms INTEGER,
  
  quality_scores JSONB,
  
  created_at TIMESTAMP DEFAULT NOW()
);

-- Language Preferences (per practice)
CREATE TABLE practice_language_preferences (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  language VARCHAR(10) NOT NULL,
  
  is_active BOOLEAN DEFAULT TRUE,
  priority INTEGER DEFAULT 1, -- 1 = highest
  
  -- Content generation settings
  auto_generate_gbp BOOLEAN DEFAULT FALSE,
  auto_generate_social BOOLEAN DEFAULT FALSE,
  auto_generate_blog BOOLEAN DEFAULT FALSE,
  
  -- Review settings
  requires_human_review BOOLEAN DEFAULT TRUE,
  
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  
  UNIQUE(practice_id, language)
);

End of Image Generation & Vernacular Content Documentation — RankFlow AI v2.0.0