Usage
Porthoster has two halves, joined by a sync. On the client side you keep a local folder of plain JavaScript and author, edit and test handlers in it. On the server side a broker reads that same folder, opens each declared port, and routes accepted traffic to the matching handler.
The join between them is the filename. A top-level file is an entry point when its name matches the handler grammar, and the number in the name is exactly the port that gets opened:
port/
echo.tcp.7000.port.js → TCP :7000 public
metrics.udp.9125.port.js → UDP :9125 public
relay.tcp.4000.port.js → TCP :4000 public
lib/framing.js → supporting code — imported, opens no port
_scratch.tcp.7001.port.js → ignored (leading _ = local only)
Server →
The broker model: how one process opens every port, screens each connection, and hands it to your
handler — the handler contract, the ctx, concurrency, and code examples.
Client →
The local workflow: the port folder, what syncs and what stays local, developing in place with an
_ prefix, and how a set of edits goes live safely.
One folder, two roles
You never write a server. You write the logic for a connection or a datagram, and the broker does
the plumbing — the listen, the accept loop, TLS, and the access checks. Because both sides read the
same flat folder, there is nothing to wire up: rename a file to change its port, prefix it with
_ to take it offline, drop the prefix to put it live.