npm package: @superhighway/loom
Description: Loom is a web server for Node.js. Web pages in Loom use [Silk][silk] for server-side rendering.
Latest version: 0.1.3

# loom

Loom is a web server for Node.js. Web pages in Loom use [Silk][silk] for
server-side rendering.

Loom has filesystem-based routing: when you start the server you provide a
directory containing static files and dynamic request handlers which are used to
serve incoming HTTP requests.

The server avoids buffering response data as much as possible, instead streaming
it to the client as soon as it becomes available.

Example websites powered by Loom & Silk are available in this repository:
<https://github.com/mkantor/silk-demos>.

## Quick Start

This creates a basic "hello world" website:

```sh
npm create loom@latest $path
cd $path
PORT=9999 npm run start
```

There should now be web server running at http://localhost:9999.

## Usage

### `createServer`

Initializes the Loom server, returning an object with a `.listen` method that
you can call to bind it to a specific port.

`createServer` is passed a configuration object with a required
`publicDirectory` property (more on this below) and other optional properties to
specify the server's behavior.

Example:

```ts
const server = createServer({
  publicDirectory: 'path/to/public/directory',
})
await server.listen(80)
```

### The Public Directory

The "public directory" is the folder in your project which corresponds to the
root of Loom's filesystem-based routing scheme. In Loom, the request method is
treated as part of the route, and the public directory is therefore expected to
have a top-level subdirectory for each HTTP method that you want to handle
(`public/get/`, `public/post/`, etc).

File naming conventions within the public directory specify how Loom treats the
file:

- Files whose names end in `#handler.js` (typically compiled from a source file
  named `#handler.tsx`) are dynamic request handlers which may include
  server-side logic. Such files should have a default export created via the
  `page` or `requestHandler` functions (see below). This filename suffix may be
  customized via the `handlerFilenameSuffix` configuration option. Everything
  preceding this suffix corresponds to the request path, meaning your top-level
  index page would be served by `public/get/#handler.js` (an empty prefix), and
  an `/about` page could either be handled by `public/get/about#handler.js` or
  `public/get/about/#handler.js`.
- A file at the root of the public directory named `#error.js` (usually the emit
  of a source file named `#error.tsx`) can be used to implement custom error
  pages. This file should have the same structure as request handlers. The
  path/filename of this file may be customized via the `errorHandler`
  configuration option.
- All other files in the public directory are treated as static files and are
  served directly.

### `page` & `requestHandler`

The default export of dynamic handler modules should be wrapped in a `page` or
`requestHandler` call.

Example:

```ts
export default page(request => (
  <html lang="en">
    <head>
      <title>Greeting</title>
    </head>
    <body>Hello, world!</body>
  </html>
))
```

- Use `page` if you need a dynamic response body but want Loom to take care of
  the response headers/status code. The value you return should be a
  `ReadableHTMLStream` (likely generated by [Silk][silk]).
- Use `requestHandler` if you want full control over the entire response,
  including headers/status code/etc. The value you return should be a complete
  [`Response`][web-response] object.

[silk]: https://github.com/mkantor/silk
[web-response]: https://developer.mozilla.org/en-US/docs/Web/API/Response