Reflection Spring Update

By Tobias, Andreas and Julian

Our goal with Reflection is not just to build one local-first GTK app, but to create the conditions for other app developers to add local-first sync to their apps as well. To enable that we need easy-to-use APIs, but also developer outreach, education, and documentation. This has been our focus over the past months, as part of Protoytpefund’s “Second Stage”.

An important step towards an easier developer story is the new p2panda crate (not released yet), which provides a higher-level API. The goal of this new API is to provide the most common features in a pre-configured way that third-party app developers can just use without having to become peer-to-peer experts. This is also the API that we made GObject bindings for, so it can be used by GTK apps in languages other than Rust.

In order to get input from the community we had a series of online sessions for developers in recent months. This includes the p2panda team’s office hours and our more formal Reflection Developer Labs series. During these events, our goal was to introduce app developers to local-first concepts, and make sure our new APIs are informed by what developers need in their apps.

Andreas and Tobias giving a FOSDEM talk about Reflection in the Open Local First devroom.

Our talk at FOSDEM 2026

We also gave talks at 39C3 and FOSDEM (One about Reflection, and a more general one on the Walkaway stack), and were featured in a podcast interview on the Solarcast.

What about the App?

After shipping the app in December we expected a lot of fallout at the network layer, because that’s where we had seen the majority of issues before then. Funnily enough, we haven’t seen almost any network issues. Sync mostly just works now, even for weirder network setups. As always though, if you find issues in your own testing please file them!

Speaking of testing: With the latest 0.3 release we have experimental builds for macOS now, and they need a lot more testing because none of us have Macs. If you do, please give it a spin and file any issues you encounter. Shoutout to Frank Rausch for his help adapting the icon to the macOS style and taking screenshots for this blogpost.

Screenshot of Reflection running on macOS Tahoe, showing a meeting notes document, with 3 connected peers.

Reflection 0.3 running on macOS

Unfortunately, since we prioritized developer APIs and outreach as part of the Second Stage we didn’t make as much progress as we hoped on the Reflection app itself. This is also in part because we realized that there will be a number of breaking changes at the lower layers of the stack in the near future. It’s not clear yet when p2panda will have its “1.0” release with concrete API stability promises, but we do know that on the road to that there will be a number of API breaks.

To avoid losing user data or having to do extensive migrations, we will probably wait for p2panda 1.0 before we ship a version of Reflection that we promsise to support long-term. For now, we’ve deferred planning for Reflection 1.0 until there’s a clear timeline on the p2panda side.

That said, stabilizing the p2panda API can’t happen without app developers trying it and giving feedback. The Reflection project has been very successful in that sense, especially since the p2panda team use it every day. We want to continue to follow p2panda upstream and be a good testing ground for new APIs, but we’ll stick to Flathub Beta until we’re confident we can promise that we’ll be able to migrate data to new versions.

One concrete first challenge in this regard is that p2panda recently changed its message format, so Reflection will have to break compatibility with old data in one of the next releases. We’re currently discussing how best to handle this.

User Research & Design

We did a number of user research exercises, including an informal session at 39C3 and some more scientific user testing sessions at Boiling The Ocean 9, with Eileen Wagner’s help. The concrete findings from these are recorded as issues in the repo and informing our next round of designs.

Eileen and Sebastian in a call booth at Cultivation Space doing user testing on Reflection.

Reflection user testing at Boiling The Ocean 9

At a higher level, one of our takeaways from both the research and our own daily use of the app is that (suprise surprise!) it’s still very early days for all of this. In order to actually replace tools like Hedgedoc for most of our target groups we still need a few features that are beyond the scope of this Prototypefund round.

The most important one is making it possible to sync in scenarios where not everyone is online at the same time. Even for mostly synchronous use cases like meeting notes, it’s still annoying because you can’t share the agenda beforehand or read the notes if you missed the meeting.

The long-term solution for this are highly available and privacy-respecting “support nodes”, which can sync fully encrypted blobs for authorized users. Short-term we’re considering just having a “headless” mode for Reflection that could be deployed on a server and configured to always sync data for your documents.

Language Bindings

The GObject bindings are experimental in that we don’t promise API stability at the moment – as part of our developer outreach we already identified some areas for improvement where APIs will change. However, as long as you’re prepared for this they work and can be used today, see the API docs to get started.

So far we’ve tested the bindings with C, Python, and GJS, and Felicitas Pojtinger made Go bindings. Some other languages require additional work similar to Go, it would be great to have help from developers from other language communities to get those up and running.

In general we’re excited to get feedback from anyone trying the APIs to build something. Thanks to everyone who already provided feedback, in particular to Sergey Bugaev for their input on the GObject introspection API.

The Future

With the end of March, our funding as part of Prototypefund 2025/26 has ended. This means we’ll have less time to devote to Reflection going forward. We are applying for followup funding, but it’s likely that the project will move at a slower pace for the coming months as people will have their primary focus on other work, such as the system sync service NLnet grant.

This is also why another important focus for us in recent weeks was making it easier for people to contribute to Reflection. It’s still early days for local-first in general, and our stack (iroh, p2panda, Loro, etc.) in particular. However, we think both Reflection and the p2panda GObject bindings are now in a good enough state for more contributors to join the projects.

For example, here are some small, fun things to do in Reflection:

  • Add shortcuts for Markdown formatting #166
  • Add headless mode (to run on a server as a cheap support node solution) #223
  • Auto-format join codes #179
  • QR code for sharing join codes #221
  • Support for deep links (e.g. reflection://3b5678aa0…) #222

During our third Reflection Developer Labs session, Julian built a clipboard sharing example app in Javascript. It’d be cool to see it ported to Vala, Python, Go, or whatever your favorite language is. It would also be interesting to build it out into a full app and publish it to Flathub (should be much easier in this case than for Reflection, since there’s no need for forward/backwards compatibility).

Screenshot of the Clippy demo app, a simple GTK app window with a listbox with some pasted strings.

Julian’s Clippy demo app

You can always find us on Matrix in #reflection:gnome.org for questions about code, design, or anything else.