Documentation

Watch the tutorial video. Watch The Simple Web Application Tutorial.

Setup With Your Server

NodeJuice Basic Explanation

NodeJuice ships with three separate servers: Seeker, Sidekick and WSGI. Seeker is what allows automatic browser refresh on file change. Sidekick is the gateway or proxy which connects to Apache, Passenger, Nginx, Cherokee, etc. WSGI is a Web Server Gateway Interface and can server static files and execute V8 JavaScript on your server. No need to worry about managing the servers yourself. NodeJuice comes with a process manager and will figure this out for you. All you need to do is add a config file to your project's directory. Then point ./nodejuice at your project's directory and say what kind of setup you want run.

Basic Static Setup

To launch
node
Juice
as a static web server, simply execute the following command:
./nodejuice /path/to/directory
This will launch both WSGI and Seeker Server. Open your browser and go to:
http://localhost:8080/some-file-name-here.htm
Now you can edit *HTML* files and they will update automatically in your web browser. No need to press reload every time you make a change.

***If all you want is a simple file server, no need to read further.

Setup for Web Applications

  1. Make a file called app.js in your application directory.
  2. Copy the following text into the app.js file.
    var app = exports;
    app.journey = function( request, response ) {
        response.impress( '/templates/index.htm', {
            dynamic : 'my text here'
        } );
    };
  3. Create an HTML file 'your-app-dir/templates/index.htm'.
  4. Have the following configuration file in your application root directory.

Configuration File

This file needs to be in your application's root directory.
// FILE: nodejuice.js
exports.sidekick = {
    host  : null, // Leave 'null' to listen on all hosts.
    port  : 8010, // access your server from this port.
    fetch : {     // point to your web server.
        host : 'localhost', // point to your web server.
        port : 8080 // point to your web server.
    }
};

exports.seeker = {
    host   : null, // Leave 'null' to listen on all hosts.
    port   : 8002,
    delay  : 200,   // milliseconds before page starts to reload.
                    // setting too low will cause apahce read file error.
    wait   : 1500,  // milliseconds before a new connection.
                    // setting this too low will make crazziness.
    add    : true,  // allow new file to push updates.
    remove : true,  // allow file delete to push updates.
    touch  : false, // allow file touch to push updates.
    access : false, // allow file reads to push updates.
    bits   : true,  // allow chmod/chown to push updates.
    save   : true,  // allow file save to push updates.
    dir    : true,  // allow directory changes to push updates.
    ignore : [ /git$/, /svn$/, /cvs$/, /swp$/, /~$/ ] // stuff to ignore.
};

exports.wsgi = {
    host  : null, // Leave 'null' to listen on all hosts.
    port  : 8080,
    root  : 'index.htm', // used for static content as the default.
    retry : { max: 4, wait: 120 }, // number of retries to load a file.
    url   : [ // interface between browser URL Request and Files.

        [/^\/app$/, '/app.js'], // run an application.
        [/^\/.*/, '/static/'],  // serve content from /static/ dir.
        [/^\/.*/, '/'] // server static content from root app dir.

    ]
};

Sidekick Setup for Apache

This instruction is on the home page.

WSGI Functions for Web Applications

node
Juice
sits on top of NodeJS. All Node's functionality is available to you. The first two arguments are modified versions of what you get from NodeJS.

App Journey

This is the main entry in your WSGI application.
var app = exports;
app.journey = function( response, request ) {
    // your code here...
};

Response Object

This object is available to you in your app.journey call.

response.attack

This is the basic response call to send text or data back to the web browser.
response.attack(
    body,       // Delivery HTML, Text or Binary
    [code],     // OPTIONAL: HTTP 3-Digit Code (200, 404, 500, etc.)
    [type],     // OPTIONAL: "Content-Type" "text/html" "text/plain"
    [headers],  // OPTIONAL: HTTP Headers
    [encoding]  // OPTIONAL: "utf8" or "binary" the default is "utf8"
);
// Example Use of response.attack()
var app = exports;
app.journey = function( request, response ) {
    response.attack(
        'hello!',    // text (body)
        200,         // response code
        'text/html', // content type.
        {},    // headers empty for no specail reason.
        "utf8" // encoding
    );
};

response.impress

This is a template rendering call which sends directly to the browser after parse complete.
response.impress(
    file,    // point the the file relative to your application directory.
    [object] // OPTIONAL: Will find all {{tags}} and impress data in place.
);
// Example Use of response.impress()
var app = exports;
app.journey = function( request, response ) {
    response.impress( '/templates/index.htm', {
        food : 'apple'
    } );
};
Also available is response.utility.impress( file, args, callback );

response.appdir

Holds the location of your application directory.

response.utility.noble

The Utility Object has many powerful functions. The first is a trustable file read command. This file read command is a reliable conncurrent non-blocking I/O function.
response.utility.noble(
    file,   // /path/to/file/name
    success // function( type, body, encoding ) callback on load.
    [fail]  // OPTIONAL: callback on failure.
);
// Example Use of response.utility.noble()
var file = response.appdir + '/templates/index.htm';
response.utility.noble( file, function( type, body, encoding ) {
    // Send File to Browser
    response.attack( body, 200, type, {}, encoding );
}, function() {
    // Send Error
    response['404']( request, response, file );
} );

response.utility.supplant

Base template impression function. This is the Crockfordian Supplant Method posted by Douglas Crockford.
response.utility.supplant(
    text,  // string of chars to update.
    object // Will find all {{tags}} and impress data in place.
);
// Example Use of response.utility.supplant()
var parsed_text = response.utility.supplant(
    // Parses as "Hello Frank Alphabet!"
    "Hello {{name}}!", { name : "Frank Alphabet" }
);

response.utility.inform

The Primary Logging Function. This is the most used function. This function is important to help you build your web application.
response.utility.inform(
    object // What is to be logged.
);
// Example Use of response.utility.inform()
var util = response.utility;
// Print to terminal: { timestamp: 1262558727644, some_text: "log this" }
util.inform({
    timestamp : util.earliest(),
    some_text : 'log this'
});

response.utility.recurse

Non-blocking Recursive Directory Loop. Use this function to safely gather all files in all directories.
response.utility.recurse(
    start,   // Starting Directory
    ignore,  // Array of regexs to ignore matching files/directories.
    callback // function(file) called EVERY TIME a File or Directory is found.
);
// Example Use of response.utility.recurse()
// Stream a list of files to the web browser:
response.sendHeader( 200, { "Content-Type" : "text/plain" } );

response.utility.recurse(
    response.appdir + '/static',
    [ /.git$/, /csv$/, /.svn$/, /pants/ ],
    function(file) { response.sendBody( file + "\n", "utf8" ); }
);

// Only allow 1 second of data streaming.
setTimeout( function() {response.finish()}, 1000 );

response.utility.fetch

Download data from an outside source. This is a low level call and you get to play with the guts of every fetch.
response.utility.fetch({
    port,     // 80
    host,     // "www.google.com"
    type,     // "GET" or "POST" or "HEAD"
    path,     // "/" or "/index.htm" or "/someurl"
    headers,  // { "Accept-Encoding" : "utf8" }
    body,     // "binary, text or POST data"
    encoding, // "binary" or "utf8"
    ready,    // function (response) {} when connection is made
    good,     // function ( chunk, response, encoding ) {} chunck recieved.
    fail,     // function ( chunk, response, encoding ) {} failure occurs.
    finished  // function ( final, response, encoding ) {} all is done.
})
// Example Use of response.utility.fetch()
response.utility.fetch({
    port     : 80,
    host     : "www.google.com",
    type     : "GET",
    path     : "/",
    finished : function( data, res, encoding ) {
        // Proxy google's home page to browser.
        response.attack( data, 200, res.headers['content-type'], {}, encoding )
    }
})

response.utility.earliest

Simple timestamp function.
response.utility.earliest();
// Example Use of response.utility.earliest()
var timestamp = response.utility.earliest();