@yarflam/nodeforest
v1.2.1
Published
Deploy Netlify-like functions as standalone workers
Maintainers
Readme
NodeForest
Deploy Netlify-like serverless functions as standalone workers.
What it does
- You write functions with a Netlify-style
exports.handlersignature. - The client bundles them with Rollup, collects runtime dependencies, snapshots your environment variables, and zips the package.
- The server receives the zip, installs dependencies, and exposes each function behind a dynamic HTTP route.
- Functions run inside an isolated
child_process.forkwith a sandboxed filesystem, blockedchild_process, configurable timeouts and isolatedprocess.env.
Prerequisites
- Node.js 18+
- npm
Installation
git clone <repo-url>
cd nodeforest
npm installCopy the environment example and set your secrets:
cp .env.example .envEdit .env:
PORT=3000
SECRET_KEY=change-me-to-a-long-random-string
JWT_SECRET=another-long-random-stringCLI Commands
Start the server
# Locally
npm start
# Or globally, if installed with -g
nf-serverThe server exposes:
GET /skills.md— API documentation for AI agentsGET /health— HealthcheckPOST /auth— Generate a JWT access tokenPOST /deploy— Upload a worker package (requires token)GET /logs/:service?— View captured worker logs (requires token)ALL /workers/:service/*— Execute a worker function (requires token)
Build and deploy a worker package
Place your Netlify functions in a directory (e.g., ./functions). Each file should export a handler:
// functions/hello.js
exports.handler = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello from NodeForest' }),
};
};The event object follows the Netlify Functions format (httpMethod, path, headers, queryStringParameters, body). event.headers is a plain key-value object.
The context object provides:
| Property | Description |
|----------|-------------|
| env | Merged environment variables from the server process.env and the uploaded .env file. |
Per-function timeout
You can configure a per-function timeout with a comment at the very top of the handler file. The server parses this comment before spawning the worker process.
// # TIMEOUT = 60s
exports.handler = async (event, context) => {
// ...
};The comment format is flexible — spaces around = are optional. These are all valid:
| Example | Result |
|---------|--------|
| # TIMEOUT = 500ms | 500 milliseconds |
| # TIMEOUT = 10s | 10 seconds |
| # TIMEOUT = 2m | 2 minutes |
| # TIMEOUT = 5min | 5 minutes |
| # TIMEOUT = 30 | 30 milliseconds (raw number) |
If no comment is found, the default timeout is 30 seconds (30000 ms). When a worker exceeds its timeout, the server kills the process and returns a Handler timeout error.
Build only
nf-deploy --dir ./functions --out ./package.zipBuild and deploy
nf-deploy \
--dir ./functions \
--service my-service \
--key your-secret-key \
--deploy \
--server http://localhost:3000Parameters:
| Flag | Description | Default |
|------------|--------------------------------------------------|-------------------------|
| --dir | Source directory containing your .js functions | ./functions |
| --out | Output zip path | ./package.zip |
| --server | NodeForest server URL | http://localhost:3000 |
| --key | SECRET_KEY for authentication | required for deploy |
| --service| Service name (must match ^[a-z_-]+$) | required for deploy |
| --deploy | Also upload the package after building | false |
Calling a deployed function
First, get a token:
curl -X POST http://localhost:3000/auth \
-H "Content-Type: application/json" \
-d '{"secret_key":"your-secret-key","service_name":"my-service"}'Then call the function:
curl -H "Authorization: Bearer <access_token>" \
http://localhost:3000/workers/my-service/helloOr with a POST body:
curl -X POST \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"name":"world"}' \
http://localhost:3000/workers/my-service/helloView worker logs
curl -H "Authorization: Bearer <access_token>" \
http://localhost:3000/logs/my-serviceOmit the service name to see logs from all workers:
curl -H "Authorization: Bearer <access_token>" \
http://localhost:3000/logsGlobal installation
To use nf-server and nf-deploy from anywhere:
npm install -g .Authors
- Yarflam
- Claude Code (Kimi K2)
License
This project is licensed under the MIT License.
Security notes
- Keep
.envout of version control (it is already ignored in.gitignore). - Each worker runs in its own
child_process.forkwith a sandboxed filesystem (fsoperations are restricted to the service directory) and a blockedchild_processmodule. A malicious worker can still consume CPU or exhaust memory, so running the server in a container is recommended for stronger isolation. - JWT tokens expire after 1 hour. The deploy endpoint requires a fresh token each time.
