 	error: (err) ->
 		logger.log 'err', "An error occured: #{err}\n", err  if err
 
+
+
+	# ---------------------------------
+	# Plugins
+
+	# Register a Plugin
+	# next(err)
+	registerPlugin: (plugin,next) ->
+		# Prepare
+		error = null
+
+		# Plugin Path
+		if typeof plugin is 'string'
+			try
+				pluginPath = plugin
+				plugin = require pluginPath
+				return @registerPlugin plugin, next
+			catch err
+				logger.log 'warn', 'Unable to load plugin', pluginPath
+				logger.log 'debug', err
+		
+		# Loaded Plugin
+		else if plugin and (plugin.name? or plugin::name?)
+			plugin = new plugin  if typeof plugin is 'function'
+			@PluginsObject[plugin.name] = plugin
+			@PluginsArray.push plugin
+			@PluginsArray.sort (a,b) -> a.priority < b.priority
+		
+		# Unknown Plugin Type
+		else
+			logger.log 'warn', 'Unknown plugin type', plugin
+		
+		# Forward
+		next error
+	
+
+	# Get a plugin by it's name
+	getPlugin: (pluginName) ->
+		@PluginsObject[pluginName]
+
+
+	# Trigger a plugin event
+	# next(err)
+	triggerEvent: (eventName,data,next) ->
+		# Async
+		tasks = new util.Group (err) ->
+			logger.log 'debug', "Plugins completed for #{eventName}"
+			next err
+		tasks.total = @PluginsArray.length
+
+		# Cycle
+		for plugin in @PluginsArray
+			data.docpad = @
+			data.logger = logger
+			data.util = util
+			plugin[eventName].apply plugin, [data,tasks.completer()]
+
+
+	# Load Plugins
+	loadPlugins: (pluginsPath, next) ->
+		unless pluginsPath
+			# Async
+			tasks = new util.Group (err) ->
+				logger.log 'debug', 'Plugins loaded'
+				next err
+			
+			tasks.push => @loadPlugins "#{__dirname}/plugins", tasks.completer()
+			if @rootPath isnt __dirname and path.existsSync "#{@rootPath}/plugins"
+				tasks.push => @loadPlugins "#{@rootPath}/plugins", tasks.completer()
+			
+			tasks.async()
+
+		else
+			util.scandir(
+				# Path
+				pluginsPath,
+
+				# File Action
+				(fileFullPath,fileRelativePath,nextFile) =>
+					@registerPlugin fileFullPath, nextFile
+				
+				# Dir Action
+				false,
+
+				# Next
+				(err) ->
+					logger.log 'debug', "Plugins loaded for #{pluginsPath}"
+					next err
+			)
+
+
+	# ---------------------------------
+	# Actions
+
 	# Clean the database
 	generateClean: (next) ->
 		# Prepare

	generating: false
	loading: true
	generateTimeout: null
	server: null
	port: 9778


		# Options
		@PluginsArray = []
		@PluginsObject = {}
		@port = port  if port
		@maxAge = maxAge  if maxAge
		@server = server  if server
		@rootPath = path.normalize(rootPath || process.cwd())
		@outPath = path.normalize(outPath || "#{@rootPath}/#{@outPath}")
		@srcPath = path.normalize(srcPath || "#{@rootPath}/#{@srcPath}")

		logger = new caterpillar.Logger
			transports:
				level: logLevel or @logLevel
				formatter:
					module: module
		
		@initSkeletons =>
			@skeletonsPath = path.normalize(skeletonsPath || @skeletonsPath)
			@skeletonPath = util.prefixPathSync(
				path.normalize(skeletonPath || @skeletonPath),
				@skeletonsPath
			)
			@loadPlugins null, =>
				logger.log 'info', 'Finished loading'
				@loading = false
	
	
	# Initialise the Skeletons
	initSkeletons: (next) ->
		child = exec 'git submodule init; git submodule update', {cwd: @corePath}, (err,stdout,stderr) =>
		child.on 'exit', (code,signal) ->
			next()

	# Clean Models
	cleanModels: (next) ->
