> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Repurposing Pipeline

> Generate a long-form blog post, then use different generation apps to create a LinkedIn ad, Twitter thread, email nurture, product page, and social captions — 5+ content pieces from 1 generation

## Scenario

You just published a 1,200-word blog post about your product launch. Now marketing needs a LinkedIn ad, a Twitter thread, an email drip sequence, a product page summary, and social captions — all derived from the same core narrative. Writing each from scratch is slow and risks message drift.

This playbook generates the long-form piece first, then feeds it as context into every subsequent generation app. Each downstream piece inherits the key messages, statistics, and examples from the original — adapted to the format's constraints (character limits, visual hooks, CTA structure).

<Info>
  **Mavera-only.** No social scheduling platform, no CMS integration. This pipeline produces the content — you publish it wherever you want.
</Info>

***

## Architecture

```mermaid theme={"dark"}
flowchart TD
    subgraph sourceGen["Source Generation"]
        brandVoice["Brand Voice Config"] --> blogGen["Generate: blog_post_generator"]
        blogGen --> sourceContent[("Source Blog Post")]
    end

    subgraph formatAdapt["Format Adaptation"]
        sourceContent --> linkedinGen["Generate: linkedin_ad_generator"]
        sourceContent --> twitterGen["Generate: social_post_generator — Twitter"]
        sourceContent --> emailGen["Generate: email_sequence_generator"]
        sourceContent --> productGen["Generate: product_description"]
        sourceContent --> socialGen["Generate: social_post_generator — Instagram"]
        linkedinGen --> linkedinOut[("LinkedIn Ad")]
        twitterGen --> twitterOut[("Twitter Thread")]
        emailGen --> emailOut[("Email Nurture Sequence")]
        productGen --> productOut[("Product Page Copy")]
        socialGen --> socialOut[("Social Captions")]
    end

    subgraph synthesis["Synthesis"]
        linkedinOut --> chatSynth["Chat: mavera-1"]
        twitterOut --> chatSynth
        emailOut --> chatSynth
        productOut --> chatSynth
        socialOut --> chatSynth
        chatSynth --> execSummary(("Executive Summary"))
    end
```

***

## What You Need

| Requirement                        | Details                                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Mavera API key**                 | Starts with `mvra_live_`. Get one at [Developer Settings](https://app.mavera.io/settings/developer). |
| **Workspace ID**                   | From your dashboard URL (`ws_...`).                                                                  |
| **Brand voice ID** (optional)      | For consistent voice across all pieces. Create via [Brand Voice](/features/brand-voice).             |
| **Topic and key points**           | The subject matter for the source blog post.                                                         |
| **Credits**                        | \~150–350 total. See [Credits Estimate](#credits-estimate).                                          |
| **Python 3.8+** or **Node.js 18+** | `requests` + `openai` SDK for Python; native `fetch` for Node.                                       |

```
MAVERA_API_KEY=mvra_live_your_key_here
MAVERA_WORKSPACE_ID=ws_your_workspace_id
BRAND_VOICE_ID=bv_optional_voice_id
```

***

## The Flow

<Steps>
  <Step title="Generate the source blog post">
    Use `POST /generations` with the `blog_post_generator` app. This produces the canonical long-form content that all downstream pieces will reference.
  </Step>

  <Step title="Define the repurposing plan">
    List the formats you need: LinkedIn ad, Twitter thread, email sequence, product page, social captions. Each maps to a generation app with format-specific input.
  </Step>

  <Step title="Generate each downstream piece">
    For each format, call `POST /generations` with the source blog post injected as `additional_context`. The generation app adapts the content to the format's constraints.
  </Step>

  <Step title="Generate an executive summary">
    Use Chat to produce a 150-word executive summary from the blog post — useful for internal stakeholders, newsletters, or Slack announcements.
  </Step>

  <Step title="Export all pieces">
    Save each piece as a separate file. Include a manifest with source, derived pieces, credits, and word counts.
  </Step>
</Steps>

***

## Stage 1 — Generate the Source Blog Post

<CodeGroup>
  ```python Python theme={"dark"}
  import os
  import time
  import json
  import requests

  API_KEY = os.environ["MAVERA_API_KEY"]
  WORKSPACE_ID = os.environ["MAVERA_WORKSPACE_ID"]
  BRAND_VOICE_ID = os.environ.get("BRAND_VOICE_ID")
  BASE = "https://app.mavera.io/api/v1"
  HEADERS = {
      "Authorization": f"Bearer {API_KEY}",
      "Content-Type": "application/json",
  }


  def generate(app_id, title, input_data, brand_voice_id=None):
      """Run a generation app and wait for completion."""
      payload = {
          "app_id": app_id,
          "title": title,
          "input_data": input_data,
          "workspace_id": WORKSPACE_ID,
      }
      if brand_voice_id:
          payload["brand_voice_id"] = brand_voice_id

      resp = requests.post(f"{BASE}/generations", headers=HEADERS, json=payload)
      resp.raise_for_status()
      gen = resp.json()

      if gen.get("status") in ("PENDING", "RUNNING"):
          gen = wait_for_generation(gen["id"])

      return gen


  def wait_for_generation(gen_id, max_wait=300):
      for _ in range(max_wait // 10):
          resp = requests.get(f"{BASE}/generations/{gen_id}", headers=HEADERS)
          data = resp.json()
          if data.get("status") == "COMPLETED":
              return data
          time.sleep(10)
      raise TimeoutError(f"Generation {gen_id} timed out")


  SOURCE_TOPIC = {
      "topic": "How We Reduced Customer Onboarding Time by 70%",
      "target_audience": "SaaS product and growth leaders",
      "length": "1200 words",
      "key_points": [
          "The old onboarding flow took 14 days on average",
          "We identified 3 critical drop-off points with analytics",
          "The automation builder cut manual steps from 12 to 3",
          "Customer time-to-value went from 14 days to 4 days",
          "NPS improved from 32 to 58 in one quarter",
      ],
  }

  print("Generating source blog post...")
  source = generate(
      app_id="blog_post_generator",
      title="Source: Onboarding Case Study",
      input_data=SOURCE_TOPIC,
      brand_voice_id=BRAND_VOICE_ID,
  )
  source_content = source.get("output", "")
  source_credits = source.get("usage", {}).get("credits_used", 0)
  print(f"  ✓ Source blog: {len(source_content.split())} words | {source_credits} credits")
  ```

  ```javascript JavaScript theme={"dark"}
  const API_KEY = process.env.MAVERA_API_KEY;
  const WORKSPACE_ID = process.env.MAVERA_WORKSPACE_ID;
  const BRAND_VOICE_ID = process.env.BRAND_VOICE_ID || null;
  const BASE = "https://app.mavera.io/api/v1";
  const HEADERS = {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  };

  async function generate(appId, title, inputData, brandVoiceId = null) {
    const payload = {
      app_id: appId,
      title,
      input_data: inputData,
      workspace_id: WORKSPACE_ID,
    };
    if (brandVoiceId) payload.brand_voice_id = brandVoiceId;

    const resp = await fetch(`${BASE}/generations`, {
      method: "POST",
      headers: HEADERS,
      body: JSON.stringify(payload),
    });
    let gen = await resp.json();

    if (gen.status === "PENDING" || gen.status === "RUNNING") {
      gen = await waitForGeneration(gen.id);
    }
    return gen;
  }

  async function waitForGeneration(genId, maxWait = 300) {
    for (let elapsed = 0; elapsed < maxWait; elapsed += 10) {
      const resp = await fetch(`${BASE}/generations/${genId}`, { headers: HEADERS });
      const data = await resp.json();
      if (data.status === "COMPLETED") return data;
      await new Promise((r) => setTimeout(r, 10000));
    }
    throw new Error(`Generation ${genId} timed out`);
  }

  const SOURCE_TOPIC = {
    topic: "How We Reduced Customer Onboarding Time by 70%",
    target_audience: "SaaS product and growth leaders",
    length: "1200 words",
    key_points: [
      "The old onboarding flow took 14 days on average",
      "We identified 3 critical drop-off points with analytics",
      "The automation builder cut manual steps from 12 to 3",
      "Customer time-to-value went from 14 days to 4 days",
      "NPS improved from 32 to 58 in one quarter",
    ],
  };

  console.log("Generating source blog post...");
  const source = await generate(
    "blog_post_generator",
    "Source: Onboarding Case Study",
    SOURCE_TOPIC,
    BRAND_VOICE_ID
  );
  const sourceContent = source.output || "";
  const sourceCredits = source.usage?.credits_used || 0;
  console.log(`  ✓ Source blog: ${sourceContent.split(/\s+/).length} words | ${sourceCredits} credits`);
  ```
</CodeGroup>

***

## Stage 2 — Define the Repurposing Plan

Each downstream piece receives the source blog as context. The generation app handles format adaptation — you provide format-specific instructions.

<CodeGroup>
  ```python Python theme={"dark"}
  REPURPOSE_PLAN = [
      {
          "app_id": "linkedin_ad_generator",
          "title": "LinkedIn Ad — Onboarding Case Study",
          "input_data": {
              "product": "Automation Builder",
              "target_audience": "VP of Product and Growth at B2B SaaS companies",
              "value_proposition": "Cut onboarding time by 70% — from 14 days to 4",
              "cta": "See the full case study",
              "additional_context": f"Based on this blog post:\n\n{source_content}",
          },
          "format": "linkedin_ad",
      },
      {
          "app_id": "social_post_generator",
          "title": "Twitter Thread — Onboarding Story",
          "input_data": {
              "topic": "How we cut onboarding from 14 days to 4",
              "platform": "Twitter",
              "tone": "conversational, data-backed",
              "count": 7,
              "additional_context": (
                  "Turn this blog post into a Twitter thread. "
                  "Each tweet should be self-contained but build on the narrative. "
                  "Use specific numbers from the post.\n\n"
                  f"{source_content}"
              ),
          },
          "format": "twitter_thread",
      },
      {
          "app_id": "email_sequence_generator",
          "title": "Email Nurture — Onboarding Proof Points",
          "input_data": {
              "sequence_goal": "Educate prospects on onboarding automation",
              "emails_count": 3,
              "target_audience": "Marketing-qualified leads interested in onboarding solutions",
              "key_points": [
                  "Email 1: The 14-day onboarding problem (pain point)",
                  "Email 2: How automation cut it to 4 days (solution)",
                  "Email 3: NPS impact and ROI (proof + CTA)",
              ],
              "additional_context": f"Draw all statistics and examples from this blog post:\n\n{source_content}",
          },
          "format": "email_sequence",
      },
      {
          "app_id": "product_description",
          "title": "Product Page — Automation Builder",
          "input_data": {
              "product_name": "Automation Builder",
              "features": [
                  "Drag-and-drop workflow automation",
                  "Reduce manual onboarding steps by 75%",
                  "Built-in analytics for drop-off detection",
              ],
              "target_audience": "SaaS product teams",
              "tone": "clear, benefit-focused",
              "additional_context": f"Use the case study data as proof points:\n\n{source_content}",
          },
          "format": "product_page",
      },
      {
          "app_id": "social_post_generator",
          "title": "Social Captions — Onboarding Stats",
          "input_data": {
              "topic": "Customer onboarding success story",
              "platform": "Instagram",
              "tone": "celebratory, data-driven",
              "count": 5,
              "additional_context": (
                  "Create Instagram captions highlighting key stats and outcomes "
                  f"from this case study:\n\n{source_content[:1500]}"
              ),
          },
          "format": "social_captions",
      },
  ]
  ```

  ```javascript JavaScript theme={"dark"}
  // Same structure as Python — each entry has app_id, title, input_data, format.
  // The key: every input_data includes additional_context with the sourceContent.
  const REPURPOSE_PLAN = [
    { app_id: "linkedin_ad_generator", title: "LinkedIn Ad", format: "linkedin_ad",
      input_data: { product: "Automation Builder", target_audience: "VP of Product at B2B SaaS",
        value_proposition: "Cut onboarding time by 70%", cta: "See the case study",
        additional_context: `Based on this blog post:\n\n${sourceContent}` } },
    { app_id: "social_post_generator", title: "Twitter Thread", format: "twitter_thread",
      input_data: { topic: "How we cut onboarding from 14 days to 4", platform: "Twitter",
        tone: "conversational, data-backed", count: 7,
        additional_context: `Turn this into a Twitter thread:\n\n${sourceContent}` } },
    { app_id: "email_sequence_generator", title: "Email Nurture", format: "email_sequence",
      input_data: { sequence_goal: "Educate prospects on onboarding automation", emails_count: 3,
        target_audience: "MQLs interested in onboarding solutions",
        key_points: ["Pain point", "Solution", "Proof + CTA"],
        additional_context: `Draw stats from:\n\n${sourceContent}` } },
    { app_id: "product_description", title: "Product Page", format: "product_page",
      input_data: { product_name: "Automation Builder", target_audience: "SaaS product teams",
        features: ["Drag-and-drop automation", "75% fewer manual steps", "Drop-off analytics"],
        additional_context: `Use case study data:\n\n${sourceContent}` } },
    { app_id: "social_post_generator", title: "Social Captions", format: "social_captions",
      input_data: { topic: "Onboarding success story", platform: "Instagram",
        tone: "celebratory, data-driven", count: 5,
        additional_context: `Key stats from:\n\n${sourceContent.slice(0, 1500)}` } },
  ];
  ```
</CodeGroup>

***

## Stage 3 — Generate All Downstream Pieces

<CodeGroup>
  ```python Python theme={"dark"}
  pieces = [
      {
          "format": "blog_post",
          "title": "Source: Onboarding Case Study",
          "output": source_content,
          "credits": source_credits,
      },
  ]
  total_credits = source_credits

  for item in REPURPOSE_PLAN:
      print(f"\nRepurposing → {item['format']}...")
      gen = generate(
          app_id=item["app_id"],
          title=item["title"],
          input_data=item["input_data"],
          brand_voice_id=BRAND_VOICE_ID,
      )

      credits = gen.get("usage", {}).get("credits_used", 0)
      total_credits += credits

      pieces.append({
          "format": item["format"],
          "title": item["title"],
          "output": gen.get("output", ""),
          "credits": credits,
      })

      word_count = len(gen.get("output", "").split())
      print(f"  ✓ {item['format']}: {word_count} words | {credits} credits")

  print(f"\n{'='*50}")
  print(f"Pipeline complete: {len(pieces)} pieces from 1 source | {total_credits} total credits")
  ```

  ```javascript JavaScript theme={"dark"}
  const pieces = [
    {
      format: "blog_post",
      title: "Source: Onboarding Case Study",
      output: sourceContent,
      credits: sourceCredits,
    },
  ];
  let totalCredits = sourceCredits;

  for (const item of REPURPOSE_PLAN) {
    console.log(`\nRepurposing → ${item.format}...`);
    const gen = await generate(item.app_id, item.title, item.input_data, BRAND_VOICE_ID);

    const credits = gen.usage?.credits_used || 0;
    totalCredits += credits;

    pieces.push({
      format: item.format,
      title: item.title,
      output: gen.output || "",
      credits,
    });

    const wordCount = (gen.output || "").split(/\s+/).length;
    console.log(`  ✓ ${item.format}: ${wordCount} words | ${credits} credits`);
  }

  console.log(`\nPipeline complete: ${pieces.length} pieces from 1 source | ${totalCredits} total credits`);
  ```
</CodeGroup>

***

## Stage 4 — Executive Summary via Chat

Use Chat to generate a concise executive summary from the source blog. Useful for internal Slack posts, newsletter previews, or stakeholder updates.

<CodeGroup>
  ```python Python theme={"dark"}
  from openai import OpenAI

  mavera = OpenAI(api_key=API_KEY, base_url=BASE)

  exec_resp = mavera.responses.create(
      model="mavera-1",
      input=[
          {
              "role": "user",
              "content": (
                  "Write a 150-word executive summary of this blog post. "
                  "Focus on the business impact and key metrics. "
                  "Use bullet points for the 3 most important takeaways. "
                  "End with a one-sentence recommendation.\n\n"
                  f"{source_content}"
              ),
          },
      ],
  )
  exec_summary = exec_resp.output[0].content[0].text

  pieces.append({
      "format": "executive_summary",
      "title": "Executive Summary",
      "output": exec_summary,
      "credits": 2,
  })
  total_credits += 2

  print(f"\nExecutive summary ({len(exec_summary.split())} words):")
  print(exec_summary)
  ```

  ```javascript JavaScript theme={"dark"}
  import OpenAI from "openai";
  const mavera = new OpenAI({ apiKey: API_KEY, baseURL: BASE });

  const execResp = await mavera.responses.create({
    model: "mavera-1",
    input: [
      {
        role: "user",
        content:
          "Write a 150-word executive summary of this blog post. " +
          "Focus on the business impact and key metrics. " +
          "Use bullet points for the 3 most important takeaways. " +
          `End with a one-sentence recommendation.\n\n${sourceContent}`,
      },
    ],
  });
  const execSummary = execResp.output[0].content[0].text;

  pieces.push({
    format: "executive_summary",
    title: "Executive Summary",
    output: execSummary,
    credits: 2,
  });
  totalCredits += 2;
  console.log(`\nExecutive summary (${execSummary.split(/\s+/).length} words):`);
  console.log(execSummary);
  ```
</CodeGroup>

***

***

## Variations

<AccordionGroup>
  <Accordion title="Start from existing content">
    Skip Stage 1 if you already have a published blog post. Load it from a file or your CMS API and use it directly as `source_content` for the repurposing loop.
  </Accordion>

  <Accordion title="Add more formats">
    Check `GET /generation-apps` for new templates (press releases, video scripts, podcast outlines) and append them to `REPURPOSE_PLAN`.
  </Accordion>

  <Accordion title="Persona-adapted repurposing">
    Map each downstream format to a different persona — LinkedIn ads for B2B decision makers, social captions for Gen Z consumers — so each piece speaks to its platform's primary audience.
  </Accordion>

  <Accordion title="Quality gate before downstream generation">
    Score the source blog post with Chat + `response_format` before repurposing. If clarity, accuracy, or engagement scores fall below a threshold, iterate on the source first — repurposing weak content just multiplies the weakness.
  </Accordion>

  <Accordion title="Parallel generation for speed">
    All downstream pieces are independent — use `asyncio.gather` (Python) or `Promise.all` (JS) to run all 5 repurposing calls concurrently instead of sequentially.
  </Accordion>

  <Accordion title="Consistency check across all pieces">
    After generating everything, feed all outputs into a single Chat call asking it to verify that key metrics (70% reduction, 14→4 days, NPS 32→58) appear consistently. Flag any contradictions or omissions.
  </Accordion>
</AccordionGroup>

***

## Credits Estimate

| Operation                        | Typical Cost          | Notes                        |
| -------------------------------- | --------------------- | ---------------------------- |
| Source blog post                 | 15–30 credits         | Long-form generation         |
| LinkedIn ad                      | 10–20 credits         | Short-form                   |
| Twitter thread (7 tweets)        | 10–20 credits         | Short-form batch             |
| Email nurture (3 emails)         | 15–30 credits         | Multi-part                   |
| Product description              | 10–25 credits         | Medium-form                  |
| Social captions (5 posts)        | 10–20 credits         | Short-form batch             |
| Executive summary (Chat)         | 1–5 credits           | Single chat call             |
| **Total (7 pieces)**             | **\~70–150 credits**  | Without brand voice creation |
| **Total (with new brand voice)** | **\~120–200 credits** | One-time voice + all pieces  |

<Tip>
  The repurposing pipeline is one of the highest-ROI workflows in Mavera. For \~100 credits you get 7 content pieces that would take a content team 2–3 days to produce manually. Run it every time you publish a blog post.
</Tip>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Brand Voice Content Library" icon="palette" href="/playbooks/brand-voice-content-library">
    Create a full content library with consistent brand voice
  </Card>

  <Card title="Content Series Generation" icon="layer-group" href="/playbooks/content-series-generation">
    Turn the source blog into a multi-part series before repurposing
  </Card>

  <Card title="A/B Copy Production" icon="clone" href="/playbooks/ab-copy-production">
    Generate A/B variants of each repurposed piece
  </Card>

  <Card title="Content Localization" icon="globe" href="/playbooks/content-localization">
    Localize the repurposed content for different markets
  </Card>

  <Card title="Content Generation" icon="wand-magic-sparkles" href="/features/content-generation">
    Full API reference for generation apps
  </Card>

  <Card title="Credits & Budget" icon="coins" href="/cookbooks/credits-budget-alerts">
    Track and manage credit usage
  </Card>
</CardGroup>
