         allFiles.map(path.basename), dirs
 
       for file in allFiles
-        log.verbose "generate", "Loading plugin: %s", file
-        # Load 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
+        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

      for key, filter of tinyliquid.filters
        unless key of bundledPlugins.filters
          bundledPlugins.filters[key] = filter
      callback()
    .fail (err) ->
      callback err

loadSitePlugins = (config, callback) ->
  # Resolve directories relative to source
  dirs = config.plugins.map (dir) ->
    path.resolve config.source, dir
  async.filter dirs, fs.exists, (results) ->
    loadPlugins(results)
      .then (plugins) ->
        callback null, plugins
      .fail (err) -> callback err

loadPlugins = (dirs) ->
  log.verbose "generate", "Looking for plugins in: %s", dirs.join ', '

  # First-run initialization
  postMask = ///^(\d{4})-(\d{2})-(\d{2})-(.+)\.(#{config.markdown_ext.join '|'}|html)$///
  time.tzset config.timezone
  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:
  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
