| .serena | ||
| examples | ||
| src | ||
| tests | ||
| .gitignore | ||
| .prettierrc | ||
| eslint.config.js | ||
| IMPLEMENTATION.md | ||
| llms.txt | ||
| oxog-serve-prompt.md | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| SPECIFICATION.md | ||
| TASKS.md | ||
| tsconfig.json | ||
| tsup.config.ts | ||
| vitest.config.ts | ||
@oxog/serve
Zero-config development server with proxy, HMR, and auto-HTTPS
A lightweight, zero-dependency development server designed for full-stack developers. Features static file serving, live reload, SPA fallback, automatic HTTPS with mkcert detection, powerful proxy support with WebSocket forwarding, and a flexible plugin system.
Installation
npm install @oxog/serve
Quick Start
import { serve } from '@oxog/serve';
// Minimal usage
const server = await serve('./dist');
// Full configuration
const server = await serve({
root: './dist',
port: 3000,
spa: true,
https: true,
proxy: {
'/api': 'http://localhost:8080'
}
});
CLI Usage
# Serve current directory
npx @oxog/serve
# Serve specific directory
npx @oxog/serve ./dist
# With options
npx @oxog/serve ./dist --port 3000 --spa --open
# HTTPS with CORS
npx @oxog/serve ./dist --https --cors
# Proxy to backend
npx @oxog/serve ./dist --proxy.api=http://localhost:8080
Features
Static File Serving
Serve files with proper MIME types, ETags, and caching headers.
const server = await serve({
root: './dist',
port: 3000
});
Live Reload
Automatic browser refresh on file changes with CSS hot reload.
const server = await serve({
root: './dist',
livereload: {
debounce: 100,
cssReload: true
}
});
SPA Fallback
Support for single-page applications with history API.
const server = await serve({
root: './dist',
spa: true,
// or with options:
spa: {
fallback: 'index.html',
ignore: ['/api', '/assets']
}
});
HTTP/WebSocket Proxy
Forward requests to backend servers.
const server = await serve({
root: './dist',
proxy: {
'/api': 'http://localhost:8080',
'/ws': {
target: 'http://localhost:8080',
ws: true,
rewrite: (path) => path.replace('/ws', '')
}
}
});
Auto-HTTPS
Automatic certificate generation with mkcert support.
const server = await serve({
root: './dist',
https: true,
// or with mkcert:
https: { mkcert: true }
});
CORS
Enable Cross-Origin Resource Sharing for development.
const server = await serve({
root: './dist',
cors: true,
// or with options:
cors: {
origin: ['http://localhost:4200'],
credentials: true
}
});
Compression
Gzip and Brotli compression.
const server = await serve({
root: './dist',
compression: true
});
Directory Listing
Auto-generated file listing for directories.
const server = await serve({
root: './files',
directory: {
icons: true,
sort: 'name'
}
});
Server API
const server = await serve('./dist');
// Get address info
const { host, port, protocol } = server.address();
// Subscribe to events
server.on('request', (req, res) => console.log(req.url));
server.on('change', (path) => console.log('Changed:', path));
server.on('error', (err) => console.error(err));
// Trigger manual reload
server.reload();
// Stop server
await server.close();
// Restart server
await server.restart();
// Add plugin at runtime
server.use(myPlugin);
// Print server URLs
server.printUrls();
Custom Plugins
Create plugins to extend server functionality.
import { serve, type Plugin } from '@oxog/serve';
const loggerPlugin: Plugin = {
name: 'logger',
version: '1.0.0',
install(kernel) {
kernel.middleware(async (req, res, next) => {
console.log(`${req.method} ${req.url}`);
await next();
}, 1); // Priority 1 (runs first)
}
};
const server = await serve({
root: './dist',
plugins: [loggerPlugin]
});
CLI Options
Usage: serve [directory] [options]
Arguments:
directory Directory to serve (default: '.')
Options:
-p, --port <port> Port number (default: 3000)
-h, --host <host> Host to bind (default: localhost)
--spa Enable SPA fallback
--https Enable HTTPS
--cors Enable CORS
--compression Enable compression
--directory Enable directory listing
-o, --open [path] Open browser on start
--no-livereload Disable live reload
--proxy.<path>=<url> Add proxy rule
--help Show help
--version Show version
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
root |
string |
'.' |
Root directory to serve |
port |
number |
3000 |
Port number |
host |
string |
'localhost' |
Host to bind |
livereload |
boolean | object |
true |
Enable live reload |
spa |
boolean | object |
false |
Enable SPA fallback |
https |
boolean | object |
false |
Enable HTTPS |
cors |
boolean | object |
false |
Enable CORS |
compression |
boolean | object |
false |
Enable compression |
directory |
boolean | object |
false |
Enable directory listing |
open |
boolean | string |
false |
Open browser |
proxy |
object |
- | Proxy configuration |
plugins |
Plugin[] |
[] |
Additional plugins |
Error Handling
import { serve, ServeError, isServeError } from '@oxog/serve';
try {
await serve({ port: 3000 });
} catch (err) {
if (isServeError(err)) {
switch (err.code) {
case 'PORT_IN_USE':
console.log('Port is busy, try another');
break;
case 'ROOT_NOT_FOUND':
console.log('Directory not found');
break;
}
}
}
Requirements
- Node.js >= 18
- Zero runtime dependencies
License
MIT - Ersin Koc