Skip to content

Conversation

@glastonbridge
Copy link

@glastonbridge glastonbridge commented Nov 21, 2025

⚠️ Investigation project, do not merge

What this adds

  1. Persistent project storage using Y.js
  2. Realtime syncing of information across tabs
  3. Project browser with delete and rename project functionality
  4. Manual project revisioning and restore functionality

Approach

Storage

There is a list of projects, stored in an IndexedDB instance. This contains the project names, last edited dates, against a fixed GUID.

There are the projects themselves, which consist of a Y.Doc per project, backed by y-indexeddb which creates a DB per doc.

The revisions themselves are serialised Y.js Updates which act as a complete binary delta since their parent revision. They are stored in a separate DB again, as a linked list.

Note that the "working copy" of the project (in a version control analogy) is a Y.Doc but all the "commits" are Uint8Arrays and have to be unpacked to a working copy before they will work.

Revisioning

image image

Currently the only way to create a revision is to click the clock button then "Save as new revision." This calculates the diff between the previously-saved revision (if any) and the current working copy, and adds it to the end of the linked list of revisions for the project.

Loading a previous revision creates a new project, so that it does not revert any of the other project's changes, but this is not necessarily a proposed behaviour for the future.

Code structure

I've tried to keep everything reusable inside the src/project-persistence folder so that it can be extracted as a modular add-on to other apps in future.

  • ProjectStorageProvider.tsx - underlying state, not intended to be used by consuming apps directly (this is a decision that helped me see clearly what was being used in the investigative work but might not be relevant for you)
  • persistent-project-hooks.ts - if a project is loaded, this provides it, as well as its awareness which is Y.js' way of managing multiple interactive users on a document, where their cursors are etc.
  • project-list-hooks.ts - create, load, delete, and list user projects
  • project-history-hooks.ts - view and interact with a project's history.

There are also some chakra components for displaying common information about a project, although loading a project also has to do app-specific things so I didn't try to force it into a complete component that works everywhere.

Python Editor specifics

CodeMirror

CodeMirror has its own easy yjs integration that makes this really intuitive to implement. Check out the diff in src/editor/CodeMirror.tsx for the directness of the implementation.

Project Browser

There was no existing project browser, so I hacked the routing to allow it in src/ProjectPageRouting.tsx. This was not a designed solution, but the Python editor already assumes it has control over the router for event information and I didn't want to get caught up in picking it apart. Currently the only way to get to the project view is via the root path /.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant