# Nosterm

Nosterm — a terminal-style Nostr chat application

**A terminal-style Nostr chat client.** The Nosterm web client: a terminal-style Nostr chat SPA built with [SvelteKit](https://kit.svelte.dev/) and served as static files by [Caddy](https://caddyserver.com/). Nostr is a client-side protocol, so there is no application backend here — the browser talks directly to relays over WebSocket. Run a relay from the companion [nosterm-relay](https://git.nerdworks.io/nerdworks/nosterm-relay) repository if you want your own home relay. This is the **public, contribution-focused** repository for the Nosterm client. Open a pull request against `main` — see [CONTRIBUTING.md](CONTRIBUTING.md). Each merge to `main` builds the container image and publishes it to ECR Public for anonymous pulls (see [Deploy](#deploy)). ## Layout ``` nosterm-client/ src/ # SvelteKit source (components, stores, nostr, commands…) static/ # static assets Dockerfile # build the SPA → serve with Caddy Caddyfile # static file server + security headers + optional /relay proxy docker-compose.yml # one-command deploy on port 8080 .env.example # copy to .env and configure package.json # dev/build/test scripts ``` ## Develop ```bash npm install npm run dev # vite dev server npm run check # svelte-check (type-check) npm run lint # prettier --check + eslint npm test # vitest npm run test:e2e # playwright npm run build # static build → ./build ``` ## Deploy ```bash cp .env.example .env # then set NOSTERM_DEFAULT_RELAYS at minimum docker compose up -d --build ``` The client is then served at . To run the prebuilt public image with your own relays — no rebuild, no AWS account (anonymous pull from ECR Public): ```bash docker run -p 8080:80 \ -e NOSTERM_DEFAULT_RELAYS=wss://relay.example.com \ public.ecr.aws/k3k1z1x5/nosterm:latest ``` `NOSTERM_DEFAULT_RELAYS` accepts a comma-separated list. On startup the container's entrypoint writes it to `/config.json`, which the SPA fetches on load — so one shared image serves every deployment with different relays. ## Configuration Relays are configured at **runtime** (`NOSTERM_DEFAULT_RELAYS`), so a single prebuilt image works for any deployment. The remaining `PUBLIC_*` tunables are **build-time** args baked into the browser bundle (client-visible, never secrets) — change one → rebuild the image. **Runtime** (set on the running container, no rebuild): | Variable | Default | Purpose | | ------------------------ | ------------ | ------------------------------------------------------------ | | `NOSTERM_DEFAULT_RELAYS` | _empty_ | Comma-separated relay WebSocket URLs to preload | | `RELAY_UPSTREAM` | `relay:3334` | Upstream for Caddy's optional `/relay` reverse-proxy (below) | **Build-time** (baked into the bundle; rebuild to change): | Variable | Default | Purpose | | ------------------------------------- | ------- | --------------------------------------------- | | `PUBLIC_DEFAULT_RELAYS` | _empty_ | Fallback relays when no runtime config is set | | `PUBLIC_DEFAULT_THEME` | `nord` | Theme applied before the user picks one | | `PUBLIC_MAX_TERMINAL_ENTRIES` | `1000` | Terminal entries kept in memory / rendered | | `PUBLIC_MAX_MESSAGE_LENGTH` | `2000` | Max outbound message length (characters) | | `PUBLIC_MAX_CACHED_MESSAGES_PER_ROOM` | `500` | Messages retained per room in IndexedDB | ## Talking to a relay The client connects directly to whatever relays are configured in `NOSTERM_DEFAULT_RELAYS` (and any the user adds at runtime). Two common setups: - **External relay** — set `NOSTERM_DEFAULT_RELAYS=wss://relay.example.com`. You can delete the `handle /relay*` block from the `Caddyfile`. - **Same-origin home relay** — run [nosterm-relay](https://git.nerdworks.io/nerdworks/nosterm-relay), set `NOSTERM_DEFAULT_RELAYS=ws://localhost:8080/relay` (or `wss://…` behind TLS), and set `RELAY_UPSTREAM` to the relay's address so Caddy proxies `/relay` to it. Put both services on a shared Docker network for name resolution. ## Production TLS For a real domain, edit the `Caddyfile`: replace `:80` with your hostname (e.g. `nosterm.example.com { … }`) and Caddy will obtain and renew a certificate automatically. Expose ports 80 and 443 in `docker-compose.yml`.