Recently, I added a signup form to my website and decided to encrypt the individuals name and email prior to sending it off to my API. In the past, I have used asymmetric encryption and worked with jsencrypt, so I thought that would be a good choice here - get a public key from the api, use that to encrypt everything, and decrypt it with a private key on the backend.

Unfortunately, my site is built with Docusaurus, which utilizes server side rendering. I didn't realize that would be an issue until I tried building and received the error: "window is not defined"

After doing some research, I came across this issue and noticed that someone was able to fake the window object by doing

global.window = {}; // fake the window object
const JSEncrypt = require("jsencrypt").default;

I tried that locally and the server built; however, running the app now threw an error about not being able to set window because it's read only.

My solution was to move the encryption logic to a separate function, and dynamically load the jsencrypt library prior to using it. If it's running on the server, we're going to fake the window and require the jsencrypt default, but if we're running in the browser we're going to import the module.

export const addContact = async (firstName, lastName, email) => {
  // Since we're using SSR, we need to do a conditional import and possibly
  // fake the window object
  if (typeof window === "undefined") {
    global.window = {};
    const JSEncrypt = require("jsencrypt").default;
    let encrypt = new JSEncrypt();
    return await addContactLogic(encrypt, firstName, lastName, email);
  } else {
    let jsEncryptModule = await import("jsencrypt");
    let encrypt = new jsEncryptModule.JSEncrypt();
    return await addContactLogic(encrypt, firstName, lastName, email);

const addContactLogic = async (encrypt, firstName, lastName, email) => {
  let key = await ApiService.request("Key", null, "POST");

  let signup = {
    FirstName: encrypt.encrypt(firstName),
    LastName: encrypt.encrypt(lastName),
    Email: encrypt.encrypt(email),

  return await ApiService.request("Signup", signup, "POST");

Now, I'm able to successfully build the client, build the server, and encrypt my subscriber's contact information before it gets sent to my API to handle the actual subscription.