   # First-run initialization
   postMask = ///^(\d{4})-(\d{2})-(\d{2})-(.+)\.(#{config.markdown_ext.join '|'}|html)$///
   time.tzset config.timezone
-  async.parallel [
-    # Check directories for existence
-    (cb) -> checkDirectories config, cb
-    # Built-in enfield plugins
-    loadBundledPlugins
-  ], (err) -> refreshContent config, (err) ->
-    if err
-      return callback err
-
-    log.info "generate", "Generated %s -> %s", config.source, config.destination
-    callback()
-    return unless config.watch
-
-    destinationPath = path.resolve config.destination
-    gaze path.join(config.source, '**/*'), {debounceDelay: 500}, (err, watcher) ->
-      log.info "watch", "Watching %s for changes", config.source
-      watcher.on 'all', (event, filepath) ->
-        # Ignore any path within the destination directory
-        return if helpers.isWithinDirectory filepath, destinationPath
-
-        # Ignore any path within hidden/ignored directories
-
-        # TODO: Special case _config.yml
-        # TODO: Reload plugins
-
-        log.info "watch", "%s %s", event, filepath
-        refreshContent config, ->
-          log.info "watch", "Regenerated"
+  Q.all([checkDirectories(config), loadBundledPlugins()])
+    .then ->
+      Q.nfcall refreshContent, config
+    .then ->
+      log.info "generate", "Generated %s -> %s", config.source, config.destination
+      callback()
+      return unless config.watch
+
+      destinationPath = path.resolve config.destination
+      gaze path.join(config.source, '**/*'), {debounceDelay: 500}, (err, watcher) ->
+        log.info "watch", "Watching %s for changes", config.source
+        watcher.on 'all', (event, filepath) ->
+          # Ignore any path within the destination directory
+          return if helpers.isWithinDirectory filepath, destinationPath
+
+          # Ignore any path within hidden/ignored directories
+
+          # TODO: Special case _config.yml
+          # TODO: Reload plugins
+
+          log.info "watch", "%s %s", event, filepath
+          refreshContent config, ->
+            log.info "watch", "Regenerated"
+    .fail (err) ->
+      callback err
 
 refreshContent = (config, callback) ->
+  log.silly "generate", "Refreshing content"
+
   # Get content in parallel:
-  async.parallel [
-    # Mimic Jekyll behavior by clearing out destination first
-    (cb) -> fs.remove config.destination, cb
-    (cb) -> loadSitePlugins config, cb
-    (cb) -> loadIncludes config, cb
-    (cb) -> loadLayouts config, cb
-    (cb) -> loadContents config, cb
-  ], (err, [_, plugins, includes, layouts, { posts, pages, files }]) ->
-    if err then return callback err
-    log.verbose "generate", "Initial content load complete"
-    processResults {config, plugins, includes, layouts, posts, pages, files}, callback
+  Q.all([
+    # Mimic Jekyll behavior by clearing out destination before regeneration
+    Q.nfcall fs.remove, config.destination
+    loadSitePlugins(config)
+    Q.nfcall loadIncludes, config
+    Q.nfcall loadLayouts, config
+    Q.nfcall loadContents, config
+  ])
+    .then ([_, plugins, includes, layouts, { posts, pages, files }]) ->
+      log.verbose "generate", "Initial content load complete"
+      processResults {config, plugins, includes, layouts, posts, pages, files}, callback
+    .fail (err) -> callback err
 
 processResults = ({config, plugins, includes, layouts, posts, pages, files}, callback) ->
   # Create site data structure


  { posts, others }

checkDirectories = (config, callback) ->
  # Check if source & destination directories are there
  async.series [
    (cb) -> fs.exists config.source, (exists) ->
      if exists then cb()
      else cb new Error "Source directory does not exist: #{config.source}"
    (cb) -> fs.exists config.destination, (exists) ->
      if exists
        fs.stat config.destination, (err, stat) ->
          if stat.isDirectory()
            cb()
          else
            cb new Error "Destination is not a directory: #{config.destination}"
      else
        fs.mkdirs config.destination, cb
  ], callback

loadBundledPlugins = (callback) ->
  loadPlugins([path.join __dirname, 'plugins'])
    .then (plugins) ->
      bundledPlugins = plugins

        allFiles.map(path.basename), dirs

      for file in allFiles
        loadFileIntoPlugins file, plugins

      plugins

loadFileIntoPlugins = (file, plugins) ->
  log.verbose "generate", "Loading plugin: %s", file
  plugin = require file

  if 'filters' of plugin
    for key, filter of plugin['filters']
      log.silly "generate", "Found filter for %s", key
      plugins.filters[key] = filter
  if 'tags' of plugin
    for key, tag of plugin['tags']
      log.silly "generate", "Found tag for %s", key
      plugins.tags[key] = tag
  if 'converters' of plugin
    for key, converter of plugin['converters']
      log.silly "generate", "Found converter for %s", key
      plugins.converters.push converter
  if 'generators' of plugin
    for key, generator of plugin['generators']
      log.silly "generate", "Found generator for %s", key
      plugins.generators.push generator
