content-publisher
Autonomous content creation, review, and multi-platform publishing for ACT ecosystem. Includes Empathy Ledger Content Hub for photography, videography, and storytelling with AI-powered tagging and ecosystem syndication.
Best use case
content-publisher is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Autonomous content creation, review, and multi-platform publishing for ACT ecosystem. Includes Empathy Ledger Content Hub for photography, videography, and storytelling with AI-powered tagging and ecosystem syndication.
Teams using content-publisher should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/content-publisher/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How content-publisher Compares
| Feature / Agent | content-publisher | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Autonomous content creation, review, and multi-platform publishing for ACT ecosystem. Includes Empathy Ledger Content Hub for photography, videography, and storytelling with AI-powered tagging and ecosystem syndication.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Content Publisher - ACT Communications Automation
## Empathy Ledger Content Hub (NEW)
Empathy Ledger serves as the **central content hub** for the ACT ecosystem - photography, videography, writing, and storytelling with intelligent tagging and API-driven syndication.
### Content Hub Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ CONTENT SOURCES │
│ • Your photography and videography │
│ • Storyteller contributions │
│ • ACT project milestones │
│ • Ralph-generated content │
└────────────────────────────┬────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────┐
│ EMPATHY LEDGER CONTENT HUB │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ MEDIA INTELLIGENCE (Consent-Gated) │ │
│ │ • Auto-tag objects/scenes in photos (Claude Vision) │ │
│ │ • Face recognition → link to storyteller profiles │ │
│ │ • Theme extraction → narrative connections │ │
│ │ • ALMA integration (interventions, evidence) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ THREE-TIER VISIBILITY │ │
│ │ • Private: Storyteller only │ │
│ │ • Community: ACT ecosystem + approved partners │ │
│ │ • Public: Anyone with attribution │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ CONTENT SYNDICATION API │ │
│ │ • GET /api/v1/content-hub/stories │ │
│ │ • GET /api/v1/content-hub/articles │ │
│ │ • GET /api/v1/content-hub/media/library │ │
│ │ • GET /api/v1/content-hub/themes │ │
│ │ • POST /api/v1/content-hub/syndicate │ │
│ └─────────────────────────────────────────────────────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────┐
│ DISTRIBUTION │
│ │
│ ACT Projects (via API) External Users Social │
│ • JusticeHub • Partner orgs • GHL │
│ • ACT Farm • Researchers • Social │
│ • The Harvest • Media • Posts │
│ • Goods on Country │
│ • ACT Placemat │
└─────────────────────────────────────────────────────────────────────┘
```
### Content Hub Database Tables
| Table | Purpose |
|-------|---------|
| `media_ai_analysis` | Smart photo/video tagging (consent-gated) |
| `media_person_recognition` | Face recognition with two-party consent |
| `media_narrative_themes` | Theme extraction and story linking |
| `articles` | Blog/article content for syndication |
| `content_syndication` | Track content distribution |
### Media Intelligence Pipeline
```typescript
// Photo analysis with consent gate
import { createPhotoAnalyzer } from './lib/media-intelligence/photo-analyzer';
const analyzer = createPhotoAnalyzer();
// 1. Grant consent (REQUIRED before any AI analysis)
await analyzer.grantConsent(mediaAssetId, storytellerId, grantedBy);
// 2. Analyze photo
const result = await analyzer.analyzePhoto({
mediaAssetId,
storytellerId,
imageUrl,
consentGranted: true
});
// Result includes:
// - detectedObjects: [{label, confidence}]
// - sceneClassification: 'portrait' | 'ceremony' | etc.
// - autoTags: ['community', 'gathering', ...]
// - culturalReviewRequired: boolean
// - emotionalTone: 'hopeful' | 'reflective' | etc.
```
### Face Recognition (Two-Party Consent)
```typescript
import { createFaceRecognition } from './lib/media-intelligence/face-recognition';
const faces = createFaceRecognition();
// Step 1: Uploader grants consent
await faces.grantUploaderConsent(recognitionId, uploaderId);
// Step 2: Person in photo grants consent
await faces.grantPersonConsent(recognitionId, storytellerId, personId, canBePublic);
// Only after BOTH consents can identity be linked
```
### Content Hub API Reference
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v1/content-hub/stories` | GET | List published stories |
| `/api/v1/content-hub/stories/:id` | GET | Single story with full content |
| `/api/v1/content-hub/articles` | GET | List published articles |
| `/api/v1/content-hub/articles/:slug` | GET | Single article by slug |
| `/api/v1/content-hub/media/library` | GET | Browse media library |
| `/api/v1/content-hub/themes` | GET | Discover content by themes |
| `/api/v1/content-hub/search` | GET | Full-text search |
| `/api/v1/content-hub/syndicate` | POST | Register syndication |
### Content Hub File References
| Need | Reference |
|------|-----------|
| Database migration | `empathy-ledger-v2/supabase/migrations/20260109000001_content_hub_schema.sql` |
| Photo analyzer | `references/photo-analyzer.ts` |
| Face recognition | `references/face-recognition.ts` |
| Theme extractor | `references/theme-extractor.ts` |
| Syndication API | `references/content-syndication-api.ts` |
---
## When to Use
- Creating social media content from project milestones
- Generating posts from Ralph PRD completions
- Publishing approved content to social platforms
- Checking content sync status
- Generating content ideas from ecosystem activity
## Quick Commands
| Command | Description |
|---------|-------------|
| `generate <topic>` | Create draft post from ecosystem knowledge |
| `sync` | Sync all sources (Notion + Empathy Ledger) to GHL |
| `sync --notion-only` | Sync only Notion content to GHL |
| `sync --empathy-only` | Sync only Empathy Ledger content to GHL |
| `status` | Check publishing pipeline status |
| `schedule <date>` | Schedule content for specific date |
| `ideas` | Generate post ideas from recent activity |
## Content Flow
```
┌─────────────────────────────────────────────────────┐
│ 1. CONTENT SOURCES │
│ • Ralph PRD completions → auto-generate posts │
│ • Sprint milestones → project updates │
│ • Codebase commits → technical insights │
│ • Brand alignment skill → voice/tone check │
│ • Empathy Ledger articles & stories (NEW) │
└─────────────────────┬───────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 2A. NOTION CONTENT HUB │
│ Database: e400e93e-fd9d-4a21-810c-58d67ed9fe97 │
│ │
│ Status Flow: │
│ Story in Development → Ready to Connect → │
│ Conversation Scheduled → Connected & Delighted │
└─────────────────────┬───────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────┐
│ 2B. EMPATHY LEDGER CONTENT HUB │
│ URL: EMPATHY_LEDGER_URL (default: localhost:3000) │
│ │
│ Status Flow: │
│ Draft → In Review → Elder Review → Published │
│ │
│ Article Types: │
│ • story_feature, program_spotlight │
│ • research_summary, community_news │
│ • editorial, impact_report │
│ │
│ Stories with syndication_enabled = true │
└─────────────────────┬───────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 3. GHL PUBLISHING │
│ Script: scripts/sync-content-to-ghl.mjs │
│ │
│ Syncs from BOTH sources automatically: │
│ • Notion "Ready to Connect" items │
│ • Empathy Ledger published articles/stories │
│ │
│ Connected Accounts: │
│ • LinkedIn (Company) - A Curious Tractor │
│ • LinkedIn (Personal) - Benjamin Knight │
│ • YouTube - A Curious Tractor │
│ • Google Business Profile │
│ • Bluesky - A Curious Tractor │
│ │
│ View engagement: GHL Dashboard → Social Planner │
└─────────────────────────────────────────────────────┘
```
## Target Accounts
| Account | Env Variable | Best For |
|---------|--------------|----------|
| LinkedIn (Company) | `GHL_LINKEDIN_ACCOUNT_ID` | Professional updates, milestones |
| LinkedIn (Personal) | `GHL_LINKEDIN_PERSONAL_ID` | Personal stories, reflections |
| YouTube | `GHL_YOUTUBE_ACCOUNT_ID` | Video announcements |
| Google Business | `GHL_GBP_ACCOUNT_ID` | Local updates, events |
| Bluesky | `GHL_BLUESKY_ACCOUNT_ID` | Tech community, open source |
## Content Generation
### From Ralph Completions
When Ralph completes a PRD feature, auto-generate announcement:
```javascript
// Read ralph/progress.txt for recent completions
// Generate post using act-brand-alignment voice
// Create in Notion with "Story in Development" status
```
### From Sprint Milestones
Query sprint tracking for completed items, generate weekly digest.
### From Ecosystem Activity
Scan all 7 project codebases for:
- New releases/tags
- Significant commits
- Documentation updates
- Test coverage improvements
## Publishing Commands
### Sync All Sources (Notion + Empathy Ledger)
```bash
node scripts/sync-content-to-ghl.mjs
```
### Sync Only Notion
```bash
node scripts/sync-content-to-ghl.mjs --notion-only
```
### Sync Only Empathy Ledger
```bash
node scripts/sync-content-to-ghl.mjs --empathy-only
```
### Dry Run (Preview)
```bash
node scripts/sync-content-to-ghl.mjs --dry-run
```
### Check Status
```bash
node scripts/sync-content-to-ghl.mjs --status
```
### Check GHL Posts
```bash
node scripts/check-ghl-engagement.mjs
```
## Brand Alignment Integration
Always invoke `act-brand-alignment` skill before publishing to ensure:
- Farm metaphors (seeds, harvest, cultivating)
- Community ownership language
- No savior framing
- Proper voice/tone
## Notion API Notes
- **API Version:** 2025-09-03
- **Endpoint:** `/data_sources/{id}/query` (not `/databases/`)
- **Create pages:** Use database ID `7005d0d1-41d3-436c-9f86-526d275c2f10`
- **Query content:** Use data source ID `e400e93e-fd9d-4a21-810c-58d67ed9fe97`
## Automated Content Pipeline
### Full Workflow
```
┌─────────────────────────────────────────────────────────────┐
│ 1. AGGREGATE ECOSYSTEM KNOWLEDGE │
│ node scripts/aggregate-ecosystem-knowledge.mjs │
│ │
│ Scans: Git activity, Ralph progress, Notion sprints, │
│ Documentation updates, Deployments │
└─────────────────────┬───────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 2. GENERATE CONTENT │
│ node scripts/generate-content-from-knowledge.mjs │
│ │
│ Types: weekly-activity, feature-shipped, sprint-milestone, │
│ technical-insight, project-spotlight │
│ │
│ Output: Drafts in Notion with "Story in Development" │
└─────────────────────┬───────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 3. HUMAN REVIEW (Notion) │
│ Edit content, add images, approve │
│ Change status to "Ready to Connect" │
└─────────────────────┬───────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 4. PUBLISH │
│ node scripts/sync-content-to-ghl.mjs │
│ │
│ Auto-syncs approved content to social platforms │
└─────────────────────────────────────────────────────────────┘
```
### Quick Commands
```bash
# Generate content drafts from ecosystem knowledge
node scripts/generate-content-from-knowledge.mjs
# Preview without creating (dry run)
node scripts/generate-content-from-knowledge.mjs --dry-run
# Generate specific type
node scripts/generate-content-from-knowledge.mjs --type weekly-activity
# Sync approved content to social
node scripts/sync-content-to-ghl.mjs
# Check status
node scripts/sync-content-to-ghl.mjs --status
# Ralph content runner (combines all)
./ralph/ralph-content.sh
```
### Content Types
| Type | Description | Best Accounts |
|------|-------------|---------------|
| `weekly-activity` | Ecosystem commit summary | LinkedIn (Company) |
| `feature-shipped` | Ralph completion announcement | Both LinkedIn |
| `sprint-milestone` | Sprint progress update | LinkedIn (Company) |
| `technical-insight` | Technical learnings | LinkedIn (Personal) |
| `project-spotlight` | Project deep dive | Both LinkedIn |
### Automated Schedule (GitHub Actions)
| Schedule | Action |
|----------|--------|
| Sunday 10pm UTC (Monday 8am AEST) | Generate weekly content |
| Every 4 hours | Sync approved content to GHL |
Trigger manually: Actions → Content Pipeline → Run workflow
## Media Handling
### Media Service
```javascript
import { createMediaService } from './scripts/lib/media-service.mjs';
const media = createMediaService();
// Get brand asset
const logoUrl = media.getBrandAsset('logo');
// Get project hero image
const heroUrl = media.getProjectAsset('JusticeHub');
// Upload local file
const result = await media.uploadFile('./image.png');
// Suggest image from content
const suggestion = media.suggestImage('Building ecosystem together');
```
### Media Storage
- **Supabase**: `tednluwflfhxyucgwigh.supabase.co/storage/v1/object/public/content-media/`
- **Brand assets**: `brand/` folder
- **Project assets**: `projects/` folder
- **Uploads**: `uploads/` folder
### Image Recommendations
Content generation auto-suggests images:
1. Project mentions → Project hero image
2. Growth/seeds keywords → Pattern asset
3. Community keywords → Cockatoo asset
4. Default → ACT logo
For custom images:
1. Upload to Supabase storage
2. Add URL to Notion "Image" field or "Notes"
3. GHL will use the URL when publishing
## File References
| Need | Reference |
|------|-----------|
| Content generation | `scripts/generate-content-from-knowledge.mjs` |
| Knowledge aggregator | `scripts/aggregate-ecosystem-knowledge.mjs` |
| Media service | `scripts/lib/media-service.mjs` |
| Sync script | `scripts/sync-content-to-ghl.mjs` |
| GHL social service | `scripts/lib/ghl-social-service.mjs` |
| **Empathy Ledger service** | `scripts/lib/empathy-ledger-content.mjs` |
| Content PRD template | `ralph/content-prd-template.json` |
| Ralph content runner | `ralph/ralph-content.sh` |
| GitHub Action | `.github/workflows/content-pipeline.yml` |
| Notion database IDs | `config/notion-database-ids.json` |
| Post creation template | `references/post-template.mjs` |
| Content ideas generator | `references/content-ideas.md` |
## Empathy Ledger Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `EMPATHY_LEDGER_URL` | Empathy Ledger API base URL | `http://localhost:3000` |
| `CONTENT_HUB_API_KEY` | API key for Content Hub access | Auto-generated |
## Empathy Ledger Content Fetcher API
```javascript
import { createEmpathyLedgerService } from './lib/empathy-ledger-content.mjs';
const el = createEmpathyLedgerService({
baseUrl: 'https://empathyledger.com',
apiKey: process.env.CONTENT_HUB_API_KEY
});
// Get published articles
const articles = await el.getArticles({ type: 'story_feature', limit: 10 });
// Get public stories
const stories = await el.getStories({ visibility: 'public', limit: 20 });
// Get content ready for GHL sync
const content = await el.getContentForGHLSync();
// Returns: { articles: [...], stories: [...], total: N }
// Transform to GHL post format
const ghlPost = el.articleToGHLPost(article, { accountIds: [...] });
// Register syndication
await el.registerSyndication({
contentType: 'article',
contentId: article.id,
destinationType: 'ghl_social',
ghlPostId: 'xxx'
});
// Health check
const health = await el.healthCheck();
// Returns: { healthy: true, baseUrl, articlesAvailable }
```Related Skills
wechat-content-skill
公众号内容创作助手 - 帮助高效采集素材、筛选选题、创作优质文章
url-content-loading
A URL content loading tool that extracts text or metadata from URLs across multiple platforms (YouTube, PTT, Twitter/X, Truth Social, Reddit, GitHub, and more). Use this when you need to load and extract content from social posts, videos, documents, or code repositories for scraping, data extraction, or content analysis.
social-content
When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform-specific strategies.
seo-content
Content quality and E-E-A-T assessment with AI citation readiness scoring. Evaluates Experience, Expertise, Authoritativeness, and Trustworthiness alongside word count analysis, readability metrics, keyword optimization, content structure, and Generative Engine Optimization (GEO) signals.
seo-content-refresher
Identifies outdated elements in provided content and suggests updates to maintain freshness. Finds statistics, dates, and examples that need updating. Use PROACTIVELY for older content.
refresh-content
Update existing content with fresh information and improvements.
instagram-content
Creates viral Instagram Reels, Stories, and posts using the Hook-Substance-Payoff framework, with technical recording settings, engagement tactics, caption copywriting, and hashtag strategy. Use when scripting short-form video, writing IG captions, or developing Instagram content strategy. Trigger phrases: "Instagram reel", "IG post", "social media content", "stories script", "caption for Instagram". Do NOT use for long-form blog posts (use web-copy), product descriptions (use product-copy), or email campaigns (use newsletter).
image-publisher
Upload local images to image hosting services and get accessible URLs. Use this skill when the user wants to upload a local image file to an image host and get the public URL. Supports GitHub and S3-compatible storage (Qiniu, Aliyun OSS, Tencent COS, etc.).
gtse-social-content
B2B social media content strategy for GTSE industrial supplies. Primary focus on LinkedIn for reaching trade professionals and procurement managers. Includes product demos, industry tips, and trade customer engagement. Adapted for industrial supplies B2B social marketing.
Generate educational content with fixed sections
Generate educational content about any topic following a user-specified structure: include a set number of learning tips/tricks or activities, fun facts, Q&A pairs, jokes, and optionally extend with additional lines. Always list supplies for activities when requested.
didactic-content-generator
Gere conteúdo didático de alta qualidade em HTML/CSS com ilustrações SVG, usando um sistema de Temas pré definidos e reutilizáveis. Capaz de criar ou editar apostilas, tutoriais e materiais educacionais que seguem filosofias pedagógicas claras.
Contentful Automation
Automate headless CMS operations in Contentful -- list spaces, retrieve space metadata, and update space configurations through the Composio Contentful integration.