I’ve been using Grunt for over 3 years now, almost all the way back since I started using CSS pre-processing. In the beginning I was using CodeKit, which is still an awesome tool. I prefer Grunt because I can code and commit my workflow into the repository of the project. There are some other technical benefits, but I encourage anyone starting out to buy a copy of CodeKit.

Most of my projects start out with some static HTML and some Sass and JavaScript that I need to write. This boilerplate Gruntfile.js is my starting point.

I have a bunch of prefixes that make keeping up with paths a lot quicker when going about editing and customizing the tasks.

I often use additional tasks, but these are the foundation of most of my work.

A lot of folks have been switching to Gulp lately. I hear one of the perks is speed. I found that once I broke up my watch task to watch Sass files and run Sass tasks then watch JavaScript files and run JavaScript tasks that things went a lot faster. Combine that with liveReload and I haven’t been motivated to switch … yet.

Notice the dev task. I use Connect to serve the root of the repository on port 9001 while using watch to compile when any changes happen. This is a great way to start coding right away on a real web server before I get into WordPress, Rails, Jekyll or whatever I’m building into.

module.exports = function(grunt) {
  'use strict';

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json')

  , coffeelint: {
      app: ['./assets/javascripts/**/*.coffee']
    }

  , coffee: {
      compile: {
        options: {
          sourceMap: true
        }
      , files: {
          './assets/javascripts/main.js': ['./assets/javascripts/_*.coffee']
        }
      }
    }

  , jshint: {
      dist: {
        src: [
          './Gruntfile.js'
        ]
      , options: {
          'strict':   true
        , 'node':     true
        , 'browser':  true
        , 'jquery':   true
        , 'onevar':   true
        , 'laxcomma': true
        , 'laxbreak': true
        , 'eqeqeq':   true
        , 'immed':    true
        , 'undef':    true
        , 'unused':   true
        , 'latedef':  true
        }
      }
    }

  , uglify: {
      dist: {
        files: {
          './assets/javascripts/modernizr.min.js': ['./assets/javascripts/modernizr.js']
        }
      , options: {
          sourceMap: true
        }
      }
    , lib: {
        files: {
          './assets/javascripts/lib.min.js': [
            './bower_components/jquery-hoverIntent/jquery.hoverIntent.js'
          , './bower_components/imagesloaded/imagesloaded.pkgd.js'
          , './bower_components/jquery-throttle-debounce/jquery.ba-throttle-debounce.js'
          , './bower_components/decently-smart-target/jquery.dst.js'
          ]
        }
      , options: {
          sourceMap: true
        , mangle: false
        }
      }
    }

  , sass: {
      dist: {
        files: {
          './assets/stylesheets/main.css': './assets/stylesheets/main.sass'
        }
      , options: {
          style: 'compressed'
        }
      }
    }

  , watch: {
      coffee: {
        files: [
          './assets/javascripts/*.coffee'
        ]
      , tasks: ['coffeelint', 'coffee']
      }
    , js: {
        files: [
          './Gruntfile.js'
        , './assets/javascripts/*.js'
        ]
      , tasks: ['jshint', 'uglify']
      }
    , sass: {
        files: [
          './assets/stylesheets/**.sass'
        , './assets/stylesheets/**.scss'
        ]
      , tasks: [
          'sass'
        ]
      }
    }

  , connect: {
      server: {
        options: {
          port: 9001
        , base: '.'
        , livereload: true
        }
      }
    }

  });

  [ 'grunt-coffeelint'
  , 'grunt-contrib-coffee'
  , 'grunt-contrib-jshint'
  , 'grunt-contrib-uglify'
  , 'grunt-contrib-sass'
  , 'grunt-contrib-watch'
  , 'grunt-contrib-connect'
  ].forEach(function (task) {
    grunt.loadNpmTasks(task);
  });

  grunt.registerTask('default', ['coffeelint', 'coffee', 'jshint', 'uglify', 'sass']);
  grunt.registerTask('dev', ['connect', 'watch']);
};

[4]: gist 8885736