How to use @edx/brand in local development and production

Hi all,
Tutor version: Redwood 18.1.0

I am using a fork of the authn mfe.
I am trying to make changes to the mfe styles. When I add the link of @edx/brand repo in the indigo theme plugin it works, but when I do the same in a custom plugin hook, it doesn’t work.

This is what the plugin looks like:

from tutor import hooks
hooks.Filters.ENV_PATCHES.add_items(
    [
        (
            "mfe-dockerfile-post-npm-install-authn",
            """
    RUN npm install '@edx/brand@git+https://github.com/.../brand-openedx.git#branch_name'
    """
        ),
    ]
)

Additionally, I want to be able to create a setting where I can make changes to the brand package locally and see the changes immediately in the tutor dev mode. Is there a way achieve this?

I also tried to use a local checkout of the brand package as mentioned here. This works but only for the tutor local and not for tutor dev. The commands also show up when I build authn-dev images, but no change to styles of mfe when i do tutor dev start.

Hello @Faizan_Shaikh ,

Please tell me more about which custom plugin hook you are using and how you are using it.

Yes, it is possible to change the brand package locally and see the changes immediately in the tutor dev mode. Follow the steps for this:

  • Clone your MFE code and brand-openedx repo in the same folder
main-folder
     |________brand-openedx
     |
     |________authn-mfe
  • Mount your authn-mfe code to /openedx/app and brand-openedx to /openedx/brand-openedx
  • Now, in your authn-mfe folder, add the file name module.config.js and add the below content:
   module.exports = {
    localModules: [
     { moduleName: '@edx/brand', dir: '../brand-openedx'  },
    ],
  };
  • Then start tutor dev start authn and make changes to brand-openedx. Those will reflect automatically.
  • Sometimes, changes won’t reflect as your page will show the cached version. In this case, you can run tutor dev restart authn and simply reload the page. My recommendation to you is to use incognito mode of browser.
1 Like

Hi @hinakhadim , I was able to see my styles changes following your setup. But the logos are still using indigos. Is there a way for it to use my custom logos in the brand-openedx?

Hi @Tidbit0519,

edx-brand package updates the styles only. To update the logo, you have to use a custom theme plugin like tutor-indigo. When you will create your theme plugin, do the following:

  • In **custom-theme**/templates/**customtheme**/lms/static/images/ folder, add your logo with filename logo.png and footer_logo.png.
  • Run command to set this theme as new theme. Refer to docs

If you have questions, feel free to ask.

Thanks for the reply @hinakhadim ! I was able to change the logo in dev following this https://github.com/overhangio/tutor-indigo?tab=readme-ov-file#customization

Could you confirm the correct way to do this?

I’ve tried mounting the brand package with tutor mounts add /path/to/brand-customized, however when I pull up the MFE (tutor dev start learning), I get the following:

learning-1  | Resolving modules from local directories via module.config.js.
learning-1  | Using local version of @edx/brand from ../brand-customized/.
learning-1  | Error: Cannot find module '/openedx/brand-customized/package.json'

I do have a package.json in my local brand directory, so I suspect the mount point was set incorrectly.

Hi @haha ,
Please try these steps:

  1. For mount, run tutor mounts add learning:/absolute-path/to/brand-customized:/openedx/brand-customized
  2. make sure module.config.js (in learning-mfe) should have following:
module.exports = {
    localModules: [
      { moduleName: '@edx/brand', dir: '../brand-customized'  },
    ],
};
  1. Run tutor dev start learning

Feel free to let me know, if this wouldn’t work for you.

1 Like

Thank you so much! That did the trick. :pray:

I’m having big problems with my local development. I’m a complete Openedx noob so I’m looking for some advice. I want to apply the styles I have in tutor-indigo to all the MFEs. From this discussion, I understand that I can do that with the brand-openedx code. Using the example in this discusison for authn

tutor mounts add /<fullpath>/openedx/brand-openedx 

But when I run tutor dev start authn this happens

tutor_dev-authn-1  | > @edx/frontend-app-authn@0.1.0 start
tutor_dev-authn-1  | > fedx-scripts webpack-dev-server --progress --config ./webpack.dev-tutor.config.js
tutor_dev-authn-1  | 
tutor_dev-authn-1  | sh: 1: fedx-scripts: not found

So I run this to build the npm dependencies.

tutor dev run authn bash -c "npm install webpack-dev-server --save-dev"

Next when I run tutor dev start authn this happens

tutor_dev-authn-1  | > @edx/frontend-app-authn@0.1.0 start
tutor_dev-authn-1  | > fedx-scripts webpack-dev-server --progress --config ./webpack.dev-tutor.config.js
tutor_dev-authn-1  | 
tutor_dev-authn-1  | Resolving modules from local directories via module.config.js.
tutor_dev-authn-1  | Using local version of @edx/brand from ../brand-openedx/.
tutor_dev-authn-1  | Error: Cannot find module '/openedx/brand-openedx/package.json'
tutor_dev-authn-1  | Require stack:
tutor_dev-authn-1  | - /openedx/app/node_modules/@openedx/frontend-build/config/getLocalAliases.js
tutor_dev-authn-1  | - /openedx/app/node_modules/@openedx/frontend-build/config/webpack.dev.config.js
tutor_dev-authn-1  | - /openedx/app/webpack.dev-tutor.config.js
tutor_dev-authn-1  | - /openedx/app/node_modules/webpack-cli/lib/webpack-cli.js
tutor_dev-authn-1  | - /openedx/app/node_modules/webpack-cli/lib/bootstrap.js
tutor_dev-authn-1  | - /openedx/app/node_modules/webpack-cli/bin/cli.js
tutor_dev-authn-1  | - /openedx/app/node_modules/@openedx/frontend-build/node_modules/webpack-dev-server/bin/webpack-dev-server.js
tutor_dev-authn-1  | - /openedx/app/node_modules/@openedx/frontend-build/bin/fedx-scripts.js
tutor_dev-authn-1  |     at Module._resolveFilename (node:internal/modules/cjs/loader:1134:15)
tutor_dev-authn-1  |     at Module._load (node:internal/modules/cjs/loader:975:27)
tutor_dev-authn-1  |     at Module.require (node:internal/modules/cjs/loader:1225:19)
tutor_dev-authn-1  |     at require (node:internal/modules/helpers:177:18)
tutor_dev-authn-1  |     at /openedx/app/node_modules/@openedx/frontend-build/config/getLocalAliases.js:48:47
tutor_dev-authn-1  |     at Array.forEach (<anonymous>)
tutor_dev-authn-1  |     at getLocalAliases (/openedx/app/node_modules/@openedx/frontend-build/config/getLocalAliases.js:45:18)
tutor_dev-authn-1  |     at Object.<anonymous> (/openedx/app/node_modules/@openedx/frontend-build/config/webpack.dev.config.js:31:17)
tutor_dev-authn-1  |     at Module._compile (node:internal/modules/cjs/loader:1356:14)
tutor_dev-authn-1  |     at Module._extensions..js (node:internal/modules/cjs/loader:1414:10) {
tutor_dev-authn-1  |   code: 'MODULE_NOT_FOUND',
tutor_dev-authn-1  |   requireStack: [
tutor_dev-authn-1  |     '/openedx/app/node_modules/@openedx/frontend-build/config/getLocalAliases.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/@openedx/frontend-build/config/webpack.dev.config.js',
tutor_dev-authn-1  |     '/openedx/app/webpack.dev-tutor.config.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/webpack-cli/lib/webpack-cli.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/webpack-cli/lib/bootstrap.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/webpack-cli/bin/cli.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/@openedx/frontend-build/node_modules/webpack-dev-server/bin/webpack-dev-server.js',
tutor_dev-authn-1  |     '/openedx/app/node_modules/@openedx/frontend-build/bin/fedx-scripts.js'
tutor_dev-authn-1  |   ]
tutor_dev-authn-1  | }
tutor_dev-authn-1  | Error in module.config.js parsing. module.config.js will be ignored.
tutor_dev-authn-1  | [webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
tutor_dev-authn-1  |  - options.proxy should be an array:
tutor_dev-authn-1  |    [object { … } | function, ...]
tutor_dev-authn-1  |    -> Allows to proxy requests, can be useful when you have a separate API backend development server and you want to send API requests on the same domain.
tutor_dev-authn-1  |    -> Read more at https://webpack.js.org/configuration/dev-server/#devserverproxy
tutor_dev-authn-1 exited with code 2

Can you help @hinakhadim ?

Hi @zemogle,

Thank you for reaching out and sharing your challenge! The theme will apply to authn, discussions, learning, learner-dashboard, profile and account MFEs. `

  1. Run tutor mounts add authn:/<full_path>/openedx/brand-openedx:/openedx/brand-openedx
  2. Go to your cloned frontend-app-authn folder. Run npm install and this command will resolve fedx-scrirpts issues.

Thanks for the update @hinakhadim. I followed your suggestion but I now see

tutor_dev-authn-1  | 
tutor_dev-authn-1  | > @edx/frontend-app-authn@0.1.0 start
tutor_dev-authn-1  | > fedx-scripts webpack-dev-server --progress --config ./webpack.dev-tutor.config.js
tutor_dev-authn-1  | 
tutor_dev-authn-1  | No local module configuration file found. This is fine.
tutor_dev-authn-1  | Browserslist: caniuse-lite is outdated. Please run:
tutor_dev-authn-1  |   npx update-browserslist-db@latest
tutor_dev-authn-1  |   Why you should do it regularly: https://github.com/browserslist/update-db#readme
tutor_dev-authn-1  | <i> [webpack-dev-server] [HPM] Proxy created: /api/mfe_config/v1  -> http://local.edly.io:8000
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:1999/
<i> [webpack-dev-server] Content not from webpack is served from '/openedx/app/public' directory
<i> [webpack-dev-server] 404s will fallback to '/authn/index.html'

I’ve made sure that there is a module.config.js. I can see in node_modules there is a simlink from @edx/brand to brand -> ../../brand-openedx but this is not the right path it should be ../../../brand-openedx.

Any ideas how to make this simlink in the right place?

I’ve inspected the files inside the docker container and they are a basic checkout of brand-openedx. It looks like the mount is not being correctly applied. I’ve tried rebuilding the containers. I’ve tried removing node_modules and running npm install from inside the authn container.

Do you have any suggestions @hinakhadim ?

I’m a little further on with this item. I needed to also mount authn to /openedx/app I can perform a npm install which correctly installs all the dependences and puts @edx/brand as a symlink to the version on my local filesystem.

However, when I start up tutor dev start authn I see these errors

tutor_dev-authn-1  | Resolving modules from local directories via module.config.js.
tutor_dev-authn-1  | Using local version of @edx/brand from ../brand-openedx/.
tutor_dev-authn-1  | [webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
tutor_dev-authn-1  |  - options.proxy should be an array:
tutor_dev-authn-1  |    [object { … } | function, ...]
tutor_dev-authn-1  |    -> Allows to proxy requests, can be useful when you have a separate API backend development server and you want to send API requests on the same domain.
tutor_dev-authn-1  |    -> Read more at https://webpack.js.org/configuration/dev-server/#devserverproxy
tutor_dev-authn-1 exited with code 2

It seems to imply that thre needs to be an options.proxy setting but I have no idea where that should be. At present my openedx-brand is a fresh checkout. Any suggestions would be very welcome @hinakhadim . Thanks!