layout | title | category | description |
---|---|---|---|
post |
Colophon |
As a way to kick off this new year, I thought it'd be fun to share some insights of just how NSHipster is made. This article covers both the website and the recently-released NSHipster book, so if you've wondered about the nitty gritty of digital or physical publishing, this article is for you. |
As a way to kick off this new year, I thought it'd be fun to share some insights of just how NSHipster is made. This article covers both the website and the recently-released NSHipster book, so if you've wondered about the nitty gritty of digital or physical publishing, this article is for you.
I created NSHipster in July of 2012 in an attempt to form a lasting writing habit. I committed to putting out a new article each week, and (for the most part) I've been able to stick to that. Having a consistent deadline keeps me motivated and accountable for writing something every week.
Here's the routine: on Monday mornings I wake up at 5AM, grab a bottle of Ito En tea, and get to work. Knowing that I need to get something out then and there allows me to stay focused on the task at hand.
The first step is to figure out what to write about. I have a list of potential topics stashed away in Things.app, compiled from random ideas I get while programming, or while reading through Twitter.
With a topic in hand, then next step is to find as many relevant articles around the web as I can. Apple's documentation and guides serve as an outline of topics to discuss, while Stack Overflow questions serve as data points for where any confusion may lie. Any blog posts that come up in search also help to highlight any interesting tidbits or tricks.
And every so often, I'll find that Mike Ash has already written the definitive blog post on the subject, in which case I go back and find a new topic.
After an hour or so of research on the web and experimentation in Xcode, I'll have a basic outline, along with a handful of code samples for the article. At this point, I have enough to go on for a first draft—and more importantly, have sufficiently warmed up my writing muscles, so that the words flow a little more easily.
Everything is written in Markdown, allowing me to focus on the content. My non-Xcode editor-of-choice is TextMate, as it has been for nearly a decade.
With dozens of articles under my belt at this point, I'm able to write comfortably in the familiar voice that you've come to expect from NSHipster. Most articles start with a philosophical interlude, or some background to provide a broader context for that week's topic. What follows is a top-level description of the class, method, function, project, or language feature being discussed, describing what it is, how it works, and why it's cool and significant. Each section follows in a similar fashion, using code samples, figures, and tables to explain each concept. Finally, the conclusion aims to wrap up any concepts introduced in the beginning, and motivate the reader to use what they've learned in their own work.
Once I've gotten most of the first draft finished, I'll throw the markdown file into Marked to get a sense of the final document as it will read on the site. With all of the formatting in place, I'm able to get a better idea of the actual length and flow of the document. The readability tools and Mac OS X's built-in grammar and spell check act as a first-pass for typos.
Jekyll is what brings all of the content together to generate the final HTML of the site. The source code for the site has evolved gradually over time to incorporate things like RSS, syndication on Twitter, Facebook, and Google+, and full-text search, as well as other best practices.
For CSS, I use Sass & Compass. Once you get used to Sass, there's just no going back to doing CSS by hand. The site itself is long overdue for a re-align, so look forward to that at some point.
I recently switched hosting over from Heroku to Amazon S3. As much as I miss ease and simplicity of Heroku's git-based deployment, S3 can serve static websites much more quickly and inexpensively. Hosting in the us-west-2
(Oregon) region also lends some extra hipster cred, with its relative proximity to Portlandia.
I use the ALIAS
feature of DNSimple to host the site at the Apex domain nshipster.com
, rather than a CNAME
like www.nshipster.com
. Everything about DNSimple has been a dream; I whole-heartedly recommend them for as a DNS registrar and nameserver provider.
Switching over from Heroku also meant coming up with a deployment script. Fortunately, s3cmd makes it easy to synchronize files from the Jekyll _site
build folder to my static hosting bucket. (If anything goes wrong during deployment, or I need to quickly futz around with something in S3 directly, Transmit is my go-to tool).
Before sending everything up to S3, I run HTML Tidy (with a highly-customized config file to accomodate HTML5), and run my HTML and XML (sitemap & RSS feed) through gzip
. By setting the 'Content-Encoding: gzip'
header on S3, compressed assets can be served directly, which dramatically reduces the size (and therefore transfer time) for files.
All together, the deploy script looks something like this:
jekyll build --config _config.en.yml
find _site/ -iname "*.html"
-exec tidy -config tidy.conf {} +
find _site/ -iname '*.html'
-exec gzip -n --best {} +
find _site/ -iname '*.xml'
-exec gzip -n --best {} +
for f in `find _site/ -iname '*.gz'`; do
mv $f ${f%.gz}
done
s3cmd sync --progress -M --acl-public
--add-header 'Content-Encoding:gzip'
--exclude '*.*'
--include '*.html' --include '*.xml'
--verbose
_site/ s3://nshipster.com/
Using a static site generator like Jekyll has the additional benefit of tracking changes of documents over time with git. If someone finds an issue with an article, or has a correction to make, they can open a Pull Request.
And since all of the content is licensed under a Creative Commons BY-NC License, anyone is welcome to translate the source material into another language.
Internationalization: NSHipster.cn
Speaking of translation—over the last couple months, I've been working with translators to make NSHipster more accessible to Chinese-speaking audiences. It's still a work in progress, but I'm excited to give you a sneak peak at what we have so far: NSHipster.cn.
Which brings us to the book. NSHipster: Obscure Topics in Cocoa & Objective-C is the culmination of all of my efforts so far with NSHipster. It combines articles from the site, along with new articles to create an essential resource for any aspiring iOS or Mac OS X developer.
I'll admit: I had no idea what I was getting myself into when I started. Turns out, writing and publishing a book is quite a bit different from a website. Working in the insulated, digital world of technology allows us to momentarily forget about most of the sharp edges of the real world. The process of writing the book was nothing if not a reality check.
I'm not proud of my process in creating the book. It was a long, manual slog using kludgy tools without much of a clue about what I was doing at any step in the process.
At first, I thought it would be pretty straightforward: run the site's articles through Pandoc and call it a day.
Nope.
After sinking at least 10 hours into hacking and tweaking every step of the process, I just wasn't able to produce anything that I could be proud of. Whether this is the fault of the tooling, or my inability to use it correctly, I can't help but conclude from my experiences that stylesheets just don't cut it when it comes to books: each page spread must be designed individually.
With this in mind, I turned to InDesign. After an hour or two of fiddling with content tools and templates, I threw in the towel and decided to just use Pages.
Yes, Pages. Seriously.
I even specifically upgraded to the latest iWork '13 version, which turned out to be even less capable than its predecessor.
What started as a command-line driven process became 40 hours of getting to know this WYSIWYG editor. To its credit, WYSIWYG can actually be a really nice way to design content, as it allows for copy-editing decisions to be made in a tight loop with its implications on layout. This was especially useful when it came to placing Conor Heelan's delightful animal illustrations.
Using Pages, I was able to generate the PDF that is available online, as well as the source document for the physical book. Even now, I'm still at a loss for what would have been a better solution.
Of all of the options for selling and distributing online goods, Gumroad is the best. In just a few minutes, I was able to put together an attractive listing, with options for pre-sale and physical book add-ons.
Gumroad's dashboard analytics and tools provide an attractive view of sales, which was exciting to watch in real-time when I first hit publish. The small cut they take on each sale to host and handle payment (including international and state sales tax) was well worth it. I'll definitely be working with Gumroad again for my next project.
The good news: it's never been easier to self-publish a book.
The bad news: parts of it are still a pain in the ass.
Here's how I did it:
- Create an account with CreateSpace. As I understand it, Amazon effectively cornered the market of Print on Demand by acquiring this company and buying all of the book printers it could find.
- Create a new title. In this case, it was a trade paperback book (6" × 9").
- Purchase ISBNs from Bowker. Since a unique ISBN is required for each retail distribution—including one for each digital format (PDF, epub, Kindle Mobi, iBooks)—I bought a 10 pack. (Don't bother buying a barcode, those can be easily generated for free elsewhere)
- Create the cover and internal content. CreateSpace has some pretty decent tools for proofing content. They were able to find issues with margin and bleed before sending out for a physical proof.
- Behold your book, now available for sale on Amazon. It's an incredible feeling, holding something you've created in your hands. This alone made everything worth it. CreateSpace offers impressive wholesale price for a physical book (between $10–15 for printing a book and shipping domestically or internationally)
Here's where I messed up:
Because I did a pre-order for physical books through Gumroad, it was up to me to translate those into wholesale orders from CreateSpace. Unfortunately, CreateSpace had no mechanism for bulk ordering online, and their support staff were unable to process that themselves. Their recommendation: go through the checkout process manually for each of the 1000+ orders.
Yikes.
Fortunately, this was the one part of the book writing process I was able to automate. Using Mechanize, I was able to write a Ruby script to go through each order, one-by-one, and manually create an order for each. Because the user input wasn't 100% correctly formatted, I had to keep watch over the script as it ran, ready to fix any errors as they came up. The process took the better part of two days. I'll try to get that cleaned up and packaged into a proper Ruby library soon.
Some other fun facts:
- I ran into the outgoing SMTP limit for my Gmail account, forcing me to create and send from several email aliases.
- I used Numbers.app to clean up the
.csv
file provided by Gumroad, but because of its delightful insistence on automatically formatting postal codes as numbers, anything with a leading zero got screwed up. NSHipsters in Massachusetts: I love you, but you were the bane of my existence for an afternoon. - For a while, each error would silently create an order sent to my house. That was the first time a bug has so directly translated into a monetary cost for me. For fun, I added an
afplay cha-ching.aiff
after each order from that moment on. - At some point, the script started to fail silently because an order to the Ukraine triggered a fraud warning for my American Express card. Thanks to their amazing customer support, I was able to get everything running smoothly within 5 minutes.
So why did I write the book, anyway? There are 3 primary reasons:
- To Craft a Structured Narrative: NSHipster.com has built up its archive week-by-week, and is likewise organized by its particular chronology. And though articles are organized by topic in a long footer, it can be difficult for new readers to know where to start. A book allows for a linear narrative structure in a way that a blog simply cannot. A great deal of care was put into structuring the content in the book according to a logical progression, such that one could read from start to finish. There are also a number of articles that are exclusive to the book, dealing primarily with the cultural and emotional aspects of coding.
- To Provide Something Tangible: It's been amazing to see how much readers have related to NSHipster. A tangible object like a book offers a tangible something that you can be proud of and cherish. It also creates a tangible means of supporting the site, in the same way that one might for a favorite public radio station, podcast, or website.
- To Change My Life: Last week, on New Year's Eve, I married the most amazing person I've ever met. Thanks to your generous support, she and I are able to start our lives together comfortably, with something set aside for a house downpayment in the future (as well as a lovely honeymoon in Hawaii; I get back later this week). I can't begin to express my gratitude for all of the blessings I've had in my work. Thank you.