grunt-jekyll is a Grunt plugin that provides seamless integration between Grunt build workflows and Jekyll static site generation. It enables developers to compile Jekyll sites, start development servers, run site validation, and watch for file changes, all with comprehensive configuration options that map to Jekyll's native command-line interface.
npm install grunt-jekyll --save-dev// Load the plugin in your Gruntfile
grunt.loadNpmTasks('grunt-jekyll');For programmatic use:
// CommonJS require
const gruntJekyll = require('grunt-jekyll');
// Load into Grunt instance
gruntJekyll(grunt);// Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
options: {
bundleExec: true,
src: 'src'
},
dist: {
options: {
dest: 'dist',
config: '_config.yml,_config.build.yml'
}
},
serve: {
options: {
serve: true,
dest: '.jekyll',
drafts: true,
future: true,
port: 4000,
host: 'localhost'
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('build', ['jekyll:dist']);
grunt.registerTask('dev', ['jekyll:serve']);
};grunt-jekyll follows the standard Grunt multi-task pattern:
The main plugin function that registers the 'jekyll' multi-task with Grunt.
/**
* Main module export function that registers the 'jekyll' multi-task with Grunt
* @param grunt - The Grunt instance
*/
module.exports = function(grunt: any): void;The core Grunt task that executes Jekyll commands based on configuration.
grunt.registerMultiTask('jekyll', 'This triggers the `jekyll` command.', function() {
// Task implementation
});Command-line interface for running grunt-jekyll tasks directly.
// bin/grunt-jekyll
require('grunt').npmTasks('grunt-jekyll').cli();Type: boolean
Default: false
Build the site and start a Jekyll development server. When true, runs jekyll serve (or jekyll server for Jekyll < 1.0, automatically detected). When false, runs jekyll build.
jekyll: {
serve: {
options: {
serve: true,
port: 4000,
host: 'localhost'
}
}
}Type: boolean
Default: false
Test your site for common errors and deprecated code. Runs jekyll doctor. Ignores all other options except src, config, and bundleExec.
jekyll: {
doctor: {
options: {
doctor: true,
src: 'src',
config: '_config.yml'
}
}
}Type: string
Default: .
Jekyll Flag: --source
Directory where Jekyll will read files.
Type: string
Default: ./_site
Jekyll Flag: --destination
Directory where Jekyll will write files.
Type: boolean
Default: false
Jekyll Flag: --safe
Disables custom plugins and ignores symbolic links.
Type: string
Default: ./_plugins
Jekyll Flag: --plugins
Specify a plugins directory.
Type: string
Default: ./_layouts
Jekyll Flag: --layouts
Specify a layouts directory.
Type: boolean
Jekyll Flag: --profile
Generate profiling information.
Type: boolean
Jekyll Flag: --trace
Show the full backtrace when an error occurs.
Type: string
Default: _config.yml
Jekyll Flag: --config
Specify a custom configuration file. Multiple files separated by a comma will cascade right to left.
Type: boolean
Default: false
Jekyll Flag: --drafts
Process and render draft posts.
Type: boolean
Default: false
Jekyll Flag: --future
Publishes posts with a future date.
Type: boolean
Default: false
Jekyll Flag: --lsi
Produce an index for related posts.
Type: number
Jekyll Flag: --limit_posts
Limit the number of posts to parse and publish.
Type: boolean
Jekyll Flag: --force_polling
Force watch to use polling.
Type: boolean
Jekyll Flag: --verbose
Print verbose output.
Type: boolean
Jekyll Flag: --quiet
Silence the normal output from Jekyll during a build.
Type: boolean
Default: false
Jekyll Flag: --watch
Regenerate the site when files are modified. If you are running multiple watch tasks in a project you should use grunt-contrib-watch instead.
Type: boolean
Jekyll Flag: --no-watch
Disable auto-regeneration.
Type: string or number
Jekyll Flag: --port
Listen on the given port (requires serve).
Type: string
Jekyll Flag: --host
Listen at the given hostname (requires serve).
Type: string
Jekyll Flag: --baseurl
Serve the website from the given base URL (requires serve).
Type: boolean
Jekyll Flag: --skip-initial-build
Skips the initial site build which occurs before the server is started.
Type: boolean
Jekyll Flag: --open-url
Opens the local URL in your default browser.
Type: boolean
Jekyll Flag: --incremental
Enable the experimental incremental build feature. Incremental build only re-builds posts and pages that have changed, resulting in significant performance improvements for large sites, but may also break site generation in certain cases.
Type: boolean
Jekyll Flag: --livereload
LiveReload refreshes your browser after a change.
Type: string
Create a temporary _config.yml with the contents of raw. This config file has greater precedence than the files in config.
jekyll: {
dist: {
options: {
config: '_config.yml',
raw: 'pygments: false\n' +
'exclude: [\'development\']\n' +
'author:\n' +
' name: John Doe\n' +
' email: john@example.com'
}
}
}Type: boolean
Default: false
Run jekyll with bundle exec.
jekyll: {
options: {
bundleExec: true,
src: 'src'
},
dist: {
options: {
dest: 'dist'
}
}
}Type: boolean
Jekyll Flag: --watch
Auto-regenerate site when files change. Use watch option instead.
Type: string or number
Jekyll Flag: --port
Legacy alias for port option.
The following options are deprecated and will show warnings when used:
paginate - Configure in Jekyll's _config.yml insteadpermalink - Configure in Jekyll's _config.yml insteadmarkdown - Configure in Jekyll's _config.yml insteadurl - Configure in Jekyll's _config.yml instead/**
* Grunt task configuration object
*/
interface GruntTaskConfig {
options?: JekyllOptions;
[target: string]: JekyllOptions | undefined;
}
/**
* Jekyll configuration options
*/
interface JekyllOptions {
// Subcommands
serve?: boolean;
doctor?: boolean;
// Global options
src?: string;
dest?: string;
safe?: boolean;
plugins?: string;
layouts?: string;
profile?: boolean;
trace?: boolean;
// Build options
config?: string;
drafts?: boolean;
future?: boolean;
lsi?: boolean;
limit_posts?: number;
force_polling?: boolean;
verbose?: boolean;
quiet?: boolean;
// Serve options
watch?: boolean;
no_watch?: boolean;
port?: string | number;
host?: string;
baseurl?: string;
skip_initial_build?: boolean;
open_url?: boolean;
incremental?: boolean;
livereload?: boolean;
// Plugin-specific options
raw?: string;
bundleExec?: boolean;
// Legacy options
auto?: boolean;
server_port?: string | number;
// Deprecated options (will show warnings)
paginate?: boolean;
permalink?: boolean;
markdown?: boolean;
url?: boolean;
}module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
dist: {
options: {
dest: 'dist',
config: '_config.yml'
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('build', ['jekyll:dist']);
};module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
serve: {
options: {
serve: true,
drafts: true,
future: true,
port: 4000,
livereload: true
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('dev', ['jekyll:serve']);
};module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
doctor: {
options: {
doctor: true,
src: 'src',
config: '_config.yml'
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('validate', ['jekyll:doctor']);
};module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
options: {
bundleExec: true,
src: 'src'
},
dist: {
options: {
dest: 'dist',
config: '_config.yml,_config.build.yml'
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('build', ['jekyll:dist']);
};module.exports = function(grunt) {
grunt.initConfig({
jekyll: {
dist: {
options: {
config: '_config.yml',
raw: 'exclude: [\'development\', \'node_modules\']\n' +
'highlighter: rouge\n' +
'author:\n' +
' name: ' + grunt.option('author-name') + '\n' +
' email: ' + grunt.option('author-email')
}
}
}
});
grunt.loadNpmTasks('grunt-jekyll');
grunt.registerTask('build', ['jekyll:dist']);
};The plugin provides comprehensive error handling:
Common error scenarios and solutions:
// Error: Jekyll not found
// Solution: Install Jekyll via `gem install jekyll` or use bundleExec: true
// Error: Invalid configuration
// Solution: Check _config.yml syntax and file paths
// Error: Port already in use
// Solution: Specify different port or kill existing Jekyll process
jekyll: {
serve: {
options: {
serve: true,
port: 4001 // Use different port
}
}
}