bleh
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
Quick start
npm install -g bleh
mkdir my-app && cd my-app
npm init
bleh init
npm run dev
Usage
const bleh = const express = const app = const port = processenvPORT || 8080appapp
File structure
├─ 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.
pages/
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.
layouts/
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/
Partials can be included in other templates. Partials are just plain ol' handlebars templates. Put your Handlebars helper methods in lib/handlebars-helpers.js
.
{{> partials/hello}}
public/
All files in the public
folder are served as static files.
Build
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.
Browserify
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.
Less
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.
reference 'layouts/html5/html5.less';.something .clearfix; color: @black;
Handlebars
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
Options
All options are optional.
var app =
- 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.
Controllers
The build automatically creates routes for .node.js
files (controllers) that exist in the pages/
folder.
For example:
pages/beep.json.node.js
// uri: /beep.jsonmodule { $}
pages/hello/hello.node.js
// uri: /hellomodule { $title = 'Hello' // set data to be rendered // add additional css or js to the page $css $ // specify the layout and call its controller function $ // send the rendered html}
pages/$user/$user.node.js
// uri: /will123195module { console // will123195 $}
layouts/website/website.node.js
module { $now = Date // set data for all pages using this layout $ // 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.
Controller methods and properties
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.