Your data is not my problem. Or at least, I've gone to considerable lengths to make sure it isn't.
I have a peculiar obsession with not being responsible for other people's data. It's partly ideological, because I believe people should own their documents, store them wherever they like, and be able to continue using them long after the company that created their software has disappeared. It's also partly selfish, because I absolutely don't want to be responsible for storing, protecting, backing up, or recovering anyone else's life's work.
I'm also not really much of a businessman. At a time when seemingly every software company has discovered the commercial potential of charging people a monthly fee to access things they already own, I've been trying to build an application that people can purchase, install, and keep. No account, no subscription, and no dependence on my continued existence.
This was going well until I showed the application to someone else.
An inconveniently reasonable request
Bookend is an entirely local-first application, designed to be installed on a computer, work without an internet connection, and store documents in files that users could manage themselves. That was what I wanted from my own software, and I had optimistically assumed that everyone else would appreciate it too.
After months of development, I finally reached the point where I could submit Bookend to Apple. I worked through their various requirements, navigated the review process, and eventually had the satisfaction of seeing my application listed on the App Store. I'd built something that worked, I'd published it, and I was pleased with myself.
Then I showed it to a friend, one of the first people outside my own development process to seriously evaluate the application, and they made a perfectly reasonable request: they wanted to access Bookend from a work computer on which they couldn't install software.
My immediate reaction was an uncomfortable mixture of deflation and seething annoyance. I'd spent months building an application specifically so that it wouldn't need to run in a browser, and here was someone asking me to make it run in a browser. Worse still, they were right.
There are plenty of people who work on shared computers, hot desks, or corporate machines with restrictions on installing software. They might spend their working day on one computer and their evenings writing or studying on another, and they might reasonably want access to their notes, manuscripts, or research without carrying their personal laptop everywhere. For these people, remote access isn't a luxury, but potentially a prerequisite for using the application at all.
Once I'd finished being irritated, I had to concede that my carefully considered philosophy had encountered a perfectly ordinary requirement, and that dismissing it simply because it contradicted my original intentions would be poor product design.
The subscription I didn't want to sell
The conventional solution would have been to build a cloud service. I could rent some server capacity, implement an account system, store users' documents remotely, and provide a browser interface, charging a modest monthly subscription to cover the infrastructure. This would have the additional advantage of providing recurring revenue, something the software industry at large has latched onto with vigour.
There are perfectly good reasons why cloud services exist, and they solve some genuinely difficult problems. I use them myself. But taking that approach would also mean managing accounts, maintaining infrastructure, handling customer data, and accepting an ongoing obligation to keep the service running. I didn't want to do any of those things, and I certainly didn't want to make Bookend dependent on them.
The alternative was simple, and it came to me while I was refactoring another project from a web app to a local one: rather than running a server for my users, I could let them run their own.
The idea was to allow the desktop application to expose its existing functionality through a local web server, which could then be accessed from a browser on another computer. Bookend would still run on the user's own hardware, with documents stored wherever they had chosen, but its interface would no longer need to run on the same machine.
This would be less convenient than a fully managed cloud service, particularly for people unfamiliar with networking, but it would preserve the underlying local-first architecture and avoid turning me into a storage provider.
A web application hiding inside a desktop application
Some of my earlier software projects were built using Python backends and browser-based interfaces, but when I began developing Bookend, I wanted something more portable and resilient. I settled on Rust, React, and Tauri, which allowed me to package the application as native desktop software while retaining a modern interface. More importantly, I could use it entirely offline, move it between computers, and avoid the dependencies that had frustrated me in earlier projects.
I'd also made a deliberate architectural decision to separate the backend and frontend as thoroughly as possible. Rust would be responsible for documents, the filesystem, persistent application state, and the underlying operations, while React would handle rendering and user interaction. Tauri would provide the bridge between them.
This turned out to be a very fortunate decision, because React is already a web technology, and Bookend's interface was largely independent of the desktop environment. Of about 210 backend calls, 207 already passed through a single `invoke<T>()` wrapper, meaning that almost the entire interface communicated with Rust through one abstraction. Browser-compatible APIs were already handling things like drag-and-drop, clipboard access, keyboard interactions, and audio capture.
Rather than rewriting the editor, I needed to adapt a handful of narrow interfaces so that requests could travel over HTTP instead of Tauri's internal communication system. The backend could remain responsible for the same operations, regardless of whether the user was sitting in front of the desktop application or connecting through a browser.
The server itself was also relatively inexpensive to add. Bookend already included much of the underlying Rust networking infrastructure through Tauri and `reqwest`, including Tokio, Hyper, Tower, and related libraries. Adding an embedded server using Axum and an authentication layer would increase the size of the approximately 33 MB application by only a few megabytes.
I had spent considerable effort escaping the browser, only to realise that I'd inadvertently preserved almost everything I needed to return to it.
I hadn't followed my own architectural principles quite as faithfully as I'd imagined, though.
Bookend's AI harnesses, which define reusable AI workflows, were stored in local files and partly managed by the frontend. This worked well enough when everything was running on one computer, but became an issue when the frontend might be running remotely. A browser shouldn't need access to the host machine's application files to understand which harnesses exist or how they should be managed.
I had to refactor the application so that all persistent state, including installation-specific settings and user-defined harnesses, was controlled by Rust. This was an architectural correction rather than a visible new feature, but it meant that the frontend could finally behave as the thin client I'd intended it to be.
Making remote access safe, or at least safer
The more serious complication was security.
A desktop application can reasonably provide broad access to the local filesystem, allowing users to open documents, browse directories, create files, and save copies wherever they choose. Bookend's Rust backend supports these operations, but exposing them to a remotely connected browser would be a very different proposition, even with password protection.
I therefore introduced a restricted server mode in which arbitrary filesystem exploration and file-selection operations are unavailable. Remote users can work with documents already present in Bookend's recent-files list, but cannot browse the host computer's filesystem at will.
Crucially, these restrictions are enforced by the Rust backend itself, rather than merely hiding the corresponding buttons in the browser interface. The restricted operations are not exposed to remote clients, which means that bypassing the frontend does not restore those capabilities.
I also needed to consider concurrency, since Bookend was designed as a personal document editor rather than a collaborative server. Supporting multiple simultaneous editing sessions would introduce an entirely different class of problems involving document conflicts, synchronisation, and shared state. For the intended use case, this seemed unnecessary, so I chose to allow only one controlling session at a time. When the server is running, the local editing interface is disabled, and a single browser session controls the backend.
These decisions don't make the system invulnerable, and exposing any service to a network creates security considerations that don't exist in a purely local application. They do, however, substantially limit what the remote interface is permitted to do, without requiring me to redesign the entire application around multi-user access.
Remote access without my infrastructure
The resulting system is simple. A button in Bookend starts the embedded server and displays a local network address, which can be opened in a browser on the same computer or another device on the same network.
For access from elsewhere, users have several options. Tailscale can provide private connectivity between devices on the same tailnet, while Caddy can be configured as a reverse proxy for users who prefer to manage their own externally accessible endpoint. Tailscale Funnel provides another option, exposing a local service through a public HTTPS address without requiring the remote computer to have Tailscale installed.
Funnel is particularly relevant to the original problem, since a work computer that prohibits installing Bookend might also prohibit installing VPN software. It does, however, expose the service more broadly than a private tailnet, making the application's authentication and security controls especially important. These approaches have different requirements and risk profiles, and the intention is to provide documentation so that users can choose an arrangement appropriate to their circumstances.
The obvious limitation is that the host computer needs to be running, with Bookend's server enabled, whenever remote access is required. This isn't an always-available cloud service, and setting up access beyond the local network will require some technical confidence.
For people who Just want to access Bookend from another computer in the same room, however, it can be as straightforward as starting the server and opening a browser.
It's also worth distinguishing remote access from file synchronisation, which I'd previously addressed in a similarly unambitious fashion: users can simply put their documents in a folder managed by their preferred cloud storage provider. This doesn't provide collaborative editing, but it does mean that Bookend doesn't need to become a cloud storage company just because someone wants to use their documents on multiple devices.
A compromise I'm happy with
The remote-access feature is mostly implemented but isn't publicly available yet, and there is still testing to complete before I'm comfortable releasing it. Nor do I pretend that this approach will suit everyone, since a managed cloud service would undoubtedly be more convenient for some users.
But I don't think every application needs to solve every problem by becoming a subscription service, and I particularly dislike the idea of making users dependent on infrastructure that I would then be obliged to maintain indefinitely. There's something appealing about selling software as a product rather than a continuing service, especially when the software is intended to hold material that people might want to keep for decades.
What began as an annoying request from an early reviewer has ultimately made Bookend more flexible, forced me to correct some architectural mistakes, and added a very decent new capability without abandoning the principles on which it was originally built.
I've also managed to do it without creating a subscription business, which, depending on your perspective, is either a modest engineering success or further evidence that I should never be allowed to run a software company.
Either way, your data remains yours, and as far as reasonably possible, not my problem.