A web framework with automatic Browserify + Less + Express + Handlebars.
- Browserify is automatic
- Less compilation is automatic
- Express routing is automatic
- Handlebars precompilation is automatic for both server and browser
- Serves static files
- Secure cookie-based sessions
npm install -g bleh
mkdir my-app && cd my-app
npm init
bleh init
npm run dev
const bleh = require('bleh')
const express = require('express')
const app = express()
const port = process.env.PORT || 8080
app.use('/', bleh())
app.on('ready', () => {
app.listen(port, () => {
console.log([
'My App',
`Running: http://localhost:${port}`,
`NODE_ENV: ${process.env.NODE_ENV}`,
].join('\n'))
})
})
├─ layouts/
├─ node_modules/
├─ pages/
│ ├─ home/
│ │ ├─ home.browserify.js
│ │ ├─ home.less
│ │ ├─ home.node.js
│ │ └─ home.html
│ └─ $name/
│ └─ $name.node.js
├─ partials/
├─ public/
│ ├─ dist/
│ └─ robots.txt
├─ test/
├─ server.js
└─ package.json
See also the sample app.
Routes are generated automatically based on the pages/
folder structure. Each page has a controller (.node.js
file) and normally has .html
, .less
and .browserify.js
files located together in that page's folder.
The page's js
and css
files are automatically embedded via the html5
layout.
Words beginning with $
in the page name are URL params. See example.
You can set the layout for the page by calling $.layout(name)
. Layouts have automatic Browserify, LESS and Handlebars compilation just like pages but the layout's .html
file must contain {{{main}}}
.
Partials can be included in other templates. Partials are just plain ol' handlebars templates. Put your Handlebars helper methods in lib/handlebars-helpers.js
.
<div>
{{> partials/hello}}
</div>
All files in the public
folder are served as static files.
The build process generates the public/dist/
folder containing the js
and css
for your app.
The build is generated at runtime (except in production
) and the app's ready
event fires when the build is complete.
In the production
environment, the build step is skipped and the ready
event fires immediately to avoid a brief delay starting the app.
When deploying to production, bleh build
will run automatically after npm install
(i.e. you should have "postinstall": "bleh build"
in package.json
).
Use npm run dev
for development so your app restarts and rebuilds when a source file changes.
If you add your commonly used client-side npm modules to the browserifyCommonDependencies
array in your package.json
, then an external browserify bundle will be used. This will reduce the size of your page-specific js
bundles.
You can reference any other .less
file to gain access to its variables/classes/mixins. For example, the html5
layout provides a .clearfix
style for convenience.
@import (reference) 'layouts/html5/html5.less';
.something {
.clearfix;
color: @black;
}
Your handlebars helpers will work on both the server and client if you specify them in lib/handlebars-helpers.js
(assuming you're using the html5
layout).
For example: handlebars-helpers.js
Also, if you're using the html5
layout, you can use window.render()
to render any of your .html
templates on the client side. You can see the templates you have available with console.log(Handlebars.templates)
.
var html = window.render('partials/hello', data)
All options are optional.
var app = bleh({
// default options
dist: 'public/dist',
helpers: {},
home: '/home',
https: false,
log: console.log,
root: __dirname,
sessions: false // {secret: 'My EncRypT10n k3Y'}
})
- dist - The folder to contain the build files.
- helpers - This object gets merged into the context of the controller.
- home - The page (uri) to be used as the homepage. By default,
/home
redirects to/
. - https - This option forces a redirect to
https
only in production. - log - The function for log output. Defaults to
console.log
. - root - The path to the root folder of your app (which contains
pages/
). See file structure. - sessions - Configuration for cookie-based sessions. To enable sessions, you need a
secret
value. See client-sessions.
The build automatically creates routes for .node.js
files (controllers) that exist in the pages/
folder.
For example:
// uri: /beep.json
module.exports = function ($) {
$.send({
beep: 'boop'
})
}
// uri: /hello
module.exports = function ($) {
$.title = 'Hello' // set data to be rendered
// add additional css or js to the page
$.css.push('//maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css')
$.layout('website') // specify the layout and call its controller function
$.render() // send the rendered html
}
// uri: /will123195
module.exports = function ($) {
console.log($.$user) // will123195
$.render()
}
module.exports = function ($) {
$.now = Date.now() // set data for all pages using this layout
$.layout('html5') // html5 boilerplate + link css & js
}
Each layout has a controller that runs when the layout
method is invoked. A generic html5
layout is provided that magically links the corresponding css
and js
onto the page if invoked.
accessDenied()
- sends 403 responsebody
- the request body (i.e. POST data)error(err)
- sends 400 responseget(fn)
- callsfn
if request method is GETlayout(name)
- invokes a layoutnotFound()
- sends 404 responsepost(fn)
- callsfn
if request method is POSTquery
- the parsed querystringredirect([301|302], uri)
- sends redirect responserender()
- sends rendered html usingthis
datareq
- the http request objectres
- the http response objectsend(obj|str)
- sends a text or json responsesession
- the values encrypted in a cookieset(helpers)
- merges new properties into this contexttemplates
- the array of precompiled template functionsview(name)
- changes the default template to berender()
ed
Additional helpers
specified in the options are merged into the controllers' context. For example, adding your db
as a helper will make it accessible in all controllers as this.db
.
Note: req
, res
and templates
are hidden for convenience so you can console.log(this)
without so much noise.