Publishing Medium Articles with AWS Lambda
Medium doesn’t natively support code block editing. While the reason behind this remains unclear (perhaps engineers aren’t their primary target audience), if you want syntax highlighting, one approach is to paste images directly, and another is to paste your code into a Gist and embed it into the post.
While posting code as images achieves syntax highlighting, it’s quite developer-unfriendly because readers can’t copy and paste it to test the code. Moreover, manually editing screenshots whenever you update an article is a huge hassle.
However, embedding Gists also comes with a few issues:
- It doesn’t display properly on mobile—it just spits out a raw link rather than the embedded content.
- Manually pasting code into Gist is tedious (though using extensions in VS Code or Sublime to upload to Gist is a decent alternative).
To get syntax-highlighted code blocks on Medium as painlessly as possible, I eventually decided to solve this with AWS Lambda.
AWS Lambda
For readers unfamiliar with Lambda, there are already plenty of resources available online, so I won’t go into detail here. Lambda lets AWS run functions for you without having to actually set up a server (though, of course, there are still servers under the hood). This way, we don’t have to deploy every little function to a server and maintain it—we just focus on execution.
GitHub Issues
To trigger the Lambda endpoint, I decided to use a GitHub webhook. Writing in Markdown via GitHub Issues is really convenient because it supports image uploads (hosted by GitHub), previews, code blocks, and more. When ready to publish, closing the issue triggers the webhook, which then prompts Lambda to upload code blocks to Gist, and finally calls the Medium API to create the post.
Medium API
Medium’s API is lightweight, straightforward, and easy to use. First, go to Settings > Integration tokens on your profile page to generate a token, and then use that token to call the API for creating a post.
Gist API
The same goes for the Gist API. To keep your main Gist profile clean and clutter-free, it’s a good idea to create a separate account specifically for article code snippets. Go to Settings > Developer settings > Personal access tokens > Generate token to create a token, and make sure to check the gist permission.
Integrating with Lambda
Once the preparations are complete, you can start integrating with Lambda.
First, add your Lambda endpoint to the GitHub webhook settings. Then, pick any package that compiles Markdown into HTML (I used marked), hook them together, and you’re good to go!
A simple implementation can be found here. Although setting it up takes a bit of effort, the workflow itself is pretty convenient. I wonder when Medium will finally support code blocks properly QQ.
Related Posts
- When a Measure Becomes a Target: From the Window Tax to Pull Request Counts I once wrote a script to tally how many PRs I contributed in a quarter, how many reviews I left, and how many tickets I closed, hoping to use numbers to prove my output to my manager. My manager simply remarked that performance isn't just about output. Years later, I finally understood—when a measure becomes a target, it ceases to be a good measure. From the British window tax and the Hanoi rat bounty to evaluating developers by PR counts today, the underlying mechanism is exactly the same.
- Using Cloudflare Images for Image Storage and Transformation Putting an image on a webpage is the simplest task in frontend development. But doing it properly—including resizing, generating multiple formats, and withstanding heavy traffic—is actually an entire end-to-end solution. Eventually, I offloaded everything to Cloudflare Images, keeping only a single original image.
- Stop Using AWS Access Keys Access Keys are an easily overlooked security risk in AWS. By pairing OIDC with IAM Roles, GitHub Actions can securely operate AWS resources without storing any secrets.
- Database Primary Keys: AUTO_INCREMENT, UUID, and UUIDv7 Backend developers often face the choice of primary keys: should you use auto-increment or UUID? What about collisions? How does UUIDv7 compare to created_at + index in performance? Here are the design decisions and benchmark results from testing 20 million rows.