Commit Graph
47 Commits
Author SHA1 Message Date
Claude 2e99893c8b Books: read DRM-free MOBI, AZW and AZW3; refuse Kindle files with DRM
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaC9HmtHMdRP8dAbN4wAKj
2026-10-24 02:54:34 +00:00
Claude 07c16ddc25 Books: EPUB, PDF and DOCX reader with synced position, bookmarks, notes and highlights
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaC9HmtHMdRP8dAbN4wAKj
2026-10-24 02:40:36 +00:00
nmemmert 747002924d Transcripts: say why a show's own transcript was not found; read Podgrab fields whatever their capitals
build-container / build (push) Successful in 4m2s
2026-10-23 11:42:43 -04:00
nmemmert c82bd7cae9 Transcripts: check the whisper model is installed, download it (trying each form the service has used), and say what came back if it will not
build-container / build (push) Failing after 6m18s
2026-10-23 11:25:50 -04:00
nmemmertandClaude Sonnet 5.5 0534bf7c4b Transcripts for podcasts and audiobooks: the show's own, or speech-to-text on your server (whisper service)
build-container / build (push) Successful in 13m20s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 10:52:59 -04:00
nmemmertandClaude Sonnet 5.5 3f57e4bde1 Audiobooks: each person's listening positions are their own (the whole library stays shared)
build-container / build (push) Successful in 9m2s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:52:38 -04:00
nmemmertandClaude Sonnet 5.5 4468c2e025 Podcast: each person has their own list of shows
build-container / build (push) Successful in 7m29s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:12:04 -04:00
nmemmertandClaude Sonnet 5.5 b3494b9720 Podcast: resume where you left off, synced between devices (shared progress store with audiobooks)
build-container / build (push) Successful in 9m26s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:37:51 -04:00
nmemmertandClaude Sonnet 5.5 aa2133ed9a Audiobooks: talk to OpenAudible directly with its own username and password (OPENAUDIBLE_URL)
build-container / build (push) Successful in 9m46s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:12:34 -04:00
nmemmertandClaude Sonnet 5.5 62ff4d815d Audiobooks: built-in library, playback and synced progress through the audiobook player (classic frame kept)
build-container / build (push) Canceled after 2m57s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 14:48:05 -04:00
nmemmertandClaude Sonnet 5.5 675df5710b Podcast: built-in screen for Podgrab (shows, episodes, playback, search)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 14:41:59 -04:00
nmemmertandClaude Sonnet 5.5 a3010299d0 Mail: folder unread counts refresh at once after a change, read state survives a late list, no wrong message after quick clicks, mark unread keeps the message in the list
build-container / build (push) Successful in 21m39s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 13:19:45 -04:00
nmemmertandClaude Sonnet 5.5 5c5a7b5155 Plex: edit a title's details (fields locked on save) and choose its poster or background, owner only, through a narrow write rule in the proxy
build-container / build (push) Successful in 19m31s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 12:42:32 -04:00
nmemmertandClaude Sonnet 5.5 b171f35be6 Plex Home: the owner's PIN is asked for and checked by plex.tv when switching back, wrong guesses are slowed down
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 12:39:24 -04:00
nmemmertandClaude Sonnet 5.5 d813884074 Calendar: several NE Hub calendars with colors, per-person view/edit sharing and per-calendar subscribe links; Movies & TV: converted video keeps the right time and seeks inside what the stream has
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 12:38:15 -04:00
nmemmertandClaude Sonnet 5.5 f3216b2f3b Movies & TV: browse and play your Plex movies and shows (resume, progress to Plex, next episode, quality, audio and subtitles, direct play or HLS conversion)
build-container / build (push) Successful in 20m38s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 10:49:53 -04:00
nmemmertandClaude Sonnet 5.5 84a0ea10e9 Mail: instant first paint from the last saved accounts, folders and list; Outlook folders in one batched call; gzip for app files and large mail responses
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 10:39:40 -04:00
nmemmertandClaude Sonnet 5.5 fb7aabff61 Mail opens faster: the page draws at once from a no-network status, the list, folders and unread counts load side by side, unread counts are cached and time-limited per account, IMAP keeps connections warmer and limits folder counting, messages are prefetched on hover
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 10:33:25 -04:00
nmemmertandClaude Sonnet 5.5 dae19176cd Music: use Plex as another person in your Plex Home (list, PIN, switch back), shown as Playing as <name>
build-container / build (push) Successful in 19m30s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 09:31:47 -04:00
nmemmertandClaude Sonnet 5.5 cedd6845ce Files: sturdier Seafile pass-through (timeouts, retries, stop on disconnect), in-place sign-in, saved folder lists, upload name clashes, undo and recycle bin, library search, zip downloads, share link options, text viewer and editor
build-container / build (push) Successful in 20m19s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 09:16:40 -04:00
nmemmertandClaude Sonnet 5.5 004209ed4f Mail: Gmail and iCloud (IMAP/SMTP with app passwords) alongside Outlook.com, several accounts per person with an account switcher, From choice and combined unread
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 09:06:52 -04:00
nmemmertandClaude Sonnet 5.5 8d38584d37 Planner: Calendar and Tasks in one menu entry, due tasks shown on the calendar; menu, More sheet and Home tiles grouped by kind
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 08:56:31 -04:00
nmemmertandClaude Sonnet 5.5 5f639eec3c Mail: fix opening messages (contentId is not selectable on the attachment list; fetch inline pictures whole)
build-container / build (push) Successful in 20m42s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 08:43:27 -04:00
nmemmertandClaude Sonnet 5.5 2d8d4f4d82 Mail setup inside the app: admins save the Microsoft app ID, secret and expiry in Settings, with the redirect address to copy, an expiry warning, and plain-language Microsoft errors
build-container / build (push) Successful in 20m34s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 08:17:40 -04:00
nmemmertandClaude Sonnet 5.5 a9c277b497 Mail: Outlook.com inside the app through Microsoft Graph (folders, reader, compose, reply, unread badge); Cypht webmail removed
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 08:09:11 -04:00
nmemmertandClaude Sonnet 5.5 1564941ea5 Split app.js into one script per feature; versioning covers every public file; README for the new features
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:57:51 -04:00
nmemmertandClaude Sonnet 5.5 c1f4a220f9 Web Push reminders for tasks and events (Settings -> Reminders)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:56:01 -04:00
nmemmertandClaude Sonnet 5.5 561b6181a0 Audit log (admin Activity list) and passkey recovery codes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:53:41 -04:00
nmemmertandClaude Sonnet 5.5 c8399ccaa7 Plex playlists you can edit (create, add, remove, rename, delete, save queue), sleep timer
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:52:29 -04:00
nmemmertandClaude Sonnet 5.5 e26b38a119 Repeating tasks and subtasks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:49:03 -04:00
nmemmertandClaude Sonnet 5.5 1f8c9493b7 Harden the server and add a Links page
Security headers, cross-site write refusal, atomic JSON writes, admin backup download, /healthz and Docker health check, OnlyOffice requires a JWT secret, npm test, CI audit, arm64 hub image. New Links tab for personal bookmarks, saved with per-person settings.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 07:43:34 -04:00
nmemmertandClaude Sonnet 5.5 b0d3aec811 Home dashboard: live Now Playing card; report playback to Plex so it shows in the Plex dashboard
build-container / build (push) Successful in 12m40s
The Home Now Playing block is now the same live card as the Music tab.
The player sends Plex timeline updates (playing/paused/stopped, position every 10 s).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 15:14:34 -04:00
nmemmertandClaude Sonnet 5.5 fc0ae05415 Lyrics and karaoke for the music player
build-container / build (push) Successful in 12m8s
- full-screen lyrics view that follows the song: highlighted current line with a colour sweep (word by word when the source has word timing), tap a line to jump, text size, timing nudge, 'Wrong lyrics?' search
- Karaoke mode: the current line large and centered
- lyrics from Plex first, then the bundled Lyrica service (LRCLIB, Musixmatch via Lrcmux, NetEase, Megalobiz); YouTube captions never used; wrong-length recordings refused; answers kept in /data/lyrics
- lyrica/: Lyrica pinned to one commit, built by the workflow as hub-lyrica; compose service sharing the hub's network
- tools/lyrics-test.js

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 11:13:00 -04:00
nmemmertandClaude Sonnet 5.5 bfd37967c3 Signal: keep messages that arrive glued together, one chat per person, receipts by time, faster reconnect; edit contacts, clear and remove chats; debug list
build-container / build (push) Successful in 7m31s
- read every JSON value in a frame (lines, arrays), binary frames too
- a person seen by number and by private id is one conversation (merged)
- delivery/read receipts match on message time, not on who sent them
- reconnect every 1-5 s; the chat list says when the link was down
- /api/signal/debug: kinds of messages seen lately (no text)
- edit a contact (kept in the app and sent to Signal), clear messages, remove a chat; right-click menu in the list; name for a new number
- tests: 54 checks

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 11:00:34 -04:00
nmemmertandClaude Sonnet 5.5 522fdba4cd Now Playing card on the Music tab; Signal alerts (chime, desktop notification, unread count in tab title and app icon)
build-container / build (push) Successful in 7m4s
- Music: a card with art, seek bar and controls above the albums, artists and playlists
- Signal: chime, optional desktop notification when the app is in the background, (n) in the tab title, app badge; Settings -> Signal alerts (per device)
- README, player test stand-in updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 10:47:15 -04:00
nmemmertandClaude Sonnet 5.5 d0070aa0bb Signal chats in the app (desktop only) with a chat button on every screen
build-container / build (push) Successful in 6m44s
- signal.js: talks to signal-cli-rest-api (a linked device of your Signal account); keeps conversations in /data/signal; live updates; send/receive text, files, replies, reactions, groups, receipts
- Signal tab and a floating chat panel on every screen, shown only on desktop-class windows; new Signal permission per person
- compose: signal bridge container sharing the hub's network
- tools/signal-test.js (fake bridge), README

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 10:18:02 -04:00
nmemmertandClaude Sonnet 5.5 5157e42bc4 Mail opens the provider shortcuts by default; the webmail is one button away
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 10:03:34 -04:00
nmemmertandClaude Sonnet 5.5 7823bbcb03 Webmail is now Cypht (several accounts in one place) instead of Roundcube
build-container / build (push) Successful in 6m58s
- cypht/: official Cypht 2.13.0 on a SQLite file, served under /webmail/; workflow builds git.necloud.us/nate/hub-cypht
- the hub passes /webmail/ through behind the passkey sign-in and signs in to Cypht for you (CYPHT_PASSWORD)
- provider sign-in pages (Google, Microsoft) open in the whole window and return to the Mail tab; other links open in a new tab
- Gmail / Outlook.com / Office365 OAuth settings (Microsoft permissions patched to the current ones)
- Roundcube removed; README, compose and webmail tests updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 09:28:50 -04:00
nmemmertandClaude Sonnet 5.5 cdf862427e Bundled Roundcube webmail in the Mail tab, optional Microsoft 365 OAuth sign-in, collapsible menu
build-container / build (push) Successful in 2m42s
- docker-compose: roundcube service with inline config (Gmail/iCloud/Yahoo presets, framing allowed, persistent key); only reachable through the hub
- hub passes /webmail/ through to Roundcube behind the passkey sign-in; Microsoft's sign-in page opens in the whole window and returns to the Mail tab
- M365_* settings add 'Login with Microsoft 365' (README has the Entra app registration steps)
- Side menu collapses to icons or hides completely (remembered per device, Ctrl/Cmd+B)
- tools/webmail-test.js

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 08:56:13 -04:00
nmemmertandClaude Sonnet 5.5 de1430928a Files like Finder, richer mini player, in-app Back/Forward, Audio tab renamed Audiobooks
- Files: multi-select, batch move/copy/delete, rename checks, sort, filter, shortcuts, drag in (files and folders) to upload with progress and retries, drag to move, drag a file out to download
- Mini player: previous, seek bar with buffered range, time, shuffle/repeat, buffering spinner, swipe for next/previous, close
- Back/Forward bar that knows what history is possible
- Audio tab is now Audiobooks

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 08:37:58 -04:00
nmemmertandClaude Sonnet 5.5 bc3710807d Seafile sign-in follows the person across devices; sturdier Plex player; audiobooks frame with server-side secret sign-in
build-container / build (push) Successful in 3m16s
- Seafile token is saved on the server (encrypted) so Settings shows the real signed-in state everywhere
- Player: whole-track cache for current and next two, stall recovery, instant track changes, shuffle/repeat, Plex play counts, transcode fallback, Plex request timeout
- Audio tab: toolbar, full-height kept-alive frame; /api/audiobooks/enter adds the secret login link on the server

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 08:26:18 -04:00
nmemmertandClaude Sonnet 5.5 1a29d500d3 Link the app's code with a build number so a proxy cache cannot serve an old copy
build-container / build (push) Successful in 2m55s
The People screens did not appear after the redeploy even after a hard refresh: a caching layer
(for example Nginx Proxy Manager's "Cache Assets") was still serving the old app.js. The pages now
reference /app.js?v=<build>, /style.css?v=<build> etc., where the build changes with every release,
so a stale cached file at the old address is never used. The service worker no longer precaches
unversioned app code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 17:00:36 -04:00
nmemmertandClaude Sonnet 5.5 12a1e50a0e Always revalidate the app's files, tell open pages when a newer version exists, and log why a session is refused
build-container / build (push) Successful in 1m58s
An open page kept running the old version after a deploy (the single page never reloads), so the new
People screens did not appear. Static files are now sent with no-cache + ETag (304 when unchanged), icons
are cached for a week, /api/config reports a build stamp, and the app shows "A new version is available -
Reload" when it comes back into view or every 10 minutes. The service worker cache name is bumped.

The server also logs, at most once a minute per reason, why it refused a session cookie (unknown account,
turned off, signed out everywhere, bad signature, expired) without printing the cookie.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 16:55:44 -04:00
nmemmertandClaude Sonnet 5.5 2d17ee9939 Plex: repair a rejected server token or moved address instead of signing the person out
build-container / build (push) Successful in 2m24s
The saved Plex server token or address can stop working (token rotated, server moved). That
looked like "signed out" and sent the person back to the sign-in screen. The proxy now asks plex.tv
(using the saved account sign-in) for a fresh token and address, retries once, and saves them.
Sign-ins saved before the server id was recorded are matched by server name. A revoked account
sign-in signs the person out cleanly; repairs are one at a time and pause 30s after a failure.
The server logs [plex] lines for sign-in, connect, repair and failure.

tools/plex-test.js (31 checks, fake plex.tv + fake Plex) runs in the Gitea workflow.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 16:45:05 -04:00
nmemmertandClaude Sonnet 5.5 f18d9dd7a9 Multiple people: an admin adds users and chooses which tabs each may use
build-container / build (push) Successful in 2m20s
- Accounts: the setup code (or an existing single-user install, migrated automatically) creates the admin;
  the admin adds people in Settings -> People and gives each a one-time invite code to enrol their own passkey
- Each person's tasks, NE Hub events and subscribe link, settings, calendar links, iCloud connection and Plex
  sign-in are private, stored in their own folder (/data/users/<id>/); Plex sign-in moved from browser cookies
  into that folder (encrypted), so it also follows them across devices
- Tab access is enforced by the server (403) and reflected in the app (nav, Home, Settings, search, /api/config
  hides addresses of tabs a person cannot use); browser storage is namespaced per person
- Admin tools: change tabs, invite a device, sign out everywhere (session epoch), turn off, make/remove admin,
  delete a person and their data; the last admin cannot be removed
- Sessions carry the person (uid.epoch.expiry.signature); old single-user cookies still work as the admin
- tools/users-test.js (83 checks: isolation, access limits, invites, sign-out/disable/delete, Plex and iCloud
  per person, migration) now runs in the Gitea workflow before the image is built

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 16:35:14 -04:00
nmemmertandClaude Sonnet 5.5 489ea0aaf0 Fix: the server crashed on every Search; Search now covers tasks and events and explains itself
build-container / build (push) Successful in 1m55s
- Restore ddgAnswer, which an earlier edit deleted: /api/ddg threw a ReferenceError and killed the
  whole server process whenever Search ran
- One failing request can no longer take the server down (errors are logged and answered with a 500)
- tools/smoke-test.js starts the real server and calls every endpoint; the Gitea workflow runs it before
  building the image, so a missing function or a crash stops the build
- Search: also searches NE Hub tasks and calendar events; Seafile file search falls back to scanning file
  names when the search index returns nothing; Plex search falls back to the library's artists/albums;
  a status line shows what was searched, per-source counts and errors, with sign-in links

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 16:18:12 -04:00
nmemmertandClaude Sonnet 5.5 044589686c PWA for iPhone and iPad: PNG icons, splash screens, manifest; stay signed in for 180 days
build-container / build (push) Successful in 1m56s
- iOS ignores SVG touch icons: add 120/152/167/180 apple-touch-icons, 192/512 and maskable manifest icons,
  and 25 splash screens (every iPhone size, iPad portrait+landscape incl. 12.9")
- Icons and splash screens are public so iOS can fetch them without a session
- Manifest: id, scope, categories, shortcuts; iOS standalone polish (no callout, no overscroll)
- Sessions last SESSION_DAYS (default 180) and renew daily while in use
- tools/make-icons.py regenerates the artwork

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 15:44:39 -04:00