Ai-Mee Help Centre
Home
Features
How-To Guides
FAQ
Need Help?
Home
Features
How-To Guides
FAQ
Need Help?

Phase 4: Social Content — Forum & Community Trend Signals

Status: ✅ IMPLEMENTED
Prerequisites: Phase 1 complete (social intent framing must be in place)
Objective: Social posts generated via the auto-generate pipeline are informed by what the customer's target audience is actually discussing in community forums (Reddit, Quora, industry boards), producing content that taps into real trends rather than generic product angles.


Background

The platform already has a forum research feature (forum.vue) that lets users manually search Reddit/Quora by keyword and get thread summaries. The fetchIndustryNews() function in auto-generate-context.ts also fetches news signals (Gemini only). Neither of these feeds into social post generation automatically.

This phase extracts the forum search logic into a reusable utility and calls it automatically during the runSingleGeneration() pipeline when social platforms are in scope, alongside the existing news fetch.


10.1 — Audit the Existing Forum Search

Before implementing, confirm where the forum search logic lives:

  • front-end/src/pages/app/client/[id]/forum.vue calls some API endpoint — identify which one
  • Trace that endpoint to its implementation in api/src/routes/
  • Determine whether the core search logic is already a reusable function or is embedded in the route handler

Expected outcome: There is likely a POST /client/:id/forum/search or similar route. The goal is to extract the core function into api/src/utils/forum-search.ts (or similar) if it is not already a standalone utility.

Tasks

  • [ ] Find the forum API route in api/src/routes/
  • [ ] Identify the core search function (e.g. searchForumThreads(keyword, industries))
  • [ ] If the logic is inline in the route handler: extract it to api/src/utils/forum-search.ts and update the route handler to call the utility
  • [ ] If already a standalone function: note the import path and proceed to 10.2

10.2 — fetchForumInsights() in auto-generate-context.ts

Target file: api/src/modules/auto-generate-context.ts

Add a new function fetchForumInsights(industries: string[]) that calls the forum search utility and returns a flat, deduped list of trending topics.

Interface

interface ForumInsight {
  title: string
  summary: string
  source: 'reddit' | 'quora' | 'other'
  relevance: 'high' | 'medium'
}

async function fetchForumInsights(industries: string[]): Promise<ForumInsight[]>

Logic

  1. For each industry (max 3 to avoid rate limits), search for recent trending threads
  2. Flatten all results, dedup by title similarity (simple: exact match or first 60 chars)
  3. Return up to 5 results total, prioritised by is_relevant: true from the existing forum search
  4. Timeout: 8 seconds — if the forum search API times out, return [] (non-blocking)
  5. If industries is empty: skip the call and return []
async function fetchForumInsights(industries: string[]): Promise<ForumInsight[]> {
  if (industries.length === 0) return []

  const industry = industries.slice(0, 3).join(', ')

  try {
    const results = await Promise.race([
      searchForumThreads(industry), // ← imported from the utility in 10.1
      new Promise<never>((_, reject) => setTimeout(() => reject(new Error('forum timeout')), 8000)),
    ])

    return (results as any[])
      .filter((r) => r.is_relevant !== false)
      .slice(0, 5)
      .map((r) => ({
        title: r.title ?? '',
        summary: r.thread_summary ?? r.snippet ?? '',
        source: detectSource(r.url ?? ''),
        relevance: r.is_relevant ? 'high' : 'medium',
      }))
  } catch {
    return [] // silent — generation continues without forum data
  }
}

Tasks

  • [ ] Add fetchForumInsights() to auto-generate-context.ts
  • [ ] Import the forum search utility extracted in 10.1

10.3 — Wire into gatherContext() and runSingleGeneration()

Target file: api/src/modules/auto-generate-context.ts

gatherContext() change

gatherContext() already returns newsInsights (passed to synthesizeTopic()). Add forumInsights alongside it.

// In gatherContext() — call in parallel with fetchIndustryNews:
const [newsInsights, forumInsights] = await Promise.all([
  fetchIndustryNews(customer.industries ?? []),
  fetchForumInsights(customer.industries ?? []),
])

return {
  ...existingFields,
  newsInsights,
  forumInsights,
}

fetchIndustryNews is Gemini-only and already returns [] when not on Gemini. fetchForumInsights runs regardless of LLM_PROVIDER.

runSingleGeneration() change

Pass forumInsights through to synthesizeTopic():

const enrichedPrompt = await synthesizeTopic(context, newsInsights, forumInsights, basePrompt)

Tasks

  • [ ] Update gatherContext() to call fetchForumInsights in parallel with fetchIndustryNews
  • [ ] Return forumInsights from gatherContext()
  • [ ] Update runSingleGeneration() to pass forumInsights to synthesizeTopic()

10.4 — Social-Scoped Injection in synthesizeTopic()

Target file: api/src/modules/auto-generate-context.ts

Change

synthesizeTopic() assembles a multi-section context string before the final LLM synthesis call. Add a forumInsights parameter and inject it only when the platform group is 'social' (using the detectPlatformGroup() helper added in Phase 7).

// Updated signature:
async function synthesizeTopic(
  context: EnrichmentContext,
  newsInsights: string,
  forumInsights: ForumInsight[],
  basePrompt?: string
): Promise<string>

Prompt section to inject (social platforms only)

Place this section between "Industry news & trends" and "Approved post examples":

TRENDING COMMUNITY DISCUSSIONS (use as social content angles):
${forumInsights.map(f => `- [${f.source.toUpperCase()}] ${f.title}: ${f.summary}`).join('\n')}

When selecting a topic for social posts, consider weaving in one of these trending discussions
as an engagement hook — reference the trend, share your perspective on it, or ask your audience
about their experience with it. Do not copy or plagiarise the original content.

If forumInsights is empty, omit the section entirely.

Tasks

  • [ ] Add forumInsights parameter to synthesizeTopic()
  • [ ] Inject forum insights section into the synthesis prompt for social platform group
  • [ ] Verify the section is omitted when forumInsights.length === 0
  • [ ] Update the synthesis prompt instruction to reference forum signals: "If forum insights are provided and the platform is social, prioritise topics that naturally intersect with trending discussions"

10.5 — Social Generator: trendingTopics Injection

Target file: api/src/agents/createPosts.ts

For social platforms that receive a forum-enriched prompt, the synthesised prompt already contains the trend signals. However, the per-platform generators can optionally receive trendingTopics directly for more granular injection (rather than relying solely on the synthesised prompt).

This is an optional enhancement — it's not required if the synthesised prompt reliably carries the forum signal through.

If implemented

Add trendingTopics?: string[] to PostContent. When provided, append to social generator prompts:

Community trends to reference naturally (pick at most one):
${trendingTopics.map(t => `- ${t}`).join('\n')}
Do not force the trend in — only use it if it fits the topic naturally.

Decision

Implement this only if testing in 10.3/10.4 shows the synthesised prompt is not reliably carrying forum signals into the per-platform generators. Start with just the synthesizeTopic() injection in 10.4.

Tasks (conditional)

  • [ ] Evaluate after Phase 10.3/10.4 testing whether direct injection is needed
  • [ ] If yes: add trendingTopics? to PostContent, inject in social generators

Testing Checklist

Setup

  1. Ensure the test customer has industries set (required for forum search)
  2. Confirm the forum search API is reachable from the API server (not just the frontend)

Verification

  • [ ] Trigger POST /plan_posts for a customer with social platforms — check server logs confirm fetchForumInsights was called
  • [ ] Inspect the synthesised prompt in logs (add a request.log.debug line in synthesizeTopic) — confirm forum insights section appears for social runs
  • [ ] Verify a customer with no industries set skips the forum call (no errors)
  • [ ] Simulate a forum search timeout (mock 9-second delay) — verify generation completes successfully with forumInsights: []
  • [ ] Verify blog/email generation runs are not affected by the forum block (section should be absent)
  • [ ] Run route tests: cd api && pnpm test:routes

Rollback

  • Remove fetchForumInsights call from gatherContext()
  • Remove forumInsights parameter from synthesizeTopic()
  • No schema changes to revert
  • No frontend changes to revert (this phase is API-only)