A GitHub Pages-ready trend monitor for reviewed URL clusters, topic momentum, source spread, and audio briefings. The static site now reads from data/stories.json, and the repo includes a small Outlook-to-review-queue pipeline so the feed can become operational instead of staying hand-seeded.
- Public-facing topic feed with filters, tag pages, trends, charts, and audio briefings
data/stories.jsonas the published source consumed by the site- Outlook ingestion script that pulls messages from Microsoft Graph into
data/review-queue.json - Review script for approving or rejecting queued items
- Publish script that turns approved review items into live site stories
- GitHub Pages workflow for static deployment
index.html- page structurestyles.css- layout and presentationapp.js- client-side rendering fromdata/stories.jsondata/stories.json- published topic input used by the sitedata/review-queue.json- editorial review queue populated from Outlookscripts/sync-stories.js- pulls candidate stories from Outlook via Microsoft Graphscripts/review-story.js- marks queued items as approved, pending, or rejectedscripts/publish-stories.js- publishes approved stories to the live feedscripts/publish-airtable.js- rebuilds the live feed from approved Airtable recordsscripts/generate-podcast-briefing.js- generates an MP3 briefing from approved Airtable stories using Gemini plus Google TTSdocs/airtable-schema.md- Airtable field layout for the review tabledocs/audio-briefing-setup.md- Gemini plus Google TTS setup and briefing workflowprompts/story-extraction.md- OpenAI prompt for Zapier extraction.github/workflows/pages.yml- GitHub Pages deployment workflow.github/workflows/publish-from-airtable.yml- on-demand Airtable publish workflow.github/workflows/generate-podcast-briefing.yml- on-demand audio briefing workflow
- Copy
.env.exampleto.envor export the variables in your shell. - Register a Microsoft Entra application with application permission to read mail for the target mailbox.
- Grant admin consent for the Graph mail permission.
- Point
OUTLOOK_USER_EMAILat the mailbox that receives story emails. - Add Airtable secrets in GitHub Actions for publish automation.
- Commit and push after publishing data updates so GitHub Pages picks them up.
The Outlook sync script uses Microsoft Graph application auth and expects:
MS_TENANT_IDMS_CLIENT_IDMS_CLIENT_SECRETOUTLOOK_USER_EMAILOUTLOOK_MAIL_FOLDERsuch asinboxor a folder id prefixed withid:OUTLOOK_MAX_MESSAGESAIRTABLE_BASE_IDAIRTABLE_TABLE_NAMEAIRTABLE_TOKENAIRTABLE_VIEW_NAMESEMRUSH_API_KEYSEMRUSH_DATABASEGOOGLE_CLOUD_PROJECT_IDGOOGLE_OAUTH_ACCESS_TOKENGEMINI_LOCATIONGEMINI_MODELGOOGLE_TTS_USE_MULTISPEAKERGOOGLE_TTS_MULTISPEAKER_VOICEGOOGLE_TTS_FALLBACK_VOICE_NAMEGOOGLE_TTS_FALLBACK_GENDERAUDIO_BRIEFING_STORY_LIMITAUDIO_BRIEFING_MINUTES
- Pull messages from Outlook into the review queue:
npm run sync:outlook- See the queued items:
npm run review:list- Approve one with an editorial patch:
node scripts/review-story.js approve story-id '{"topic":"Water access","tags":["drought","policy"],"whyItMatters":"Why this should be in the public feed.","momentum":72}'- Publish approved stories into the live site feed:
npm run publish:stories- Push the updated JSON to GitHub so Pages republishes.
To rebuild the site directly from Airtable:
npm run publish:airtableFor GitHub automation, add these repository secrets:
AIRTABLE_BASE_IDAIRTABLE_TABLE_NAMEAIRTABLE_TOKENAIRTABLE_VIEW_NAME(optional)SEMRUSH_API_KEY(optional but recommended for trend direction)SEMRUSH_DATABASEsuch asus(optional)
Then trigger .github/workflows/publish-from-airtable.yml manually, or from Zapier using GitHub repository_dispatch with event type publish-stories.
When SEMRUSH_API_KEY is present, the publish pipeline enriches each clustered story with Semrush daily traffic for its source domain and uses that traffic series as the preferred directional signal for topic trend movement.
To generate an audio briefing from approved Airtable stories:
npm run generate:podcastSee docs/audio-briefing-setup.md for Google Cloud setup, secrets, and the GitHub workflow path.
- Outlook new email in
Story Intake - OpenAI extraction using
prompts/story-extraction.md - Airtable create record using
docs/airtable-schema.md - Airtable status changed to
Approved - Zapier webhook to GitHub
repository_dispatch
The site consumes data/stories.json in this form:
{
"stories": [
{
"id": "string",
"headline": "string",
"source": "string",
"date": "YYYY-MM-DD",
"slug": "string",
"tags": ["string"],
"topic": "string",
"summary": "string",
"whyItMatters": "string",
"relevance": "string",
"momentum": 0,
"recentMovement": [1, 2, 3],
"related": ["story-id"]
}
],
"audioBriefings": []
}- The frontend falls back to embedded sample data if
data/stories.jsonis missing or unreadable. - The review queue is intentionally JSON-first for speed. If you want multi-editor workflow next, Airtable is the obvious next source of truth.