nex-protocol 0.1.1

An implementation of the Nex protocol (nex://): async client, directory-serving server, listing parser, and a CLI. The minimal smolweb protocol — plaintext TCP, no TLS, no status codes.
Documentation

nex-protocol

Home: mark-ik/serval, at components/errand/protocols/nex-protocol (adopted 2026-07). The former standalone repository is archived and links here.

A Rust implementation of the Nex protocol (nex://): an async client, a directory-serving server, a listing parser, and a small CLI.

Nex, from nightfall.city, is the minimal smolweb protocol, inspired by gopher and gemini. The whole wire format: the client connects to TCP port 1900 and sends a path (which may be empty); the server responds with text or binary data and closes the connection. No TLS, no status codes, no headers, no state. The spec lives at nex://nightfall.city/nex/info/specification.txt.

This crate is independent and unaffiliated with the protocol's author. The crates.io name is qualified (nex-protocol) because the bare nex name is used by an unrelated project.

Library

use nex_protocol::{fetch, parse_listing, ListingLine, FetchOptions};

let body = fetch("nex://nightfall.city/", &FetchOptions::default()).await?;
for line in parse_listing(&String::from_utf8_lossy(&body)) {
    if let ListingLine::Link { url, .. } = line {
        println!("{url}");
    }
}

Serving is a Handler (any async closure) plus serve; FileHandler serves a directory tree — index.nex per directory when present, else a generated => listing — with traversal protection.

CLI

cargo install nex-protocol --features cli

nex fetch nex://nightfall.city/
nex serve --root ./site --listen 0.0.0.0:1900

Spec coverage

Spec point State
Selector request (path, may be empty), response = bytes until close client + server
Port 1900 default both sides
Directory listing format (=> link lines, absolute or relative URLs) parser + generated listings
Empty path / trailing / = directory is_directory_path, honored by FileHandler
Extension-based display, plain text default left to the consumer (a transport crate doesn't render); FileHandler serves bytes verbatim

Notes on choices the spec leaves open: link-line labels (text after the URL) are preserved as a client convention; the selector line accepts bare LF as well as CRLF (the spec's own example is a telnet session); over-long selectors just close the connection, since nex has no error channel.

License

MIT. The specification text declares no license; this implementation is original code.