Drafts, private data, and obscurity.
The at:// protocol currently lacks any real means to have data which is both 'on-protocol', i.e. stored on your PDS in a way that you can guarantee access to, including in the event of an adversarial migration, and private. Bluesky preferences, DMs, and other settings, as well as features like blacksky.app's private posts, are off-protocol integrations. This was a conscious tradeoff they made to maintain the other guarantees (in particular adversarial migration) and make the protocol support apps which act like other apps normal people use and not like Mastodon or crypto nerd apps, much like the creation and use of of did:plc for identity.
This has been the cause of a fair bit of grief. This is the reason blocks are public data and sites like Clearsky can exist and drive people mad. This is the reason private accounts aren't available for people who don't want everyone to read their posts. It's the reason why an unpublished Whitewind blog post is identical to a published one except for a 'don't look at me' boolean flag. And it's the reason Weaver's drafts are a bit weird.
Conflict-free replicated data types
Weaver represents a notebook entry in progress via a Loro document, which is a format called a "conflict-free replicated data type". This is a way to sync document state and history between devices without central coordination and in a way that ultimately resolves state conflicts over time. Technically, these are very cool algorithms and formats, but the specifics are less important than the results. Using a CRDT as the source of truth for a notebook/entry has a number of useful features for Weaver. One is that it allows collaborative editing of a notebook without anyone ever needing to write to someone else's repository, or store data off-protocol. Edit records go to your own repository, along with periodic document snapshots. When you publish a notebook entry, you capture a snapshot of your current view of the document state and push it to your repository, then update your copy of the notebook record. But the document state and edits don't have to go to your PDS. They can remain entirely local to your machine, or just as easily be shared peer-to-peer, or synced to an app server which doesn't store them on-protocol and doesn't give general public access to them.
However, just because document snapshots and edit records are available in your repository doesn't mean they're easy for just anyone to read. They're stored as binary blobs in Loro's encoding, not as JSON, except for a bit of metadata. Reading a draft requires collecting and decoding them all using Loro to assemble a complete picture of the current document state. They're not encrypted, from a technical perspective this is little more than the 'don't look at me' boolean flag, it's very much "security by obscurity", but it's enough steps that someone using pdsls, atp.tools or Weaver's own raw record viewer can't just read them. If you have a work-in-progress article you don't want anyone to be able to read, keep it local-only (or use the dedicated app server, once that's available). But if you mostly just don't want casual drive-by reading, you can pretty safely sync them to your PDS, so you can edit them on another device (and just generally keep them backed up).
Collaboration
I mentioned collaboration above. It's not something I've implemented yet, but it's been part of the plan from nearly the beginning, as soon as Weaver went from an "I want to turn my Obsidian vault into a personal atproto blog" tool to something more ambitious, and most of the groundwork is laid.
Here's how it will work. You can invite someone to be a collaborator on a notebook (or just a single entry). If they accept, and as long as both your invitation record and their matching acceptance record exist, the app pulls in both of your edit records for drafts, and considers whichever publication record (the actual sh.weaver.notebook.book or sh.weaver.notebook.entry record) was most recently updated as canonical for the thing you're collaborating on. Note that this is app-level logic. Because of the nature of atproto data, someone else can, via a badly-behaved client, fork an entry unauthorized and publish their version, unless the drafts are kept actually private.
However, this also protects the data itself against breakdowns in collaboration. Even if you and your co-author have a falling-out and they delete all their records, you are unlikely to loose much that you worked on, because enough of the work-in-progress state will be in your repository, accessible to you. This is perhaps double-edged, but I think it is to the overall good, and sidesteps some of the social issues, or at least puts them thoroughly back in the realm of social issues, rather than allowing technical leverage over co-authors. This is something I actually feel fairly strongly about. Because I've seen it happen a number of times. People collaborate, things go south, and then the person who was the junior partner there loses access to their work. And regardless of who is "at fault" in the situation, assuming you can even assign full blame to one party, it's just a crappy situation, and it makes for weird incentives. By reducing the stakes a bit, at least as far as your access to your own writing (sans intentional out-of-band backups) goes, and your ability to easily re-host it on your terms, the hope is to help those scenarios go less 'kinetic' within communities, reducing collateral damage, particularly within communities of marginalized people. Being a super fan of Hot Allostatic Load is a red flag, but the dynamic it describes is unfortunately a real one, and I think part of what drives it, at least within communities of marginalized artists, journalists, and authors, is a lack of sovereignty over your own work's publication, downstream of how existing platforms usually work, and things like this feature of Weaver (and others I am planning but am not ready to discuss yet) are my little way of hopefully changing that.
I know, I know, "you can't solve social problems with technological solutions", but if you can cause them with technology (as I think it is very clear that you can in the year of our lord 2025), it stands to reason that you can at least do things to mitigate them with technology, because technology inherently creates certain social affordances based on how it behaves, or did you think that the ability of parents to be incredible helicopters and deny their children privacy via cellphone surveillance well into adulthood was entirely a product of culture and had nothing to do with that becoming quite easy to do in the early 2010s, particularly when combined with young adults being more economically dependent on their parents in that period than those immediately beforehand, and thus parents having more leverage?
Social Features
One thing that I have, perhaps oddly for one working on something at the very least social media-adjacent, not given a ton of thought to yet is social features. Partially that was because I had several other problems that needed solving first to get to the bare minimum of functionality, to get the core experience right, and partially because it felt obvious. What are people going to want to do? Well, they're going to want to subscribe to see more stuff they like. A lot of social media only allows that at an account level. If you like some stuff a person makes but not other stuff, it's hard to only get the stuff you like, and algorithms which attempt to do that tend to be pretty imperfect in practice. And the reality is simply that people are multi-faceted! That's why Weaver will split following a person's account from subscribing to a notebook. It will also allow gating follows and subscriptions, so that the app can enforce a consent/accept record there. I also intend to have notebook-specific author profiles, though I haven't figured out the right shape for them.
To make a personal example, just because you like my devlogs on Weaver doesn't mean you're interested in my personal and political ramblings, or my devlogs on Jacquard, or fiction writing, or electronics projects, or whatever else I might end up writing. And sure, one can make alt accounts for those different things, but then there's more of a barrier for someone who starts off interested in one thing from a person to get into their other stuff.
The request/accept record pattern itself is important as well. Because while we cannot yet have properly private data without going off-protocol (and for a number of reasons, including interoperability and to give people the assurance that if I can no longer continue this project for some reason that their data is not locked away in a defunct database, I'm going to minimize off-protocol data), we can enforce patterns like that at an app level, and that will meaningfully affect the behaviour for the vast majority of users, in the same way that the bluesky in-app nuclear block doesn't actually entirely prevent you from seeing what's behind it, you just have to go out of your way to do it (via a service like skythread or one of the aforementioned record viewers). That friction does most of the work in practice (and there really isn't a way to make it harder still, because people can always create alt accounts, just like they did on Twitter even before Elon screwed around with blocks, without actual private data/accounts).
Analytics
Here's a related thing I'm not entirely sure about yet. Writers, especially those writing for an audience, want to know with some amount of accuracy, how many people read their thing, and various other related pieces of data. Blog platforms you self-host and platforms like Substack tend to provide you with that data, in varying levels of granularity. Atproto apps tend to be a fair bit more sparse. If they have 'likes' and similar you can obviously collect those up, but that notably doesn't count views or interactions from people who don't have atproto accounts. Once I write the back-end index I can potentially persistently record that data for notebooks and entries, and provide it via an interface, along with whatever other metadata (currently that's not really possible, as the web app as it stands is entirely stateless, with all data either living in browser local storage, or on people's PDSes, or in Constellation's back-link index and some related services run by the wonderful @bad-example.com), but I am something of a privacy/data sovereignty enthusiast. I technically have Cloudflare's analytics on for this domain, because it was easy to do and why not, but my ad blocker actually blocks it and honestly that's fine. Once things get more built out I'm going to have more analytics, for my own debugging if nothing else, but also clear and straightforward ways to opt in or out of as much of that data collection as reasonable.
As a result, I'm not sure where to go here. Bluesky has created a 'feed feedback' mechanism for custom feeds which forwards interaction data from users to the provider of the custom feed they're viewing. And I can provide a similar thing, with the outputs stored in the index server and presented to the authors of the notebooks in question. It can even be an XRPC request defined by a lexicon. But it's not 'on protocol' data, it can't really be 'on protocol' data, and it's also something that opens up the GDPR compliance Pandora's Box, as anyone doing anything on atproto has encountered, primarily via very put out Germans in their replies, mentions, or inboxes. Who's responsible for that data? The notebook author(s)? It's their content that the analytics is about, it's stored on their PDS, I'm just providing an interface. Me as the service provider? Both? Honestly that's the sort of question I should probably find an EU lawyer about, but even aside from the legal question there's a question of principles. The Weaver web-app quite deliberately only uses client-side OAuth sessions for the moment and currently sets no cookies whatsoever. The server side of the web-app has no idea who you are, or even if you're logged in, and the client side never communicates that logged-in state to the server. The only time I get any data from you that isn't strictly public is if you hit "Report Bug" in the editor and send me an email.
This has actually caused some interesting problems with hydration when you're logged in (if stuff doesn't load and you were logged in, currently just hit 'refresh', you might get logged out, but things will behave, and it's easy enough to log back in if you need to. Yes this isn't ideal, that is why the domain is alpha.weaver.sh) but might have an expired session, and needing to fix those bugs ultimately might lead me to change this. Even so, I still want the web-app to be as dumb as possible here, partially so that I can throw copies of it up wherever without much thought to reduce latency (the indexing server will be the primary persistent state holder, the leaf web app instances will only do some light caching if anything, the possible exception being OAuth sessions for usability reasons), and partially because as a person who respects privacy and hates surveillance capitalism, I actually want to know as little about you as possible beyond what's necessary to provide a good service and not host things like actual CSAM (aka child porn). If I find out you're somehow running the equivalent of Libs of TikTok off of Weaver, I'll take what steps I can to block you from using things I personally host, because my commitment to freedom of expression is not a suicide pact, and I make no pretentions to strict neutrality, certainly not while this is in alpha or beta. For that reason and just general usability (particularly of the landing page, once people who aren't me start posting stuff), I will ultimately end up doing moderation of some description, but that doesn't mean I want to proactively know lots of things. Because what I know about my users can be subpoenaed, and because it feels creepy.
Fin
Anyhow, I don't have a super neat conclusion to this one. Because a lot of this is prospective, about things I have not yet done, things I am planning, and it is really several related thoughts, mixing the technical, social and political. It will happen again.