![]()
Baxxon Documentation
Baxxon is a minimalist, structural web framework for Node.js that is designed to be learned in minutes, not days. This guide will you get started.
Getting Started
Installation
Baxxon is available via npm. Create a new directory and install it to begin.
mkdir my-baxxon-project && cd my-baxxon-project
npm install baxxon
npx baxxon init
Virtual Hosting (VHosts)
Baxxon includes a built-in VHost engine that allows you to host multiple domains from a single installation. By default these are located in the my-app/sites/ directory. Each site directory include site specific content and scripts. When no vhost can be parsed from the request URL then content is served from the my-app/sites/_default directory.
Configuration
While Baxxon follows convention-over-configuration, you can customize framework behavior via the "baxxon" key in your package.json. Here you can override defaults like directory names, but most importantly this is where map hostnames to subdirectories within your sites/ folder:
"baxxon": {
"vhosts": {
"domainDirs": {
"example.com": "my-site",
"api.example.com": "my-api"
}
}
}
Project Initialization
You must run npx baxxon init to initialize your project. Baxxon will prompt you to create a sites/ directory with a "Hello World" example. This is the fastest way to see the framework in action.
Adding Virtual Hosts
You can scaffold a new site directory and map it to a hostname in one command:
npx baxxon add example.com my-site
Loading Examples
If you want to explore different architectural patterns, you can use the Baxxon CLI to load specific examples. You can also specify an optional destination directory.
npx baxxon load static [dest] # For a pure HTML/CSS experience
npx baxxon load dynamic [dest] # For server-side JS Modules
npx baxxon load api [dest] # For client-side interaction & APIs
npx baxxon load spa [dest] # For a full Single Page Application
Environment Variables
You can also override ports and host settings using standard environment variables:
BAXXON_PORT_HTTP: Default 3000BAXXON_PORT_HTTPS: Default 3001BAXXON_HOST: Default 0.0.0.0
Core Concepts
The Visual Contract
Baxxon eliminates routing ambiguity by splitting the web into two mutually exclusive categories based on the URL structure:
- Physical Assets (Static): URLs containing a dot (e.g.,
/style.css,/logo.png) are treated as static files. Baxxon serves these directly from thepublic/directory with proper MIME types and caching headers. - Dynamic Logic (JS Modules): URLs without a dot (e.g.,
/about,/api/user) are routed to themodules/directory. These are standard JS Modules exporting a request handler.
Cascading Module Resolution
When a dynamic URL is requested, Baxxon uses a deterministic resolution order to find the matching module. For a request to /about, the framework checks for files in this exact order:
modules/about.js(Exact module match)modules/about/index.js(Directory default)modules/index.js(Site-wide default fallback)
Dynamic Logic via JS Modules
Baxxon believes in "No Magic." Your dynamic routes are handled by standard Node.js JS Modules. Each module exports a default function that receives the bx controller.
// modules/index.js
export default function(bx){
bx.render.HTML('<h1>Hello World</h1>');
}
The Slash-Param Engine
Baxxon uses a deterministic parser that treats trailing URL segments as data. This eliminates the need for complex regex routers or centralized configuration files.
// URL: /shop/shoes/color/red/size/10
// Access as a raw positional array
bx.params // ["shoes", "color", "red", "size", "10"]
// Access as Key/Value pairs via standard URLSearchParams
bx.reqURL.searchParams.get('color') // "red"
Consistent API Logic
Baxxon implements an API paradigm that uses the same render logic and filesystem structure as other output methods.
In Baxxon, an API is simply a JS module that returns JSON. The framework uses the same logic and directory structure for APIs as it does for HTML pages, ensuring a unified development experience.
Automatic Body Parsing
Baxxon automatically handles the boilerplate of reading request streams. For POST requests, the parsed body is available instantly on the controller:
- JSON: Content-Type
application/jsonis parsed into a JS object. - Forms: Content-Type
application/x-www-form-urlencodedis parsed into Key/Value pairs.
// Accessing parsed data in modules/api/user.js
export default function(bx) {
const userData = bx.server.req.body;
bx.render.JSON({
status: "received",
data: userData
});
}
Files as Database (TextDB)
Baxxon encourages transparency by using the filesystem as the primary data store. Folders act as tables and .txt files act as records. This makes your data human-readable, version-controllable, and easy to audit without specialized tools.
Deterministic Error Handling
Because of the Visual Contract, Baxxon knows exactly when a file is missing or invalid. This eliminates the "silent failures" common in more complex frameworks. Requests are evaluated instantly against the filesystem:
- 404 Not Found: Triggered when a static asset isn't in
public/or a JS module isn't inmodules/. - 415 Unsupported File Type: Triggered when a physical asset has an extension not defined in the safety whitelist, preventing execution of unauthorized scripts.
The Controller API ( bx )
The bx object is the "No Magic" interface passed to every JS Module. It provides direct access to the request, response, and framework utilities.
Properties
bx.params: An array of positional parameters parsed from the URL.bx.reqURL: A standard Node.jsURLobject representing the current request.bx.host: The requested hostname (from theHostheader).bx.server.req.body: The automatically parsed body for POST requests.bx.paths: An object containing the generated absolute paths for the current request:bx.paths.doc: The root directory of the Baxxon framework.bx.paths.app: The root directory of your application.bx.paths.site: The root directory of the current site.bx.paths.stat: The static assets directory.bx.paths.mod: The JS modules directory.
Rendering Methods
Terminates the request and sends a response. These methods are consistent across both pages and APIs.
bx.render.HTML(string): Standard HTML response.bx.render.JSON(object): API-ready JSON response. Note: The root must be an object.bx.render.TEXT(string): Plain text response.bx.render.MARKDOWN(string): Converts Markdown to HTML and renders it.bx.render.FILE(filename): Streams a file from thepublic/directory (ideal for custom asset logic).
Content Rendering & Templates
Baxxon's content rendering allows you to build dynamic pages by composing static fragments.
bx.renderContent(filename, vars): Loads a file from themodules/directory and optionally replaces{placeholder}tags.- Markdown Native: If the file extension is
.md, Baxxon automatically parses the content into HTML using the integratedmarkedengine. bx.templates: A minimalist engine for merging data into reusable HTML structures using{placeholder}syntax.
// modules/about.js
export default function(bx){
// render content from intro.md
// replace {name} with "Baxxon"
const content = bx.renderContent(
'content/intro.md', {
name: "Baxxon"
}
);
bx.render.HTML(`
<main>
<div>${content}</div>
</main>
`);
}
Logging
Use the built-in log for clean, categorized terminal feedback.
bx.log: A unified logger for framework-consistent console output (Note, Warn, Error).
bx.log.note( "This is a message" );
bx.log.warn( "This is a Pro Tip: If you have run npm link inside the baxxon folder, you can simply type baxxon load
<type> from your project root without needing to point to the node path every time. warning message" );
bx.log.error( "This is an error message" );
Template Engine
Baxxon includes a recursive, string-based template engine that uses standard {placeholder} syntax. It is the same engine used to render framework error pages.
Usage
Initialize: Define your template structures.
bx.templates.init({ root: `<html><body>{body}</body></html>`, body: `<h1>{title}</h1>{content}` });Set Variables: Inject data into specific templates.
bx.templates.get('body').setVars({ title: "My Page", content: "<p>Hello World</p>" });Recursive Merging: Merge a template and all its nested placeholders.
// Automatically merges 'body' into 'root' if {body} is found const html = bx.templates.merge('root'); bx.render.HTML(html);
Appending Content
Use pushVar to append strings to an existing placeholder instead of overwriting it. You can also use pushVars to append multiple variables at once:
bx.templates.get('body')
.pushVar('content', '<p>More content...</p>');
bx.templates.get('body')
.pushVars({
content: '<p>Even more content...</p>',
title: ' (Updated)'
});
Client API Utility
Baxxon provides a production-grade, resilient API class for client-side communication. It is designed to handle the instability of real-world networks without complicating your application logic.
Configuration
Instantiate the utility with a configuration object:
import API from "/js/baxxon/api.js";
const api = new API({
requestURI: "/api/user",
maxRetry: 5, // Maximum attempts on network failure
initialDelay: 1000, // Starting backoff delay (ms)
maxBackoff: 30000, // Maximum backoff cap (ms)
pingAction: "ping" // Endpoint for connectivity checks
});
Methods
async send(action, payload): Executes an asynchronous POST request. It automatically manages the retry loop with exponential backoff and returns a structured response object.async isReachable(): A lightweight utility that performs aHEADrequest to verify the server is reachable.setBaseURI(uri): Updates the root API path dynamically.
Response Contract
The send method returns a standardized object, ensuring your UI can react predictably to any condition:
- Success: Returns the parsed JSON data from the server.
- Failure: Returns
{ success: false, error: { type, msg, status, attempt } }.
Additionally, the API client dispatches a global api-failure CustomEvent on the window object whenever a critical failure occurs, allowing the application to intercept connection drops deterministically.
Error Types: http (Server errors), network (Connection lost), parse (Invalid server response), offline (Requested while connectivity is known to be lost), and bad request (Missing configuration).
TextDB
A lightweight, flat-file database engine. It parses .txt files into JavaScript objects and maintains a live cache of your filesystem data.
Configuration
Customize TextDB behavior via the constructor options:
import TextDB from 'baxxon/textdb';
const db = new TextDB({
rootPath: './data',
dirs: ['posts', 'users'],
fileFields: ['category', 'slug'], // Generates filenames: category-slug.txt
fileFieldsJoin: '-'
});
Record Format
TextDB uses a simple, human-readable format for its records. Each file consists of Header: Value pairs, followed by a double-newline and the record body.
Title: My First Post
Author: Lorne Taylor
Date: 2026-05-09
This is the body of the post. It can contain any text, including Markdown.
Reading Data
await db.setData(): Scans the filesystem and hydrates the internal cache.db.getData(): Returns a flat object containing all records indexed by ID (e.g.,posts/my-post).
Writing Data
TextDB supports atomic, asynchronous writes using file locks and temporary files.
db.addRecord(dir, meta, body): Adds a new record to the cache.db.updateRecord(id, meta, body): Updates metadata or body of an existing record.db.removeRecord(id): Marks a record for deletion.await db.write(): Persists all pending cache changes to the physical filesystem.
CLI
The Baxxon CLI is your primary tool for project initialization and rapid prototyping. It is available immediately after installing the baxxon package.
Audit Logging
For improved observability, all CLI operations and errors are automatically recorded in a cli.log file in your project root. Each entry is timestamped (ISO format), providing a durable audit trail for troubleshooting initialization or configuration issues.
Initialization
Running the baxxon command in your app directory triggers the interactive setup. This utility validates your environment and offers to create the standard sites/_default directory structure, including your first JS Module and a baseline CSS file.
cd <my-baxxon-app>
npx baxxon init
Adding Virtual Hosts
The add command scaffolds a new site directory and registers the hostname mapping in your package.json simultaneously.
npx baxxon add <domain> [dir]
Validation Guards:
- Domain Collision: The CLI will abort if the specified domain is already registered in your configuration.
- Directory Overwrite: If the target directory already exists, you will be prompted for confirmation before it is modified.
Loading Examples
The load command allows you to inject standalone tutorial sites into an existing site directory. This is the fastest way to explore different architectural patterns or to start a new project from a proven template.
cd <my-baxxon-app>
npx baxxon load <type> [dest]
Validation Guards:
- Type Verification: The CLI strictly validates the example type. Providing an invalid type (or reversing the arguments) will result in an error message and an abort.
- Existence Check: The destination directory (
[dest]) must already exist and be mapped in yourvhostsconfiguration. If it does not exist, the CLI will direct you to usebaxxon addfirst.
Available Example Types:
static: A zero-config baseline demonstrating pure HTML/CSS serving and the "Visual Contract" for physical assets.dynamic: Showcases server-side JS Modules, the Slash-Param Engine, and the native Template Engine.api: Demonstrates client-server interaction and Network Resiliency. Features theAPIutility with built-in Exponential Backoff, robust error handling, and connectivity tracking.spa: A complex Single Page Application template featuring the TextDB Engine, automatic data lifecycle management, and Optimistic UI.
Note: Loading an example will overwrite existing files in your
sites/_defaultdirectory. It is recommended to use this command in a clean project or to back up your work before proceeding.
Pro Tip: If you have run npm link inside the baxxon directory, you can simply type baxxon load