hugo-syndicate
v1.0.0
Published
Multi-provider content syndication tool for Hugo static sites. Currently supports dev.to and Qiita with extensible architecture for more providers. Works with Hugo source files, not published sites.
Maintainers
Readme
Hugo Syndicate
Multi-provider content syndication for Hugo static sites
Sync your hugo blog posts to dev.to, Qiita and more (coming soon)
Hugo Syndicate automatically distributes your Hugo blog posts across multiple platforms.
⚠️ This is Alpha Software: While functional, it may contain bugs and the API may change in future versions. Currently supports dev.to and Qiita. Use in production at your own risk.
Table of Contents
- Quick Start
- Features
- Requirements
- Installation
- Configuration
- Usage
- Hugo Front Matter
- GitHub Actions
- Provider Details
- Troubleshooting
- Contributing
- Support
Quick Start
Install globally:
npm install -g hugo-syndicateSet environment variables:
export DEVTO_API_KEY=your_devto_key export QIITA_ACCESS_TOKEN=your_qiita_tokenMark posts for syndication:
--- title: "My Blog Post" devto: true qiita: true ---Run from your Hugo project root:
hugo-syndicate
Features
Current
- Multi-Provider Architecture: Extensible provider system supporting multiple platforms
- Smart Sync Control: Only syncs posts explicitly marked with provider flags
- Hugo Shortcode Transformation: Converts Hugo shortcodes to provider-compatible formats
- Canonical URL Support: Generates canonical URLs based on Hugo site structure
- Git Integration: Detects changed files to sync only updates
- Orphaned Article Detection: Finds and manages articles deleted from Hugo
- Flexible Configuration: Environment variables and CLI options
- Debug Logging: Multiple levels for detailed operation tracking
Planned
- Medium, Hashnode, Ghost, WordPress integration
- Official GitHub Action
- Bi-directional sync (import comments/metrics)
- Content scheduling
Requirements
- Node.js: Version 16.0.0 or higher
- Git: Required for change detection
- Hugo Source Files: Works with markdown + front matter (not published HTML)
- API Keys: For the providers you want to use
Platform Compatibility
- macOS/Linux: Full support out of the box
- Windows: Requires Git for Windows (Git Bash) or WSL
- CI/CD: Compatible with GitHub Actions, GitLab CI, etc.
Installation
Global Installation (Recommended)
npm install -g hugo-syndicateLocal Installation
npm install hugo-syndicateQuick Setup Script
curl -sSL https://raw.githubusercontent.com/px4n/hugo-syndicate/develop/scripts/install.sh | bashConfiguration
Environment Variables
Create a .env file in your Hugo project root:
# Required: Provider API Keys
DEVTO_API_KEY=your_dev_to_api_key
QIITA_ACCESS_TOKEN=your_qiita_token
# Optional: Configuration
HUGO_BASE_URL=https://yoursite.com
CONTENT_DIR=content/
DEBUG_LEVEL=2
PROVIDERS=devto,qiita
AUTO_DELETE=falseGetting API Keys
- dev.to: Settings → Account → API Keys
- Qiita: Settings → Applications
Usage
Run from your Hugo project root directory where your content folder is located.
Basic Commands
# Sync changed posts to all configured providers
hugo-syndicate
# Sync to specific provider
hugo-syndicate --provider qiita
# Force sync all posts
hugo-syndicate --force-all
# Auto-delete orphaned articles
hugo-syndicate --auto-delete
# Show help
hugo-syndicate --helpDebug Modes
# Basic info (default)
DEBUG_LEVEL=2 hugo-syndicate
# Detailed debugging
DEBUG_LEVEL=3 hugo-syndicate
# Verbose (includes API payloads)
DEBUG_LEVEL=4 hugo-syndicateHugo Front Matter
Mark posts for syndication in your markdown front matter:
YAML Format
---
title: "My Blog Post"
date: 2025-01-15
tags: ["javascript", "webdev"]
devto: true # Sync to dev.to
qiita: true # Sync to Qiita
syndicate: true # Sync to all providers
draft: false # Must not be draft
---TOML Format
+++
title = "My Blog Post"
date = 2025-01-15
tags = ["javascript", "webdev"]
devto = true
qiita = true
draft = false
+++Sync Rules
Posts are synced when they meet ALL criteria:
- Provider flag:
devto = true,qiita = true, orsyndicate = true - Not a draft:
draft = false(or not set) - Not private:
visibility != "private" - Allowed directory: In blog/, articles/, posts/, tech/, or tutorials/
- Post type: Has type "post" (default)
GitHub Actions
Example workflow for automatic syncing:
name: Sync to Providers
on:
push:
branches: [main]
paths: ["content/**/*.md"]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm install -g hugo-syndicate
- name: Sync to providers
env:
DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
QIITA_ACCESS_TOKEN: ${{ secrets.QIITA_ACCESS_TOKEN }}
HUGO_BASE_URL: ${{ vars.HUGO_BASE_URL }}
run: hugo-syndicateSee examples/github-workflows/ for more workflow templates.
Provider Details
dev.to
Limitations:
- Maximum 4 tags per post
- Only alphanumeric tags (a-z, 0-9)
- 150,000 character limit
- Rate limit: 30 requests per 30 seconds
Tag Examples:
- ✅
javascript,react,webdev - ❌
日本語,c++,node.js
Qiita
Limitations:
- Maximum 5 tags per article
- Alphanumeric + hyphens (a-z, 0-9, -)
- Tags converted to lowercase
- 40 character tag limit
Tag Examples:
- ✅
javascript,react-hooks,web-dev - ❌
日本語,c++,node.js
Internationalization
Hugo Syndicate fully supports international content:
- Content: Any language (Japanese, Chinese, Korean, etc.)
- Titles: Full Unicode support
- URLs: Handles language prefixes (
/ja/blog/...) - Tags: Limited to ASCII due to API restrictions
Supported Hugo Shortcodes
Hugo shortcodes are automatically transformed:
{{< image src="/images/pic.jpg" alt="Picture" >}}
→ 
{{< youtube dQw4w9WgXcQ >}}
→ {% youtube dQw4w9WgXcQ %}
{{< twitter 1234567890 >}}
→ {% twitter 1234567890 %}
{{< gist username abc123 >}}
→ {% gist abc123 %}Troubleshooting
Common Issues
"Failed to parse front matter"
- Check YAML syntax (needs
---delimiters) - Verify proper indentation
- For TOML use
+++delimiters
"No markdown files to process"
- Ensure posts have provider flags
- Posts must not be drafts
- Use
--force-allto process all
"Warning: Tags were removed"
- dev.to: Only alphanumeric allowed
- Qiita: Alphanumeric + hyphens
- Add ASCII alternatives
API Authentication Failed
- Verify API keys are set correctly
- Check token permissions/scopes
- Regenerate if expired
Recovery from Failed Syncs
# Re-sync all posts
hugo-syndicate --force-all
# Debug the issue
DEBUG_LEVEL=3 hugo-syndicate
# Check provider dashboards for orphaned draftsContributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
For provider development, see Provider Development Guide.
Commit Convention
We use Conventional Commits:
feat: add Medium provider # Minor version
fix: handle empty responses # Patch version
feat!: change config format # Major version
docs: update installation # No version bumpRelease Process
Releases are automated via semantic-release:
- Commit with conventional format
- Push to
developbranch - Automatic version bump, changelog, and NPM publish
License
Apache License 2.0 - see LICENSE file
Support
For issues and questions:
- Check Troubleshooting section
- Run with
DEBUG_LEVEL=3for detailed logs - Open an issue with details
