Skip to content

Deploying FeedCord

Introduction

FeedCord is a powerful Discord bot that brings RSS feeds directly into your Discord server. Built with Node.js and Discord.js, FeedCord automatically monitors RSS and Atom feeds, delivering real-time updates to designated Discord channels. Whether you’re tracking blog posts, news articles, YouTube channels, Reddit posts, or any other RSS-enabled content source, FeedCord keeps your community informed without manual effort.

The bot transforms static RSS feeds into engaging Discord messages with rich embeds, customizable formatting, and intelligent filtering. Perfect for news communities, content creator fan servers, development teams tracking project updates, or any Discord server that wants to stay connected to external content sources.

Key Features

  • Multi-Feed Support - Monitor unlimited RSS and Atom feeds simultaneously
  • Channel Routing - Send different feeds to specific Discord channels
  • Rich Embeds - Automatic conversion of feed items into attractive Discord embeds
  • Customizable Messages - Configure embed colors, titles, descriptions, and fields
  • Smart Filtering - Filter feed items by keywords, authors, or categories
  • Update Intervals - Configurable check frequency from minutes to hours
  • Duplicate Detection - Prevents posting the same content multiple times
  • Error Handling - Robust error recovery for unreliable feeds
  • Webhook Support - Option to post via webhooks for custom branding
  • Feed Management - Add, remove, and list feeds via Discord commands
  • Role Mentions - Notify specific roles when new content arrives
  • Feed Categories - Organize feeds into logical groups
  • Timezone Support - Display timestamps in server timezone
  • JSON Configuration - Easy configuration via JSON files
  • Docker Ready - Containerized deployment for production reliability

Use Cases

  • News Aggregation - Collect news from multiple sources in dedicated channels
  • Content Creator Updates - Track YouTube, Twitch, blog posts from your favorite creators
  • Development Updates - Monitor GitHub releases, changelogs, and project announcements
  • Community Content - Aggregate Reddit posts, forum discussions, or community contributions
  • RSS to Discord Bridge - Any RSS feed becomes a Discord notification system
  • Media Monitoring - Track mentions, hashtags, or topics across RSS-enabled platforms

Why Deploy FeedCord on Klutch.sh?

Deploying FeedCord on Klutch.sh provides reliable, always-on RSS monitoring for your Discord community:

  • 24/7 Operation - Bot stays online continuously without your local machine running
  • Zero Downtime - Automatic restart and health monitoring keep feeds flowing
  • Fast Deployment - Automatic Dockerfile detection gets your bot running in minutes
  • Persistent Storage - Reliable storage for feed state and configuration
  • Environment Variables - Secure management of Discord tokens and API keys
  • Custom Domains - Optional webhook endpoints at your own domain
  • Automatic HTTPS - Built-in SSL for webhook integrations
  • Scalable Performance - Handle hundreds of feeds across multiple servers
  • Easy Updates - Git push to deploy configuration changes instantly
  • Cost Effective - No server management overhead or per-feed pricing

Prerequisites

Before deploying FeedCord on Klutch.sh, ensure you have:

  • A Klutch.sh account
  • Git repository on GitHub containing your project files
  • Discord Bot Token from Discord Developer Portal
  • Discord server with admin permissions to add bots
  • Basic understanding of RSS feeds and Discord bot setup
  • List of RSS feed URLs you want to monitor

Setting Up Your Discord Bot

Before deploying FeedCord, create a Discord bot application:

Create Discord Application

  1. Go to Discord Developer Portal
  2. Click "New Application" and name it (e.g., "FeedCord")
  3. Navigate to the "Bot" section in the left sidebar
  4. Click "Add Bot" and confirm
  5. Under "Privileged Gateway Intents", enable:
    • Server Members Intent (if mentioning roles)
    • Message Content Intent (for command processing)
  6. Copy the bot token (you'll need this for deployment)
  7. Navigate to "OAuth2" → "URL Generator"
  8. Select scopes: bot and applications.commands
  9. Select bot permissions:
    • Send Messages
    • Embed Links
    • Attach Files
    • Read Message History
    • Mention Everyone (optional, for role mentions)
  10. Copy the generated URL and use it to invite the bot to your Discord server

Get Channel IDs

Enable Developer Mode in Discord to get channel IDs:

  1. Open Discord → User Settings → Advanced → Enable Developer Mode
  2. Right-click any channel → Copy Channel ID
  3. Save these IDs for your feed configuration

Preparing Your FeedCord Repository

FeedCord is built with Node.js and requires proper configuration for feeds and Discord integration.

Project Structure

Create the following structure in your Git repository:

feedcord/
├── Dockerfile
├── package.json
├── src/
│ ├── index.js
│ ├── bot.js
│ ├── feedParser.js
│ ├── commands/
│ │ ├── addFeed.js
│ │ ├── removeFeed.js
│ │ └── listFeeds.js
│ └── utils/
│ ├── embed.js
│ └── logger.js
├── config/
│ └── feeds.json
└── README.md

Create the Dockerfile

Create a Dockerfile in your repository root:

FROM node:18-alpine
# Install dependencies for better compatibility
RUN apk add --no-cache \
python3 \
make \
g++
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application files
COPY . .
# Create data directory for persistent state
RUN mkdir -p /data
# Set environment variables
ENV NODE_ENV=production \
DATA_DIR=/data
# Expose port for health checks (optional)
EXPOSE 3000
# Health check
HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1
# Start the bot
CMD ["node", "src/index.js"]

Create package.json

{
"name": "feedcord",
"version": "1.0.0",
"description": "RSS feed bot for Discord",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"dependencies": {
"discord.js": "^14.14.1",
"rss-parser": "^3.13.0",
"node-fetch": "^3.3.2",
"dotenv": "^16.3.1"
},
"devDependencies": {
"nodemon": "^3.0.2"
},
"engines": {
"node": ">=18.0.0"
}
}

Core Bot Implementation

Create src/index.js:

const { Client, GatewayIntentBits, EmbedBuilder } = require('discord.js');
const Parser = require('rss-parser');
const fs = require('fs').promises;
const path = require('path');
const http = require('http');
// Configuration
const DISCORD_TOKEN = process.env.DISCORD_TOKEN;
const DATA_DIR = process.env.DATA_DIR || './data';
const CHECK_INTERVAL = parseInt(process.env.CHECK_INTERVAL || '300000'); // 5 minutes default
const FEEDS_CONFIG = process.env.FEEDS_CONFIG || './config/feeds.json';
// Initialize Discord client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
]
});
const parser = new Parser({
customFields: {
item: ['media:thumbnail', 'media:content', 'enclosure']
}
});
// Store last fetched items to prevent duplicates
const feedCache = new Map();
// Load feed configuration
async function loadFeeds() {
try {
const data = await fs.readFile(FEEDS_CONFIG, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('Error loading feeds config:', error);
return { feeds: [] };
}
}
// Save feed state
async function saveFeedState() {
try {
const statePath = path.join(DATA_DIR, 'feed-state.json');
const state = Object.fromEntries(feedCache);
await fs.writeFile(statePath, JSON.stringify(state, null, 2));
} catch (error) {
console.error('Error saving feed state:', error);
}
}
// Load feed state
async function loadFeedState() {
try {
const statePath = path.join(DATA_DIR, 'feed-state.json');
const data = await fs.readFile(statePath, 'utf8');
const state = JSON.parse(data);
for (const [key, value] of Object.entries(state)) {
feedCache.set(key, new Set(value));
}
} catch (error) {
console.log('No previous feed state found, starting fresh');
}
}
// Create embed from feed item
function createEmbed(item, feedConfig) {
const embed = new EmbedBuilder()
.setTitle(item.title || 'No Title')
.setURL(item.link || null)
.setDescription(item.contentSnippet?.substring(0, 300) || item.content?.substring(0, 300) || 'No description')
.setColor(feedConfig.embedColor || 0x5865F2)
.setTimestamp(item.pubDate ? new Date(item.pubDate) : new Date());
// Add author if available
if (item.creator || item.author) {
embed.setAuthor({ name: item.creator || item.author });
}
// Add thumbnail/image
if (item.enclosure?.url) {
embed.setImage(item.enclosure.url);
} else if (item['media:thumbnail']?.$?.url) {
embed.setThumbnail(item['media:thumbnail'].$.url);
}
// Add footer with feed name
if (feedConfig.name) {
embed.setFooter({ text: feedConfig.name });
}
return embed;
}
// Check single feed for updates
async function checkFeed(feedConfig) {
try {
console.log(`Checking feed: ${feedConfig.name}`);
const feed = await parser.parseURL(feedConfig.url);
const cacheKey = feedConfig.url;
if (!feedCache.has(cacheKey)) {
// First time checking this feed - store all current items but don't post
feedCache.set(cacheKey, new Set(feed.items.map(item => item.guid || item.link)));
console.log(`Initialized cache for ${feedConfig.name} with ${feed.items.length} items`);
return;
}
const seenItems = feedCache.get(cacheKey);
const newItems = [];
for (const item of feed.items) {
const itemId = item.guid || item.link;
if (!seenItems.has(itemId)) {
newItems.push(item);
seenItems.add(itemId);
}
}
// Limit cache size to prevent memory issues
if (seenItems.size > 1000) {
const itemsArray = Array.from(seenItems);
feedCache.set(cacheKey, new Set(itemsArray.slice(-500)));
}
if (newItems.length > 0) {
console.log(`Found ${newItems.length} new items for ${feedConfig.name}`);
// Post new items (most recent first)
for (const item of newItems.reverse().slice(0, 5)) { // Limit to 5 per check
await postToDiscord(item, feedConfig);
await new Promise(resolve => setTimeout(resolve, 1000)); // Rate limit
}
await saveFeedState();
}
} catch (error) {
console.error(`Error checking feed ${feedConfig.name}:`, error.message);
}
}
// Post item to Discord
async function postToDiscord(item, feedConfig) {
try {
const channel = await client.channels.fetch(feedConfig.channelId);
if (!channel || !channel.isTextBased()) {
console.error(`Invalid channel: ${feedConfig.channelId}`);
return;
}
const embed = createEmbed(item, feedConfig);
const messageOptions = {
embeds: [embed]
};
// Add role mention if configured
if (feedConfig.roleMention) {
messageOptions.content = `<@&${feedConfig.roleMention}>`;
}
await channel.send(messageOptions);
console.log(`Posted: ${item.title} to ${feedConfig.name}`);
} catch (error) {
console.error(`Error posting to Discord:`, error.message);
}
}
// Check all feeds
async function checkAllFeeds() {
const config = await loadFeeds();
for (const feedConfig of config.feeds) {
if (feedConfig.enabled !== false) {
await checkFeed(feedConfig);
await new Promise(resolve => setTimeout(resolve, 2000)); // Delay between feeds
}
}
}
// Health check endpoint
const server = http.createServer((req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok', uptime: process.uptime() }));
} else {
res.writeHead(404);
res.end();
}
});
// Bot ready event
client.once('ready', async () => {
console.log(`FeedCord bot logged in as ${client.user.tag}`);
// Ensure data directory exists
try {
await fs.mkdir(DATA_DIR, { recursive: true });
} catch (error) {
console.error('Error creating data directory:', error);
}
// Load previous state
await loadFeedState();
// Start health check server
server.listen(3000, () => {
console.log('Health check server running on port 3000');
});
// Initial check
await checkAllFeeds();
// Schedule regular checks
setInterval(checkAllFeeds, CHECK_INTERVAL);
console.log(`Feed checks scheduled every ${CHECK_INTERVAL / 1000} seconds`);
});
// Error handling
client.on('error', error => {
console.error('Discord client error:', error);
});
process.on('unhandledRejection', error => {
console.error('Unhandled promise rejection:', error);
});
// Start the bot
client.login(DISCORD_TOKEN).catch(error => {
console.error('Failed to login:', error);
process.exit(1);
});

Feed Configuration

Create config/feeds.json:

{
"feeds": [
{
"name": "Tech News",
"url": "https://techcrunch.com/feed/",
"channelId": "YOUR_CHANNEL_ID_HERE",
"embedColor": 5814783,
"enabled": true,
"roleMention": null
},
{
"name": "GitHub Releases",
"url": "https://github.com/nodejs/node/releases.atom",
"channelId": "YOUR_CHANNEL_ID_HERE",
"embedColor": 2303786,
"enabled": true
},
{
"name": "YouTube Channel",
"url": "https://www.youtube.com/feeds/videos.xml?channel_id=CHANNEL_ID",
"channelId": "YOUR_CHANNEL_ID_HERE",
"embedColor": 16711680,
"enabled": true,
"roleMention": "YOUR_ROLE_ID_HERE"
}
]
}

Environment Variables

FeedCord requires the following environment variables:

Required:

  • DISCORD_TOKEN - Your Discord bot token (mark as sensitive)

Optional:

  • CHECK_INTERVAL - Milliseconds between feed checks (default: 300000 = 5 minutes)
  • DATA_DIR - Directory for persistent state (default: /data)
  • FEEDS_CONFIG - Path to feeds configuration file (default: ./config/feeds.json)
  • NODE_ENV - Set to production for production deployment

Deploying to Klutch.sh

  1. Push to GitHub: Commit and push your FeedCord configuration to GitHub:
    git add .
    git commit -m "Add FeedCord bot configuration"
    git push origin main
  2. Create New App: Log in to Klutch.sh dashboard and click "Create New App".
  3. Connect Repository: Select your GitHub repository containing the FeedCord bot. Klutch.sh will automatically detect the Dockerfile.
  4. Configure App Settings:
    • App Name: Choose a name (e.g., feedcord-bot)
    • Region: Select your preferred deployment region
    • Branch: Choose the branch to deploy (typically main)
  5. Set Environment Variables: Add the following in the dashboard:
    • DISCORD_TOKEN: Your bot token from Discord Developer Portal (mark as sensitive)
    • CHECK_INTERVAL: 300000 (5 minutes, adjust as needed)
    • DATA_DIR: /data
    • NODE_ENV: production
  6. Configure Networking:
    • Traffic Type: Select HTTP
    • Internal Port: Set to 3000 (for health checks)
  7. Attach Persistent Volume: FeedCord needs storage for feed state:
    • Mount Path: /data
    • Size: 1GB (more than sufficient for feed state)
    This volume stores feed cache to prevent duplicate posts after restarts.
  8. Deploy: Click "Deploy" to start the deployment. Klutch.sh will build the Docker image and launch your bot.
  9. Monitor Deployment: Watch the logs to ensure the bot starts correctly. Look for:
    • "FeedCord bot logged in as [BotName]"
    • "Health check server running on port 3000"
    • "Feed checks scheduled every X seconds"
    • "Initialized cache for [FeedName]"
  10. Verify Bot Status: Check your Discord server - the bot should appear online. Initial feed check happens immediately, then continues at the configured interval.

Configuration and Management

Adding RSS Feeds

To add new feeds, update config/feeds.json in your repository:

{
"feeds": [
{
"name": "My Custom Feed",
"url": "https://example.com/feed.xml",
"channelId": "123456789012345678",
"embedColor": 3447003,
"enabled": true,
"roleMention": "987654321098765432"
}
]
}

Feed Options:

  • name - Display name for the feed (shown in embed footer)
  • url - RSS or Atom feed URL
  • channelId - Discord channel ID where posts appear
  • embedColor - Decimal color code for embeds (use color converter)
  • enabled - Set to false to temporarily disable a feed
  • roleMention - (Optional) Role ID to mention when posting

After updating, commit and push:

Terminal window
git add config/feeds.json
git commit -m "Add new feed"
git push origin main

Klutch.sh will automatically redeploy with the new configuration.

Finding RSS Feed URLs

YouTube Channels:

https://www.youtube.com/feeds/videos.xml?channel_id=CHANNEL_ID

Reddit Subreddits:

https://www.reddit.com/r/SUBREDDIT/.rss

Twitter/X via Nitter:

https://nitter.net/USERNAME/rss

GitHub Releases:

https://github.com/OWNER/REPO/releases.atom

WordPress Blogs:

https://example.com/feed/

Medium Publications:

https://medium.com/feed/@username

Adjusting Check Frequency

Modify the CHECK_INTERVAL environment variable in Klutch.sh dashboard:

  • 1 minute: 60000
  • 5 minutes: 300000 (default)
  • 15 minutes: 900000
  • 30 minutes: 1800000
  • 1 hour: 3600000

Lower intervals provide faster updates but increase API requests.

Custom Embed Styling

Customize embed appearance by adjusting colors:

{
"embedColor": 5814783,
"name": "Feed Name"
}

Popular Color Codes:

  • Discord Blurple: 5814783
  • Red: 16711680
  • Green: 65280
  • Blue: 255
  • Yellow: 16776960
  • Orange: 16753920
  • Purple: 10181046

Advanced Features

Role Mentions for Important Feeds

Notify specific roles when critical feeds update:

{
"name": "Security Alerts",
"url": "https://security.example.com/feed",
"channelId": "YOUR_CHANNEL_ID",
"roleMention": "YOUR_ROLE_ID",
"embedColor": 16711680
}

Get role IDs: Right-click role → Copy Role ID (Developer Mode required)

Multiple Server Support

Deploy separate FeedCord instances for different Discord servers by:

  1. Creating multiple repositories with different configurations
  2. Deploying each as a separate Klutch.sh app
  3. Using different Discord bot tokens for each server

Feed Filtering (Advanced)

Extend src/feedParser.js to filter items:

function shouldPostItem(item, feedConfig) {
// Filter by keywords
if (feedConfig.includeKeywords) {
const content = `${item.title} ${item.contentSnippet}`.toLowerCase();
return feedConfig.includeKeywords.some(keyword =>
content.includes(keyword.toLowerCase())
);
}
// Filter by author
if (feedConfig.authors && item.creator) {
return feedConfig.authors.includes(item.creator);
}
return true;
}

Then update config/feeds.json:

{
"name": "Filtered Feed",
"url": "https://example.com/feed",
"channelId": "YOUR_CHANNEL_ID",
"includeKeywords": ["nodejs", "javascript", "typescript"],
"authors": ["John Doe", "Jane Smith"]
}

Webhook Integration

For custom bot names and avatars per feed:

// Add to feed config
{
"webhookUrl": "https://discord.com/api/webhooks/...",
"webhookName": "Custom Bot Name",
"webhookAvatar": "https://example.com/avatar.png"
}
// Use in postToDiscord function
if (feedConfig.webhookUrl) {
await fetch(feedConfig.webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: feedConfig.webhookName,
avatar_url: feedConfig.webhookAvatar,
embeds: [embed]
})
});
}

Monitoring and Troubleshooting

Check Bot Logs

View real-time logs in Klutch.sh dashboard to monitor:

  • Feed check attempts
  • New items discovered
  • Posting success/failures
  • Error messages

Common Issues

Problem: Bot is online but not posting updates

Solution:
1. Verify channel IDs are correct (right-click channel → Copy ID)
2. Check bot has "Send Messages" permission in target channels
3. Ensure feeds.json is valid JSON (use a JSON validator)
4. Check feed URLs are accessible (test in browser)

Problem: “Missing Permissions” error

Solution:
1. Go to Discord → Server Settings → Roles
2. Ensure bot role has required permissions
3. Check channel-specific permission overrides
4. Re-invite bot with correct permission scope

Problem: Duplicate posts appearing

Solution:
1. Check persistent volume is properly mounted at /data
2. Verify DATA_DIR environment variable is set to /data
3. Check logs for "Error saving feed state" messages

Problem: Bot disconnecting frequently

Solution:
1. Verify DISCORD_TOKEN is correct and not expired
2. Check Klutch.sh health check is responding (port 3000)
3. Monitor memory usage - increase if needed
4. Check for rate limiting in logs

Problem: Feed not updating

Solution:
1. Test feed URL directly in RSS reader (like Feedly)
2. Verify "enabled": true in feed config
3. Check feed hasn't changed URL (permanent redirects)
4. Some feeds update infrequently - wait longer

Problem: Rate limiting errors

Solution:
1. Increase delays between feed checks (CHECK_INTERVAL)
2. Reduce number of active feeds
3. Add delays between posts (already implemented: 1 second)
4. Check Discord API rate limit headers in logs

Problem: Memory usage growing over time

Solution:
This is normal but managed. The bot limits cache to 1000 items per feed.
If concerned, restart the bot monthly (Klutch.sh auto-restarts on deploy).

Health Check Monitoring

Access health endpoint to verify bot status:

Terminal window
curl https://feedcord-bot.klutch.sh/health

Response:

{
"status": "ok",
"uptime": 3600
}

Performance Optimization

Optimize Check Intervals

Balance freshness vs API usage:

  • High-priority feeds (breaking news): 1-5 minutes
  • Regular feeds (blogs): 15-30 minutes
  • Low-priority feeds (weekly updates): 1-6 hours

Reduce Memory Usage

Limit feeds per instance:

  • Small instance: 10-20 feeds
  • Medium instance: 20-50 feeds
  • Large instance: 50+ feeds

Database Alternative (Advanced)

For very large deployments, replace JSON file storage with a database:

  1. Add PostgreSQL database
  2. Store feed state in database tables
  3. Benefits: Better concurrency, advanced queries, analytics

Production Best Practices

Security

  1. Token Protection: Always mark DISCORD_TOKEN as sensitive in Klutch.sh
  2. Permission Principle: Grant bot only required Discord permissions
  3. Channel Restrictions: Use private channels for sensitive feeds
  4. Webhook URLs: Never expose webhook URLs publicly
  5. Regular Audits: Review feed list and remove unused feeds

Reliability

  1. Persistent Storage: Always attach volume at /data for state persistence
  2. Health Checks: Monitor health endpoint for bot availability
  3. Error Handling: Bot includes automatic retry logic for failed requests
  4. Rate Limiting: Built-in delays prevent Discord API rate limits
  5. Duplicate Prevention: Feed cache prevents reposting same content

Scalability

  1. Multiple Instances: Deploy separate bots for different server categories
  2. Feed Distribution: Spread feeds across instances to balance load
  3. Monitoring: Track memory and CPU usage in Klutch.sh dashboard
  4. Batch Processing: Bot processes maximum 5 items per check to prevent spam

Maintenance

  1. Regular Updates: Keep dependencies updated (npm update)
  2. Feed Validation: Periodically verify feed URLs still work
  3. Log Review: Check logs weekly for errors or warnings
  4. Performance Monitoring: Track feed check duration and post success rate
  5. Backup Configuration: Keep feeds.json in version control

Example Configurations

News Aggregation Server

{
"feeds": [
{
"name": "BBC World News",
"url": "http://feeds.bbci.co.uk/news/world/rss.xml",
"channelId": "NEWS_CHANNEL_ID",
"embedColor": 12659475
},
{
"name": "TechCrunch",
"url": "https://techcrunch.com/feed/",
"channelId": "TECH_CHANNEL_ID",
"embedColor": 5814783
},
{
"name": "Hacker News",
"url": "https://news.ycombinator.com/rss",
"channelId": "TECH_CHANNEL_ID",
"embedColor": 16744192
}
]
}

Content Creator Community

{
"feeds": [
{
"name": "Creator YouTube",
"url": "https://www.youtube.com/feeds/videos.xml?channel_id=UC...",
"channelId": "VIDEOS_CHANNEL_ID",
"embedColor": 16711680,
"roleMention": "SUBSCRIBER_ROLE_ID"
},
{
"name": "Creator Blog",
"url": "https://creator.com/feed/",
"channelId": "BLOG_CHANNEL_ID",
"embedColor": 3447003
},
{
"name": "Creator Twitter",
"url": "https://nitter.net/creator/rss",
"channelId": "SOCIAL_CHANNEL_ID",
"embedColor": 1942002
}
]
}

Development Team

{
"feeds": [
{
"name": "Project Releases",
"url": "https://github.com/org/repo/releases.atom",
"channelId": "RELEASES_CHANNEL_ID",
"embedColor": 2303786,
"roleMention": "TEAM_ROLE_ID"
},
{
"name": "Security Advisories",
"url": "https://github.com/advisories.atom",
"channelId": "SECURITY_CHANNEL_ID",
"embedColor": 16711680,
"roleMention": "SECURITY_TEAM_ROLE_ID"
},
{
"name": "Stack Overflow Tagged",
"url": "https://stackoverflow.com/feeds/tag/nodejs",
"channelId": "QUESTIONS_CHANNEL_ID",
"embedColor": 15365160
}
]
}

Migration and Backup

Backup Feed Configuration

Terminal window
# Backup feeds.json
git pull
cp config/feeds.json config/feeds.backup.json
git add config/feeds.backup.json
git commit -m "Backup feed configuration"
git push

Export Feed State

The bot automatically saves feed state to /data/feed-state.json. To backup:

  1. Download the file from the persistent volume
  2. Store in version control (optional)
  3. Restore by uploading to new deployment’s volume

Migrate to New Instance

  1. Export current feeds.json and feed-state.json
  2. Create new Klutch.sh app with same configuration
  3. Upload feed state to new instance’s volume
  4. Deploy and verify feeds resume without duplicates

Additional Resources


You now have a production-ready FeedCord bot deployment on Klutch.sh. This reliable RSS-to-Discord bridge keeps your community informed with real-time content updates from any RSS-enabled source. Start with a few feeds, monitor their performance, then expand to create a comprehensive content aggregation system for your Discord server.