mklabs/nabe — Issue #15: nabe next: collection of (cake) scripts, static site generation
Author: mklabs
Created: 2011-11-23 15:59:01+00:00
State: open

Thoughs about a possible nabe v.next, static site generation.

The idea would be to implement a collection of commands, say cake scripts (ala cakes, and tasks/ folder), or another build tool system.

### description

Static site generated should be compliant with current folder structure. Would be cool to also generate stuff from the git history.

On each article, the script should lookup in git commits, get the content of file for each commits and generate the static webpage.

The current server/connect/express implementation would remain. Static site generated should provide the same UX, folder structure, resulting site.

### on front markers

Currently, wheat/nabe compliant stuff relies on a yaml front marker, delimited by a `\n\n` character.

Jekyll relies on a [yaml front marker](https://github.com/mojombo/jekyll/wiki/YAML-Front-Matter) with some options (layout, title, date, etc.).

---
layout: post
title: Blogging Like a Hacker
---

Instead, a little variation, relying on html comments trick (so that, markdown content would still be the same).

Between the triple-dashed lines, you can set predefined variables (see below for a reference) or custom data of your own.

Some of the jekyll config values:

Variable	Description

layout	If set, this specifies the layout file to use. Use the layout file name without file extension. Layout files must be placed in the _layouts directory.

permalink	If you need your processed URLs to be something other than the default /year/month/day/title.html then you can set this variable and it will be used as the final URL.

published	Set to false if you don’t want a post to show up when the site is generated.

category/categories	Instead of placing posts inside of folders, you can specify one or more categories that the post belongs to. When the site is generated the post will act as though it had been set with these categories normally. Categories can be specified as a YAML list.

date	A date here overrides the date from the name of the post. This can be used to ensure correct sorting of posts.

### config

The order of precedence for conflicting settings is this:

* Command-line flags
* prompts ?
* Configuration file settings
* Defaults

There are also flags for the jekyll executable which are described below next to their respective configuration options.

baseurl: /
source: .
destination: ./publish
plugins: ./_plugins
...

#### few notes

* node environments: should adapt and configure the build depending on `NODE_ENV` (like running the build script on prod)

* git stuff: would be nice if somehow the scripts could use git, and exec necessary git command to get commit history for a file, and generates the according file revision page (possibly a diff view too, commit to commit).

* socket.io sugar: in watch mode, would be nice to add the same socket.io sugar than docco (after regenerating, emit to clients the files that were changed)

* html comment front marker: basically like jekyll but allow the use of html comments front marker instead of `---` delimiters

### practical implementation

Just looked at the really neat flatiron/broadway. The simple plugin system and good API are really nice.

nabe in cli mode, would be a broadway app, or a close clone of a broadway app.

nabe inherits from event emitter, defines a prototype with few method: use, init, inspect.

each functionnality is implemented as a plugin loaded by use and initilaized by init (config, log, etc.)

each command (init, run, generate, etc.) is a file following a certain convention (probably the npm one, see gimme). The action method is called with a set of options and the nabe/broadway like app.

each commands are async and either would rely on a last callback arg, or EE ability of nabe app.

options provided would probably be the result of options parsing (using nopt), or simply the nconf.Provider (that has built-in methods for overrides with optimist).

### plugins and extending functionnality

based on EE stuff, and plugin system, there should be a way to provide some level of extensibility. Most of these may be inspired by the way Jekyll handles plugins.

Jekyll defines three categories of plugins:

1. Generators
2. Converters
3. Tags

A generator is used when you need Jekyll to create additional content based on your own rules. Ex: jammit, less, categories, ...

Generators are only required to implement one method:

1. generate: string output of the content being generated

Converters are used to implement the processing of a Markdown or Textile page for instance. A file with a yaml front matter is send through converters. They implement a match method (testing to process or not, by testing .ext), an output extension, and a convert method (take input, return results).

tag/filters are related to templates below.

Jekyll has flags for plugins, safe and priority: priority: determines what order the plugin is loaded in. Valid values are: :lowest, :low, :normal, :high, :highest

another options to priority, would be a simple system or require/depends system ala rake/cake. A converter/generator may need to wait another generator(s) to end to do their task.

### templates

will use https://github.com/janl/mustache.js/, possibly handlebar.

supports higher order sections (This can be used to implement caching, filters (like syntax highlighting), etc. fit well with plugin system) and simple partials system.

a plugin tag implement a render method, they gets auto lazy loaded from a given folder, say plugins/ (inherits from a Tag object).

idea, might be terrible: get plugins loaded in a jsdom environment, tag filters (for mustache's higher order sections) and such could get a jsdom document + jquery instance to mess with it. Probably, they could safely go sync (and if async is needed, maybe returning an instance of EventEmitter and checking the return value to be instanceof, like vows does could fit).

using this jsdom idea, options to be passed to the tags filter could be handcoded like normal html and used formerly in plugins itself (or preparsed by the plugin system).

plates: even tough I really like mustache and have all I need, and would be probably simpler since it's closer to liquid templates. Plates is to look at more closely. Pure html views are sexy.

## semantic of commands

as I see it from there

main ones

* init: create a new folder structure, with optionnal `--skeleton`. Optionnaly, should run `git init` and create a new git repo.
* run: generates content and run the dev server.
* generate: build and generate static web site
* serve: starts up a new serve instance in the content directory
* watch: starts a server and watch for file changes to regenerate (maybe add socket.io here)

others

* config: inspect and edit configuration
* post: related to post management, create, list, etc.

support

* help: get help on any command, like npm
* docs: open up the relevant doc using `--browser`, like npm

experimental

* docco: creates blog like page from docco generated stuff and source files.
* assets: hook in gimme-assets, for easy file assets inclusion/work.
* status: wrapper around git status, show usefull infos.
* admin: start a server instance with an express/backbone app (or go flatiron way to see how awesome it is) to edit the website using a web interface. Markdown editors should look like dillinger.io, save means git commits (so a git message prompt). commit history/compare feature. Basically, a git-aware CRUD on top of posts.
* hooks: automatically set up a collection of git(hg too?) hooks to easily generate a website. Could be useful on the server (live sites) part. post-receive hook to regenerate the website. pre-receive hook to validate the output.
* post-receive: a command to setup a long running process (probably using forever), setting up a webserver to validate and process incoming post-receive hooks (like github's one). Basic idea is to regenerate a website when a git push occurs on github repos.

*plugins*: maybe worth adding a fourth plugin type (after generator, converter, tag): cmd. Users may want to add their own command to nabe, should be easy to do (with completion hooks, and docs/manpage).

These plugin commands would be available if ./plugins have files implementing this kind of plugins.

### nabe post

a command to interract with posts:

# show help for post command.
nabe post

# list the post in the console
nabe post ls
nabe post list

# create a new post (ala npm init, read prompt)
nabe post create
nabe post init

# view meta informations about the post
nabe post info

# view.. as manpage!
nabe post view

### nabe init

a command to quickly set up a new nabe folder structure

# like npm, prompted
# generate in the current directory if empty,
# otherwise warn and ask for output folder (possibly `.`)
nabe init

# use a template structure
nabe init --template ./path/to/template

# output directory
nabe init ./path/to/output

### nabe run

a command to generate and start a new server (combination of generate/serve or watch?)

# if current dir is a valid nabe dir
# otherwise warn and fail
nabe run
nabe start

nabe run ./path/to/app
nabe start ./path/to/app

### nabe generate

(or build, maybe) Build and generate the static content.

nabe generate
nabe build

nabe generate ./path/to/app
nabe build ./path/to/app

### nabe serve

Create and start a new server, serving content dir (warn or generates if no content dir)

nabe serve
nabe serve --port 4000
nabe serve ./path/to/app

### nabe watch

basically the same as `serve`, but adds `fs.watchFile`/`fs.watch` use to (re)generate changed files automatically. Maybe, add the same feature as connect-docco, updating browser content or url depending on socket.io/watch events.

nabe watch
nabe watch --port 4000
nabe watch ./path/to/app

### nabe config

config helpers, to show and edit configuration values (should all be overridable through cli args)

nabe config
nabe config ls
nabe config edit
nabe config get
nabe config set

### nabe help

get help on nabe.

nabe help
nabe help
nabe help some search terms

If supplied a topic, then show the appropriate documentation page using man viewer on unix (browser on windows)

### nabe docs

basically the same as help, but using `--browser` options.

nabe docs
nabe docs
nabe docs some search terms

##### sources of inspiration

* jekyll: https://github.com/mojombo/jekyll
* docpad: https://github.com/balupton/docpad