The client has no requirement for adding dynamic content themselves and no blog: therefore I don't need anything like Pelican (Python) or Jeckyll (js) to build indexes of tags; categories; or authors.

Of course, if there's no requirement for a blog, there's certainly no requirement for a CMS (Content Management System) or its underlying content database.

So I can enjoy this workflow:

edit
edit the markup (html) and style files in Sublime Text;
html completions
use the Emmett plugin for html completions in Sublime Text;
html templates
nunjucks templates to minimise common markup between the few pages of the static website. nunjucks is very much like jinja, so is familiar froDjango and Pelican projects;
css extension language
use sass (actually scss files) for my pre-compied style sheets;
automated workflow
watch source directories (html templates and scss) for changes to trigger automatic recreation of the app's - the website's - runtime markup (html) and style (css) files.
browser reload
use browser-sync to reload the browser anytime application source files are changed

Version 1

For the time-being I shan't add a JavaScript task to the automated workflow as, for this client, the only js is for the mobile menu and will not change very often, if at all, during develpment.

Here's the gulpfile.js :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var gulp            = require('gulp');
var nunjucksRender  = require('gulp-nunjucks-render');
var sass            = require('gulp-sass');
var sourcemaps      = require('gulp-sourcemaps');
var browserSync     = require('browser-sync').create();
var reload          = browserSync.reload;

// Static Server + watching scss/html files
gulp.task('serve', ['sass'], function() {

    browserSync.init({
        server: "./app"
    });

    gulp.watch("templates/*.html", ['nunjucks']);
    gulp.watch("scss/*.scss", ['sass']);
    gulp.watch("app/*.html").on('change', reload);
});

gulp.task('nunjucks', function () {
    nunjucksRender.nunjucks.configure(['templates/']);
    return gulp.src('templates/*.html')
        .pipe(nunjucksRender())
        .pipe(gulp.dest('app'))
        .pipe(reload({stream: true}));
});

// Compile sass into CSS & auto-inject into browsers
gulp.task('sass', function() {
    return gulp.src("scss/*.scss")
        .pipe(sourcemaps.init())
        .pipe(sass({
            errLogToConsole: true
        }))
        .pipe(sourcemaps.write("app/maps"))
        .pipe(gulp.dest("app/css"))
        .pipe(reload({stream: true}));
});

gulp.task('default', ['serve']);

Version 2

I have found this in past projects also: there's something not quite right with the workflow so, before long you have to try a different module and / or add more tasks and pipes.

What happened here was that:

  1. I was getting a Nunjucks error that was throwing the nunjucks task without reporting any meaningful errors so I needed to add an error handler.

    As soon as I had added the error handler I could see the source of the error: merely a missing {% endblock %}

  2. At the same time I changed from gulp-nunjucks-render to gulp-nunjucks-html partly because I could understand the documentation better and could see how to supply local variables.

  3. In the meantime I needed to find a location for the base.html from which other templates are extended, because I didn't want the base template base.html rendered into the app.

    Prepending the path of a separate base template directory did not suit the Nunjucks preprocessor: it couldn't find the base template there.

    I came across a solution for excluding files from the nunjuck task source.

  4. I added the nunjucks task as a dependency of the default task serve .

I've highlighted the changed parts of gulpfile.js in the listing below.

This is my directory structure at this point:

├── README.rst
├── app
│   ├── contact.html
│   ├── css
│   ├── images
│   ├── index.html
│   ├── js
│   ├── submit.php
│   └── thankyou.html
├── gulpfile.js
├── node_modules
│   ├── browser-sync
│   ├── gulp
│   ├── gulp-data
│   ├── gulp-nunjucks-html
│   ├── gulp-sass
│   └── gulp-sourcemaps
├── package.json
├── scss
│   ├── basic.scss
│   ├── layout.scss
│   └── responsive.scss
└── templates
    ├── base.html
    ├── contact.html
    ├── index.html
    └── thankyou.html

And here is the new (Version 2) gulpfile.js :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var gulp            = require('gulp');
var nunjucks        = require('gulp-nunjucks-html');
var data            = require('gulp-data');
var sass            = require('gulp-sass');
var sourcemaps      = require('gulp-sourcemaps');
var browserSync     = require('browser-sync').create();
var reload          = browserSync.reload;

function swallowError (error) {
    // details of the error in the console
    console.log(error.toString());
    this.emit('end');
}

// Static Server + watching scss/html files
gulp.task('serve', ['sass', 'nunjucks'], function() {

    browserSync.init({
        server: "./app"
    });

    gulp.watch("templates/*.html", ['nunjucks']);
    gulp.watch("scss/*.scss", ['sass']);
    gulp.watch("app/*.html").on('change', reload);
});

gulp.task('nunjucks', function() {
  return gulp.src(['templates/*.html', '!templates/base.html'])
    .pipe(nunjucks({
      locals: {
        username: 'James'
        },
        searchPaths: ['templates']
        }))
    .on('error', swallowError)
    .pipe(gulp.dest('app'));
});

// Compile sass into CSS & auto-inject into browsers
gulp.task('sass', function() {
    return gulp.src("scss/*.scss")
        .pipe(sourcemaps.init())
        .pipe(sass({
            errLogToConsole: true
        }))
        .pipe(sourcemaps.write("app/maps"))
        .pipe(gulp.dest("app/css"))
        .pipe(reload({stream: true}));
});

gulp.task('default', ['serve']);

Yes, while this is working for me right now, there will almost certainly be a version 3 in the near fulture. If you have the RSS / Atom feed for this blog, you'll hear about it.

Well no .... actually the gulpfile.js : actually hasn't changed as of now: the site's on the staging server awaiting review by the client.