Porting Vikunja (todo list manager) to webxdc

I’m trying to port this app https://try.vikunja.io/ to webxdc. I’ll share how it’s going here.
Right now I’ve managed to make a (super raw) prototype, which can somewhat handle tasks.
The diff can be found here.

The Vikunja app relies on the backend a lot. Most of the API interactions are in the src/services folder. So what I’m doing is rewriting the services to use a “local backend” (src/localBackend folder). For now only tasks are somewhat implemented. The webxdc API is not used at all, so no cooperation for now.

My plan is:

  1. Improve typing of services to better see where they are used in the app
  2. Implement the most important services locally (tasks, kanban buckets)
  3. Use webxdc API (set up sync between users)
  4. Simply remove the code that relies on unimplemented services
  5. Maybe implement some more of the services and bring back the features that rely on them (lists, namespaces, users).
  6. See the result and evaluate whether it’s sensible to try to integrate the changes into the upstream (the maintainers said that it’s unlikely). The alternative is to keep a separate git branch and keep merging the upstream into it (resolving conflicts could be a pain).

If you have ideas for improving the steps, please share.

For more info, here’s the Vikunja project’s chat, I chat with the maintainers there.


Ok, looks like there is actually a lot of logic that is backend-only. See, for example, the (t *Task) Update function. Marking a task as “done” is not just a matter of flipping its done property. See the updateDone function. There’s plenty of stuff going on. If you send done: true to the backend it could flip it back, depending on, for example, the repeat_after property.

I’m afraid that simply translating the Go backend to JS is not the way to go.


  • Strip off some of the functions, like repeating tasks.
  • Actually try to make a best-effort Go-to-JS translation, with no guarantees that it’s gonna behave exactly the same as the original one.
  • Try to modify the upstream repos, transfer as much logic as we can to the front-end, i.e. make it so that the front-end doesn’t try to set done: true if the backend would actually flip it back to false.
    It seems kind of weird that if you send done: true it returns done: false anyway. But maybe it’s because the alternative is to make a properly named and described endpoint, while keeping the logic the same.
  • Somehow use the actual Go backend. Translate it to WASM + JS with Emscripten? That would make the bundle super big. And can you translate the database that the backend uses as well?

Perhaps when this

is implemented, it’s gonna be much easier to convert it to fully offline. But they say it’s complex, so not sure if/when to expect that.
I’m still working on the fork though, will probably post another version soon.

I’ve deployed a web version that stores all the data in the browser https://wofwca.github.io/vikunja-frontend/.

I’ll be working on webxdc sync now.

Also need to make sure that the PWA version can work offline.

I’ve set up the webxdc build workflow. You can download the .xdc here.

It still pretty raw and doesn’t have any sync between users, and you can’t use it on the device that you sent it from due to .xdc file size limitations in Delta Chat (ask the chat members to forward your message to the same chat, and it will work for you).


I have implemented communication between users using Yjs. And guess what? It works both with webxdc and online (with WebRTC).

To check out WebRTC sync, head to Vikunja , go to “Settings” and check “Enable sharing” and enter room name and password, then open another instance (say, in a different browser) and enter the same credentials. If the signaling server works, your instances will sync (gotta reload the page for now).

.xdc can be found here, as usual.

Source code of the sync part: src/localBackend/sync.ts

I’ll pause the development of Vikunja for now. I’ll be happy to assist whoever finds this relatable.


I see this topic is pretty popular, so I’ll make a small update.

For those who are looking to do a similar thing. There is now a discrete library to sync data with arbitrary schemes, i.e. sync any object/array/string between peers:

And here is the “official” library that does the same, but with different API and slightly different behavior:

The editor app was used to depend on the former, but now it’s the latter.

Adding WebRTC support is also easy: WofWca/webxdc-yjs-provider: Sync webxdc app state automatically with Yjs - webxdc-yjs-provider - Codeberg.org. The code is roughly the same for the “official” library.

uups sorry, didn’t read until the end