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.vuecalls 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.tsand 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
- For each industry (max 3 to avoid rate limits), search for recent trending threads
- Flatten all results, dedup by title similarity (simple: exact match or first 60 chars)
- Return up to 5 results total, prioritised by
is_relevant: truefrom the existing forum search - Timeout: 8 seconds — if the forum search API times out, return
[](non-blocking) - If
industriesis 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()toauto-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,
}
fetchIndustryNewsis Gemini-only and already returns[]when not on Gemini.fetchForumInsightsruns regardless ofLLM_PROVIDER.
runSingleGeneration() change
Pass forumInsights through to synthesizeTopic():
const enrichedPrompt = await synthesizeTopic(context, newsInsights, forumInsights, basePrompt)
Tasks
- [ ] Update
gatherContext()to callfetchForumInsightsin parallel withfetchIndustryNews - [ ] Return
forumInsightsfromgatherContext() - [ ] Update
runSingleGeneration()to passforumInsightstosynthesizeTopic()
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
forumInsightsparameter tosynthesizeTopic() - [ ] 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?toPostContent, inject in social generators
Testing Checklist
Setup
- Ensure the test customer has
industriesset (required for forum search) - Confirm the forum search API is reachable from the API server (not just the frontend)
Verification
- [ ] Trigger
POST /plan_postsfor a customer with social platforms — check server logs confirmfetchForumInsightswas called - [ ] Inspect the synthesised prompt in logs (add a
request.log.debugline insynthesizeTopic) — 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
fetchForumInsightscall fromgatherContext() - Remove
forumInsightsparameter fromsynthesizeTopic() - No schema changes to revert
- No frontend changes to revert (this phase is API-only)