diff --git a/README.md b/README.md index 7eba899..8c2a891 100644 --- a/README.md +++ b/README.md @@ -110,10 +110,23 @@ hyprcrd/ │ │ └── vendor/ # marked.js, DOMPurify │ ├── plugins/ # Optional, drop-in plugin folders │ │ ├── canvas/ # ASCII art canvas editor +│ │ ├── chat/ # Encrypted relay chat +│ │ ├── collab-buckets/ # Collaborative bucket sync +│ │ ├── email/ # Email overlay +│ │ ├── gitea/ # Gitea issue integration +│ │ ├── logseq-import/ # Logseq markdown importer +│ │ ├── slideshow/ # Presentation mode │ │ └── tests/ # UI + state test runner │ └── uploads/ # User media (writable) -├── relay/ # Relay service (mobile inbox + card sharing) -│ ├── index.php # Single-file API + Mobile UI +├── electron/ # Electron desktop app wrapper +│ ├── main.js # Spawns PHP, creates BrowserWindow +│ ├── router.php # PHP built-in server router +│ ├── fetch-php.sh # Downloads static PHP binaries +│ └── php-bin/ # Platform-specific PHP binaries +├── relay/ # Relay service (multi-tenant messaging + collab) +│ ├── index.php # Entry point + API dispatch +│ ├── inc/ # Backend modules (bootstrap, crypto, auth, routes) +│ ├── ui/ # Frontend (layout.php, style.css, app.js) │ ├── .htaccess # URL rewriting + data protection │ ├── Dockerfile │ └── dist.sh # Build relay distribution ZIP @@ -128,7 +141,7 @@ hyprcrd/ - **Tags** written as `#tagname` or hierarchical `#parent/child` in card body, extracted automatically - **Markdown** with `[[Card Title]]` wiki-links, ```` ```gallery ```` image galleries, ```` ```tree ```` list views, ```` ```ascii ```` art canvas (via canvas plugin) - **Search** combining text and `#tag` filters (e.g. `#project meeting notes`) -- **Image gallery** with orphan detection and fullscreen viewer +- **Assets gallery** (images, audio, PDFs) with orphan detection and fullscreen viewer - **Split view** showing tag-related and content-related cards - **Import/Export** as JSON+media ZIP or Obsidian/Logseq-compatible markdown vault - **Drag & drop** card reordering and grouping @@ -141,7 +154,14 @@ hyprcrd/ - **Notification banner** for upcoming events, birthdays, overdue tasks - **Board split view** with side-by-side preview - **Superview** compact multi-column list with hover cards -- **Keyboard shortcuts**: `Ctrl+K` search, `F1` help, `Shift+scroll` zoom, arrow keys in autocomplete +- **Super-buckets** — nest buckets one level deep with a dropdown for children +- **Card groups** — drag-to-group, join multiple cards, dissolve +- **Context menu** — color, tags, copy text, mark done, join cards, make ticket (gitea) +- **Find & replace** — in-card (Ctrl+H) and across all cards (Ctrl+Shift+H via search) +- **Arrow key navigation** on the board with Enter to open +- **PDF upload** in the editor toolbar +- **Keyboard shortcuts**: `Ctrl+K` search, `F1` help, `?` shortcut reference, arrow keys, 1–9 bucket switch +- **Electron desktop app** — standalone AppImage/DMG/NSIS with bundled PHP, no server needed ## Plugins @@ -150,7 +170,13 @@ hyprcrd has a drop-in plugin system. A plugin is just a folder under `public/plu ### Bundled plugins - **`canvas/`** — ASCII art canvas editor. Adds a toolbar button + ` ```ascii ` fenced block. Draw with brush, line, rectangle, ellipse, fill, and text tools using a monospace character grid. -- **`tests/`** — UI + state test runner (40+ test files). Loaded only when `?test` is in the URL or `Ctrl+Shift+T` is pressed, so production users pay no cost for it. +- **`chat/`** — Encrypted chat between relay tenants. Footer flyout with delivery + read receipts. +- **`collab-buckets/`** — Collaborative buckets shared between relay tenants with exclusive card locking and E2E encrypted sync. +- **`email/`** — Email overlay (toggled with `M` key). +- **`gitea/`** — Gitea integration: create issues from cards, link to repos. +- **`slideshow/`** — Slideshow presentation mode for cards with `slide-image` blocks. +- **`logseq-import/`** — Import Logseq markdown journals and pages. +- **`tests/`** — UI + state test runner (40+ test files). Loaded only when `Ctrl+Shift+Alt+T` is pressed, so production users pay no cost for it. ### Plugin layout @@ -417,9 +443,8 @@ Starts hyprcrd on `http://localhost:8088` and the relay on `http://localhost:808 master key lives outside the DB in a chmod-600 file - **24-hour ephemeral**: messages and attachments auto-delete after a day. Cards extracted in hyprcrd are the long-term store -- **Future: end-to-end encrypted chat** between tenants is planned and - will require per-pair key exchange — see `relay/README.md` for the - roadmap +- **Encrypted chat**: tenant-to-tenant chat with delivery + read receipts + (via chat plugin). Per-pair E2E key exchange is on the roadmap ### Relay Security @@ -451,6 +476,26 @@ your next visit. You'll need to: The old `relay_key` was bcrypt-hashed and cannot be recovered, so all client secrets need to be reissued. +## Electron Desktop App + +hyprcrd can run as a standalone desktop app via Electron — no web server needed. + +```bash +cd electron +./fetch-php.sh # download static PHP binary (~20MB) +npm install +npm start # dev mode +npm run dist # build AppImage / DMG / NSIS +``` + +The app bundles a static PHP binary per platform and stores user data (database + uploads) outside the app bundle: + +- **Linux**: `~/.config/hyprcrd/data/` +- **macOS**: `~/Library/Application Support/hyprcrd/data/` +- **Windows**: `%APPDATA%/hyprcrd/data/` + +See [`electron/README.md`](electron/README.md) for details. + ## Rebuilding Tailwind CSS After changing Tailwind utility classes in HTML or JS files: diff --git a/electron/README.md b/electron/README.md index 174ed0c..be7d481 100644 --- a/electron/README.md +++ b/electron/README.md @@ -10,8 +10,13 @@ per platform so users don't need PHP installed. 3. A `BrowserWindow` loads `http://127.0.0.1:/` 4. On quit, the PHP process is killed cleanly -Data is stored in `data/hyprcrd.db` (SQLite), relative to the project root -(dev) or inside the app's `resources/` directory (packaged). +User data (database + uploads) is stored **outside** the app bundle so it +survives updates: + +- **Dev**: `electron/appdata/` +- **Linux**: `~/.config/hyprcrd/data/` +- **macOS**: `~/Library/Application Support/hyprcrd/data/` +- **Windows**: `%APPDATA%/hyprcrd/data/` ## Development diff --git a/electron/php-bin/README.md b/electron/php-bin/README.md index 6c745b4..1c8ffb7 100644 --- a/electron/php-bin/README.md +++ b/electron/php-bin/README.md @@ -6,17 +6,17 @@ installation. ## Download -Get static builds from https://github.com/crazywhalecc/static-php-cli/releases -(look for `php-8.3-*-cli` assets). Required extensions: pdo_sqlite, zip, session. +Get static builds from https://dl.static-php.dev/static-php-cli/common/ +(look for `php-8.3.*-cli-*` files). Required extensions: pdo_sqlite, zip, session. linux/php — x86_64 Linux ELF binary - darwin/php — macOS universal binary (arm64 + x86_64) - win32/php.exe — Windows PE binary + darwin/php — macOS aarch64 binary + win32/php.exe — Windows PE binary (not available from static-php-cli; use windows.php.net) -## Quick fetch (Linux example) +## Quick fetch - curl -L -o linux/php \ - "https://dl.static-php.dev/static-php-cli/common/php-8.3.23-cli-linux-x86_64.tar.gz" \ - && tar -xzf linux/php -C linux/ && rm linux/php.tar.gz +Use the included script from the `electron/` directory: -Make sure the binary is executable: `chmod +x linux/php` + ./fetch-php.sh + +This auto-detects the latest PHP 8.3 version and downloads Linux + macOS binaries. diff --git a/relay/README.md b/relay/README.md index 360594f..d4b44db 100644 --- a/relay/README.md +++ b/relay/README.md @@ -2,9 +2,8 @@ A self-hosted **multi-tenant** message relay for hyprcrd. Multiple users share one relay instance; each one has their own login, their own client -encryption secret, and their own inbox. Cards (and in the future: -encrypted chat messages) can be sent **between tenants** on the same -relay. +encryption secret, and their own inbox. Cards and encrypted chat +messages can be sent **between tenants** on the same relay. The relay is a single-file PHP app — drop the directory into any PHP webspace and it works. @@ -55,9 +54,9 @@ The admin only ever touches secrets #1 and #3. The user only ever touches secret The relay **does** see plaintext briefly during the cross-tenant hop (steps 2–3 and 5–6). This is the same trust model as email: you trust -the relay operator. **Strict end-to-end encryption** for the planned -chat feature is on the roadmap and will require a per-pair key exchange -(Curve25519/ECDH) — this is documented as future work in `index.php`. +the relay operator. Chat between tenants is shipped (via the chat +plugin with delivery + read receipts). **Strict end-to-end encryption** +with per-pair key exchange (Curve25519/ECDH) is on the roadmap. For at-rest data, all sensitive values are encrypted with the master key, so a stolen DB without the master key file gives an attacker @@ -155,7 +154,7 @@ incoming messages. ### 6. Send a card to another tenant -(currently in the relay UI; hyprcrd-side recipient picker is coming) +(in the relay UI compose tab) In the relay UI **compose** tab: - Pick a recipient from the dropdown (defaults to yourself) @@ -166,8 +165,7 @@ The recipient will see it on their next hyprcrd poll, materialized as a card in their board. You can also right-click a card in hyprcrd and pick **push to relay** — -this currently sends to your own inbox; recipient picker on the hyprcrd -side is on the TODO. +this sends to your own inbox (or pick a recipient in the relay UI). ## Data lifetime @@ -226,6 +224,10 @@ All endpoints under `/api/`. JSON in/out. | GET | `/api/me` | — | Current tenant info | | GET | `/api/tenants` | — | List of all usernames (for recipient picker) | | POST | `/api/messages` | `{title, body, recipient?}` | UI compose path: server encrypts with inter-tenant key | +| GET | `/api/messages/inbox` | — | Read own inbox messages (decrypted for display) | +| DELETE | `/api/messages/{id}` | — | Delete a message from own inbox | +| GET | `/api/chat/sent` | — | Sent chat messages with delivery/read status | +| POST | `/api/chat/seen` | `{ids: [...]}` | Mark chat messages as seen (read receipts) | ### Admin only (session + `is_admin`) @@ -302,8 +304,7 @@ use the same code path. - A compromised relay machine = compromised messages. Use HTTPS, keep PHP up to date, restrict shell access. -**Future work for stronger guarantees** (planned for the encrypted chat -feature): +**Future work for stronger guarantees** (roadmap for strict E2E): - Per-tenant Curve25519 key pair stored in the DB (public key plus master-key-encrypted private key, or even private key never on the server) @@ -522,7 +523,9 @@ relay/ │ └── routes/ │ ├── public.php # /api/status, /setup, /login, /logout, /me │ ├── admin.php # /api/users CRUD, /api/tenants directory -│ └── messages.php # /api/messages, /api/attachments, cross-tenant routing +│ ├── messages.php # /api/messages, /api/attachments, cross-tenant routing +│ ├── chat.php # /api/chat/sent, /api/chat/seen (read receipts) +│ └── collab-buckets.php # /api/collab-buckets CRUD + card sync ├── ui/ │ ├── layout.php # HTML shell + view containers │ ├── style.css # all CSS (including responsive media queries)