upmk docs

Basics Commands install secrets deploy dev dyna build generate package pull push filters Templating Dynamic Pages Redirects JSON endpoints Auth Serving Files Editor Templates AddOns Plugins

Basics

At it's core the upmk tool is a sytem of conventions for building a static site.

upmk has the notion of a Model. Models have a schema definition, and have supporting instances of that model. Schema definitions are written into app/config/db/<name>.json as json files. Instances are written into app/models/<name>/<instance-name>.md as markdown files (with a toml front matter section for data attributes).

upmk has the notion of a View, which are templates for generating views. Views are located in app/views/<name>/<action>.html.njk.

It has the notion of a Controller. Controllers are js files that expose actions (functions) that pull data from the DataStore and expose it to the approprite View.

Controller Actions build Pages

Unlike some other approaches to static page generation, upmk builds pages based on exposed controller actions. For example, if you have a controller at app/controllers/event_controller.js that exposes a testing action:

function testing(ds) {
  return {context: {}, settings: {}}
}
module.exports = {
  testing
}

The build would look for a template view in app/views/event/testing.html.njk and would create a static page in static/event/testing.html

Controller Actions Interface

Controller Actions have a specific interface. Actions get passed an instance of the datastore (often called ds). They are expected to return an ActionResult object.

ActionResult objects have the following shape:

{
  context: {
    this: "is",
    some: "data that the view uses to build the template"
  },
  settings: {
    route: "/testing",
    model: "blog"
  }
}

The context object is generally used to pass data along to your view template for buidling the page view.

There are a few available, optional keys for the settings object. Each are described here:

route

The route attribute defines the route at which a generated file will be written. By default it is the name of the controller without the _controller.js.

model

The model attribute is used in show actions to determine what type of models the show action should iterate over to build the show action (see section on Show Actions for more details). It also defaults to the name of the controller.

layoutTemplate

The layoutTemplate defaults to "layouts/application". In your views, you'll see it used as a variable to choose the appropriate template to extend.

onlyIn

The optional onlyIn attribute is used to only build views in a specific mode. For example setting it to development means that these views will only be created when building for development. (i.e. `upmk build --mode )

Here's what a default event_controller.js would look like with an index action:


const defaults = {
  route: 'event',
  model: 'event'
}

function index(ds) {
  return responds({items: ds[defaults.model].instances})
}

function responds(context, settings) {
  let finalSettings = Object.assign({}, defaults, (settings || {}))
  return {
    settings: finalSettings,
    context: context
  }
}

module.exports = {
  index: index
}

See the generate command for more details on generating pages (controllers, actions, views) from the cli.

DataStore Structure

The DataStore is created during an upmk build and is the cobmination of data schema for your models, and the collection of instances of that specific type. Given a project with a single event model type, it is structured like this:

{
  event: {
    typeDef: {},
    instances: []
  }
}

In this above example we have a single model type called event. The typeDef key is an object containing the schema for the model type. The instances attribute is an array of instances of the event type.

The DataStore is passed to every controller action during a build.

Index Actions

Controller actions named index are typically used to show the listing of the various models of a given type ... but they don't need to be. They can be any type of page that you'd like. By default they'll be written to an index.html file. With the default server settings in nginx, they'll be served at the controller name (without the index.html being necessary)

Show Actions

Controller actions named show are considered special in upmk. They are used to generate individual pages for each model instance of a given model type. By default upmk chooses the model based on the name of the controller. This can be over written by supplying a settings.model in your ActionResult object.

As an example, assume we have an event_controller.js that exposes a show. When it processes the show action for our event controller, it will call the show action once for each event model instance we have in our project. It will write these files to event/<slug>.html (where slug is an attribute of the model, or the model file name)

A show action's interface is slightly different in that it expects an instance of the DataStore, and an instance of the model to be passed. Note that the ActionResult object it returns is the same.

function show(ds, item) {
  return responds({item: item})
}

Be aware that prior to building your actual show action views, the upmk tool will call your show action one time to determine which model type it should be itterating over. (Due to the fact that the model may be set on the ActionResults.settings). This generally means that your show action should be resilient to getting called with a datastore, and a blank item, ie:

show(dataStore, {})