--- /dev/null
+[Node][] is a server-side [JavaScript][] engine (i.e. it executes
+JavaScript without using a browser). This means that JavaScript
+developers can now develop tools in their native language, so it's not
+a surprise that the [Bootstrap][] folks use [Grunt][] for their build
+system. I'm new to the whole Node ecosystem, so here are my notes on
+how it works.
+
+Start off by installing [npm][], the Node package manager. On Gentoo,
+that's:
+
+ # USE=npm emerge -av net-libs/nodejs
+
+[Configure npm][npm-config] to make ["global"
+installs][npm-folders-prefix] in your personal space:
+
+ # npm config set prefix ~/.local/
+
+Install the [Grunt][] command line interface for building
+[Bootstrap][]:
+
+ $ npm install -g grunt-cli
+
+That installs the libraries under `~/.local/lib/node_modules` and
+drops symlinks to binaries in `~/.local/bin` (which is [already in my
+`PATH`][PATH] thanks to my [[dotfiles]]).
+
+Clone Boostrap and [install it's
+dependencies][bootstrap-dependencies]:
+
+ $ git clone git://github.com/twbs/bootstrap.git
+ $ cd bootstrap
+ $ npm install
+
+This looks in the local [package.json][] to extract a list of
+dependencies, and [installs each of them][npm-folders] under
+[node_modules][]. Node likes to isolate its packages, so every
+dependency for a given package is installed underneath that package.
+This leads to some crazy nesting:
+
+ $ find node_modules/ -name graceful-fs
+ node_modules/grunt/node_modules/glob/node_modules/graceful-fs
+ node_modules/grunt/node_modules/rimraf/node_modules/graceful-fs
+ node_modules/grunt-contrib-clean/node_modules/rimraf/node_modules/graceful-fs
+ node_modules/grunt-contrib-qunit/node_modules/grunt-lib-phantomjs/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs
+ node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/glob/node_modules/graceful-fs
+
+Sometimes the redundancy is due to different version requirements, but
+sometimes the redundancy is just redundant :p. Let's look with [npm
+ls][npm-ls].
+
+ $ npm ls graceful-fs
+ bootstrap@3.0.0 /home/wking/src/bootstrap
+ ├─┬ grunt@0.4.1
+ │ ├─┬ glob@3.1.21
+ │ │ └── graceful-fs@1.2.3
+ │ └─┬ rimraf@2.0.3
+ │ └── graceful-fs@1.1.14
+ ├─┬ grunt-contrib-clean@0.5.0
+ │ └─┬ rimraf@2.2.2
+ │ └── graceful-fs@2.0.1
+ ├─┬ grunt-contrib-qunit@0.2.2
+ │ └─┬ grunt-lib-phantomjs@0.3.1
+ │ └─┬ phantomjs@1.9.2-1
+ │ └─┬ rimraf@2.0.3
+ │ └── graceful-fs@1.1.14
+ └─┬ grunt-contrib-watch@0.5.3
+ └─┬ gaze@0.4.1
+ └─┬ globule@0.1.0
+ └─┬ glob@3.1.21
+ └── graceful-fs@1.2.3
+
+Regardless of on-disk duplication, Node [caches modules][caching] so a
+given module only loads once. If it really bothers you, you can
+[avoid some duplicates by installing duplicated packages higher up in
+the local tree][npm-folders-nesting]:
+
+ $ rm -rf node_modules
+ $ npm install graceful-fs@1.1.14
+ $ npm install
+ $ npm ls graceful-fs
+ bootstrap@3.0.0 /home/wking/src/bootstrap
+ ├── graceful-fs@1.1.14 extraneous
+ ├─┬ grunt@0.4.1
+ │ └─┬ glob@3.1.21
+ │ └── graceful-fs@1.2.3
+ ├─┬ grunt-contrib-clean@0.5.0
+ │ └─┬ rimraf@2.2.2
+ │ └── graceful-fs@2.0.1
+ └─┬ grunt-contrib-watch@0.5.3
+ └─┬ gaze@0.4.1
+ └─┬ globule@0.1.0
+ └─┬ glob@3.1.21
+ └── graceful-fs@1.2.3
+
+This is probably not worth the trouble.
+
+Now that we have Grunt and the Bootstrap dependencies, we can build
+the distributed libraries:
+
+ $ ~/src/node_modules/.bin/grunt dist
+ Running "clean:dist" (clean) task
+ Cleaning dist...OK
+
+ Running "recess:bootstrap" (recess) task
+ File "dist/css/bootstrap.css" created.
+
+ Running "recess:min" (recess) task
+ File "dist/css/bootstrap.min.css" created.
+ Original: 121876 bytes.
+ Minified: 99741 bytes.
+
+ Running "recess:theme" (recess) task
+ File "dist/css/bootstrap-theme.css" created.
+
+ Running "recess:theme_min" (recess) task
+ File "dist/css/bootstrap-theme.min.css" created.
+ Original: 18956 bytes.
+ Minified: 17003 bytes.
+
+ Running "copy:fonts" (copy) task
+ Copied 4 files
+
+ Running "concat:bootstrap" (concat) task
+ File "dist/js/bootstrap.js" created.
+
+ Running "uglify:bootstrap" (uglify) task
+ File "dist/js/bootstrap.min.js" created.
+ Original: 58543 bytes.
+ Minified: 27811 bytes.
+
+ Done, without errors.
+
+Wohoo!
+
+Unfortunately, like all [language-specific][pypi] [packing][gem]
+[systems][cpan], npm has trouble installing packages that aren't
+written in its native language. This means you get things like:
+
+ $ ~/src/node_modules/.bin/grunt
+ …
+ Running "jekyll:docs" (jekyll) task
+ `jekyll build` was initiated.
+
+ Jekyll output:
+ Warning: Command failed: /bin/sh: jekyll: command not found
+ Use --force to continue.
+
+ Aborted due to warnings.
+
+Once everybody wises up and starts writing packages for [[Gentoo
+Prefix|Gentoo_Prefix_overlay]], we can stop worrying about
+installation and get back to work developing :p.
+
+[[!tag tags/programming]]
+[[!tag tags/tools]]
+[[!tag tags/web]]
+
+[Node]: http://nodejs.org/
+[JavaScript]: http://en.wikipedia.org/wiki/JavaScript
+[Bootstrap]: http://getbootstrap.com/
+[Grunt]: http://gruntjs.com/
+[npm]: https://npmjs.org/
+[npm-folders]: https://npmjs.org/doc/files/npm-folders.html
+[npm-folders-prefix]: https://npmjs.org/doc/files/npm-folders.html#prefix-Configuration
+[npm-folders-nesting]: https://npmjs.org/doc/files/npm-folders.html#Cycles-Conflicts-and-Folder-Parsimony
+[npm-config]: https://npmjs.org/doc/config.html
+[PATH]: http://git.tremily.us/?p=dotfiles-public.git;a=blob;f=src/.bash_profile;hb=HEAD
+[bootstrap-dependencies]: https://github.com/twbs/bootstrap/blob/master/README.md#install-grunt
+[package.json]: https://npmjs.org/doc/json.html
+[node_modules]: http://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders
+[npm-ls]: https://npmjs.org/doc/cli/npm-ls.html
+[caching]: http://nodejs.org/api/modules.html#modules_caching
+[pypi]: https://pypi.python.org/pypi
+[gem]: http://rubygems.org/
+[cpan]: http://www.cpan.org/