A modular toolkit for building static websites.
Currently in early WIP / planning state.
npm i stakit
var stakit = require('stakit')
var { appendToHead } = require('stakit/transforms')
var { render, hydrate } = require('@stakit/choo')
var app = require('.')
var kit = stakit()
.routes(function (state) {
return [ '/' ]
})
.render(render(app))
.transform(hydrate)
kit.output(stakit.writeFiles('./public'))
Generally, you do 2 things when generating a static site:
- fill your app with some content
- copy static files
There are many modular (and lovely) tools for bundling Javascript or transforming CSS, Stakit is something similar, but for the full site, and especially focuses on HTML files.
You'll have to handle the bundling of your app and including the bundle if that's what you need. Following Choo's philosophy, it's small, understandable and easy to use. It was designed to work mainly with Choo, but it should work with other isomorphic frameworks too.
Stakit is called programmatically, not from the command-line, therefore you'll need a Javascript file (like build.js
), where you require it. Afterwards you can initialize the kit with stakit()
and then chain a couple of methods.
Two methods must appear in the chain:
All other methods are optional and called in the following order:
- all the middlewares applied by
kit.use()
- the applied
routesReducer
function - for every route:
- a single call to the applied
renderer
- all
transform
calls
- a single call to the applied
End the chain with kit.output()
.
This section provides documentation on how each function in Stakit works. It's intended to be a technical reference.
Initialize a new kit
instance.
Sets the starting HTML template and selector.
Pushes a middleware / plugin to the middlewares list, general purpose functions ran before the route generation. You can modify the context any way you want, from altering the state
to installing transform
s.
kit.use(function (ctx) {
ctx._transforms.push(transform)
})
See Middlewares for more information.
The routeReducer
is a function that gets context.state
as a parameter and returns an Array
of strings / routes. These are the routes on which Stakit will call render
.
kit.routes(function (state) {
return Object.keys(state.content)
// or statically
return [ '/', '/about', '/blog' ]
})
Sets the renderer of the build. This is where the magic happens. The renderer
will be called for every route returned by routes
.
It has to return an object with the following values:
{
html: string, // the result of the render
state: object // the state after the render (optional)
}
Transforms will receive the updated state returned here.
Pushes a transform to the list of transforms. Stakit uses documentify
and streams to build up the HTML.
They're called after the rendered content has been replaced in the HTML.
See Transforms for more information.
Starts the build chain and ends it with passing all the routes to writerObject.write({ destination, stream })
. Returns a Promise
that waits until all files (routes and static) has been completely written.
By default it uses a Writer that outputs the site to the ./public
directory.
See Writers for more information.
Built-in middlewares:
Utility to help you with adding values to context.state
kit.use(stakit.state({ message: 'good morning!' }))
Middleware for copying files to the output directory.
// Copy files to the same location
kit.use(stakit.copy([ 'robots.txt' ]))
// Copy files to a different location within the output path
kit.use(stakit.copy({
'robots.txt': 'robots.txt',
'sitemap.xml': 'sitemaps/sitemap.xml'
}))
Documentify
is very powerful and can easily be modulized. The general format of a Stakit transform is:
// wrapped in a function
function lang (context) {
// return the documentify transform
return function (lang) {
// return a transform stream
return hstream({ html: { lang: lang } })
}
}
Note: hstream
is a very good friend!
The documentify
transform is wrapped in a function, so we can get the context
when we need it, without messing with documentify
's API.
See what transforms come with Stakit in docs/transforms.md
.
Writers output the generated, transformed static files. This can vary from outputting to the file-system, to putting them into a Dat archive.
A writer must implement a method: write
. For every file, including the generated pages + the files added to context._files
, writer.write
will be called with a file object. It should return a Promise
that returns after the pipe was flushed (the file was completely written).
A file object looks like this:
{
destination: string,
stream: Stream
}
It's recommended to clean up the output directory before every build.
Have a look at the built-in stakit.writeFiles
method as an example.
That's all about writers.
- jalla - Lightning fast web compiler and server in one (also thanks for a lot of code snippets!)
- documentify - Modular HTML bundler