The JavaScript blog.


news blogs

Migrating DailyJS to Ghost

Posted on .

I've been running DailyJS since 2009 using Jekyll, but for the last few years it's made writing more difficult in many ways. The main issue I had was the time it takes to generate the site--it was at about 15 minutes on my VPS, which meant any correction took an inordinate amount of effort.

Running a static site was great for server efficiency, but not friendly for writing. Using a CMS-style blog engine definitely makes writing and supporting contributors easier, so I decided to switch.

The blog engine I've ended up using is Ghost, which is written with Node. I've hosted it within an Express app so I can set up redirections for old URLs--Ghost doesn't have an in-built redirection system. Because you can run Ghost as a standard npm module, I came up with this short program:

var ghost = require('ghost');  
var express = require('express');  
var app = express();  
var redirects = require('./redirects.json');

redirects.forEach(function(redirect) {  
  var newUrl = redirect[1];
  if (!newUrl.match(/^http/)) {
    newUrl = 'http://dailyjs.com' + newUrl;
  console.log('Redirecting %s to %s', redirect[0], newUrl);
  app.get(redirect[0], function(req, res) {

ghost({ config: __dirname + '/ghost-config.js' }).then(function(ghostServer) {  

I have JSON file that's just an array of URLs (redirects.json), and it uses this file to set up an Express route handler for each redirection.

The theme I've used is the Astro Responsive Theme which is commercial--I paid $19 which included a $2 charge for using PayPal. I customised the theme so it includes the advertising I use to fund DailyJS. The sidebar where I want to show the ads is hidden on smaller screens, which would probably cut a huge amount of revenue, so I had to write some client-side JavaScript to detect this and move the ads. This may need to be improved upon later!

Other things that still need fixing includes links to tags: Ghost has proper support for tags, so we no longer need my hacked Jekyll tags.html#tagname file. I need to somehow remap all of these links to /tag/tagname.

The thing that everyone likes about Ghost is the admin area--the editor is very friendly, and it supports pages, top-level navigation, and data import/export.

I actually used the data import feature to import my old posts. I wrote a Node program that pulls in Jekyll posts, strips the YAML frontmatter, converts it to Ghost JSON, and then maps all the relationships for tags and authors. This took quite a long time because I had to also convert older Textile posts to Markdown. I used Pandoc for that, which is awesome, except it forces Textile to use smartquotes, which means all of my code examples got messed up. I had to build a version of Pandoc that turned smartquotes off just for this purpose.

The JSON for the old site ended up being 5 MB, which I wasn't able to import into Ghost when it ran on Heroku. To get around this, I tried connecting Ghost running locally to Heroku's database, but it wouldn't work that way either. It kept timing out without a clear error. As a last resort, I ran Ghost connected to a local PostgreSQL database, then restored Heroku's database from an export of the local database.

In the end migrating DailyJS to Ghost was lots of work, and there are still more issues to iron out. I really hope readers prefer the new site, I think the design is cleaner and the tags are definitely better. If you see anything you think is wrong, you can try contacting us through contact.dailyjs.com or just hassle me with my Twitter account (@alex_young).



Writing for DailyJS

Posted on .

Every day we receive many submissions for Node modules, jQuery plugins, and weird and wonderful JavaScript projects. However, we're also interested in your articles about JavaScript. They can be tutorials for projects you've created, or tutorials on well-known projects like AngularJS, Backbone.js, Express, and so on.

Articles don't need to be long -- three to five paragraphs is more than enough given how often we post. You can cross-post from your own blogs. We pay for original articles, and will negotiate a fee: as a guide we've paid $25 for short articles in the past.

If you'd like to write for us, send article ideas to contact.dailyjs.com.


community news

DailyJS is Looking for Writers

Posted on .

Over the last three years I've written over 700 articles for DailyJS. I've written through national holidays, trips to Europe and Asia, and I've enjoyed every minute of it! The time has come, however, to look for more writers. In September I'm going to become a father, and naturally family obligations will take priority for a few weeks.

Rather than leave readers without their daily dose of JavaScript news and tutorials, I'm looking for writers to contribute to the site. If you're an open source developer and would like to promote your latest Node module or client-side library by writing a tutorial: this is your chance! I'm also interested in hearing from developers of commercial services that are relevant to JavaScript developers.

Before writing anything, fill out this form to get in touch. I'll let you know if your suggestion is appropriate for the site.

Writing Guide

  • Articles do not need to be long -- three to five paragraphs is great, otherwise consider writing a series of articles
  • Markdown is fine, although we use weird tags for code samples -- here is an example post
  • British or American English is acceptable
  • DailyJS reserves the right to edit your article before publishing it


Articles will be paid for at a base rate of $25. Payment terms are negotiable, and may be subject to exchange rate conversion.

Submit your article idea here.


libraries jquery news

jQuery 1.4 Released

Posted on .

Last week, version 1.4 of the popular jQuery
library was released. The new version includes some big performance
gains, alongside other cool stuff like:

* The ability to use .attr -style setter functions for all setters.

* Rails-style nested-parameter serialization for Ajax calls.

* Quick Element Construction: You can now pass in an object to add attributes and events at element-creation time:

jQuery("", {
    id: "foo",
    css: {
        height: "50px",
        width: "50px",
        color: "blue",
        backgroundColor: "#ccc"
    click: function() {
       $(this).css("backgroundColor", "red"); 

* Per-property Easing: You can now specify easing for individual properties of an

* The new jQuery.proxy() method allows you to bind this inside an event-handler to a
specific object.

* You can now bind many events to an element by passing an object containing those events:

  click: function(){
  mouseenter: function(){
  mouseleave: function(){
  • All events can now be .live events.
  • Some new DOM-traversal, manipulation and utility functions have been introduced.

The 14 Days of jQuery website, created to
celebrate the new release, covers what's
in more detail.