Introduction
It’s tedious to manually post to social media every time you update your blog, isn’t it? I recently implemented a feature that automatically posts to X (formerly Twitter) when a new article is published on this blog. While this feature might seem simple at first glance, the implementation presented more challenges than expected. In this article, I’ll share in detail the problems I encountered during implementation and how I solved them.
What I Tried to Implement
Requirements
- Automatically post to X when a new article is added to the blog
- Post content includes article title, description, tags, and URL
- Mechanism to prevent duplicate posts
- Draft articles are excluded from posting
- Ability to skip automatic posting when needed
Services and Technologies Used
- GitHub Actions: Workflow execution environment for automation
- X API v1.1: Tweet posting API (free plan)
- twitter-api-v2: X API client library for Node.js
- Astro: Static site generator for the blog
Challenges Encountered and Solutions
1. ES Module Error
Problem: The following error occurred on first execution
ReferenceError: require is not defined in ES module scope
Cause: Since the project uses "type": "module"
, CommonJS require
cannot be used
Solution:
- Changed file extension from
.js
to.mjs
- Rewrote
require
toimport
statements
2. Authentication Error (401 Unauthorized)
Problem: Despite correctly setting API keys, 401 errors persisted
Investigation Process:
- Checked GitHub Secrets configuration
- Verified permissions in X Developer Portal
- Regenerated Access Token
- Investigated differences between API v2 and v1.1
Real Cause:
- App was created as “Standalone Apps”
- Standalone Apps don’t have write permissions for X API v2
- Didn’t regenerate Access Token after changing app permissions to “Read and write”
Solution:
- Check and change permissions in X Developer Portal
- Important: Always regenerate Access Token after changing permissions
- Implement fallback processing to v1.1 API
3. File Change Detection Issues
Problem: GitHub Actions couldn’t detect new files
Cause:
- Insufficient history with
fetch-depth: 2
- Inadequate consideration for manual execution (workflow_dispatch)
Solution:
- Changed to
fetch-depth: 0
to get full history - Added special handling for manual execution
4. URL Mismatch
Problem: URLs in tweets were showing as semiramisu.github.io
Cause: Using GitHub Pages default domain
Solution: Fixed to actual domain semiramisu.com
Implementation Key Points
URL Generation with SHA256 Hash
The blog generates URLs by creating SHA256 hashes from filenames:
const fileName = path.basename(file, '.md');
const slug = crypto.createHash('sha256').update(fileName).digest('hex').substring(0, 8);
const postUrl = `https://semiramisu.com/posts/${slug}`;
Duplicate Post Prevention
Saving post history in .github/tweeted/
directory:
fs.writeFileSync(tweetedFile, JSON.stringify({
tweetId: tweet.id_str,
timestamp: new Date().toISOString(),
file: file,
title: postTitle
}, null, 2));
Skipping Automatic Posts
Skip automatic posting by including [skip-tweet]
in commit message:
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && !contains(github.event.head_commit.message, '[skip-tweet]'))
X API Configuration Notes
Required Authentication Information (OAuth 1.0a)
- API Key (Consumer Key)
- API Key Secret (Consumer Secret)
- Access Token
- Access Token Secret
Important Notes
- Free tier can only use v1.1 API (Standalone Apps)
- App permissions must be “Read and write”
- Always regenerate Access Token after changing permissions
- Monthly post limit is 1,500 (free plan)
The Creation Process of This Article
Interestingly, this article itself was created through dialogue with an AI assistant (Claude). What’s fascinating is how the article came to be:
- Feature Implementation Request: “I want to automatically post to X when updating the blog”
- Collaborative Debugging: Identifying problems while sharing error logs
- Step-by-Step Resolution: Solving ES modules → authentication → API versions in order
- Documentation: Looking back at the implementation process and organizing it as an article
What was particularly impressive was the time it took to identify the cause of the 401 error. Checking API key formats, adding debug output, sharing X Developer Portal screen information - it was like a pair programming experience.
Summary
Implementing the X automatic posting feature had more pitfalls than expected. The following points are particularly important:
- Understand X API versions and limitations (v1.1 vs v2)
- Always regenerate tokens after changing permissions
- Read error messages carefully and debug step by step
- Pay attention to differences between official documentation and actual behavior
I hope this experience helps those trying to implement similar features. May automation make blog management more efficient!
コメント