| 1 | # tinyclient |
| 2 | |
| 3 | `tinyclient` is the relay website. It includes the HTML templates, styles, |
| 4 | JavaScript modules and embedded browser bundles used by the integrated `tiny` |
| 5 | backend. Pages render on the server and remain readable without JavaScript. |
| 6 | Signing, encrypted messages, uploads and live updates use browser enhancements. |
| 7 | |
| 8 | ## Build and run |
| 9 | |
| 10 | Run these commands from the repository root: |
| 11 | |
| 12 | `` `sh |
| 13 | go build -o tinyclient-server ./cmd/tinyclient |
| 14 | ./tinyclient-server \ |
| 15 | -listen 127.0.0.1:8081 \ |
| 16 | -backend http://127.0.0.1:7447 \ |
| 17 | -public-url https://relay.example |
| 18 | `` ` |
| 19 | |
| 20 | The backend must be a compatible tinyrelay backend (`tiny serve` ) from this |
| 21 | repository. Set its `--public-url` to the same `https://relay.example` address. |
| 22 | Route that public |
| 23 | origin to tinyclient through your HTTPS reverse proxy, preserving the Host |
| 24 | header. Keep the backend listener on the private network. The frontend renders |
| 25 | pages and assets locally and forwards relay APIs, WebSocket connections, |
| 26 | streams, signed requests and mutations to the backend. |
| 27 | |
| 28 | For a path-based tenant, include the same path in both URLs: |
| 29 | |
| 30 | `` `sh |
| 31 | ./tinyclient-server \ |
| 32 | -backend http://127.0.0.1:7447/r/team \ |
| 33 | -public-url https://relay.example/r/team |
| 34 | `` ` |
| 35 | |
| 36 | Each process serves one tenant. The root path and `/r/<name>` are supported; |
| 37 | arbitrary mount paths and different frontend and backend tenant paths are not. |
| 38 | A root-mounted frontend rejects `/r/<name>` requests before rendering or |
| 39 | forwarding them. A prefixed frontend accepts only its configured tenant path. |
| 40 | The default listener is `127.0.0.1:8081` . Run `tinyclient-server -help` for flags. |
| 41 | |
| 42 | The binary embeds its assets and needs no working directory, SQLite database, |
| 43 | Git installation or relay signing key at runtime. It requires a running backend |
| 44 | for relay data and session validation. Embedded scripts and icons remain available |
| 45 | when the backend is unavailable. Failure to load the relay snapshot |
| 46 | returns HTTP 502 rather than serving cached private data. It is not an offline client or a frontend for |
| 47 | an arbitrary Nostr relay. |
| 48 | |
| 49 | ## Authentication |
| 50 | |
| 51 | Keep the relay's public origin and tenant path unchanged when splitting the |
| 52 | processes. NIP-98 signatures bind the exact URL, method and body. Tinyclient does |
| 53 | not re-sign requests, accept a public key as authentication or translate proofs |
| 54 | between origins. Incoming requests for a different public Host are rejected. |
| 55 | Configure the relay's HTTPS public URL even when the private hop uses HTTP so |
| 56 | it verifies the original scheme and issues secure cookies. |
| 57 | |
| 58 | Browser sessions remain owned, checked and revoked by the relay. The frontend |
| 59 | loads the presentation snapshot through the read-only contract at |
| 60 | `/api/tinyclient` using the browser's session cookie. Anonymous method and typed |
| 61 | reads omit that cookie, including public article feeds requested by signed-in |
| 62 | users. Authenticated reads require the requested actor to match the snapshot's |
| 63 | authenticated actor. The relay derives the actor from the session, checks access |
| 64 | on data reads and redacts private relay metadata. Owner-only settings are not |
| 65 | included in anonymous or nonowner snapshots. Signed operations and relay |
| 66 | protocol traffic retain their authorization headers, paths, query strings and |
| 67 | bodies as they pass upstream. Signed page requests are handled by the integrated |
| 68 | backend renderer rather than replaying a signature across several reads. |
| 69 | |
| 70 | Private pages and authenticated no-JavaScript navigation are supported with a |
| 71 | valid browser session. Creating that session still requires a browser signer. |
| 72 | Pointing the frontend at a different public origin is not a supported migration |
| 73 | path for existing sessions or signed URLs. |
| 74 | |
| 75 | ## Embed |
| 76 | |
| 77 | Import `github.com/FelineStateMachine/tinyrelay/tinyclient` and call `New` with a |
| 78 | `Backend` and `Options` . Public `Policy` , `Features` , `CustomView` and room types |
| 79 | let another package implement the interfaces without importing relay-internal |
| 80 | types. `DefaultPolicy` supplies the normal feature settings. |
| 81 | |
| 82 | `Backend.Query` owns authorization for method calls. `Options.Actor` resolves |
| 83 | authenticated requests; it must verify a session or proof, never a caller's |
| 84 | claimed public key. Optional `RoomsReader` , `PrivateReader` , |
| 85 | `AccountPreferencesReader` , `CustomViewSource` and `ChatActivityReader` |
| 86 | interfaces provide typed room reads, membership checks and richer page data. |
| 87 | The remote adapter preserves typed room summaries, folded replies, reaction |
| 88 | counts, activity cards and account preferences. |
| 89 | |
| 90 | `App.BackendHandler()` exposes the read contract for an embedded data service. |
| 91 | `App.ServeHTTP` mounts it automatically. `NewRemote` returns the standalone HTTP |
| 92 | handler for use in another executable. |
| 93 | |
| 94 | The `/api/tinyclient` contract is a project-specific, read-only HTTP extension, |
| 95 | not a Nostr NIP. See the [read-adapter specification](../docs/extensions/tinyclient-read-adapter.md) |
| 96 | for request forms, authorization, errors and compatibility. GET without a method returns the authorized presentation |
| 97 | snapshot. `method` and JSON-array `params` select an allowlisted backend read; |
| 98 | `op=rooms|room|thread|activity` selects a typed read with its room, root, cursor |
| 99 | and limit parameters. Every call resolves authentication at the tinyrelay |
| 100 | backend. This adapter introduces no event kinds, signing formats or storage |
| 101 | identifiers. Frontend validation improves feedback; the backend remains the |
| 102 | authority for protocol validation, membership and mutation permissions. |
| 103 | |
| 104 | ## Test and rebuild browser bundles |
| 105 | |
| 106 | `` `sh |
| 107 | go test ./tinyclient ./cmd/tinyclient |
| 108 | go test ./internal/daemon -run TestStandaloneTinyclient |
| 109 | npm ci |
| 110 | npm run test:tinyclient |
| 111 | npm run build:tinyclient |
| 112 | `` ` |
| 113 | |
| 114 | Go builds use the checked-in browser bundles, so Node.js is not required to build |
| 115 | or run the binary. Rebuild the bundles when their JavaScript sources or pinned |
| 116 | dependencies change. Bundle verification compares regenerated bytes with the |
| 117 | checked-in assets. |