Crushing the Command Line with Amazon Q: Building a Medium to DEV.to Converter
This is a submission for the Amazon Q Developer "Quack The Code" Challenge: Crushing the Command Line What I Built I built medium2dev, a command-line tool that automatically converts Medium blog posts to DEV.to-compatible markdown format and optionally publishes them directly to DEV.to as draft posts. This tool solves a common problem for technical writers who publish on multiple platforms: maintaining consistent formatting across different publishing platforms. The tool preserves: Article title and headings Text formatting (bold, italic, etc.) Code blocks with proper syntax highlighting Inline images (automatically downloaded and referenced) Lists and other structural elements Generates proper DEV.to frontmatter Demo Here's a demonstration of converting a Medium article to DEV.to format: # Basic conversion python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 # Publish directly to DEV.to as a draft python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 --publish --api-key YOUR_DEVTO_API_KEY # Or use environment variable for API key export DEVTO_API_KEY=your_api_key python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 --publish Output: 2025-05-03 15:07:49,696 - medium2dev - INFO - Fetching article from https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 2025-05-03 15:07:51,100 - medium2dev - INFO - Original Medium content word count: 463 2025-05-03 15:07:51,100 - medium2dev - INFO - Downloaded 0 content images 2025-05-03 15:07:51,116 - medium2dev - INFO - Conversion complete! Output saved to /Users/vivekvelso/Documents/opensource/medium2dev/new/aws-resource-tag-compliance-with-automation-64ae16e42a11.md Conversion successful! Output saved to: /Users/vivekvelso/Documents/opensource/medium2dev/aws-resource-tag-compliance-with-automation-64ae16e42a11.md Images saved to: /Users/vivekvelso/Documents/opensource/medium2dev/images When publishing to DEV.to, it also displays a word count comparison: Successfully published as draft to DEV.to! Word Count Comparison: | Platform | Word Count | |----------|------------| | Medium | 463 | | DEV.to | 458 | The tool successfully: Fetches the Medium article Cleans up author metadata and unnecessary UI elements Removes Medium-specific UI elements like "Listen", "Share", etc. Converts the content to markdown Generates a properly formatted DEV.to markdown file (Optionally) Publishes the article as a draft to DEV.to Provides a word count comparison between platforms Code Repository The code is available on GitHub: medium2dev Key files: medium2dev.py: The main Python script requirements.txt: Dependencies README.md: Documentation How I Used Amazon Q Developer I used Amazon Q Developer CLI to create this entire project from scratch. Here's how the conversation went: Initial Prompt I started by explaining my idea to Amazon Q: I am submitting an idea for this challenge. Crushing the Command Line Build an automation with Amazon Q Developer CLI that makes your work easier, faster, or better. My idea is to create a tool to convert medium posts to dev.to markdown posts preserving the title heading, formatting and inline images the same way. Please give exact steps and prompts by referring to collection from promptz tool if you find anything to enhance the solution, and also what prompts were given to automate the whole command line solution to q and how q responded, log all that in this blog post for submission, along with the code that is generated, then test it on the url https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 and verify the markdown generated, and confirm that all text, image, formatting is same. Amazon Q's Approach Amazon Q first checked for relevant prompts in the promptz.dev collection that might help with this task: ["CLI", "Markdown"] After finding no specific prompts for Markdown conversion, Amazon Q proceeded to design a solution from scratch. It created a Python script that would: Fetch Medium articles using web scraping Extract content while preserving structure Download and properly reference images Convert HTML to Markdown format Generate DEV.to compatible frontmatter Solution Implementation Amazon Q generated the complete medium2dev.py script with these key components: class Medium2Dev: def __init__(self, url, output_dir=None, image_dir=None, api_key=None): """Initialize the converter with the Medium post URL.""" self.url = url self.output_dir = output_dir or os.getcwd() self.image_dir = image_dir or os.path.join(self.output_dir, 'images') self.api_key = api_key

This is a submission for the Amazon Q Developer "Quack The Code" Challenge: Crushing the Command Line
What I Built
I built medium2dev
, a command-line tool that automatically converts Medium blog posts to DEV.to-compatible markdown format and optionally publishes them directly to DEV.to as draft posts. This tool solves a common problem for technical writers who publish on multiple platforms: maintaining consistent formatting across different publishing platforms.
The tool preserves:
- Article title and headings
- Text formatting (bold, italic, etc.)
- Code blocks with proper syntax highlighting
- Inline images (automatically downloaded and referenced)
- Lists and other structural elements
- Generates proper DEV.to frontmatter
Demo
Here's a demonstration of converting a Medium article to DEV.to format:
# Basic conversion
python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11
# Publish directly to DEV.to as a draft
python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 --publish --api-key YOUR_DEVTO_API_KEY
# Or use environment variable for API key
export DEVTO_API_KEY=your_api_key
python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 --publish
Output:
2025-05-03 15:07:49,696 - medium2dev - INFO - Fetching article from https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11
2025-05-03 15:07:51,100 - medium2dev - INFO - Original Medium content word count: 463
2025-05-03 15:07:51,100 - medium2dev - INFO - Downloaded 0 content images
2025-05-03 15:07:51,116 - medium2dev - INFO - Conversion complete! Output saved to /Users/vivekvelso/Documents/opensource/medium2dev/new/aws-resource-tag-compliance-with-automation-64ae16e42a11.md
Conversion successful! Output saved to: /Users/vivekvelso/Documents/opensource/medium2dev/aws-resource-tag-compliance-with-automation-64ae16e42a11.md
Images saved to: /Users/vivekvelso/Documents/opensource/medium2dev/images
When publishing to DEV.to, it also displays a word count comparison:
Successfully published as draft to DEV.to!
Word Count Comparison:
| Platform | Word Count |
|----------|------------|
| Medium | 463 |
| DEV.to | 458 |
The tool successfully:
- Fetches the Medium article
- Cleans up author metadata and unnecessary UI elements
- Removes Medium-specific UI elements like "Listen", "Share", etc.
- Converts the content to markdown
- Generates a properly formatted DEV.to markdown file
- (Optionally) Publishes the article as a draft to DEV.to
- Provides a word count comparison between platforms
Code Repository
The code is available on GitHub: medium2dev
Key files:
-
medium2dev.py
: The main Python script -
requirements.txt
: Dependencies -
README.md
: Documentation
How I Used Amazon Q Developer
I used Amazon Q Developer CLI to create this entire project from scratch. Here's how the conversation went:
Initial Prompt
I started by explaining my idea to Amazon Q:
I am submitting an idea for this challenge. Crushing the Command Line
Build an automation with Amazon Q Developer CLI that makes your work easier, faster, or better.
My idea is to create a tool to convert medium posts to dev.to markdown posts preserving the title heading, formatting and inline images the same way. Please give exact steps and prompts by referring to collection from promptz tool if you find anything to enhance the solution, and also what prompts were given to automate the whole command line solution to q and how q responded, log all that in this blog post for submission, along with the code that is generated, then test it on the url https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11 and verify the markdown generated, and confirm that all text, image, formatting is same.
Amazon Q's Approach
Amazon Q first checked for relevant prompts in the promptz.dev collection that might help with this task:
["CLI", "Markdown"]
After finding no specific prompts for Markdown conversion, Amazon Q proceeded to design a solution from scratch. It created a Python script that would:
- Fetch Medium articles using web scraping
- Extract content while preserving structure
- Download and properly reference images
- Convert HTML to Markdown format
- Generate DEV.to compatible frontmatter
Solution Implementation
Amazon Q generated the complete medium2dev.py
script with these key components:
class Medium2Dev:
def __init__(self, url, output_dir=None, image_dir=None, api_key=None):
"""Initialize the converter with the Medium post URL."""
self.url = url
self.output_dir = output_dir or os.getcwd()
self.image_dir = image_dir or os.path.join(self.output_dir, 'images')
self.api_key = api_key
# ...
def fetch_article(self):
"""Fetch the Medium article content."""
# ...
def extract_content(self, html_content):
"""Extract the article content from the HTML."""
# ...
def download_images(self, content):
"""Download images and update their references in the content."""
# ...
def convert_to_markdown(self, content):
"""Convert HTML content to Markdown format suitable for DEV.to."""
# ...
def generate_frontmatter(self, title, date):
"""Generate DEV.to frontmatter."""
# ...
def convert(self):
"""Convert the Medium post to DEV.to markdown format."""
# ...
def publish_to_devto(self, title, markdown_content):
"""Publish the converted markdown as a draft post to DEV.to."""
# ...
Amazon Q also created the necessary supporting files:
-
requirements.txt
with the required dependencies -
README.md
with usage instructions
Improving the Solution
After initial testing, I noticed some issues with the generated markdown:
- Author metadata was still being included
- The script wasn't properly extracting content images
- Medium-specific UI elements like "Listen", "Share", etc. were appearing in the output
I asked Amazon Q to improve the solution, and it made several key enhancements:
Better Content Extraction: Improved the HTML parsing to focus only on the actual article content
# Create a new div to hold only the content we want
content_div = soup.new_tag('div')
# Find all the content sections (paragraphs, headings, code blocks, images)
content_elements = article_tag.find_all(['p', 'h2', 'h3', 'h4', 'pre', 'figure', 'img', 'blockquote', 'ul', 'ol'])
Metadata Removal: Added more robust filtering to remove author bylines, claps, and other Medium-specific UI elements
# Skip elements with author info, claps, etc.
if element.find(string=re.compile(r'clap|follow|min read|sign up|bookmark|Listen|Share')):
continue
# Skip elements that just contain "--" or numbers at the beginning
if element.name == 'p' and re.match(r'^\s*--\s*$|^\s*\d+\s*$', element.text.strip()):
continue
Enhanced Image Handling: Improved the image extraction and downloading process
# For Medium images, try to get the full-size version
if 'miro.medium.com' in img_url:
# Remove size constraints from URL to get original image
img_url = re.sub(r'/resize:[^/]+/', '/', img_url)
Better Markdown Cleanup: Added post-processing to clean up Medium-specific elements
# Remove Medium-specific footer text and links
markdown = re.sub(r'\n\s*\[.*?\]\(https?://medium\.com/.*?\)\s*\n', '\n\n', markdown)
# Remove clap indicators and other Medium UI elements
markdown = re.sub(r'\d+\s*claps?', '', markdown)
CLI Enhancements: Added command-line options for publishing directly to DEV.to
parser.add_argument('-p', '--publish', action='store_true', help='Publish to DEV.to as draft')
parser.add_argument('-k', '--api-key', help='DEV.to API key (if not set via DEVTO_API_KEY environment variable)')
DEV.to Integration: Added functionality to publish directly to DEV.to as a draft post
def publish_to_devto(self, title, markdown_content):
"""Publish the converted markdown as a draft post to DEV.to."""
if not self.api_key:
logger.error("No DEV.to API key provided. Skipping publish.")
return False
logger.info("Publishing to DEV.to as draft...")
api_url = "https://dev.to/api/articles"
headers = {
"api-key": self.api_key,
"Content-Type": "application/json"
}
# Prepare the article data
article_data = {
"article": {
"title": title,
"body_markdown": markdown_content,
"published": False # Set as draft
}
}
try:
response = requests.post(api_url, headers=headers, json=article_data)
response.raise_for_status()
article_data = response.json()
logger.info(f"Successfully published draft to DEV.to!")
return True
except requests.RequestException as e:
logger.error(f"Error publishing to DEV.to: {e}")
return False
Word Count Comparison: Added functionality to compare word counts between Medium and DEV.to versions
# Calculate the word count of the original content
content_text = ' '.join([element.get_text() for element in content_div.contents])
self.medium_word_count = len(content_text.split())
logger.info(f"Original Medium content word count: {self.medium_word_count}")
# Calculate DEV.to word count
devto_word_count = len(re.sub(r'---.*?---\n', '', markdown_content, flags=re.DOTALL).split())
# Display comparison when publishing
print("\nWord Count Comparison:")
print("| Platform | Word Count |")
print("|----------|------------|")
print(f"| Medium | {converter.medium_word_count} |")
print(f"| DEV.to | {devto_word_count} |")
Testing the Solution
I tested the improved solution with the provided Medium article URL:
python3 medium2dev.py https://medium.com/aws-in-plain-english/aws-resource-tag-compliance-with-automation-64ae16e42a11
The script successfully:
- Downloaded the article content
- Removed author metadata and Medium-specific UI elements
- Converted the HTML content to clean markdown
- Generated a properly formatted DEV.to markdown file with valid tags
I also tested with a different URL format to ensure the solution is robust:
python3 medium2dev.py https://medium.com/@vivek-aws/aws-resource-tag-compliance-with-automation-64ae16e42a11
The tool worked perfectly with both URL formats, demonstrating its flexibility.
Challenges and Solutions
During development, Amazon Q addressed several challenges:
Medium's Dynamic Content: Used proper headers and request parameters to ensure content was fully loaded
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
# Additional headers...
}
Content Extraction: Developed a robust approach to extract only the relevant content
# Try multiple approaches to find the content
article_tag = soup.find('article')
if not article_tag:
article_tag = soup.select_one('div.section-content')
if not article_tag:
article_tag = soup.find('div', class_='postArticle-content')
Metadata Removal: Created comprehensive filters to remove Medium-specific UI elements
# Remove Medium-specific UI elements and metadata
for element in content.select('.postMetaLockup, .graf--pullquote, .section-divider'):
if element:
element.decompose()
DEV.to Integration: Added support for publishing directly to DEV.to using their API
# Get API key from environment or command line
api_key = args.api_key or os.environ.get('DEVTO_API_KEY')
DEV.to Tag Format: Fixed tag format to comply with DEV.to requirements
# Convert "aws in plain english" to "awsinplainenglish"
potential_tag = re.sub(r'[^a-zA-Z0-9]', '', potential_tag)
Word Count Comparison: Added functionality to compare word counts between platforms without modifying the output file
# Calculate word counts and display comparison
medium_word_count = converter.medium_word_count
devto_word_count = len(re.sub(r'---.*?---\n', '', markdown_content, flags=re.DOTALL).split())
Conclusion
Using Amazon Q Developer CLI, I was able to quickly create a functional tool that solves a real problem for technical writers. The entire process from idea to implementation took just minutes, demonstrating how Amazon Q can accelerate development workflows.
This tool saves significant time for writers who publish on multiple platforms, eliminating the need for manual reformatting and ensuring consistent presentation across platforms. The addition of direct publishing to DEV.to makes the workflow even more streamlined, allowing writers to go from Medium article to DEV.to draft with a single command.