| … | … | @@ -24,46 +24,34 @@ Built on the [Holepunch](https://holepunch.to) stack: Hypercore, Hyperdrive, Hyp |
| 24 | 24 | |
| 25 | 25 | ## Install |
| 26 | 26 | |
| 27 | | ### From pear-git (P2P) |
| 27 | ### As a pgh app (recommended) |
| 28 | |
| 29 | Hypernote is distributed as a content-addressed **pgh** app (Bare runtime): |
| 28 | 30 | |
| 29 | 31 | ```bash |
| 30 | | # 1. Install pear-git (if you don't have pgh) |
| 31 | | npm install -g pear |
| 32 | | pear dump pear://dpjhhzqgm6wqxc9nmw1y3m7eaptfufr6o5p7r4xegjghju8mkweo ~/.local/share/pear-git |
| 33 | | cat > ~/.local/bin/pgh << 'EOF' |
| 34 | | #!/bin/sh |
| 35 | | exec bare ~/.local/share/pear-git/index.js pgh "$@" |
| 36 | | EOF |
| 37 | | chmod +x ~/.local/bin/pgh |
| 38 | | |
| 39 | | # 2. Clone hypernote |
| 40 | | pgh repo clone punch://1290678432f9573b463d4472a9426c5408b34579bf8576e26957a1321fd5e836/hyper-note |
| 41 | | |
| 42 | | # 3. Install and run |
| 43 | | cd hyper-note |
| 44 | | npm install |
| 45 | | bare hypernote-server.js serve |
| 32 | pgh app install hypernote # resolves pgh://1dd36bdf…/hypernote and fetches the release |
| 33 | pgh app restart hypernote # canonical start/restart — and the day-to-day management command |
| 46 | 34 | ``` |
| 47 | 35 | |
| 36 | The launcher bakes in the production args |
| 37 | (`serve 4040 --network --prefix /hypernote --storage ${HOME}/.config/hypernote/server-data`), |
| 38 | so you never pass them by hand. The server self-updates over pgh content-addressed OTA on each |
| 39 | start (pass `--no-updates` to disable). Storage lives at `~/.config/hypernote/server-data` and is |
| 40 | reused across reinstalls and updates. |
| 41 | |
| 48 | 42 | ### System Dependencies |
| 49 | 43 | |
| 50 | | - **[Bare runtime](https://github.com/nicknisi/bare)** -- JavaScript runtime for P2P applications |
| 44 | - **[Bare runtime](https://github.com/holepunchto/bare)** -- JavaScript runtime for P2P applications |
| 51 | 45 | - **ffmpeg** -- required for HLS video transcoding (`apt install ffmpeg` / `brew install ffmpeg`) |
| 52 | 46 | |
| 53 | | ### From local checkout |
| 47 | ### From a local checkout (development) |
| 54 | 48 | |
| 55 | 49 | ```bash |
| 56 | 50 | git clone <repo-url> hyper-note |
| 57 | 51 | cd hyper-note |
| 58 | 52 | npm install |
| 59 | | bare hypernote-server.js serve |
| 60 | | ``` |
| 61 | | |
| 62 | | ### As a Pear app (auto-updates) |
| 63 | | |
| 64 | | ```bash |
| 65 | | pgh app install pear://p84snzmpxca3ii7nfdqjbd5wxjdqzccpoj9xjwzz96wpe4m557zo --name hypernote |
| 66 | | hypernote serve |
| 53 | # dev run (add --storage <path> for a non-default data dir): |
| 54 | bare hypernote-server.js serve 4040 --network --prefix /hypernote |
| 67 | 55 | ``` |
| 68 | 56 | |
| 69 | 57 | ## Quick Start |
| … | … | @@ -182,7 +170,9 @@ CLI (bin/hn) AuthManager — multi-method auth |
| 182 | 170 | - **CLI** (`bin/hn`) — calls HTTP API with bearer token auth |
| 183 | 171 | - **REST API** — JSON endpoints at `/api/*` |
| 184 | 172 | |
| 185 | | **SSR foundation** (prepared, not yet wired as default): |
| 173 | **Server-side rendering (SSR)** — public pages are server-rendered (live; see `lib/routes/web.js` |
| 174 | `renderPage`). Public user pages, notebook pages, note pages and 404s are served as SSR HTML; |
| 175 | the SPA takes over for authenticated editing: |
| 186 | 176 | - `lib/views/*-ui.js` — server-rendered HTML pages |
| 187 | 177 | - `lib/page-layout.js` — shared page wrapper |
| 188 | 178 | - `lib/markdown.js` — server-side markdown renderer |
| … | … | @@ -234,7 +224,15 @@ Only announced notebooks are discoverable. The registry (users, tokens, permissi |
| 234 | 224 | |
| 235 | 225 | ### Multi-Writer / Device Linking |
| 236 | 226 | |
| 237 | | Hypernote supports linking multiple instances via [Autobase](https://github.com/holepunchto/autobase) for multi-device and multi-user collaboration. |
| 227 | Hypernote links multiple instances via [Autobase](https://github.com/holepunchto/autobase) so devices/users share a replicated registry and shared notebooks. |
| 228 | |
| 229 | > **Scope — this is async multi-writer sync, not live co-editing.** Shared notes use a Yjs CRDT |
| 230 | > stored in a per-notebook Autobase and replicated P2P, so concurrent edits from different |
| 231 | > instances merge conflict-free *eventually*. There is **no** real-time transport (no WebSocket), |
| 232 | > **no** presence/awareness (no live cursors), and the browser editor does not drive Yjs directly |
| 233 | > — the server synthesizes the CRDT from saved note content. The `/shared-notes/:id/yjs` endpoint |
| 234 | > and the writer-admission path are **experimental** and not yet hardened (writer admission is |
| 235 | > currently unauthenticated). Treat shared notebooks as eventually-consistent multi-device sync. |
| 238 | 236 | |
| 239 | 237 | **How it works:** |
| 240 | 238 | 1. An admin on instance A creates a link invite (`POST /api/multiwriter/link`) and gets an invite hex |
| … | … | @@ -345,22 +343,36 @@ See [docs/api.md](docs/api.md) for the complete REST API reference. |
| 345 | 343 | |
| 346 | 344 | ### pear-git CI/CD |
| 347 | 345 | |
| 348 | | Hypernote deploys automatically via pear-git: |
| 346 | Hypernote deploys automatically through the pear-git CI/CD pipeline: |
| 349 | 347 | |
| 350 | 348 | ```bash |
| 351 | | git push pear master # triggers auto-deploy |
| 352 | | pgh deploy log hyper-note # check deploy status |
| 349 | git push pear master # triggers auto-deploy (post-receive hook) |
| 350 | pgh deploy log hyper-note # NB: git repo is "hyper-note"; the pgh app name is "hypernote" |
| 353 | 351 | ``` |
| 354 | 352 | |
| 355 | | The CI pipeline (`.pear-git/ci.yaml`) installs dependencies, then pear-git runs `pear stage` -> `pear release` -> `pear seed`. |
| 353 | The CI pipeline (`.pear-git/ci.yaml`) has two steps: `copy-deps` (copies the pre-built |
| 354 | `node_modules`, preserving the postinstall lib0 patch and bare native prebuilds) then |
| 355 | `pgh publish` (pushes a content-addressed release to the registry). There is **no** |
| 356 | `pear stage` / `pear release` / `pear seed` — that is the old paradigm and must never be |
| 357 | run manually. |
| 356 | 358 | |
| 357 | | ### Manual |
| 359 | Once published, OTA reaches running instances automatically (each instance shells out to a |
| 360 | detached `pgh app update hypernote` on start). The git **source** also replicates to sister |
| 361 | backends (e.g. stortron) over the pear-git P2P mirror — no direct push to those machines is |
| 362 | needed. |
| 363 | |
| 364 | ### Running it |
| 365 | |
| 366 | Day-to-day, hypernote is a pgh-managed service: |
| 358 | 367 | |
| 359 | 368 | ```bash |
| 360 | | NODE_OPTIONS="--max-old-space-size=4096" bare hypernote-server.js serve 4040 --network |
| 369 | pgh app restart hypernote # start/restart (args + storage come from the install manifest) |
| 370 | pgh app status hypernote # running state, version, autostart |
| 371 | pgh app autostart hypernote on |
| 361 | 372 | ``` |
| 362 | 373 | |
| 363 | | For production, run in tmux or as a systemd service. |
| 374 | It is served behind a reverse proxy at `https://7rnx.net/hypernote/`. On tabertron the |
| 375 | operator scripts `hypercore-up` / `hypercore-down` drive it via `pgh app start` / `pgh app stop`. |
| 364 | 376 | |
| 365 | 377 | ## Backup & Restore |
| 366 | 378 | |
| … | … | @@ -417,7 +429,7 @@ node scripts/restore-direct.js ~/hypernote-backups/latest |
| 417 | 429 | ## Testing |
| 418 | 430 | |
| 419 | 431 | ```bash |
| 420 | | # Run all tests (150+ assertions) |
| 432 | # Run all tests (25 brittle test files under test/unit/) |
| 421 | 433 | npm test |
| 422 | 434 | |
| 423 | 435 | # Run specific test |
| … | … | @@ -526,7 +538,7 @@ hypernote/ |
| 526 | 538 | jsuites.js # jSuites dependency (local) |
| 527 | 539 | fullcalendar.min.js # calendar editor (local) |
| 528 | 540 | test/ |
| 529 | | unit/ # 17 test files (brittle) |
| 541 | unit/ # 25 test files (brittle) |
| 530 | 542 | helpers/ |
| 531 | 543 | fixtures.js # test helpers |
| 532 | 544 | docs/ |