I've been playing around with lightweight app views for a while now but with my recent project it was time to go all - in.
I recently launched branchline.ink – it's a social, collaborative writing platform. Each story is part of a branching tree. Each bud at the end of a branch represents a unique story, starting from a shared seed, following a path from different authors.
I think the idea behind branchline is interesting, not novel but a cool way to crowd source writing prompts, give you a way to remix stories and add your own flavor. What I want to focus this blog post on is both the conception of the idea, the process it took to build it, and the lessons I learned along the way.
Creative Outlets
One thing I've learned about myself over the last 2 years is that I desperately need creative outlets. Normally that need was filled by building software – but as building software has become less and less part of my day to day job that creative need has been pent up. I've been blessed in the last few months to be able to be a bit more hands on with some code bases at work while at the same time carving out some space for side projects in my free time. I've really embraced tools like Claude Code as part of this which honestly helps make my limited chances to dive into building much more productive and therefore much more fulfilling. That being said I'm sure my fortune will turn, work and life will shift and I'll find myself starved for a creative outlet again.
Last year I had the idea of building a creative daily ritual app. I needed something easy and hit on the idea of a daily Haiku, ultimately I think there's still an app idea there but for now I've let that project fall to the wayside. Rather the genesis of branchline came when I was thinking about daily writing prompts.
Conceptually the idea of a daily writing prompt is simple – I've found a community I like in the atproto developer space, so I imagined how I could build there. The problem I found myself wrestling with was that while a daily writing prompt may scratch my creative itch it also poses a maintenance nightmare. First and foremost you need prompts. That means that rather than a daily creative exercise for me this app would become something I'd be stuck churning out content for – unless I could find other people to do it for me.
Community
I'd ruled out LLMs as a means of content generation – in part because I didn't want to pay for them, and in part because I don't particularly like their unguided writing, nor do I think my opinion is out of the norm. If it wasn't going to be me generating writing prompts, and it wasn't going to be LLMS, I was going to need to build a community. The good news is I'd already waded pretty deep into the atprotocol so I knew I had the technical underpinnings there.
Thinking about community working together to tell stories rattled around in my head for a little bit before I imagined overlaying it on the idea of a Directed Acyclic Graph or DAG. I'd played with this using git commits tied to bluesky posts earlier but the idea of applying it to a story felt particularly interesting. Each piece of a story would be a node in a DAG, pointing to the proceeding piece. Starting from any node you could walk the tree back to it's root and create a complete story. This would mean that rather than a daily writing prompt we would have a set of incomplete stories that you could add on to. As many authors built off of the same story the narratives would diverge. This would naturally lead to a forest of stories all grown from the same seed.
Of course following a graph from end to beginning is fairly simple. But we don't read stories from the end to the beginning – so if I was going to make this site at-all usable I was going to need to invert the graph and go from beginning to end. While the PDS technology that underpins atprotocol is very cool it has very specific limitations which meant that if I was going to be serious about building branchline I was going to need to build a real app view.
A Quick Aside for Terminology
Before we get into the structure of the app view I want to define the terms I'm going to use. I attempted to adopt tree names for as many things as I could.
Seeds - These are tokens that let you start a story, they can be given to other people, or planted to start a new story
Buds - These are bits of a story that are being written, each bud is 500 words and points to a previous bud (or a seed)
Pollen - Effectively a Like, used to create a feed for users to write from
Growing - The 24 hour window between when a bud is published and when someone can create another bud off of it.
Blooms - After 24 hours growing a bud becomes a bloom and can have new buds grown off of it.
Bookmarks - You can bookmark any bud to find it for later.
Rules
There were 2 sets of rules I wanted to lay out when building branchline, the first were the functional and non-functional requirements for the application.
- 1.
Authors should not be able to grow off their own buds – We should see stories grow over time with multiple contributors not one author.
- 2.
You should not feel like you need to log in to the app many times a day. Rather it should be a daily ritual.
- 3.
Planting seeds should be a rare event, most writing is growing buds off of existing blooms.
Enforcing these rules would fall to the App View - after all anyone could just write a section of a story to their PDS and if we indexed it naively it would let people skip all these rules.
Additionally there were 2 general "rules for working with a PDS" that I wanted to follow.
- 1.
Assume that if the user is offline their PDS is offline - obviously this isn't true for most people but our app should remain functional when a user's PDS is offline.
- 2.
Assume people will take hostile action on their PDS to game the system.
- 3.
You should only write to a pds with permission
When scoping out what would be required of an App view these 5 rules had some specific fallouts.
I would need to keep a copy of bud - this would allow me to serve a complete story beginning to end without needing to depend on PDS' being online
We would need to limit who could create new seeds.
Any record on the jetstream should point back to a known record, either a bud, or a seed
I was also faced with the question of what to do with edits and deletes, after some consideration I decided.
If there's no buds growing on top of your bud an edit is allowed, although it removes all the pollen. Otherwise edits are rejected.
If there's no buds growing on top of your bud a delete is allowed. Otherwise we erase the author record and mark a record as anonymous.
When coupled with the 24 hour growing window we give authors a chance to make edits to fix typos, but don't allow them to pull the rug out from under authors that followed their story.
Ultimately with the requirements and decision to build a real backend it was time to bring out our old friend.
Postgres
I've been doing most of my deployments on Fly.io and generally been really happy with what they have on offer. Their Postgres offering was no different. I opted for Prisma as a schema management / orm. It took a few minutes to provision Postgres and it configured Fly secrets for my app so it all just worked on deployment.
The Database Model is pretty straightforward. Mostly just a direct copy of the lexicons with a few exceptions. For instance on each of the buds we store the complete path from seed to bud. This means that when you view a bud we can hydrate the entire path with a single call. It's also very fast because we need to lookup the parent record when we write a new bud record to ensure it exists, we can just extend the path to the root by one element when we do this.
Records in Postgres are written in one of two ways. Either they are seen on the jetstream, validated and placed in the database, or they are written through one of our xrpc endpoints, hitting the user pds and then written to the database.
Generally I've tried to keep most of the content in a PDS but there are certain things that only live in Postgres
Permission grants to know who can create seeds
Tracking last read buds from a root so we can resume reading when new buds are published
Tracking notification state.
"Moderator" actions such as deleting records from Postgres, or locking buds to prevent further growth.
With these the framing was simple - if someone wanted to make their own branchline they could and the systems would interoperate for free. Currently the only limitation to that is that branchline only trusts itself to make new seeds, but if there was another client we wanted to trust we had the infrastructure in place to do that.
What's Next
Branchline is a cool idea, while it's something that I built for myself I'd like to see it flourish into a small social media site. I hope in a few months I'm looking at standing up a serious moderation service because it's become popular enough that people are abusing the system. However I'm also cognizant that I don't have any clout in author circles that would be the primary users. Also like any site it's network effects are everything. If no-one is writing stories then no-one is going to be using the app, not even me.
There's a few things on the immediate roadmap.
Monthly writing challenges with seeds planted on the first of the month and trees locked up at the end of the month
Follow authors for notifications about what they're writing
Setting KPIs
One thing I've decided to be clear eyed about with Branchline is what it's worth to me, and what it costs me. It was something I built in some free time, as long as it stays that way and it's an app I continue to use I can keep it running. But I'm going to take a hard look at the end of June 2026. With 3 months in the bag I'll be about $150 infrastructure cost in. Not crazy but I'm setting myself a simple goal. 1 author per dollar of infra spend in the first 3 month. If I managed to get past 150 authors in 3 months then I'll make a serious commitment to getting Branchline to grow to thousands of users with all the infrastructure cost and headache that brings.
If you think that this is a cool idea I'd encourage you to do check it out. (branchline.ink) login with your Atmosphere account, grow a bud and pollenate some stories. Tell a friend or two and with some luck I'll blow past my 150 author goal and need to take this thing seriously.