How It Works

Redux VCR is built to be modular. It consists of 4 main parts. Each of these pieces operate with Cassettes, plain objects that hold the sequence of actions needed to recreate a user’s session, as well as some metadata.

Capture

Capture is responsible for observing the stream of Redux actions, and selecting the ones it wants to record.

It’s pretty flexible: You can blacklist certain actions that you don’t want to record, or provide a “start action” that will kick off the recording (if, say, you don’t want to bother recording the onboarding process).

It creates a Cassette object, keeps track of how much time has elapsed between actions, and passes it on to the next module when stuff happens.

Persist

Persist is responsible for, well, persistence. The default module uses Firebase, and it will update the remote copy of the Cassette whenever it’s handed an updated version.

It can be debounced, to avoid spamming the server.

Retrieve

Retrieve is the inverse of Persist; it’s responsible for securely fetching the Cassettes. The default module uses Firebase as well.

Unlike the previous two modules, you likely don’t want to ship Retrieve in production. It’s used exclusively in development, so that you and you alone can re-watch user sessions.

Replay

Finally, Replay is the cute little VCR UI that lets you select and control cassettes. It offers the ability to modify the playback speed of actions, and I hope to add a scrubber that will let you jump to specific parts of the sequence.

It also consists of a middleware that allows us to pass custom options. For example, we can specify a max wait time between actions, to trim out long gaps where users are idle.

It also uses a higher-order reducer, to update the state when cassettes are loaded and ejected.

Similar to Retrieve, this is a production-only module.

Serverless Security

A concern with the development of this project was to ensure that users’ sessions were kept secure. At the same time, I didn’t want to enforce any kind of back-end. Key&Pad lives on GitHub Pages with no server-side logic.

Firebase provides a nice solution, with its custom Rules API.

When your application loads, all users are automatically authenticated using Anonymous Authentication. Essentially this just gives them a unique ID that persists for the session.

Regular users are not able to read from the database at all, and they’re only allowed to write to their custom slice of the database, using their unique ID as the key.

For admins, I’m using GitHub OAuth. You specify, in the Firebase Rules, that read access is only given to users who match a specific GitHub account, and then authenticate by clicking the VCR and signing into GitHub.