Metadata-Version: 2.5
Name: tutor-indigo
Version: 22.1.0
Summary: Indigo theme plugin for Tutor
Project-URL: Code, https://github.com/overhangio/tutor-indigo
Project-URL: Community, https://discuss.openedx.org
Project-URL: Documentation, https://docs.tutor.edly.io/
Project-URL: Homepage, https://github.com/overhangio/tutor-indigo
Project-URL: Changelog, https://github.com/overhangio/tutor-indigo/blob/release/CHANGELOG.md
Project-URL: Issues, https://github.com/overhangio/tutor-indigo/issues
Author: Edly
Author-email: hello@edly.io
Maintainer: Hammad Yousaf, Muhammad Faraz Maqsood
Maintainer-email: hammad.yousaf@arbisoft.com, faraz.maqsood@arbisoft.com
License: AGPLv3
License-File: LICENSE.txt
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: tutor-mfe<23.0.0,>=22.0.0
Requires-Dist: tutor<23.0.0,>=22.0.0
Provides-Extra: dev
Requires-Dist: django; extra == 'dev'
Requires-Dist: djangorestframework; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: tutor[dev]<23.0.0,>=22.0.0; extra == 'dev'
Description-Content-Type: text/x-rst

Indigo, a cool blue theme for Open edX
======================================

Indigo is an elegant, customizable theme for `Open edX <https://openedx.org>`__.

.. image:: ./screenshots/01-landing-page.png
    :alt: Platform landing page

You can view the theme in action at https://sandbox.openedx.edly.io.

Installation
------------

Indigo was specially developed to be used with `Tutor <https://docs.tutor.edly.io>`__ (at least v14.0.0). If you have not installed Open edX with Tutor, then installation instructions will vary.

Install and enable Indigo plugin::

    tutor plugins install indigo
    tutor plugins enable indigo
    tutor local launch

The Indigo theme will be automatically enabled if you have not previously defined a theme. To override an existing theme, use the `settheme command <https://docs.tutor.edly.io/local.html#setting-a-new-theme>`__::

    tutor local do settheme indigo

Configuration
-------------

- ``INDIGO_WELCOME_MESSAGE`` (default: "The place for all your online learning")
- ``INDIGO_PRIMARY_COLOR`` (default: "#15376D")
- ``INDIGO_FOOTER_NAV_LINKS`` (default: links to About Us, Blog, Donate, Terms of Service, Privacy Policy, Help and Contact Us)
- ``INDIGO_ENABLE_DARK_TOGGLE`` (default: True)
- ``INDIGO_ENABLE_DYNAMIC_THEME`` (default: True)
- ``INDIGO_BRAND_CSS_BASE_URL`` (default: ``"https://cdn.jsdelivr.net/gh/edly-io/brand-openedx@<version>/dist"``): base URL of the compiled brand-openedx CSS loaded by the MFEs (see `Using your own brand in production`_)
- ``INDIGO_BRAND_OPENEDX_PATH`` (default: ``""``): path to a local checkout of your brand-openedx repository, used in development mode only (see `Developing the brand-openedx theme`_)
- ``INDIGO_BRAND_OPENEDX_DEV_PORT`` (default: ``3000``)
- ``INDIGO_BRAND_OPENEDX_DEV_DOCKER_IMAGE`` (default: ``"docker.io/node:22"``)

The ``INDIGO_*`` settings listed above may be modified by running ``tutor config save --set INDIGO_...=...``. For instance, to remove all links from the footer, run::

    tutor config save --set "INDIGO_FOOTER_NAV_LINKS=[]"

Or, to set the primary color to forest green, run::

    # Note: The nested quotes are needed in order to handle the hash (#) correctly.
    tutor config save --set 'INDIGO_PRIMARY_COLOR="#225522"'

Theme Toggle Button
-------------------

The theme toggle button is enabled by default when Tutor Indigo is installed. The theme can be switched from light to dark and vice versa. To disable it, run::

    tutor config save --set INDIGO_ENABLE_DARK_TOGGLE=false
    tutor images build openedx
    tutor local start -d


Developing the brand-openedx theme
----------------------------------

The MFE styles (Paragon design tokens and SCSS overrides) live in a brand-openedx repository. By default, Indigo uses a tagged version of `edly-io/brand-openedx <https://github.com/edly-io/brand-openedx>`__ and the MFEs load its compiled CSS from jsDelivr. To customize the styles, fork that repository (or use your own brand package with the same structure).

To work on a local checkout, point Indigo to it and launch the development environment::

    git clone <brand-openedx-repository-url> /path/to/brand-openedx
    tutor config save --set INDIGO_BRAND_OPENEDX_PATH=/path/to/brand-openedx
    tutor dev launch

In development mode, this:

- starts an ``indigo-brand`` container that builds the brand-openedx CSS and serves it at http://localhost:3000 (see ``INDIGO_BRAND_OPENEDX_DEV_PORT``);
- rebuilds ``core.css`` within a few seconds when you edit the SCSS files in ``paragon/`` or ``themes/``, and rebuilds all the CSS (about 2 minutes) when you edit the design tokens in ``paragon/tokens/``;
- makes all MFEs load the theme CSS from http://localhost:3000 instead of ``INDIGO_BRAND_CSS_BASE_URL``.

Refresh the page in your browser to see your changes. Build logs are available with ``tutor dev logs -f indigo-brand``. Note that the builds update the ``dist/`` and ``paragon/build/`` folders of your checkout.

.. note::
    Before committing your brand-openedx changes, wait for the build to finish so that the ``dist/`` folder reflects your edits: a few seconds after editing SCSS files, and around 2 minutes after editing design tokens. You can follow the build progress with ``tutor dev logs -f indigo-brand``.

Production (``tutor local``, ``tutor k8s``) is not affected by this setting and always loads the CSS from ``INDIGO_BRAND_CSS_BASE_URL``. To go back to the remote CSS in development, run::

    tutor config save --unset INDIGO_BRAND_OPENEDX_PATH
    tutor dev launch

If the ``paragon`` plugin (tutor-contrib-paragon) is enabled, the local brand-openedx CSS takes precedence over its themes in development mode.

Using your own brand in production
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The MFEs load the compiled ``core.min.css``, ``light.min.css`` and ``dark.min.css`` files from ``INDIGO_BRAND_CSS_BASE_URL``. To use your own brand-openedx fork in production, build it, publish its ``dist/`` folder, and point Indigo to it. For instance, after committing ``dist/`` to your fork and pushing a tag::

    tutor config save --set INDIGO_BRAND_CSS_BASE_URL=https://cdn.jsdelivr.net/gh/<your-org>/<your-brand-repo>@<your-tag>/dist
    tutor local restart lms

Any server that serves these files with the ``text/css`` content type and CORS headers works too, such as your own CDN or object storage. Prefer tags over branch names in jsDelivr URLs: jsDelivr caches branches for up to 12 hours, but tags are served immediately and never change.


Dynamic theme
-------------

Every learner can pick their own theme. From the Account settings page, in the "Profile Information" section, users choose an appearance preset (Light or Dark) and, if they want, personalize five core `Paragon <https://github.com/openedx/paragon>`__ colours, labelled by what they change: buttons and links, button and link highlights, brand accents, body text, and navigation links. The appearance choice is saved as soon as it is picked, while colour changes are previewed live and only stored with the "Save" button. Colours are kept separately for each preset. Preferences are saved per user and applied across the micro-frontends, so they follow the learner from one device to another.

.. image:: ./screenshots/02-dynamic-themes.png
    :alt: Theme settings in the Account page

The light/dark toggle in the header stays available alongside this feature: it switches between the Light and Dark presets, while the Account settings page is where the presets are personalized.

The colour picker shows the contrast ratio of the colour being edited against the page background, against the WCAG AA (4.5:1) and AAA (7:1) levels, with threshold lines drawn over the picker. Colours below AA are still saved, with a warning naming the ones the learner changed. The colour used behind button and link highlights is measured against the body text drawn on it rather than against the page background. If a learner still ends up with a theme they cannot read, appending ``?indigo-theme-reset=1`` to any micro-frontend URL offers to clear their stored colours, without needing to read the settings page. The confirmation is a browser dialog, so it stays legible whatever colours the learner has chosen, and it means a link sent by someone else cannot wipe their choices silently.

.. note::
    The theme settings block is registered through the legacy plugin slots of the Account micro-frontend, in the only slot it offers for this (``additional_profile_fields``), which is why it appears under "Profile Information" rather than "Site Preferences". Sites running the frontend-base version of ``frontend-app-account`` will not see the block at all, because the compatibility layer does not map that slot. Learners on those sites can still switch between Light and Dark with the header toggle, but cannot personalize colours.

.. note::
    The chosen colours are applied in every micro-frontend, including those Indigo does not otherwise style, because the theme script runs on load rather than waiting for a slot to render. The runtime retint of the legacy Django pages is more limited: it rewrites the colours it finds in stylesheets the browser lets it read, so it covers the primary colour but not brand accents or navigation links, whose defaults do not occur in the compiled legacy CSS, and it is skipped entirely for stylesheets served from another domain, such as a CDN.

    Dark appearance follows ``INDIGO_ENABLE_DARK_TOGGLE``. When that setting is off, the Dark preset is not offered and the dark variant is not applied to new choices. Learners whose browser already holds a dark preference from an earlier install keep it, as they do without this plugin.

The preferences are stored by the ``indigo_theme`` Django app, which ships with this plugin and is installed into the ``openedx`` image and serves them from ``/api/indigo/v1/theme/``. The presets table is prefilled with the default token values for the light and dark variants by a database migration.

After enabling the plugin, rebuild the images and relaunch the platform so that the app is installed and its migrations are applied::

    tutor images build openedx mfe
    tutor local launch

Developers working on the Django app can mount their local copy in place of the one copied from the plugin's build context::

    tutor mounts add ./tutorindigo/templates/indigo_theme

To disable the feature, run::

    tutor config save --set INDIGO_ENABLE_DYNAMIC_THEME=false
    tutor images build openedx mfe
    tutor local start -d

Customization
-------------

This plugin can serve as a starting point to create your own themes. Just fork this repository and modify the files as you see fit.

You will have to start by installing indigo from source::

    git clone https://github.com/overhangio/tutor-indigo.git
    pip install -e ./tutor-indigo
    tutor plugins enable indigo

Any change you make to the theme can be viewed immediately in development mode (with `tutor dev ...` commands) after you run::

    tutor config save

To deploy your changes to production, you will have to rebuild the "openedx" Docker image and restart your containers::

    tutor images build openedx
    tutor local start -d

Changing the Styling in Sass files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To customize the theme stylesheets, modify the files in the ``tutorindigo/templates/indigo/lms/static/sass/`` and  ``tutorindigo/templates/indigo/cms/static/sass/`` directories. In particular, the ``_extras.scss`` files should contain most styling rules.


Changing the default logo and other images
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The theme images are stored in `tutorindigo/templates/indigo/lms/static/images <https://github.com/overhangio/tutor-indigo/tree/release/tutorindigo/templates/indigo/lms/static/images>`__ for the LMS, and in `tutorindigo/templates/indigo/cms/static/images <https://github.com/overhangio/tutor-indigo/tree/release/tutorindigo/templates/indigo/cms/static/images>`__ for the CMS. To use custom images in your theme, just replace the files stored in these folders with your own.

Overriding the default "about", "contact", etc. static pages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default, the ``/about`` and ``/contact`` pages contain a simple line of text: "This page left intentionally blank. Feel free to add your own content". This is of course unusable in production. In the following, we detail how to override just any of the static templates used in Open edX.

The static templates used by Open edX to render those pages are all stored in the `edx-platform/lms/templates/static_templates <https://github.com/edx/edx-platform/tree/open-release/sumac.master/lms/templates/static_templates>`__ folder. To override those templates, you should add your own in the following folder::

    ls tutorindigo/templates/indigo/lms/templates/static_templates"

For instance, edit the "donate.html" file in this directory. We can derive the content of this file from the contents of the `donate.html <https://github.com/edx/edx-platform/blob/open-release/sumac.master/lms/templates/static_templates/donate.html>`__ static template in edx-platform:

.. code-block:: mako

    <%page expression_filter="h"/>
    <%! from django.utils.translation import gettext as _ %>
    <%inherit file="../main.html" />

    <%block name="pagetitle">${_("Donate")}</%block>

    <main id="main" aria-label="Content" tabindex="-1">
        <section class="container about">
            <h1>
                <%block name="pageheader">${page_header or _("Donate")}</%block>
            </h1>
            <p>
                <%block name="pagecontent">Add a compelling message here, asking for donations.</%block>
            </p>
        </section>
    </main>

This new template will then be used to render the /donate url.

Troubleshooting
---------------

Changes to the MFE styles are not applied
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Indigo styles the LMS/CMS pages and the MFEs in two different ways:

- The LMS and CMS pages are styled by the Indigo theme itself (see `Customization`_), including ``INDIGO_PRIMARY_COLOR``. Changes to these files require rebuilding the "openedx" image.
- The MFEs are styled by the compiled CSS of a brand-openedx repository, which they load at runtime from ``INDIGO_BRAND_CSS_BASE_URL``. Changes to the Indigo theme files and to ``INDIGO_PRIMARY_COLOR`` do not affect the MFEs.

To change the MFE styles, edit your brand-openedx fork and preview your changes with ``INDIGO_BRAND_OPENEDX_PATH`` (see `Developing the brand-openedx theme`_). Then publish it and point ``INDIGO_BRAND_CSS_BASE_URL`` to it (see `Using your own brand in production`_). There is no need to rebuild the "mfe" image.

Earlier versions of this documentation recommended installing a custom ``@edx/brand`` package in the MFE image with the ``mfe-dockerfile-post-npm-install`` patch. You should remove this patch: the MFE styles now come from ``INDIGO_BRAND_CSS_BASE_URL``. With the default MFEs, the ``@edx/brand`` package installed in the image is only used as a fallback, when the CSS from ``INDIGO_BRAND_CSS_BASE_URL`` cannot be loaded. However, if you build MFEs from forks or older versions whose stylesheets still import ``@edx/brand``, that package is compiled into the MFE bundles, and the CSS from ``INDIGO_BRAND_CSS_BASE_URL`` only overrides the rules that it also defines: rules from a custom package may then still apply.

If your changes still do not show up, reload the page without the browser cache, and check in the "Network" tab of your browser's developer tools that the ``core.min.css``, ``light.min.css`` and ``dark.min.css`` files are loaded from the URL that you expect. jsDelivr may serve files from a branch URL from its cache for up to 12 hours, so prefer tags.

This Tutor plugin is maintained by Muhammad Faraz Maqsood and Hammad Yousaf from `Edly <https://edly.io>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.edly.io/troubleshooting.html>`__ section from the Tutor documentation.


License
-------

This work is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor-indigo/blob/release/LICENSE.txt>`_.
