One feature of Wordpress that I really liked, was the ability to easily schedule the publication of a post for a specified date and time. Another was the seperation of drafts and posts in the webinterface.
I wanted these features back, but without all the clutter the Wordpress webinterface introduced in the past versions. It admittedly got better in the last version I used1, but the damage was done.
Now, firmly settled into my Octopress
driven txt
-only environment, I could implement these features on my own.
Tailored to my very own needs. Throwing in some sync-o-magic to keep my posts and
drafts updated across all my devices.
So if you’re into these things, follow me to see how posts get published in this corner of the Internet.
Search what other people have done
The very first thing to do, when you attempt to do anything remotely technical, is to check if other people encountered2 your current problem before you.
This incron-method was one of the first posts i found3 but it could not provide me with the seperation of drafts and the scheduling I grew so accustomed to. And I just don’t want my site to rebuild everytime I change a typo in an old post. Also: instant-thinking.de lives on kinda cheap shared webspace with no Dropbox-sync-o-matic capabilities. I would need to solve this with a different approach.
Another very interesting post I found is this one by Mr. Jonathan Poritsky. He is also using Dropbox to sync his site across his iOS Devices4 and his Mac at home.
This nicely mirrors my own setup:
- A Mac mini at home, almost always on
- A MacBook Pro, almost always at home, not always on
- iPhone and iPad at home and on the go
He then continues to build the site manually via a SSH-login on his Mac and deploys the
finished site via git push
to a private git-repo at Beanstalk. From there he uses FTP to update his Website.
This sounded a bit cumbersome to me and so I came up with my own solution.
My own remote blogging setup
In additon the the queueing of posts and the separation of drafts, I added syncing across my devices to the mix. So here is what I needed to achieve:
- Keep my drafts and posts seperated
- Keep my drafts and posts synced across all my devices
- Have an easy way, to change the status of my latest masterpiece5 from draft to post
- Have an easy way, to choose a specific date and time for the publication of posts
- Have an easy way, to automate the build and deployment - no manual
ssh
ish stuff, thank you very much
So, to first reach for the low hanging fruits:
Seperate drafts and posts
Inside each Octopress source
-folder is a _posts
folder containing all the
posts. I simply created another folder _drafts
to hold my drafts. For good measure,
I patched the Rakefile
to include a new task to create a new draft. Here is
the diff:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Basically, this is just a copy of the new_post
task. Please notice the added published: false
in the YAML-header. This, as documented in Octopress Blogging Basics, would prevent this post from getting
published if it was found in the _posts
folder. This will come in handy later…
It is of course still possible to create a new draft or post any other way.
Just make sure the filename follows Octopress/Jekyll convention of
YYYY-MM-DD-post-title.markdown
, include the YAML-header and you’re good to
go.
Sync across all my devices
Which brings me to syncing. These days, this usually means Dropbox. Apples iCloud could be another option one day, but right now it does not seem like Apple is going to send some love to the filesystem part of it’s operating systems. And because virtually any iOS text editor comes with Dropbox support, the choice for Dropbox is a no brainer.
So I logged into my Mac mini at home to create a new folder in my Dropbox.
I named it, oh the creativity, blog
. Inside this folder I put _drafts
,
_posts
, _queue
and images
. Viewed from an iOS Dropbox-Client, it looks
a lot like this:
These folders are actually symlinks that got created on the Mac mini like so:
1 2 3 4 |
|
When finished, the blog
-folder looks like this on the Mac mini:
1 2 3 4 5 6 |
|
On any other machine, these become actual folders:
1 2 3 4 5 6 |
|
The underscores are there to make sure that these folders won’t get deployed to
the live site. So all these folders, with the exception of images
, are kept
on the local machines. This way, all the essential folders containing my
content are in sync across anything which can talk to Dropbox.
From draft to queue to published post
So now we have a perfectly synced draft. How will this draft get to the live site? And how will this happen at a given date and time?
This will happen with the help of two YAML-properties in the frontmatter and
the it_queue.rb
script which lives on the Mac mini and can also be found in this
GitHub repo.
The script gets run every five minutes by a LaunchAgent6. It starts by looking
into the YAML-frontmatter of every file in the _drafts
-folder. If it finds
a post with published:true
in the frontmatter it will move it from _drafts
to _queue
. During this move, the script reads the date part of the
date:
-property and renames the file accordingly.
Let me explain:
A draft, created by the mentioned new_draft
task on the 1st of May 2012,
would live in the _drafts
-folder as the file
2012-05-01-rant-on-some-apple-thingie.markdown
. In it’s YAML-frontmatter it
would carry the following properties7:
1 2 |
|
After some work on it, I decide to mark this draft as finished on May, 15th by changing the properties to:
1 2 |
|
Next time the script runs, it moves the file to the _queue
-folder, renaming
it to 2012-06-12-rant-on-some-apple-thingie.markdown
in the process.
The date:
property not only defines the filename of the post, but also it’s
publishing date and time.
This is, because it_queue.rb
also checks the YAML-frontmatters of the posts
in the _queue
-folder. Here, it scans for the date and time of the date:
property, transforms the found string into a Ruby time object and checks, if
this object is in the past or in the future of Time.now
. If it is in the
future, nothing happens. If it is in the past, the build
-variable is set to
1
and the build and deployment of instant-thinking.de is triggered.
The file in question would trigger the build on the first run of the script
after June 12th, 2012, 09:00. During this run, the file gets moved out of
_queue
and into _posts
. From there, it will get rendered and put on the live
site.
Wrapping up the build and deployment
Both parts, build and deployment, turned out to be a bit more tricky than I thought…
The problems I encountered are nonexistent, if I go manually through the steps needed to build and deploy the site. But everything goes south when the LaunchAgent tries to automatically do it’s duty.
It all comes down to the environment used when the neccessary actions are performed. Things that needed to get fixed:
- The Ruby version. The Mac mini runs OS X 10.6.8 Snow Leopard which comes with Ruby 1.8.7. Octopress needs Ruby 1.9.2, which I installed on the mini via RVM
- The encoding. Each and every Umlaut caused the build to fail catastrophically
- The SSH authentification. I use a passwordless SSH-login for the
rsync
-deployment. But the LaunchAgent has no access to the used key
To solve the problem with the Ruby version, I used the wrapper _rvmruby
which
I found at urgetopunt.com.
In the LaunchAgent, I do not call it_queue.rb
directly, but use it as the
argument to ruby, which in turn gets called with the Ruby version 1.9.2
provided by RVM. The whole LaunchAgent plist
looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Following this approach, I modified the original wrapper to include
de:DE.UTF-8
-encoding just like in my own interactive sessions. This took care
of all the Umlaut-problems I encountered.
Finally, I found a hint from Linc Davis on discussions.apple.com in which he explains, how a script can be told to use an existing SSH auth socket on OS X 10.5+. This approach requires, that the given user is logged into the system each time the script runs and that the script is run either under the same account or as root but that is pretty much a given on my Mac mini.
I had to change the name of the SSH auth socket variable from SSHAUTHSOCK
to
SSH_AUTH_SOCK
but other than this nuisance, it worked like a charm.
My final wrapper looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
And that’s pretty much it.
The scheduling is not exact to the minute because the script only runs every five minutes and even then, the build of instant-thinking.de takes almost 15 minutes on the Mac mini.
But the fact, that I can decide when my drafts become posts and when they’ll get published is really quite convenient. This is nothing I would want to write a liveblog with, but for my usual posting frequency, it is really convenient.
Even more, if you consider that the whole Wordpress date picker thingie with
buttons and bells and whistles is replaced by two lines in a txt
-file.
A little Ruby-script and some tinkering with YAML-properties is all it takes to
use Octopress in a much more pleasing way. A blogging framework for hackers,
indeed.
If this setup suits your needs, you can find everything you need in the Github Repo. Have fun, and if you made it down here, thanks for reading.