# Hosting and maintenance

This folder is a self-contained Node.js documentation site. Markdown files are the canonical content. The server renders HTML, serves screenshots, and offers plain Markdown and JSON entry points for AI agents.

## Run locally

Requirements: **Node.js 22 or newer** and npm.

```powershell
cd C:\git_repos\scishield\documentation
npm ci
npm start
```

Open `http://127.0.0.1:4173`. The application itself does not need to be running to read these guides and screenshots.

On macOS/Linux, change into the equivalent checkout's `documentation` folder and use the same npm commands. The server resolves files relative to its own location, independently of the launch directory.

## Configure host and port

The default listener is `127.0.0.1:4173`. Set `HOST` and `PORT` to change it.

```powershell
$env:HOST = '127.0.0.1'
$env:PORT = '4180'
npm start
```

```bash
HOST=127.0.0.1 PORT=4180 npm start
```

The site is read-only and has no application login. It does not reuse the SciShield session or query live application data. Its screenshots include the captured dataset; use your webserver's authentication/access controls when hosting them for a restricted audience.

## Host behind a webserver

Copy the folder to a server with Node.js, run `npm ci --omit=dev`, and run `node server.mjs` under your preferred service manager. Keep the Node listener on loopback when a reverse proxy runs on the same machine.

Example nginx location inside your existing HTTPS server block:

```nginx
location / {
    proxy_pass http://127.0.0.1:4173;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
}
```

The site uses root-relative URLs. Host it at the root of a dedicated hostname, for example `docs.example.org/`. Mounting it under a subpath such as `/help/` requires adapting the URL generation and asset links. Configure TLS and any required authentication at the reverse proxy.

There is no static HTML build step. A plain static file host alone will serve Markdown but will not provide this HTML renderer or search endpoints.

## Routes for readers and agents

| Route | Response |
| --- | --- |
| `/` | HTML application guide |
| `/docs/training` | HTML rendering of `training.md` |
| `/training.md` | Unwrapped UTF-8 Markdown with `text/markdown` content type |
| `/llms.txt` | Plain-text index linking every Markdown guide |
| `/api/pages` | JSON page titles, HTML URLs, and Markdown URLs |
| `/all.md` | All Markdown guides concatenated |
| `/search?q=training%20overdue` | Server-rendered HTML search results |
| `/api/search?q=training%20overdue` | JSON results with title, slug, and excerpt |
| `/assets/screenshots/home.jpg` | Original captured image |

All guide and search routes work without client-side JavaScript. The small browser script only preserves the search input value. Every rendered guide has a direct **View Markdown** link, and its links to other guides point to HTML. The original Markdown keeps its ordinary relative `.md` links for repository and agent reading.

## Search specification

Search trims the query, splits it on Unicode whitespace, lowercases and deduplicates the terms, and requires every term to occur in a single page's complete Markdown source. Matching is literal substring matching. Terms can appear in any order and in different sections of a page.

Conceptually, the predicate is `contains(word1) AND contains(word2)`. It is equivalent to the requested `LIKE '%word1%' AND LIKE '%word2%'` behavior for ordinary terms, without SQL wildcard interpretation. Percent signs, underscores, punctuation, and quotes are literal. Search does not use a database.

Results follow the guide navigation order. Blank queries return no results. Unknown words return an explicit no-results state. Screenshot pixels and live application data are not indexed.

## Update content

1. Edit an existing root-level `.md` file or add a new one with a single level-one title.
2. Link to another guide with a relative Markdown path, for example `[Training](training.md)`.
3. Put screenshots under `assets/screenshots` and use a relative image reference, for example `![Home page](assets/screenshots/home.jpg)`.
4. Review the image for the intended audience and provide written steps alongside it.
5. Update [Scope and verification](coverage.md) when adding verified screens or changing limits.
6. Reload the guide. Content and search read Markdown at request time.

New `.md` files automatically appear in navigation, search, `/api/pages`, `/llms.txt`, and `/all.md`. The ordering list in `server.mjs` places core guides first; additional guides follow alphabetically. Screenshot files are served as local assets; no CDN or external font service is required.

`capture-evidence.json` is maintainer evidence from the browser exploration. It is not a guide and is not exposed by the Node server. Refresh it only when performing another documentation capture.

## Verify changes

```bash
npm test
```

Tests cover AND search with reversed terms, case and whitespace, literal special characters, no-result queries, raw Markdown and AI indexes, HTML rendering, source links, screenshots, missing routes, request methods, path handling, sanitization, and local Markdown/image links.

The server serves only the guide routes, indexes, and approved assets. Raw HTML in Markdown is sanitized, and a Content Security Policy restricts executable assets to this origin. Dependencies are recorded in `package-lock.json`; use `npm ci` for reproducible installation.
