Skip to main content

⚙️ Configuration

Configure your curate.fun instance through the curate.config.json file ⚡

🏗️ Structure

🌍 Global Settings

{
"global": {
"botId": "curatedotfun", // @handle for twitter bot
"defaultStatus": "pending",
"maxDailySubmissionsPerUser": 15,
"blacklist": { // ignore submissions according to inbound platform
"twitter": [
"blocked_id"
]
}
}
}

🔌 Plugins

Plugins extend functionality with transformations and distribution capabilities. See the Plugins section for detailed documentation on each plugin.

{
"plugins": {
"@curatedotfun/telegram": {
"type": "distributor",
"url": "./external/telegram"
},
"@curatedotfun/rss": {
"type": "distributor",
"url": "./external/rss"
},
"@curatedotfun/gpt-transform": {
"type": "transformer",
"url": "./external/gpt-transform"
}
}
}

📡 Feeds

Each feed represents a distinct content stream:

{
"feeds": [
{
"id": "example", // hashtag
"name": "Example Feed",
"description": "Example feed description",
"moderation": {
"approvers": {
"twitter": ["approver1", "approver2"] // twitter handles, without @
}
},
"outputs": {
"stream": {
"enabled": true, // if enabled but no distribute, then will sit in queue
"transform": { // Optional
"plugin": "@curatedotfun/gpt-transform",
"config": {
"prompt": "Format this update..."
}
},
"distribute": [ // Optional (can be processed later, with /api/feed/:feedId/process)
{
"plugin": "@curatedotfun/telegram",
"config": {
"botToken": "{TELEGRAM_BOT_TOKEN}",
"channelId": "{TELEGRAM_CHANNEL_ID}"
}
},
{
"plugin": "@curatedotfun/rss",
"config": {
"title": "Feed Title",
"path": "./public/feed.xml"
}
}
]
},
"recap": {
"enabled": false,
"schedule": "0 0 * * *",
"transform": { // Required to summarize
"plugin": "@curatedotfun/gpt-transform",
"config": {
"prompt": "./prompts/recap.txt"
}
},
"distribute": [ // Required for recap
{
"plugin": "@curatedotfun/telegram",
"config": {
"botToken": "{TELEGRAM_BOT_TOKEN}", // gets injected by .env
"channelId": "{TELEGRAM_CHANNEL_ID}"
}
}
]
}
}
}
]
}

🔄 Stream Configuration

Stream configuration controls real-time content distribution:

outputs: {
stream?: {
enabled: boolean;
transform?: { // Optional transformation
plugin: string;
config: {
prompt: string;
};
};
distribute?: [ // Optional distribution, can configure multiple
{
plugin: string;
config: Record<string, string>;
}
];
};
}

When stream is enabled:

  • 🔄 Without transform, content is distributed as-is
  • 📥 Without distribute, submissions stay in queue until:
    • ✅ Distribution is added later (/api/feeds/:feedId/process)
    • 📅 Recap schedule completes
    • 🗑️ Manual removal

This queue system helps you:

  • 📦 Collect submissions for later
  • 🔌 Add distribution channels flexibly
  • 📝 Use content in recaps only

📅 Recap Configuration

Recap configuration handles periodic content summaries:

outputs: {
recap?: {
enabled: boolean;
schedule: string; // Cron expression
transform: { // Required
plugin: string;
config: {
prompt: string;
};
};
distribute: [ // Required
{
plugin: string;
config: Record<string, string>;
}
];
};
}

Key differences from stream configuration:

  • 🔄 transform is required (content must be summarized)
  • 📢 distribute is required (summaries must be distributed)

📝 Note: Messages in a recap are removed from the queue after distribution.