Skip to content

sureshdsk/hn-export

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Hashnode Blog Exporter

Export your Hashnode blog posts and drafts to markdown and JSON files with local image storage.

Hashnode-Blog-Exporter.mp4

Features

  • πŸ“ Export published posts and drafts (including unpublished drafts)
  • πŸ“„ Export static pages (e.g., /privacy-policy)
  • πŸ“š Export series/collection metadata
  • πŸ–ΌοΈ Download and store images locally with smart URL handling
  • πŸ“„ Output in Markdown and/or JSON formats
  • 🎨 Beautiful terminal UI with accurate progress tracking
  • πŸ”§ Customizable output directory
  • ⚠️ Comprehensive error logging for failed operations
  • πŸš€ Built with Typer for modern CLI experience
  • βœ… 35 unit tests with full mock coverage

Installation

Option 1: Install via pip

python -m venv hn-export-env
source hn-export-env/bin/activate
pip install git+https://github.com/sureshdsk/hn-export.git

Option 2: Clone and run with uv

git clone https://github.com/sureshdsk/hn-export.git
cd hn-export
uv sync

Setup

  1. Get your Hashnode API key from https://hashnode.com/settings/developer

  2. Set the environment variable:

export HASHNODE_API_KEY=your_api_key_here

Or create a .env file in the directory where you run the command:

HASHNODE_API_KEY=your_api_key_here

Usage

Basic Usage

Export everything (posts, drafts, static pages, series) from your primary publication:

If installed via pip:

hn-export

If using the cloned repo with uv:

uv run hn-export

Advanced Options

# Specify a publication
hn-export --publication blog.example.com

# Custom output directory
hn-export --output-dir my-blog-backup

# Export only posts
hn-export --posts-only

# Export only drafts
hn-export --drafts-only

# Export only series metadata
hn-export --series-only

# Export only markdown (skip JSON)
hn-export --format markdown

# Export only JSON (skip markdown)
hn-export --format json

# Skip image downloads
hn-export --no-images

# Combine options
hn-export --posts-only --format markdown --no-images

Output Structure

{domain-name}/
β”œβ”€β”€ posts/
β”‚   β”œβ”€β”€ markdown/          # Post markdown files
β”‚   β”œβ”€β”€ json/              # Post JSON files
β”‚   └── images/            # Downloaded images
β”œβ”€β”€ drafts/
β”‚   β”œβ”€β”€ markdown/          # Draft markdown files
β”‚   β”œβ”€β”€ json/              # Draft JSON files
β”‚   └── images/            # Downloaded images
β”œβ”€β”€ pages/
β”‚   β”œβ”€β”€ markdown/          # Static page markdown files
β”‚   β”œβ”€β”€ json/              # Static page JSON files
β”‚   └── images/            # Downloaded images from static page content
β”œβ”€β”€ series/
β”‚   β”œβ”€β”€ {series-slug}.md   # Series metadata (markdown)
β”‚   └── {series-slug}.json # Series metadata (JSON)
β”œβ”€β”€ export_errors.log      # Error log (if errors occurred)
└── export_errors.json     # Error log in JSON format

Development

Setup Development Environment

  1. Install dependencies with dev tools:
uv sync --extra dev
  1. Install pre-commit hooks:
uv run pre-commit install
  1. Run pre-commit manually (optional):
uv run pre-commit run --all-files

Code Quality Tools

Ruff - Fast Python linter and formatter:

# Lint code
uv run ruff check .

# Fix linting issues
uv run ruff check --fix .

# Format code
uv run ruff format .

# Check formatting without changes
uv run ruff format --check .

ty - Fast static type checker from Astral:

uv run ty check src/hn_blog_exporter

Pre-commit - Runs automatically on git commit:

  • Trailing whitespace removal
  • End-of-file fixer
  • YAML/JSON/TOML validation
  • Ruff linting and formatting
  • ty type checking

Project Structure

src/hn_blog_exporter/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ main.py              # CLI interface (Typer)
β”œβ”€β”€ config.py            # Configuration
β”œβ”€β”€ hashnode_client.py   # GraphQL API client
β”œβ”€β”€ exporter.py          # Export logic
β”œβ”€β”€ image_downloader.py  # Image downloading
└── error_logger.py      # Error logging

tests/
β”œβ”€β”€ conftest.py          # Pytest fixtures
β”œβ”€β”€ test_config.py       # Config tests
β”œβ”€β”€ test_hashnode_client.py  # API client tests
β”œβ”€β”€ test_exporter.py     # Export logic tests
└── test_image_downloader.py # Image download tests

Running Tests

# Install dev dependencies
uv sync --extra dev

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=src/hn_blog_exporter

# Run specific test file
uv run pytest tests/test_config.py

# Run with verbose output
uv run pytest -v

Troubleshooting

API Key Issues

If you get authentication errors:

  1. Verify your API key is correct in .env
  2. Ensure the .env file is in the project root
  3. Check that your API key has the necessary permissions

Rate Limiting

The Hashnode API has generous rate limits (20k requests/min for queries). If you hit rate limits, wait a moment and try again.

Image Download Failures

If images fail to download:

  • Errors are logged to export_errors.log in the output directory
  • Export continues without interruption
  • Original URLs are preserved in the markdown
  • Check the error log for details (URL, error type, timestamp)
  • Use --no-images to skip image downloads entirely

Error Logging

When errors occur during export, two log files are created:

  • export_errors.log - Human-readable format
  • export_errors.json - Machine-readable format

The export summary will show the error count and log file location.

Screenshot

Hashnode Blog Exporter

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

hashnode blog exporter - export Hashnode blog content into markdown files with frontmatter and images

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages