Post to WordPress from Simplenote or Dropbox

January 30, 2012 by Gabe | [mmd] |

Edit: See this updated post for enhancements

This is for all of you Markdown and plain text nerds out there. You're my people.

I've been tinkering with a simplified mechanism for posting to this site. Most of my posts are started in Simplenote. If it's a long post then I'll work in BBEdit but the document still resides in my Simplenote/NVAlt/Dropbox folder1. When I'm done with a post, I'll preview it in Marked and copy the html. I have a Keyboard Maestro macro that will post the html on the clipboard directly to Macdrifter.

However, if I'm away from home, I must post via the web on Windows or iOS. Neither is a great option. I have Brett's MD Quicktags plugin installed, but it seemed like I could streamline the process a bit.

I've come up with a solution that lets me write in MultiMarkdown on Simplenote or Dropbox and automatically post the article when it is tagged with "post".


Hazel is the next level of folder actions. Hazel watches items in a folder and performs actions based on a defined condition. For some context, take a look at Eddie's post on Practically Efficient. He has a very good introduction to Hazel.

I setup two Hazel rules. NVAlt supports Simplenote tags through OpenMeta extended attributes. The first rule looks for a file in my Simplenote folder to get the OpenMeta tag of "post" and makes a copy of the file to another folder. Importantly, the Hazel rule will not overwrite a file if it already exists in the destination folder. This is critical and I'll explain more later.

Copy Rule

The second Hazel rule does all of the work. Once a new .txt file appears that has never been processed, Hazel runs it through a Shell script. Well, it's a Python script run by Hazel's embedded shell script action. Note how Hazel passes in the file path.

Hazel Script

Here's the full script (you will need to provide your own WordPress connection credentials):


import markdown

import xmlrpclib

import os

import sys

filePath = sys.argv[1]

Connection details for the WordPress xmlrpc connection




wpBlogid = ''

status_draft = 0

status_published = 1

categories = ''

title = ''

Create server instance

wpServer = xmlrpclib.ServerProxy(wpUrl)


myFile = open(filePath, "r")

rawText =

# Process with MD Extras and meta data support

md = markdown.Markdown(extensions = ['extra', 'meta'])

# Get the html text

html = md.convert(rawText)

# extract the title from the meta dictionary

title = md.Meta['title']

# title is actually a list

title = title[0]

# extract the categories but keep them as a list

categories = md.Meta['category']

# Only post if there is a title in the meta data. I don't want to hassle with parsing the file name.

if title != '' :

    data = {'title':title, 'description':html, 'categories':categories}

    post_id = wpServer.metaWeblog.newPost(wpBlogid, wpUser, wpPass, data, status_published)

    # Pass the result for a growl message

    print data

except (RuntimeError, TypeError, NameError):

# Make the error message as elaborate as you like. It's all right there in the exception.

pyStatus = "Error"

print pyStatus

The Script

I've looked at several Python options for processing Markdown and posting to WordPress but I've never been happy with any of them. Python is generally my weapon of choice, when I have one. I generally like to use as few odd-ball modules as possible to reduce maintenance overhead when upgrading or porting to another system. In this instance, I'm using the most common Python Markdown module to process the text. There are a couple very cool things with this module. First, it supports Markdown Extras like the ones I use in MultiMarkdown. This includes footnotes, code blocks, tables and meta data. The second is how it supports meta data. It can pretty much extract anything. In this example, I'm extracting the "title" and "category" fields but I could use date, author or just about anything I want. For multiple categories, I put each category on a subsequent indented line and the module knows they are all categories.

Once I've extracted all of the content, I then take advantage of another common Python module, the xmlrpclib module. This is the bit for getting the content posted. The xmlrpclib module also supports the necessary meta data for WordPress posts. For a nice overview of the same process I went through in coming to this conclusion, see Sami Slkosuo's post.

I considered using the Python WordPress XMLRPC module but it looked like over-kill for my needs. I may yet use it to avoid double posting and make updating published posts possible. It's very tempting.

Start to Finish

The new workflow looks something like this. I write as much as I want in MultiMarkdown in Simplenote/NVAlt. If I want, I preview with Marked. When I'm ready to post, I just add a Simplenote/NVAlt tag of "post" to the entry. The article gets published by my server at home without any other effort from me. Additionally, the Markdown version of the article is saved my archive folder for permanent reference.

There is a small catch though. Because I'm lazy and a bit squeezed for time I didn't come up with a satisfactory way to avoid duplicate posts. I needed to avoid multiple posts of the same article if I made a small edit in Simplenote. If I accidentally make a small edit to an entry already tagged, It could get posted multiple times. The easiest solution I came up with is to not overwrite the file if it exists in my "Posts" archive. That way the second Hazel rule will not run a again.

I'm sure there's a more complete solution that would save the post id returned from the initial post and keep track of it. Or maybe just check to see if I already have a post with that title and do an update if I do. I'll get around to that feature when I get some more time. For now, I think this is pretty nice.

It's not just the simplicity of the workflow that I like. I also like that I can twiddle a post for awhile in Simplenote without ever having to reload a draft from WordPress or log back in to the site. I can write and then when I am done (or tired of the subject), I can add the "post" tag.


This post made it to the site via this mechanism. If you're reading this, then everything worked according to plan. 2 Ok, I've actually been using this method and tweaking it for awhile. If you've noticed odd unprocessed Markdown or other artifacts, then you've been part of this grand experiment. Thanks for your patience.

  1. I have my Dropbox notes folder syncing with Simplenote by way of NVAlt. NVAlt is always open on my computer at home and that computer is always awake. I've posted about that before. 
  2. There you have my secret. I don't run a dev or test instance of this site. I'm making live changes like an idiot.