Automatically Upload Images in Typora Editor

Typora is a markdown editor I truly love. To this day, I haven’t found any editor that feels smoother to use. Whenever I write more complex blog posts, I draft them in Typora before publishing. Typora comes packed with features, including:
- Table support
- LaTeX syntax support for easily writing formulas
- Direct drag-and-drop for images to generate the corresponding Markdown syntax
- Support for a wide variety of HTML tags, such as iframe, video, ruby, etc.
- Custom themes (written in CSS)
- Built-in file and folder browsing and switching
- And plenty of other useful features
These well-crafted features make it hard for me to put Typora down. However, using it comes with one hassle: uploading images. By default, Typora only inserts the local file path into your Markdown, like this:

If you copy and paste this directly onto the web, the image will break immediately because readers cannot access your local file path—the image must be uploaded to the cloud or server storage first. Handling this manually is tedious. Sometimes images are quite large, so you want to compress them before uploading. Just thinking about taking that extra step feels like a chore, and it easily breaks your writing flow.
I couldn’t help but wonder if there was a way to upload images directly without leaving the editor. Typora itself already has great drag-and-drop handling for images, and copying and pasting from the web works seamlessly too—the UI is fantastic on its own.
Then, I came across this:
Finding this was an absolute game-changer! This feature lets you define what happens when you insert an image into the editor—such as moving it to a specific folder or uploading it. Even better, you can define a custom command to handle the upload!

Inside this upload command, I compress the image, upload it to S3, and return the image URL. Typora takes care of all the UI and state management. Just like that, uploading images becomes completely painless!
Here is what the finished result looks like:
Implementation
Feel free to check out my code on GitHub (written in Node.js). The implementation is quite straightforward—I just threw together a few packages to get it up and running quickly. If you prefer building things from scratch, you can definitely write your own. Currently, it only supports uploading to S3.
Wrap-up
This has truly been life-changing—no more postponing blog posts just because I dread dealing with images. Hopefully, this helps anyone else who loves creating content with Markdown!
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.