A template repo for building locally-compiled static sites using Gulp, Pug, Sass, and Webpack.
There's a number of quality-of-life customizations built into the Gulp processes in this template repo using bespoke node packages.
- If you haven't already, use nvm to install node and npm
- If you haven't already, globally install the gulp command line tools:
npm install --global gulp-cli
- Clone this repo
- In the project folder, install the node package dependencies:
npm install
Run the default Gulp task (gulp
or gulp default
) in the project root to compile all files, watch for future changes, and start up Browsersync. See the /gulpfile.js
file for the more granular compilation and watch tasks you can run.
Compiled files (for the most part) end up in the /docs/
directory, which is helpful if the site is to be hosted on GitHub Pages.
The component-indexer
module makes the /src/pug/mixins/_index.pug
file automatically update to include include
references to all the other Pug files in that /src/pug/mixins/
directory when Gulp is running. Including that /src/pug/mixins/_index.pug
file elsewhere will in turn make all mixins available within that scope.
Instead of compiling to HTML files like /about.html
and /about-our-team.html
that exist in the root directory and have to have a file extension in the URL, the gulp-url-builder
package makes it possible to easily compile as index files in (optionally nested) directories based on a Pug file naming convention. So those previously mentioned pages can instead exist at /about/
and /about/our-team/
.
The Pug files in the /src/pug/views/
directory are what get compiled into HTML pages. Name files with hyphens delimiting words. If the file should exist in a directory path, prepend the necessary directory names to the Pug file name, delimiting each with underscores.
All hypothetical pug files below exist in the /src/pug/views/
directory.
pug filename | compiles to | accessible at |
---|---|---|
index.pug |
/docs/index.html |
/ |
about.pug |
/docs/about/index.html |
/about/ |
about_our-team.pug |
/docs/about/our-team/index.html |
/about/our-team/ |
The /src/pug/templates/_root.pug
file has a head
block inside the <head>
element. The contents and attributes of the <title>
element, OpenGraph meta tags, and canonical link all rely on variables passed up from the Pug view file extending that template. See /src/pug/views/index.pug
for an example of how to extend the root template with the necessary variables.
The component-indexer
module makes the _index.pug
file in the /mixins/
, /partials/
, and /views/
directories automatically update to include import
references to all other Sass files in those directories. This makes importing everything into the main styles.scss
file easier.
Note that partials are imported in alphabetical order, which could cause cascade issues if you aren't careful. The auto-indexing of any directory can be turned off if needed.
Normalize is automatically included as a vendor stylesheet.
The Tachyons utility class library is automatically included as a vendor stylesheet. All of the classes have been transformed into placeholder selectors which means the classes can't be used directly in HTML. Instead they must be extended using the @extend
at-rule within other selectors. Because the library has been transformed into placeholder selectors, any unused utility classes will automatically be ignored when Sass compiles.
The gulp-sass-extend-shorthand module provides a shorthand for extending classes and placeholder selectors in Sass. This makes it much quicker to frequently extend a utility class library that has been transformed into placeholder selectors.
In order for a file to be processed by this package, it must be prefixed with %
. These files are processed by the Sass Gulp tasks first, and are then output as regular Sass files with the expanded syntax and the same filename (with the %
replaced with a _
). These new files can be imported into other Sass files as needed.
Additionally see /src/scss/partials/%hello-world.scss
for an example of how to use this syntax while referencing Tachyons utilities.
// shorthand
.myClass {
.myMixin;
}
// is expanded to
.myClass {
@extend .myMixin;
}
// shorthand
.myClass {
%myPlaceholderSelector;
}
// is expanded to
.myClass {
@extend %myPlaceholderSelector;
}
// shorthand
.myClass {
.mixinA, .mixinB, .mixinC;
}
// is expanded to
.myClass {
@extend .mixinA;
@extend .mixinB;
@extend .mixinC;
}
// shorthand
.myClass {
.mixinA,
.mixinB,
.mixinC;
}
// is expanded to
.myClass {
@extend .mixinA;
@extend .mixinB;
@extend .mixinC;
}
// shorthand
.myClass {
.mixinA, .mixinB !optional;
.mixinC;
}
// is expanded to
.myClass {
@extend .mixinA !optional;
@extend .mixinB !optional;
@extend .mixinC;
}
JSON-LD is a format for providing linked data in JSON format—commonly used to add Schema.org structured data to webpages via inclusion within a <script>
element in the document <head>
.
JSON-LD can take awhile to write, so this template provides a way to author JSON-LD using Pug syntax.
Files with the .json.pug
compound extension within the /src/json/
directory are processed by Gulp and then output as two true JSON files within the same directory—one minified, one formatted. This Gulp task is run before the Pug tasks, so Pug files can include
the minified JSON within script
elements to add the structured data to each page.
XML is used as an intermediary between Pug and JSON, and as such, each .json.pug
must explicitly provide an XML doctype.
The JSON-LD markup must be wrapped in root
and entity
elements because of how the intermediary process works. See /src/json/index.json.pug
for an example.
Pug elements become JSON property names, and the text content of those elements become the values of those properties.
foo bar
becomes
{
"foo": "bar"
}
Nested Pug elements become nested objects.
lorem
foo bar
consecutor
amit nunc
becomes
{
"lorem": {
"foo": "bar",
"consecutor": {
"amit": "nunc"
}
}
}
Duplicate pug elements are combined into arrays.
palette
id 1
colors red
colors green
colors blue
becomes
{
"palette": {
"id": "1",
"colors": [
"red",
"green",
"blue"
]
}
}
JSON-LD syntax tokens—property names that start with @
, such as @context
—must be written in a special format because XML is used as an intermediary and @
is invalid in XML element names. Instead, syntax tokens need to be prefixed with at-
. So instead of writing @context
, write at-context
.
at-context http://www.schema.org
at-type Person
name Jean-Luc Picard
jobTitle Captian
becomes
{
"@context": "http://www.schema.org",
"@type": "Person",
"name": "Jean-Luc Picard",
"jobTitle": "Captian"
}