A content aggregator for the Astoria Tech community, built with Astro.
- Aggregates content from multiple sources (RSS, Atom, and YouTube feeds)
- Automatically handles different feed formats
- Advanced HTML sanitization and content security with DOMPurify
- Intelligent image extraction from multiple RSS formats (media:content, media:thumbnail, enclosure)
- Prevents future-dated posts
- Unified RSS export for all aggregated content
- Clean, modern UI with dark mode
- Mobile-friendly design
- Automated Discord notifications with rich embeds and rate limiting
- Rich embeds with content previews
- Author attribution and source links
- Image thumbnails when available
- Rate limiting (max 5 notifications per run)
- Duplicate prevention using post tracking
- Manual triggering via
npm run notify-discord
- Framework: Astro 5.3.0
- Frontend: React 19.0.0, TypeScript 5.8.2
- Styling: Tailwind CSS 3.4.1
- Content Processing: fast-xml-parser 5.2.0, isomorphic-dompurify 2.22.0
- RSS Generation: @astrojs/rss 4.0.11
- Code Quality: ESLint, Prettier, Knip
- Icons: Lucide React 0.479.0
The feed system is designed to aggregate content from various sources into a unified stream. It supports:
- RSS feeds
- Atom feeds
- YouTube channel feeds
-
Feed Configuration: Feeds are configured in
src/data/feeds.ts
:export const feeds = [ { url: 'https://example.com/feed.xml', authorName: 'Author Name', }, ];
Current Feed Sources:
- Ash Ryan Arnwine (ashryan.io)
- Nicolas F. R. A. Prado (nfraprado.net)
- Jawaun (jtbx.substack.com)
- The Underlying (theunderlying.substack.com)
- meremortaldev YouTube channel
-
Feed Processing:
- Feeds are fetched and processed using
src/utils/feedCollector.ts
- Each feed entry is stored as a JSON file in
src/content/feeds/
- Advanced HTML sanitization using DOMPurify for content security
- Intelligent image extraction from multiple RSS formats:
media:content
andmedia:thumbnail
elementsenclosure
attributes for media files- HTML content parsing for embedded images
- The system handles various date formats and ensures dates are valid
- Future-dated posts are automatically adjusted to the current time
- Content preprocessing including CDATA handling and HTML cleaning
- Feeds are fetched and processed using
-
Content Management:
- Each feed entry becomes a content file in Astro's content collection
- Entries are automatically sorted by date
- Duplicate entries are prevented using unique filenames
- Unified RSS export available at
/rss.xml
for all aggregated content
-
Discord Integration:
- Automated Discord notifications for new feed entries
- Rich embeds with titles, descriptions, authors, and images
- Rate limiting and duplicate prevention
- Configurable via
DISCORD_WEBHOOK_URL
environment variable - Manual triggering available via
npm run notify-discord
To refresh the feeds:
npm run refresh
This will:
- Clean the existing feed cache
- Fetch fresh content from all feeds
- Process and store the new entries
To add a new feed:
- Edit
src/data/feeds.ts
- Add a new entry with:
url
: The feed URLauthorName
: The author's name
- Run
npm run refresh
to fetch the new content
Each feed entry contains:
{
title: string; // The entry title
link: string; // URL to the original content
pubDate: string; // ISO 8601 date string
snippet: string; // Description or excerpt
author: string; // Author's name
feedSource: string; // Original feed URL
lastFetched: string; // When the entry was last updated
imageUrl?: string; // Optional image URL extracted from feed content
}
- Node.js 18+
- npm
# Install dependencies
npm install
# Refresh the rss feed list if you're running it for the first time
npm run fetch
# Start development server
npm run dev
# Build for production
npm run build
npm run dev
- Start development servernpm run build
- Build for productionnpm run preview
- Preview production buildnpm run refresh
- Refresh all feedsnpm run fetch
- Fetch feeds without clearing cachenpm run clean
- Clear feed cachenpm run notify-discord
- Send Discord notifications for new contentnpm run lint
- Run ESLint code quality checksnpm run knip
- Find unused files and dependencies
- Feed Collection:
fetchFeeds.ts
orchestrates the collection process - Feed Processing:
feedCollector.ts
handles individual feed parsing and content extraction - Content Security:
sanitizeHtml.ts
ensures safe HTML content using DOMPurify - Storage: Processed entries are stored as JSON files in
src/content/feeds/
- Site Generation: Astro builds the static site with all aggregated content
- RSS Export: Unified RSS feed is generated at
/rss.xml
- Discord Notifications:
discordNotifier.ts
sends notifications for new content
The Discord integration automatically notifies your server when new content is aggregated:
- Create a Discord webhook in your server
- Set the
DISCORD_WEBHOOK_URL
environment variable - New content will automatically trigger notifications
For detailed setup instructions, see docs/DISCORD_NOTIFICATIONS.md
.
Subcurrent implements comprehensive SEO optimization with a dual focus: making the Astoria Tech community discoverable while driving traffic back to original authors. Our community-first, additive approach to content aggregation ensures that authors receive proper attribution and traffic benefits.
The SEO implementation balances two key objectives:
- Community Visibility: Making Subcurrent discoverable to help grow the Astoria Tech community
- Author Support: Driving traffic back to original content creators through proper attribution and links
This community-first approach ensures that content aggregation is additive rather than competitive, supporting authors while building community awareness.
- Open Graph Tags: Rich social media previews with titles, descriptions, and images
- Twitter Cards: Optimized Twitter/X sharing with proper card formatting
- Enhanced social sharing across all major platforms
- JSON-LD Schemas: Comprehensive structured data implementation
- Organization Schema: Defines Subcurrent as a tech community organization
- CollectionPage Schema: Marks the main page as a curated content collection
- BlogPosting Schema: Individual entries with proper author attribution
- Author Attribution: Ensures proper author crediting in search engine results
- Geographic Targeting: NYC/Astoria location data for local tech community discovery
- robots.txt: Search engine crawl guidance and sitemap location
- Automated Sitemap: Dynamic sitemap generation for all content
- Canonical URLs: Prevents duplicate content issues
- Meta Tag Optimization: Enhanced descriptions targeting NYC/Astoria tech keywords
Key SEO implementation files:
public/robots.txt
- Search engine crawl guidance and sitemap reference- Automated sitemap generation enabled in
astro.config.mjs
- Structured data implementation in
src/pages/index.astro
andsrc/layouts/Layout.astro
- Social media meta tags across all page templates
The SEO strategy directly supports Subcurrent's community mission:
- Community Growth: Improved discoverability helps new members find the Astoria Tech community
- Author Traffic: Structured data and attribution drive search traffic to original content creators
- Local Focus: Geographic targeting connects NYC-area developers and tech professionals
- Content Quality: Proper schema markup improves content presentation in search results
- Web interface for managing feeds
- Feed health monitoring (detect dead feeds)
- Feed categories and tags
- Feed autodiscovery from URLs
- Search functionality
- Filter by author/source
- Read/unread tracking
- Favorite/bookmark system
- Share buttons
- Mastodon feed support
- GitHub activity feeds
- Twitter/X integration
- LinkedIn posts
- Incremental feed updates
- Feed content caching
- Rate limiting for feed fetches
- Feed validation tools
- Better error reporting
- Testing utilities
- Periodic content fetching
- Automated backups