Releases: voilelab/plainshelf
Release list
v0.8.0
Added
- Added right-click context menus to book card view items, with actions for reading, viewing detail, opening the book folder (desktop only), downloading, editing, and deleting.
- Added Zoom In, Zoom Out, and Reset Zoom commands to the desktop app View menu (⌘=, ⌘-, ⌘0), with zoom level persisted across sessions.
- Added an experimental Android mobile app (a Capacitor shell around the existing frontend) that connects to a self-hosted PlainShelf server: first-run connection setup (server URL, optional access token, shelf selection) with a Settings entry to edit the connection later, persistent on-device caching of downloaded books and reading progress for offline reading (stored as app-private files via the Capacitor Filesystem plugin, exempt from WebView storage eviction), and native HTTP requests so plain-HTTP LAN servers work without CORS configuration.
- Added the native Android project under
frontend/android/,justrecipes for building it (mobile-add-android,mobile-sync,build-mobile-android,open-mobile-android), and a README section covering prerequisites and server reachability. - Added PlainShelf launcher icons and splash screens (light and dark) for the Android app, generated from the brand images in
frontend/assets/via@capacitor/assets. - Added a dashboard home page (now the default landing route, with a sidebar entry) with stats cards (total books, added this month, star distribution, total characters), a tag cloud, a random book pick, and a reading heatmap driven by live daily reading-time data.
- Added server-side daily reading-time tracking (
POST/GET /api/shelves/:id/reading_activity) backing the dashboard heatmap, plus an opt-inchar_countfield on the book list endpoint. - Added a mobile-friendly book detail layout on narrow viewports: centered hero cover, centered title, a full-width Read button with secondary actions in a two-column grid, and single-column metadata rows.
- Added foldable sidebar sections (Layers, Reading, Maintenance, Admin) that collapse and expand independently.
- Added first/last page buttons and numbered page buttons with ellipsis to the pagination controls, alongside the existing prev/next controls.
Changed
- Changed the main layout sidebar to an off-canvas drawer with a topbar menu button on viewports up to 768px wide (phones and narrow windows); it closes on backdrop tap or navigation, and wide-viewport splitter behavior is unchanged.
- Changed the book star rating input in the metadata editor to use reka-ui
RatingRootandRatingItemIndicator, aligning with the reka-ui component migration started in v0.7.0. - Removed the inline Edit button from book card view items; edit access is now exclusively through the right-click context menu.
- Changed library search to pure frontend filtering instead of a backend query parameter, unifying case-insensitive title/author/tag/comment matching across desktop, mobile offline mode, and mock dev data.
- Changed release archives to also include the README preview image and a version-matched copy of
docs/, so the README's relative documentation links work from the extracted archive as well as online.
Fixed
- Fixed the mobile app showing errors instead of downloaded books when the device has connectivity but the PlainShelf server is unreachable (e.g. on mobile data away from the home LAN); book listing, metadata, sources, covers, and reading progress now fall back to the on-device offline cache on transport failures and timeouts, while real server error responses are still surfaced.
- Fixed resizable panel drag handles leaving all panel interactions unresponsive after a drag gesture; moved
hitAreaMarginsfrom an inline template literal to a module-level constant to prevent reka-ui drag-state corruption mid-drag. - Fixed scrollable content areas in the sidebar and main content panel after the reka-ui Splitter migration; added inner wrapper elements to work around
SplitterPanel'soverflow: hiddeninline style enforcement. - Fixed mobile book covers failing to load (showing as NO COVER) because Android WebView blocks mixed-content
<img>requests against the app'shttps://localhostorigin; covers are now fetched and rendered viablob:object URLs on mobile. - Fixed the library page landing on the wrong page number when committing or clearing a search with client-side filtering active.
- Fixed the desktop app's Settings repository link opening inside the app window instead of the system browser.
- Fixed the compiled server binary silently dropping underscore-prefixed frontend asset files (e.g. the shared Vue export-helper chunk) from the embedded build, which blanked most pages when served from the binary.
What's Changed
- fix(cask): update deprecated depends_on macos string format by @mudream4869 with @Copilot in #191
- Replace layer action buttons with context menu by @mudream4869 in #192
- fix(VOI-44): fix desktop Download button via native save dialog by @mudream4869 with @Copilot in #194
- VOI-42: Add desktop “Open folder” action for layer context menu by @mudream4869 with @Copilot in #196
- Desktop: Add 'Open Folder' action for book detail by @mudream4869 in #197
- Extract book actions into reusable composable by @mudream4869 in #199
- Add Markdown (.md) file support for book imports by @mudream4869 in #193
- Render Markdown books in the reader by @mudream4869 in #201
- Add zoom controls to desktop app with CSS-based scaling by @mudream4869 in #200
- Migrate published_at from timestamp to date-only format by @mudream4869 in #202
- Add update-docs skill for syncing project documentation by @mudream4869 in #204
- Code-split routes and vendor chunks to reduce bundle size by @mudream4869 in #203
- Add book identifiers support (ISBN, ASIN, etc.) by @mudream4869 in #206
- Add native mobile support with IndexedDB persistence by @mudream4869 in #207
- fix(reader): stop clipping text and hide titles on mobile by @mudream4869 in #208
- fix(mobile): fall back to persisted shelf when shelf list is unreachable by @mudream4869 in #209
- Add filesystem-backed mobile book cache (no wiring change) by @mudream4869 in #211
- Switch mobile offline cache to filesystem storage by @mudream4869 in #212
- Add mobile saved-books UI: downloads page, size accounting, cover cache by @mudream4869 in #210
- Handle server unreachable while device online in mobile app by @mudream4869 in #213
- build(deps): bump golang.org/x/crypto from 0.51.0 to 0.52.0 in /desktop by @dependabot[bot] in #214
- docs: add Homebrew install option by @mudream4869 in #215
- Add About modal to Settings page by @mudream4869 in #216
- Add 'Shelf Cache and Disk I/O' documentation and link from SMB/known-issues by @mudream4869 in #217
- Add collapsible (foldable) sidebar sections to MainLayout by @mudream4869 in #218
- Move book search filtering to client-side by @mudream4869 in #221
- Extract book cover handling into useCoverSrc composable by @mudream4869 in #220
- Enhance Pagination component with full page list, first/last buttons and styles by @mudream4869 in #222
- Refactor responsive design for mobile book detail view by @mudream4869 in #223
- Add reading activity tracking and dashboard page by @mudream4869 in #224
- Update go.mod by @mudream4869 in #225
- Update documentation for PlainShelf by @mudream4869 in #227
- Improve readability and performance of loops and date handling by @mudream4869 in #226
- Add comprehensive tests for shelf functionality and cover management by @mudream4869 in #228
- refactor by @mudream4869 in #229
- Refine CI/version/script by @mudream4869 in #230
- Release v0.8.0 by @mudream4869 in #231
Full Changelog: v0.7.0...v0.8.0
Plainshelf v0.7.0
Added
- Added shelf creation and deletion confirmation modals to the frontend shelf management UI.
- Added
scan_intervalconfiguration support when creating shelves through the settings UI. - Added
book_check_intervalshelf configuration option to rate-limit per-book staleness checks, reducing filesystem and network I/O on SMB mounts. - Added
GET /api/shelves/:id/statusendpoint returning shelf readiness and initialization error state. - Added ETag and
Cache-ControlHTTP caching headers for book cover responses. - Added async shelf cache initialization; list endpoints return 503 with
Retry-Afteruntil the cache is ready. - Added frontend 503 auto-retry with "Shelf is loading…" status during shelf initialization, capped at 10 attempts with a manual retry button on failure.
- Added frontend
AbortControllerrequest timeout on all API fetch calls with distinct timeout error handling. - Added a shelf modify modal in desktop Settings for editing a shelf's name and scan interval.
- Added resizable sidebar and source-list panels (previously fixed-width) via drag handles.
- Added a Homebrew cask for installing the macOS desktop app (
brew install --cask voilelab/plainshelf/plainshelf). - Added a GitHub Actions release workflow publishing prebuilt server binaries (Linux amd64/arm64, macOS arm64) and a Docker image on tagged releases.
- Added application version reporting via
GET /api/version, startup logs, and a Settings page About section, using build-time version injection. - Added native fullscreen mode support for the macOS desktop app.
Changed
- Hardened SMB mount support: configurable flock timeout (default 30 s), atomic writes for source and metadata files, and initialization failures now exposed via
/statusinstead of hanging indefinitely. - Made per-book stat checks asynchronous to reduce round-trips on SMB mounts; list operations serve from the in-memory cache between scheduled checks.
- Changed the Settings page from stacked panels to a tabbed layout (cover, read history, about, shelves).
- Changed native
<select>inputs and hand-rolled dropdown menus throughout the app to a consistent reka-ui-based menu with shared styling and full keyboard navigation. - Changed the layer tree to reka-ui Tree, adding keyboard navigation (arrow keys, Home/End, typeahead) and proper ARIA tree semantics.
- Changed the book tag input so Backspace on an empty field selects the last tag chip before deleting it on a second press (previously deleted immediately), and chips can now be selected with arrow keys.
- Changed reader side-action buttons to show styled hover tooltips instead of native browser title tooltips.
Fixed
- Fixed cache write lock held across filesystem I/O in book cache refresh, blocking concurrent list reads.
- Fixed shelf lock acquisition errors not being propagated to callers.
- Fixed two data races in shelf book-cache scan-interval handling and shelf listing that could corrupt state under concurrent access.
- Fixed source ID collisions when multiple sources for the same book are created within the same second.
- Fixed layer/book path parsing to always split on
/instead of the OS path separator, which broke on Windows. - Fixed shelf startup to clear leftover temp files from a previous crashed run, and to skip unreadable/non-directory source entries instead of failing the whole listing.
- Fixed the desktop app crashing when the backend fails to start (e.g. data directory not creatable, port in use); it now shows an error dialog instead of panicking.
What's Changed
- Add shelf initialization handling and SMB mount optimizations by @mudream4869 in #157
- Improve file write safety and shelf initialization error handling by @mudream4869 in #158
- Add shelf creation modal by @mudream4869 in #161
- Add shelf delete confirmation modal by @mudream4869 in #162
- Support scan_interval when creating shelves by @mudream4869 in #163
- Decouple book staleness checks from full cache scans by @mudream4869 in #164
- Add SMB shelf configuration guide and navigation entry by @mudream4869 in #167
- Add shelf modification functionality to desktop app by @mudream4869 in #166
- Refactor file locking to support multiple lock modes by @mudream4869 in #168
- Refactor Shelf methods and update locking mechanism by @mudream4869 in #169
- Handle backend startup errors gracefully with user dialog by @mudream4869 in #170
- Fix source and book ID collisions and improve robustness by @mudream4869 in #171
- Add release pipeline, version injection, and installation docs by @mudream4869 in #172
- Simplify development workflow with just task runner by @mudream4869 in #173
- Update documentation to reflect planned format support by @mudream4869 in #175
- Enable fullscreen mode on macOS by @mudream4869 in #176
- Add Claude session governance framework and rules by @mudream4869 in #177
- Extract dialog logic into reusable BaseDialog component by @mudream4869 in #178
- Extract modal UI into reusable BaseDialog component by @mudream4869 in #179
- Refactor modals to use BaseDialog component by @mudream4869 in #180
- Refactor ImportBookModal to use BaseDialog component by @mudream4869 in #181
- Refactor ConfirmModal to use BaseDialog component by @mudream4869 in #182
- Replace custom dropdown with reka-ui DropdownMenu by @mudream4869 in #183
- Update go dependency by @mudream4869 in #184
- Add comprehensive e2e tests for layer tree UI interactions by @mudream4869 in #185
- Refactor LayerTree to use reka-ui TreeRoot/TreeItem components by @mudream4869 in #186
- Replace custom tag input with reka-ui TagsInput component by @mudream4869 in #187
- Migrate UI components to reka-ui for consistent design system by @mudream4869 in #188
- Add macOS desktop app distribution via Homebrew cask by @mudream4869 in #174
- Release v0.7.0 by @mudream4869 in #189
Full Changelog: v0.6.0...v0.7.0
Release v0.6.0
Added
- Added drag-layer visual preview when repositioning layers via drag-and-drop.
- Added
SetCurrentSourceAPI endpoint and "Set as current" button in the book source editor. - Added log-file listing and access API endpoints and a frontend admin log viewer with date-picker navigation.
- Added multi-shelf support: API endpoints are now shelf-scoped, with a new
GET /api/shelvesendpoint to list configured shelves. - Added frontend shelf selector with live switching across configured shelves.
- Added duplicate-page delete action.
- Added drag-and-drop upload for book covers.
- Added
cover_to_jpgconversion setting with API endpoints and a frontend settings page toggle. - Added ASCII input support in the UTF-8 re-encoding path.
- Added configurable read history limit with API endpoints and a settings page control.
- Added layer rename and move support via API and frontend UI, including a dedicated rename modal.
- Added desktop shelf management: add new shelves and remove existing shelves from the settings page.
- Added book star ratings to the book detail and edit views.
- Added read-only server mode with write controls disabled in the frontend.
Changed
- Changed book package directory extension from
.novlto.bookpkg. - Changed frontend license from ISC to BSD-3-Clause.
- Moved shelf selector from the top bar to the top of the left sidebar, above the layer tree.
Fixed
- Fixed HTTP status code for book and log content stream responses in desktop mode.
- Fixed book cover upload to infer MIME type from filename extension when not supplied.
- Fixed desktop local import to route through the active shelf.
- Fixed empty active shelf fallback on startup.
- Fixed shelf routes being accessible before shelf data is fully loaded.
- Fixed line counter to handle long lines correctly.
- Fixed desktop shelf loading to retry on failure.
- Fixed desktop shelf persistence migration.
- Fixed book source metadata not refreshing after content update.
Removed
- Removed single-shelf configuration; shelves are now managed exclusively through the multi-shelf configuration.
- Removed obsolete snapshot-to-source migration tool.
Release v0.5.0
Added
- Added shelf cache refresh controls and stale-book cache handling improvements.
- Added MkDocs-based project documentation and known-issues pages.
- Added a canvas-based simple book-cover generator in the frontend.
- Added desktop history navigation controls and menu actions.
- Added frontend drag-and-drop support for importing external TXT files.
- Added frontend i18n foundations with locale switching support (
en,zh-Hant). - Added a soft-delete trash feature for books with original-path retention.
- Added book source create/delete actions in the source editor.
- Added desktop native file-dialog import selection and server-side local-path import support.
Changed
- Changed CI to include desktop module Go test coverage.
Release v0.4.0: Experimental Desktop App
Added
- Added configurable shelf logging output support through application logging configuration.
- Added experimental Wails GUI support for local desktop usage.
- Added frontend support for creating empty books.
- Added frontend support for editing a book's publish date.
Changed
- Improved server API error logging to include richer response diagnostics.
- Refined logger argument handling and shelf-close error handling paths for more predictable shutdown behavior.
- Refined shelf configuration.
- Improved tag input UI in metadata editor.
Fixed
- Fixed shelf logging integration issues after initial logger wiring.
- Fixed a potential race condition from shared error state in the server listen goroutine.
- Fixed log writer lifecycle handling to avoid closing standard I/O outputs while still closing closable writers.
Release v0.3.0
What's Changed
Breaking Change: snapshots renamed to sources
This release migrates the internal content directory and metadata naming from snapshots to sources.
Existing shelf directories must be migrated before using v0.3.0.
The migration script will:
- Rename the
snapshots/folder tosources/ - Update
book.json:current_snapshot→current_source - Update
CURRENT_VERSION_LOCATION.txtif it exists
Run:
go run migration/migrate_snapshot_to_source/main.go <shelf_dir>It is recommended to back up your shelf directory before running the migration.
Full Changelog: v0.2.0...v0.3.0
Release v0.2.0
What's Changed
Added
- Added GitHub Actions CI coverage for Go tests and frontend builds.
- Added server-side API contract tests for core library and reader workflows.
- Added a book-detail download action with frontend error handling.
- Added an API endpoint for retrieving a specific book snapshot.
- Added current snapshot line and character counts to the book detail view.
- Added maintenance navigation icons for recently read, missing-field, and
duplicate-content views.
Changed
- Updated GitHub issue templates to improve issue reporting and triage.
- Aligned the frontend reader split setting with the boundary-based API contract.
- Clarified the supported security release policy.
- Removed the duplicate back button from the book detail view.
Fixed
- Tightened server-side import validation for uploaded text formats.
- Fixed split configuration contract behavior covered by API tests.
- Fixed omitted security configuration handling and loopback listen-address
detection. - Hid the layer delete action when a layer still contains books.
- Fixed download error dismiss and reset behavior.
Full Changelog: v0.1.1...v0.2.0
Release v0.1.1
What's Changed
- Remove GUI/CLI implementation in #10
- Harden shelf path and upload handling in #8
- Use MaxBytesError type checks for oversized upload bodies
- Add SECURITY.md with project security policy
Full Changelog: v0.1.0...v0.1.1
First release
PlainShelf v0.1.0
PlainShelf v0.1.0 is the first early-development release of PlainShelf, a local-first personal reading library for plain text books.
PlainShelf is designed for single-user local usage, with a filesystem-first data model and a web-based reading interface. This release focuses on the core server/web workflow: importing TXT books, browsing and organizing a local library, reading books in the browser, tracking reading progress, and running the app locally or through Docker.
Status: pre-alpha / early development.
APIs, data layout, and UI behavior may still change in future releases.
Highlights
- Local-first personal TXT library for single-user reading workflows.
- Web UI for browsing, importing, organizing, editing, and reading books.
- Filesystem-first shelf layout intended to keep user-owned data local and backup-friendly.
- Stable internal book IDs independent from display titles.
- Reading progress and recent reading history support.
- Layer-based organization for grouping books.
- Duplicate-content maintenance view based on current snapshot hashes.
- Snapshot viewing/editing and split configuration support.
- Cover upload, retrieval, conversion, and deletion support.
- Docker image support with a built-in health check.
What is included
Library and reader workflow
- Import TXT files into a local shelf.
- Re-encode uploaded text content to UTF-8 during import.
- Automatically create an initial snapshot for imported books.
- Detect book language during import when possible.
- Browse the local book library through the web UI.
- View, edit, and delete book metadata.
- Read book content in the browser reader.
- Save and restore reading position.
Organization and maintenance
- Organize books into layer paths.
- Create and delete layers.
- Move books between layers.
- Search books by title/comment.
- Find duplicate books by grouping matching current snapshot MD5 hashes.
- View books missing common metadata such as author, cover, and language.
- View and clear recent reading history.
Snapshots and content editing
- List book snapshots.
- View snapshot content.
- Edit snapshot content.
- Configure reader split behavior for the current snapshot.
Covers
- Get, upload, and delete book covers.
- Convert uploaded cover images to JPEG when configured.
Docker
- Multi-stage Docker build for the frontend and Go server.
- Runtime image includes a
/healthhealth check. - Default Docker config stores data under
/data. - Recommended local run command:
docker run --rm \
--name plainshelf \
-p 127.0.0.1:20000:20000 \
-v plainshelf-data:/data \
plainshelfDevelopment and testing
Recommended local verification flow:
npm --prefix frontend run build
go test ./...The frontend build must run before the Go build/test flow because the Go frontend package embeds the generated frontend dist files.
Known limitations
- This is still a pre-alpha / early-development release.
- APIs, data layout, and UI behavior may change in later versions.
- PlainShelf is currently TXT-focused. EPUB, PDF, CBZ/CBR, DRM formats, OCR, cloud sync, multi-user support, public sharing links, and plugins are not in the current scope.
- Server-side pagination is not implemented yet; the current API returns the full book list and the frontend paginates client-side.
- The CLI and Fyne GUI entrypoints are experimental and may lag behind the main server/web workflow.
- Some internal packages and commands still use the older txtlib name and may be renamed as the project stabilizes.
Upgrade notes
This is the first 0.1.0 release. There are no previous stable PlainShelf releases to migrate from.
Because PlainShelf is still pre-alpha, users should back up their shelf directory before upgrading to future releases.