
🐣 Fledge
Build & bundle tool for modern JavaScript applications
From nestling to flight-ready.
Transforms your development application into production-ready deployables across three distinct modes: static site generation, optimized script bundling, and standalone binary compilation. No framework lock-in, no complex build chains—Fledge operates at the protocol and filesystem level to prepare your code for any deployment target.
Built on Wings Terminal for surgical CLI precision with automatic flag validation, comprehensive error handling, and intuitive command routing.
Whether you need CDN-optimized static files, performance-tuned JavaScript bundles, or self-contained native executables, Fledge systematically processes your application and delivers deployment artifacts. Your development workflow stays untouched—Fledge hunts at the boundaries where development ends and deployment begins.
Installation
npm install -D @raven-js/fledge
Usage
Fledge transforms development applications through three hunting modes, each targeting different deployment scenarios:
🌐 Static Mode - CDN-Ready Sites
Transform any HTTP server into static files optimized for edge deployment.
Config-as-Code
Fledge configuration is executable JavaScript—not JSON, not YAML, but real code with imports, variables, and conditional logic. Three input methods with clear precedence:
echo "export default {server: 'http://localhost:3000'}" | fledge static --out dist
fledge static fledge.config.js --out dist
fledge static --server http://localhost:3000 --out dist
Configuration Example:
export default {
server: "http://localhost:3000",
routes: ["/shop", "/about", "/contact"],
discover: {
depth: 3,
ignore: ["/admin", "/api/*"],
},
basePath: "/my-app",
assets: "./public",
output: "./dist",
};
export const productionConfig = {
server: async ({ port }) => {
const { createServer } = await import("./server.js");
await createServer().listen(port);
},
routes: async () => {
const products = await fetchProducts();
return products.map((p) => `/product/${p.slug}`);
},
};
Lean Resolver Mode (Advanced)
For maximum performance, bypass HTTP entirely with direct function resolution. Perfect for wings/core Context integration or custom routing systems:
export default {
resolver: async (path) => {
const ctx = await myRouter.resolve(path);
return ctx.toResponse();
},
routes: ["/", "/about", "/api/data"],
discover: false,
output: "./dist",
};
export const customResolver = {
resolver: async (path) => {
const routes = {
"/": "<html><body><h1>Home</h1></body></html>",
"/about": "<html><body><h1>About</h1></body></html>",
"/api/data": JSON.stringify({ message: "Hello API" }),
};
const content = routes[path] || "<html><body>404 Not Found</body></html>";
const contentType = path.startsWith("/api/")
? "application/json"
: "text/html";
const status = routes[path] ? 200 : 404;
return new Response(content, {
status,
headers: { "content-type": contentType },
});
},
routes: ["/", "/about", "/api/data"],
};
Resolver vs Server Mode:
| Performance | HTTP overhead | Direct function calls |
| Setup | Requires running server | Zero server boot time |
| Flexibility | Any HTTP server | JavaScript function only |
| Use Case | Existing apps, dev servers | Performance-critical, wings integration |
Note: Specify exactly one of server OR resolver—not both. Resolver mode eliminates HTTP serialization overhead for maximum static generation performance.
Blackbox Server Integration
Fledge treats your server as a blackbox—it doesn't care about your framework, build tools, or internal architecture. Just serve HTTP responses:
const servers = [
"http://localhost:3000",
"http://127.0.0.1:5173",
"http://localhost:8080",
async ({ port }) => {
const server = createYourServer();
await server.listen(port);
},
];
Boot Function Pattern:
export default {
server: async ({ port }) => {
const { app } = await import("./src/server.js");
await setupDatabase();
await app.listen(port);
console.log(`Server ready on port ${port}`);
},
routes: ["/"],
discover: true,
};
Crawling Process
The crawling process is deterministic and comprehensive:
- Server Boot: Fledge allocates an OS port and boots your server function or connects to existing URL
- Route Seeding: Initial routes added to crawl frontier
- Systematic Crawling: Each URL fetched with attempt tracking, redirects followed manually
- URL Discovery: HTML responses parsed for
<a>, <img>, <link> tags—relative URLs added to frontier
- Asset Processing: Static assets saved with original paths, HTML saved as directory indexes
- URL Rewriting: If
basePath configured, all internal links rewritten for subdirectory deployment
- Cleanup: Server killed gracefully, statistics reported
Crawl Example:
fledge static --server http://localhost:3000 --out dist
fledge static config.js --validate --verbose --out ./build
fledge static prod.config.js --base /my-app --out dist
Discovery Control:
export default {
server: "http://localhost:3000",
routes: ["/"],
discover: {
depth: 2,
ignore: [
"/admin/*",
"/api/*",
"*.pdf",
],
},
};
export const staticRoutes = {
server: "http://localhost:3000",
routes: ["/home", "/about", "/contact", "/pricing"],
discover: false,
};
⚡ Script Mode - Server-Side Bundles
Transform your Node.js application into self-contained bundles with embedded assets for lightweight distribution.
fledge script src/server.js --out dist/bundle.js
Generates single JavaScript files that include all dependencies and assets, running anywhere Node.js is installed. Optimal for CLI tools, FaaS environments, and scenarios requiring minimal deployment footprint without external dependencies or asset directories.
Target deployment scenarios:
- CLI tools and utilities
- AWS Lambda / Serverless functions
- Lightweight server applications
- Development tool distribution
🔧 Binary Mode - Native Executables
Transform your Node.js application into native executables using Node.js SEA (Single Executable Applications) with embedded code and assets.
Config-as-Code
Binary configuration supports the same executable JavaScript pattern as other modes:
echo "export default {entry: './src/server.js'}" | fledge binary --out dist/myapp
fledge binary fledge.config.js --out dist/myapp
fledge binary fledge.config.js:binary --out dist/myapp
fledge binary src/server.js --out dist/myapp
Configuration Example:
export const binary = {
entry: "./src/server.js",
output: "./dist/myapp",
bundles: {
"/app.js": "./src/client.js",
"/admin.js": "./src/admin.js",
},
assets: ["./public", "./templates", "./config.json"],
env: {
NODE_ENV: "production",
API_BASE: "https://api.example.com",
},
sea: {
disableExperimentalSEAWarning: true,
useSnapshot: false,
useCodeCache: true,
},
signing: {
enabled: true,
identity: "Developer ID Application: Your Name (XXXXXXXXXX)",
},
metadata: {
name: "My Application",
version: "1.0.0",
description: "Standalone server application",
},
};
export const productionBinary = {
entry: "./boot.js",
output: `./dist/myapp-${process.platform}-${process.arch}`,
bundles: async () => {
const pages = await import("./src/pages.js");
return pages.getClientBundles();
},
assets: () => {
const base = ["./public", "./templates"];
if (process.env.INCLUDE_DOCS) {
base.push("./docs");
}
return base;
},
env: {
NODE_ENV: "production",
BUILD_TIME: new Date().toISOString(),
},
};
Binary Generation Process
The binary compilation process is systematic and comprehensive:
- Configuration Loading: Parse config from pipe, file, or CLI flags with named export support
- Asset Resolution: Resolve and validate all asset paths, compute file hashes
- Client Bundling: Use ESBuild to create optimized browser bundles with minification
- Server Bundling: Bundle your Node.js application with embedded asset references
- SEA Configuration: Generate Node.js SEA config with embedded assets and environment variables
- Binary Creation: Copy Node.js runtime and inject application blob using postject
- Code Signing: Sign macOS executables with developer certificates (optional)
- Validation: Test executable launch and report statistics
Generation Example:
fledge binary src/server.js --out dist/myapp
fledge binary config.js:binary --validate --verbose
fledge binary prod.config.js --out dist/myapp-v1.0.0
Generates truly standalone executables containing the Node.js runtime, your application code, and all assets. Larger file size (~100MB) but zero external dependencies—works like Go or Rust binaries. Current platform only, perfect for VPS deployments that skip containerization entirely.
Real-World Example:
export const binary = {
entry: "./boot.js",
output: "./dist/helloworld",
bundles: {
"/app.js": "./src/client.js",
"/admin.js": "./src/admin.js",
},
assets: ["./public", "./src/templates"],
env: {
NODE_ENV: "production",
PORT: "3000",
},
signing: { enabled: true },
metadata: {
name: "HelloWorld Server",
version: "1.0.0",
},
};
npm run bundle:binary
scp dist/helloworld user@server:/opt/myapp/
ssh user@server '/opt/myapp/helloworld'
Target deployment scenarios:
- VPS server deployments (alternative to Docker)
- Desktop applications and CLI tools
- Edge computing without Node.js runtime
- Distribution to environments without package managers
CLI Reference
Static Mode
fledge static [config.js] [options]
echo "export default {server: 'http://localhost:3000'}" | fledge static --out dist
fledge static myconfig.js --out dist
fledge static --server http://localhost:8080 --out dist
fledge static myconfig.js --validate
--server <url> Server origin (e.g. http://localhost:3000)
--out <path> Output directory (default: ./dist)
--base <path> Base path for URLs (default: /)
--validate Validate config and exit
--verbose, -v Verbose output
--help, -h Show help
Script Mode (Coming Soon)
fledge script <entry> [options]
fledge script src/server.js --out dist/bundle.js
fledge script src/cli.js --assets public/ --out dist/tool.js
fledge script src/lambda.js --out dist/function.js
--out <path> Output bundle file
--assets <dir> Directory to embed in bundle
--minify Enable minification (default: true)
--node <version> Target Node.js version (default: 22)
Binary Mode
fledge binary [config.js[:exportName]] [options]
echo "export default {entry: './src/server.js'}" | fledge binary --out dist/myapp
fledge binary config.js --out dist/myapp
fledge binary config.js:binary --validate --verbose
fledge binary src/server.js --out dist/myapp
--out <path> Output executable file
--export <name> Named export from config file
--validate Validate config and exit
--verbose, -v Verbose output
--help, -h Show help
Requirements
Static Mode
- Node.js 22.5+
- ESM-only environment (
"type": "module" in package.json)
- HTTP server running on localhost during build
Script Mode (Coming Soon)
- Node.js 22.5+
- Server-side JavaScript entry point
- Assets and dependencies accessible at build time
Binary Mode
- Node.js 22.5+
- Node.js SEA (Single Executable Applications) support
- Current platform only (builds for the platform you're running on)
- macOS: Xcode Command Line Tools (for code signing)
- Sufficient disk space (~100MB per executable)
The Raven's Fledgling
Young ravens undergo systematic development before their first solo hunt—observing prey patterns, practicing flight mechanics, learning territory boundaries. Fledge transforms development applications through the same methodical progression: static crawling for CDN deployment, server-side bundling for lightweight distribution, native compilation for standalone survival. Each mode represents a different deployment maturity, preparing your code to thrive in environments where weak applications perish from dependency failures.
🦅 Support RavenJS Development
If you find RavenJS helpful, consider supporting its development:

Your sponsorship helps keep RavenJS zero-dependency, modern, and developer-friendly.
Built with ❤️ by Anonyfox