Skip to content
A modular toolkit for building static websites
JavaScript
Branch: master
Clone or download
Latest commit f793e1d Sep 13, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs added includeScript and includeStyle Aug 27, 2019
example fixing code styling Aug 27, 2019
lib
test a bit late to start git Aug 25, 2019
transforms fixing code styling Aug 27, 2019
.gitignore
.npmignore
.npmrc a bit late to start git Aug 25, 2019
index.js added the optional from property to files + pump Aug 29, 2019
package.json 0.0.4 Sep 12, 2019
readme.md added the mobile meta to the defaults Sep 12, 2019

readme.md

stakit

A modular toolkit for building static websites


Stakit is a framework that helps you compose powerful build pipelines for static-websites without breaking a sweat. It's minimal and modular, uses streams and the Stakit toolkit has a bunch of plugins and transforms that you can use.

Stakit is still early in development, but you can take it and use it to see if you should care about it or not.

Features

  • framework agnostic: works with any framework that can output a string
  • modular: you never have what you don't need, but you can npm install it
  • small api: it only has 7 core methods, only 3 of them you must use
  • no constraints: you are never limited by the features and templates of a static-site generator
  • fast, memory efficient: heavily using streams

Installation

npm i stakit

Example

var stakit = require('stakit')
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'))

Why?

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.

Usage

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 pipeline:

All other methods are optional and called in the following order:

  1. all the middlewares applied by kit.use()
  2. the applied routesReducer function
  3. for every route:
    1. a single call to the applied renderer
    2. all transform calls

End the pipeline with kit.output().

API

This section provides documentation on how each function in Stakit works. It's intended to be a technical reference.

kit = stakit()

Initialize a new kit instance.

kit.html(template, selector)

Sets the starting HTML template and selector.

kit.use(fn(context))

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 transforms.

kit.use(function (ctx) {
  ctx._transforms.push(transform)
})

See Middlewares for more information.

kit.routes(routeReducer(state))

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' ]
})

kit.render(renderer(route, state))

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.

kit.transform(transformFn, opts)

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.

kit.output(writerObject)

Starts the build pipeline 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.

Middlewares

Built-in middlewares:

stakit.state(extendState)

Utility to help you with adding values to context.state

kit.use(stakit.state({ message: 'good morning!' }))

stakit.copy(files)

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'
}))

Transforms

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. If you want to bypass this, you can simply return the documentify transform from a function.

See what transforms come with Stakit in docs/transforms.md.

Writers

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:

{
  source: null | string,
  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.

See Also

  • choo - sturdy 4kb frontend framework
  • documentify - Modular HTML bundler
  • jalla - Lightning fast web compiler and server in one (also thanks for a lot of code snippets!)
You can’t perform that action at this time.