jus is a development server and build tool for making static websites with no configuration and no boilerplate code. It has built-in support for browserify, ES6 and ES2015 with Babel, React JSX, GitHub Flavored markdown, syntax highlighting, Sass, Less, Stylus, Myth, Handlebars, browsersync and more.
The year is 2016 and you're building a new website. At first you just create a single HTML file with some inline scripts and style tags. This works for a bit, but soon your code grows and you decide to extract the styles and scripts into standalone files. This is slightly better, but eventually you want to do something more sophisticated, like writing your stylesheets in Sass, or concatenating and minifying assets, or using npm dependencies with browserify. These conveniences are essential to building a website of any magnitude, but setting them up is tedious and time-consuming. It's at this point in the project that your attention turns from the creative to the mundane. Rather than building, you're now configuring.
In this day and age, most developers would turn to Gulp, npm scripts, Jekyll or one of dozens of static site tools. This is where jus comes in as an alternative.
There is no setup with jus. It has just two commands: serve
and build
. Run jus serve
in your project directory and you've got a live develpment server running, watching for file changes, autorefreshing your browser with browsersync, and serving your content with clean URLs. Write a foo.sass
file and it'll be served at /foo.css
. Use an npm-style require
statement in your script, and jus will serve it up as a browserified bundle. Write React's JSX syntax and it'll be transpiled to javascript on the fly. Write a GitHub-flavored /markdown/file.md
and it'll be served as syntax-highlighted HTML at /markdown/file
.
When it's time to deploy, run jus build
to compile your site down into plain old HTML, CSS, and Javascript files, ready for deployment to GitHub Pages, Surge, or any other static site host that supports clean URLs.
jus requires node 4 or greater, because it uses some newer Javascript features. Install the command-line interface globally, then run it to see usage instructions:
npm i -g jus && jus
jus has a lot of dependencies, so it takes a while to install. Maybe go grab a :coffee: and read up on how to make npm faster.
If you like to learn by example, check out the repos of sites using jus. Otherwise, read on...
Pages are written in Markdown, HTML, Handlebars, or any combination thereof. At render time each page is passed a Handlebars context object containing metadata about all the files in the directory.
H1
, H2
, etc) are automatically converted to anchored hyperlinks.Extensions: html|hbs|handlebars|markdown|md
All javascript files in your project are automatically browserified and babelified using the es2015
and react
presets.
You can use node-style require
statements to include node and npm modules in your code:
const url = require('url').parse('https://example.com')
console.log(`the domain is ${url.host}`)
You can also use ES6-style imports, if you prefer:
import React from 'react'
import ReactDOM from 'react-dom'
import domready from 'domready'
domready(() => {
// do some React magic
})
Scripts are browserified using babel-preset-react
, so you
can write JSX in your scripts.
Extensions: js|jsx|es|es6
Stylesheets can be written in Sass, SCSS, Less, Stylus, Myth, or plain old CSS. Use whatever preprocessor suits your fancy.
Extensions: css|less|sass|scss|styl
When the jus server is initialized, it recursively finds all the files in the directory tree,
ignoring node_modules
, .git
, and other unwanted patterns. These files are then stored in
memory in an array called files
. For convenience, this list of files is broken down
into smaller arrays by type: an array for pages
, another array for scripts
, etc.
{
files: [...],
pages: [...]
scripts: [...]
stylesheets: [...]
images: [...]
datafiles: [...]
}
When you request a page, the server renders the page on the fly, passing this object to the given page's template. This means every page has access to metadata about every file in the site at render time.
Using handlebars in your pages is entirely optional. If your pages don't need to do any dynamic rendering at build time, that's okay. The context will simply be ignored at render time.
jus supports HTML frontmatter. This allows you to add key-value metadata to your pages:
<!--
title: Alice in Wonderland
year: 1951
-->
Any such values present in an HTML comment at the top of a page are made available in that page's Handlebars context object at render time.
Note: Jekyll uses YAML for frontmatter, but jus uses HTML, because it can be included in a file without adversely affecting the way it renders on github.com.
Handlebars templates can be used to wrap layouts around your pages.
/layout.(html|hbs|handlebars|markdown|md)
is present, it will be applied to all pages by default.{{{body}}}
string, to be used as a placeholder for where the main content should be rendered.layout
in their filename.layout: foo
will refer to the /layout-foo.(html|hbs|handlebars|markdown|md)
layout file.layout: false
in their frontmatter.Extensions: html|hbs|handlebars|markdown|md|mdown
jus provides a number of helper functions you can use in your handlebars templates. All of the helpers are from lobars, a collection of utility functions plucked directly from lodash.
lobars includes comparison helpers like endsWith, eq, gt, gte, includes, isArray, isBoolean, isDate, isEmpty, isMatch, isNumber, isString, isSymbol, isUndefined, lt, lte, startsWith and more.
Here's an example use of the gte
(greater than or equal to) helper:
\{{#gte age 21}}
You are old enough to drink in the United States.
\{{/gte}}
lobars also provides helpers for manipulating input like camelCase, capitalize, escape, kebabCase, lowerCase, lowerFirst, pad, padEnd, padStart, parseInt, repeat, replace, snakeCase, split, startCase, template, toLower, toUpper, trim, trimEnd, trimStart, truncate, unescape, upperCase, upperFirst, and more.
Here's how you use the string helpers:
\{{lowerCase someString}}
Delicious metadata is extracted from images and included in the Handlebars context object, which is accessible to every page.
Extensions: png|jpg|gif|svg
JSON and YML files are slurped into the Handlebars context object, which is accessible to every page.
Extensions: json|yaml|yml
jus uses a clean URL strategy that is compatible with
GitHub Pages
and
surge.sh.
In essence, pages get their extension lopped off,
and pages named index
inherit the name of their directory.
Filename | URL |
---|---|
index.html | / |
nested/index.html | /nested |
nested/page.html | /nested/page |
also/markdown.md | /also/markdown |
also/handlebars.hbs | /also/handlebars |
stylesheet.scss | /stylesheet.css |
stylesheet.sass | /stylesheet.css |
stylesheet.styl | /stylesheet.css |
stylesheet.styl | /stylesheet.css |
Add the following to your package.json:
{
"scripts": {
"start": "jus serve",
"deploy": "npm run build && npm run commit && npm run push && npm run open",
"build": "jus build . dist",
"commit": "git add dist && git commit -m 'update dist'",
"push": "git subtree push --prefix dist origin gh-pages",
"open": "open http://zeke.sikelianos.com"
}
}
Now whenever you want to publish to GitHub Pages, run:
npm run deploy
Note: GitHub's User Pages (like yourname.github.io
) are built from the master
branch,
whereas Project Pages (like yourname.github.io/project
) are built from the gh-pages
branch.
Be aware of this when setting up your npm scripts.
Note: GitHub's CDN can take a minute to update, so you might have to refresh a few times when visiting.
surge.sh is an awesome new platform for publishing static websites.
Install the Surge CLI:
npm i -g surge
Add the following to your package.json:
{
"scripts": {
"start": "jus serve",
"deploy": "npm run build && npm run build && npm run open",
"build": "jus build . dist",
"push": "surge dist YOUR-URL",
"open": "open YOUR-URL"
}
}
Now whenever you want to publish to Surge, run:
npm run deploy
jus was inspired by a number of existing tools:
Sometimes real examples are the easiest way to learn. Check out these open-source sites built with jus:
Find more static site generators.