A Bun-powered script that automatically scrapes the latest articles from rekt.news and publishes them to Nostr as NIP-23 long-form content events.
- π·οΈ Smart Scraping: Extracts articles and metadata from rekt.news
- π Markdown Conversion: Converts HTML content to clean, NIP-23 compliant Markdown
- π Nostr Publishing: Publishes articles as NIP-23 addressable events
- π Flexible Authentication: Supports both nsec keys and NIP-46 bunker URIs
- π Batch Processing: Handles multiple articles with configurable delays
- π Duplicate Detection: Skips already published articles
- π§ͺ Dry Run Mode: Preview articles before publishing
- Bun v1.0.0 or later
- A Nostr private key (nsec) or NIP-46 bunker connection
- Clone and install dependencies:
git clone <your-repo>
cd rekt-nostr-mirror
bun install- Make the script executable:
chmod +x index.ts# Preview articles without publishing (dry run)
bun run index.ts --dry-run --limit 3
# Publish latest 5 articles with nsec key
bun run index.ts --signer nsec1your_private_key_here --limit 5
# Use NIP-46 bunker for remote signing
bun run index.ts --signer "bunker://pubkey@relay.com?relay=wss://relay.com" --limit 3
# Publish to custom relays
bun run index.ts --signer nsec1... --relays "wss://relay.damus.io,wss://nos.lol"The CLI uses yargs for robust argument parsing and validation:
| Option | Short | Description | Default |
|---|---|---|---|
--signer |
-s |
Nostr signer (nsec or bunker URI) | Required* |
--limit |
-l |
Number of articles to fetch | 5 |
--delay |
-d |
Delay between publications (ms) | 5000 |
--relays |
-r |
Comma-separated relay URLs | Default set |
--skip-existing |
Skip already published articles | true | |
--dry-run |
Preview mode - don't publish | false | |
--help |
-h |
Show help message | |
--version |
-v |
Show version number |
*Required unless using --dry-run
Validation features:
- Automatic type checking for numeric values
- Custom validation messages for invalid inputs
- Smart help formatting with examples
- Proper error handling with usage display
# Quick preview of latest articles
bun run index.ts --dry-run --limit 2
# Test with minimal delay
bun run index.ts --signer nsec1... --limit 1 --delay 1000# Daily sync - publish latest 10 articles
bun run index.ts --signer nsec1... --limit 10
# Weekly batch - publish up to 25 articles
bun run index.ts --signer nsec1... --limit 25 --delay 10000
# Custom relay setup
bun run index.ts \
--signer "bunker://..." \
--limit 5 \
--relays "wss://relay.damus.io,wss://nos.lol,wss://relay.snort.social"The script uses advanced HTML-to-Markdown conversion with several optimizations:
β What works well:
- Automatic cleanup of navigation, ads, and social widgets
- Preservation of code blocks with syntax highlighting
- Smart handling of embedded content (Twitter, YouTube)
- Relative URL conversion to absolute URLs
- Clean paragraph and heading formatting
- Very image-heavy articles may need manual review
- Complex tables might lose some formatting
- Interactive elements become static content
π§ Customization:
Edit src/markdown-converter.ts to adjust conversion rules for specific content patterns.
Recommended approach:
- Start with dry run: Always preview articles first
- Small batches: Use
--limit 5or less for initial testing - Reasonable delays: Keep
--delayat 5000ms+ to respect relays - Monitor duplicates: The default
--skip-existingprevents reposts
Rate limiting considerations:
- Most relays accept 1 event per second
- Large articles may take longer to propagate
- Use
--delay 10000for conservative publishing
Default relays (automatically used):
- wss://relay.damus.io
- wss://nos.lol
- wss://relay.nostr.band
- wss://nostr.wine
- wss://relay.snort.social
Custom relays:
# Specify your preferred relays
--relays "wss://your-relay.com,wss://backup-relay.com"Relay recommendations:
- Use 3-5 relays for good distribution
- Include at least one major public relay
- Consider geographic distribution
- Test relay connectivity before batch operations
Articles are published as NIP-23 Long-form Content events with:
- Kind: 30023 (addressable event)
- Content: Clean Markdown formatted text
- Tags:
d: Unique article identifier (derived from URL)title: Article titlepublished_at: Original publication timestampsummary: Article summary/descriptionimage: Featured image URLt: Topic tags (rekt, defi, security)r: Reference to original rekt.news URLclient: Attribution to rekt-nostr-mirror
Add to your crontab for automated publishing:
# Every 6 hours - check for new articles
0 */6 * * * cd /path/to/rekt-nostr-mirror && bun run index.ts --signer "nsec1..." --limit 5 >> /var/log/rekt-mirror.log 2>&1
# Daily at 9 AM - larger batch
0 9 * * * cd /path/to/rekt-nostr-mirror && bun run index.ts --signer "nsec1..." --limit 10 --delay 8000 >> /var/log/rekt-mirror.log 2>&1Create /etc/systemd/system/rekt-mirror.service:
[Unit]
Description=Rekt News Nostr Mirror
After=network.target
[Service]
Type=oneshot
User=your-user
WorkingDirectory=/path/to/rekt-nostr-mirror
ExecStart=/usr/local/bin/bun run index.ts --signer "nsec1..." --limit 5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetThen create a timer /etc/systemd/system/rekt-mirror.timer:
[Unit]
Description=Run Rekt News Mirror every 6 hours
Requires=rekt-mirror.service
[Timer]
OnCalendar=*-*-* 00,06,12,18:00:00
Persistent=true
[Install]
WantedBy=timers.targetEnable with:
sudo systemctl enable rekt-mirror.timer
sudo systemctl start rekt-mirror.timerThe script includes comprehensive error handling:
- Network failures: Retries with graceful degradation
- Parsing errors: Skips problematic articles and continues
- Relay issues: Continues with available relays
- Signing errors: Clear error messages with troubleshooting hints
Common issues:
-
"Failed to initialize signer"
- Check nsec format (starts with
nsec1) - Verify bunker URI is complete and accessible
- Check nsec format (starts with
-
"No articles found"
- rekt.news might be down or changed structure
- Try with
--dry-runto debug scraping
-
"Publication failed"
- Check relay connectivity
- Verify your key has required permissions
rekt-nostr-mirror/
βββ src/
β βββ scraper.ts # rekt.news content extraction
β βββ markdown-converter.ts # HTML β Markdown conversion
β βββ nip23-publisher.ts # Nostr NIP-23 publishing
βββ nostr.ts # Nostr client setup
βββ index.ts # Main CLI application
βββ package.json # Dependencies and scripts
- New content sources: Extend
RektScraperclass - Custom formatting: Modify
MarkdownConverterrules - Different event types: Create new publisher classes
- Additional metadata: Update tag generation in
NIP23Publisher
- applesauce-***: Nostr client and cryptography
- cheerio: HTML parsing and manipulation
- turndown: HTML to Markdown conversion
- turndown-plugin-gfm: GitHub Flavored Markdown support
- Fork the repository
- Create a feature branch
- Test with
--dry-runextensively - Submit a pull request
MIT License - see LICENSE file for details.
This tool is for educational and informational purposes. Always respect:
- rekt.news terms of service
- Relay policies and rate limits
- Content attribution and licensing
- Nostr protocol best practices
The mirrored content retains links to original articles and proper attribution.