Bogart
Fast, Sinatra-Inspired JavaScript Framework running on JSGI with Node.JS!
Install / Use
/learn @nrstott/BogartREADME
Bogart
A blazing fast rapid application development web framework using JSGI for node.
Getting Started
Bogart can be installed via npm.
npm install bogart
Alternatively, clone the git repository.
git clone git://github.com/nrstott/bogart.git
Hello World in Bogart
Make a directory: mkdir hello-world
Create the following file:
app.js
var bogart = require('bogart');
var router = bogart.router();
router.get('/', function(req) {
return "hello world";
});
router.get('/:name', function(req) {
return 'hello '+req.params.name;
});
var app = bogart.app();
app.use(bogart.batteries({secret: "my-super-secret"})); // A batteries included JSGI stack including streaming request body parsing, session, flash, and much more.
app.use(router); // Our router
app.start();
Start your app: node app.js
Visit it in a web browser at http://localhost:8080. Visit the route that says hello to you by name at http://localhost:8080/bob
Changing the port
If you can't run on 8080, change the app.start call e.g. app.start(9090, '127.0.0.1')
Routing
Routing in Bogart is simple and intuitive. A route is an HTTP method paired with an URL matching pattern and a handler function.
var router = bogart.router();
router.get('/', function(req) {
return bogart.html('Hello World');
});
Routes are tested for matches in the order in which they are defined.
Route Patterns
Route patterns are matched against URLs. They may include named parameters that will
be accessible via the params object of the req object passed to the route handler.
var router = bogart.router();
router.get('/hello/:name', function(req) {
var greeting = 'Hello '+req.params.name;
return bogart.html(greeting);
});
Route patterns support wildcards. Wildcards will match anything whereas regular named parameters will not match beyond a path separator ("/").
var router = bogart.router();
router.get('/hello/*', function(req, name) {
return bogart.html('Hello '+req.params.splat[0]);
});
No Route Found
When no route pattern matches the request, a next jsgi application to be called may
be specified either with the Router#notFound method or via a parameter to the function
returned by bogart:router. If both techniques are used, then the parameter overrides
the app specified by the Router#notFound method.
Specified by calling the Router#notFound method
var myRouter = bogart.myRouter();
router.get('/', index);
myRouter.notFound(function (req) {
return bogart.html('Not Found', { status: 404 });
});
Specified as a parameter to the router
var myRouter = bogart.router();
myRouter.get('/', index);
var app = bogart.app();
app.use(myRouter(function (req) {
return {
status: 404,
body: [ 'Not Found' ]
};
}))
Regex Routes
When a route pattern is not powerful enough, regular expressions may be used to specify which URLs are to be matched.
var router = bogart.router();
router.get(/\/posts?/, function(req) {
// Matches 'post' or 'posts'
return bogart.html('Regex Route');
});
Parameters are via regular expression groups in regular expression routes. The parameter values
are put in an Array in req.params.splat of the req object passed to the route handler.
var router = bogart.router();
router.get(/hello-(.*)/, function(req) {
var name = req.params.splat[0];
return bogart.html('Hello '+name);
});
Custom HTTP Verbs
To handle HTTP Verbs other than get, post, put, and delete, the route method of
Router can be invoked.
var router = bogart.router();
router.route('options', '/', function (req) {
// Logic for handling the request goes here.
});
Bogart Application
bogart.app makes it easy to setup a middleware chain and start coding. Combined with
bogart.batteries (See Below), you can setup a full-stack JSGI application in two lines of code.
var app = bogart.app();
app.use(bogart.batteries({ secret: "my-super-secret" });
After adding bogart.batteries, you will normally want to add a Router. This is also done
with app.use. To start the application, use the start method.
var app = bogart.app();
app.use(bogart.batteries({ secret: "my-super-secret" }));
var router = bogart.router();
// NOTE: Here you would normally add some routes.
app.use(router);
app.start();
Response Helpers
Bogart includes helpers for creating JSGI Responses. The helpers, by convention, take a final parameter of an options object that allows the caller to override defaults. The options object is merged with the default JSGI Response values of the helper before the JSGI Response is returned.
Respond with JSON
Helper to create an HTTP 200 Success response with a Content-Type of application/json.
Sample Route:
var router = bogart.router();
router.get('/', function(req) {
return bogart.json({ framework: 'Bogart' });
});
This route yields the following JSGI Response:
{
status: 200,
headers: { 'Content-Type': 'application/json' },
body: [ '{ "framework": "Bogart" }' ]
}
Respond with CORS headers
Helper to send a JSON response with 'Access-Control-Allow-Origin', 'Access-Control-Allow-Methods', and 'Access-Control-Allow-Headers' headers to faciliate Cross-Origin Resource Sharing (CORS).
Sample Route:
var router = bogart.router();
router.get('/', function(req) {
return bogart.cors({ framework: 'Bogart' });
});
This route yields the following JSGI Response:
{
status: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
'Access-Control-Allow-Headers': 'x-requested-with,*'
},
body: [ '{ "framework": "Bogart" }' ]
}
Redirect
Helper to create an HTTP 302 Temporary Redirect response.
Sample Route:
var router = bogart.router();
router.get('/', function(req) {
return bogart.redirect('/some/other/url');
});
This route yields the following JSGI Response:
{
status: 302,
headers: { 'Location': '/some/other/url' },
body: []
}
Error
Helper to create an HTTP 500 Internal Server Error response.
Sample Route:
var router = bogart.router();
router.get('/', function(req) {
return bogart.error('<html>...</html>');
});
This route yields the following JSGI Response:
{
status: 500,
headers: { 'Content-Type': 'text/html' },
body: [ '<html>...</html>' ]
}
Not Modified
Helper to create an HTTP 304 Not Modified response.
Sample Route:
var router = bogart.router();
router.get('/', function(req) {
return bogart.notModified();
});
This route yields the following JSGI Response:
{
status: 304,
headers: {},
body: []
}
File (Streaming!)
Helper to create an HTTP 200 Success response with a body streamed from the contents of a file. The Content-Type of the response is determined by the mime type of the file.
Sample Route:
var path = require('path');
var router = bogart.router();
router.get('/download/*', function(req) {
var filePath = path.join(__dirname, 'public', req.params.splat[0]);
return bogart.file(filePath);
});
This route yields the following JSGI Response:
{
status: 200,
headers: { 'Content-Type': '<mimetype of the file>' },
body: fileStream // <-- A file stream
}
Proxy (Streaming!)
Helper to create a response that proxies the response from a URL.
Sample Route:
var router = bogart.router();
router.get('/google', function(req) {
return bogart.proxy('http://www.google.com');
});
This route yields a JSGI Response that matches the response from the proxied URL.
Imperative Response Builder
Bogart includes the ResponseBuilder helper to provide an imperative interface. While not
recommended as a goto style of programming in Bogart, there are times when buiding a
response imperatively makes for cleaner, better code. This is true especially
when working with callback based functions that cannot be wrapped by bogart.promisify.
var router = bogart.router();
router.get('/', function(req) {
// Get a ResponseBuilder
var res = bogart.res();
doSomethingAsync(function(err, messageStr) {
res.setHeader('Content-Type', 'text/plain');
if (err) {
res.status(500);
res.send('Error');
return res.end(); // We use return to break out of the function, do not want to continue executing after res.end()
}
res.status(200);
res.send(messageStr);
res.end(); // End the Response. This is analagous to resolving a promise for a JSGI Response.
});
return res;
});
Using Session
The session middleware can be included individually with app.use(bogart.middleware.session) or
by using batteries app.use(bogart.batteries) which includes a default stack of JSGI middleware.
A session function will be available on the request object passed to your route handlers. This
function follows the jQuery style of arity determining if it is getting or setting a key/value pair.
A call to session with one argument is a get to the value of the key referenced by the argument.
req.session('name'); // => value associated with 'name'
A call to session with two arguments is a set.
req.session('name', 'Nathan'); // sets the value of 'name' to 'Nathan'
Contrived Example
A set of two routes that use session:
router.get('/:name', function(req) {
req.session('name', req.params.name);
return bogart.redirect(
Related Skills
node-connect
345.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
104.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。

