Sxo
SXO is a multi-runtime server-side JSX tool for Node.js, Bun, Deno, and Cloudflare Workers. It includes SXOUI, a framework-agnostic UI library inspired by shadcn/ui
Install / Use
/learn @gc-victor/SxoREADME
Server-Side JSX. Build Simple. Build Fast
A fast, minimal architecture convention and CLI for building websites with server‑side JSX. No React, no client framework, just composable JSX optimized for the server, a clean directory-based router, hot replacement, and powered by esbuild plus a Rust JSX transformer.
Multi-Platform Library: SXO runs seamlessly across Node.js, Bun, Deno, and Cloudflare Workers. The CLI automatically detects your runtime and loads the optimized adapter, while providing a consistent development and production experience across all platforms.
Table of Contents
- Why SXO
- Key Features
- Multi-Runtime Support
- Architecture Overview
- Quick Start
- SXOUI Component Library
- Examples
- Platform Adapters
- Routing Guide
- Page Module API
- Middleware
- Hot Replace (Dev)
- Build Outputs & Manifest
- Static Generation & Production Behavior
- HTML Template and Styles
- Static Asset Serving
- Configuration
- Environment Variables
- JSX Transformer & Runtime Helpers
- Performance and DX
- Security
- Testing
- Deployment
- Acknowledgements
- Contributing
- License
- Contact
Why SXO
- Server-side JSX, zero client framework by default.
- Directory-based routing that stays explicit (route = folder with
index.(jsx|tsx)). - Composable HTML ergonomics using plain functions.
- Blazing-fast builds via esbuild and a Rust/WASM JSX transform step.
- Single CLI covering dev, build, start & clean.
- Predictable output: public client bundle + private server bundle + manifest.
- Multi-Runtime Support: Deploy to Node.js, Bun, Deno, or Cloudflare Workers.
Key Features
- Directory-based routing: each directory is a route and can include dynamic parts (for example a post ID or slug) which are provided to the page at render time.
- Full HTML page components: each page's render function returns a complete <html> document (including <head> and <body>).
- Full-document pages: each page is self-contained and returns its own
<html>,<head>, and<body>. - Optimized for Reactive Components: pair with tiny primitives from reactive-component to add islands only where needed.
- Dev server: hot replace (SSE partial replacement) and auto-open with readiness probe.
- Production server: minimal core (bring your own policy via middleware).
- Dual build outputs: client assets use hashed filenames; separate server bundles (never exposed publicly).
- Rust-powered JSX transformer: fast + small runtime helpers.
- Platform Adapters: First-class support for Node.js, Bun, Deno, and Cloudflare Workers.
- Configurable esbuild loaders for server build: assign loaders per file extension via config, env, or CLI flags (e.g.,
--loaders ".svg=file" --loaders ".ts=tsx"). - Configurable public base path for assets: set via flag (
--public-path), env (PUBLIC_PATH), or config; empty string "" allowed for relative URLs.
Multi-Runtime Support
SXO is designed as a truly multi-runtime library that runs seamlessly across different JavaScript runtimes:
- Node.js: Full-featured production server with HTTP/2 support, timeouts, and graceful shutdown
- Bun: High-performance runtime with native file I/O optimizations
- Deno: Secure-by-default runtime with native TypeScript support
- Cloudflare Workers: Edge computing with distributed deployment
How It Works
The SXO CLI automatically detects your JavaScript runtime and loads the appropriate platform adapter:
# Same command works everywhere
npx sxo dev # Development server
npx sxo start # Production server
Runtime Detection: The CLI checks globalThis.Bun and globalThis.Deno to identify the current platform, falling back to Node.js. Each adapter uses platform-native APIs (e.g., Bun.serve(), Deno.serve(), http.createServer()) for optimal performance.
Shared Core Logic: All adapters share the same Web Standard-based core (Request/Response), ensuring consistent behavior across platforms. Routing, SSR, static file serving, and middleware execution work identically everywhere.
Cloudflare Workers: Due to its unique environment, Cloudflare Workers requires a custom entry point using the sxo/cloudflare export and a factory pattern (see Platform Adapters).
Architecture Overview
Model
- Source Directory (default
src) containing:- Optional
componentsdirectory with JSX components - Optional
utilsdirectory with utility functions - Optional
middleware.jsdefining user middleware chain
- Optional
- Pages Directory (default
src/pages) containing:global.css(optional)- Route directories each with an
index.(tsx|jsx)
- Entry Point Discovery
- Each directory containing an
index.*page file becomes a route. - Optional
<clientDir>/index.(ts|tsx|js|jsx)inside that route directory is added as a client entry (defaultclientDiris "client"; precedence: .ts > .tsx > .js > .jsx). global.css, if present, is added as a shared stylesheet entry for every route.
- Each directory containing an
- Build
- Client bundle →
dist/client - Server bundle (SSR modules) →
dist/server - Manifest →
dist/server/routes.json
- Client bundle →
- Runtime
- Dev: SSE hot replace updates the <body> innerHTML and re-applies relevant asset tags.
- Prod: Minimal HTTP server loads server bundles (ESM) and injects JSX output.
Aliases Available in both client & server builds:
@components -> src/components
@pages -> src/pages
@utils -> src/utils
Quick Start
Install & run (no install needed if using npx):
npx sxo dev
or
pnpm dlx sxo dev
Example structure:
your-app
├── src
│ ├── middleware.js
│ ├── components
│ │ ├── Page.jsx
│ │ └── Header.jsx
│ └── pages
│ ├── global.css
│ ├── index.jsx
│ └── about
│ ├── index.jsx
│ └── client
│ └── index.js
└── package.json
Example component:
// src/components/Page.jsx
export function Page({ children }) {
return <div className="page">{children}</div>;
}
Example page:
// src/pages/index.jsx
import { Header } from "@components/Header.js";
export default () => (
<html lang="en">
<head>
<meta charSet="UTF-8" />
<title>Home</title>
</head>
<body>
<Header title="Home" />
<p>Welcome to SXO.</p>
</body>
</html>
);
Commands:
sxo create <project> # Create a new SXO project from templates (prompts for runtime; defaults to node)
sxo add <component> # Add a component from the basecoat library to src/components
sxo dev # Start the development server with hot replace
sxo build # Build the project for production (client and server bundles)
sxo start # Start the production server to serve built output
sxo clean # Remove the output directory (clean build artifacts)
sxo generate # Pre-render static routes to HTML after a successful build
Create a new project:
# Create a new project in a new directory
sxo create my-app
# Create a project in the current directory
sxo create .
# Or omit the name entirely (uses current directory name)
sxo create
Runtime Selection:
When you run the command, you'll see an interactive prompt to select your target runtime:
Select a runtime:
1) node (default)
2) bun
3) deno
4) workers
>
- Press Enter → selects
node(default) - Type
1→ selectsnode - Type
2→ selectsbun - Type
3→ selectsdeno - Type
4→ selectsworkers(Cloudflare Workers)
In non-interactive environments (CI, tests), the prompt is skipped and node is used automatically.
Templates are fetched from the gc-victor/sxo repository under templates/<runtime>/....
Existing Directory:
If the target directory already exists, you'll be prompted to confirm overwriting:
Create SXO template in "my-app"? (This will overwrite existing files.) (y/N)
Full Example Workflow:
# 1. Create the project
sxo create my-app
# 2. Select runtime when prompted (or press Enter for node)
# > 2 (selects bun)
# 3. Follow the next steps printed by the CLI
cd my-app
pnpm install
pnpm run dev
Add components from SXOUI:
# Add a button component
sxo add button
# Add a dialog component
sxo add dialog
# Components are installed to src/components/
# Browse all available components at https://sxoui.com
SXOUI Component Library: SXO includes access to 25+ production-ready components via the sxo add command. Visit sxoui.com to browse the complete component library with live demos, accessibility documentation, and copy-paste ready code examples.
Point to a different pages directory:
sxo build --pages-dir examples/node/src/pages
sxo start --pages-dir examples/node/src/pages --port 4011
Configure custom esbuild loaders for the server build:
# Via CLI flags (repeatable or comma-sepa
