Short answer: not today. That string (catalog.home-page.subtitle) is a translated message inside the app, and there’s no config setting for it, so the plugin slot is the supported route. The good news is you only need to write that plugin once, not once per site.
The trick is to have the plugin read its text from config rather than hardcode it. Anything you put in MFE_CONFIG / MFE_CONFIG_OVERRIDES is served by /api/mfe_config/v1 and merged into getConfig(), custom keys included, so:
// env.config.tsx
import { getConfig } from '@edx/frontend-platform';
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const HomeOverlay = () => {
const { SITE_NAME, HOMEPAGE_TITLE, HOMEPAGE_SUBTITLE } = getConfig();
return (
<>
<h1 className="display-1 text-white text-center">
{HOMEPAGE_TITLE || `Welcome to ${SITE_NAME}`}
</h1>
{HOMEPAGE_SUBTITLE && (
<p className="lead text-white text-center mb-3">{HOMEPAGE_SUBTITLE}</p>
)}
</>
);
};
const config = {
pluginSlots: {
'org.openedx.frontend.catalog.home_page.overlay_html': {
keepDefault: false,
plugins: [{
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_home_page_overlay',
type: DIRECT_PLUGIN,
RenderWidget: HomeOverlay,
},
}],
},
},
};
export default config;
Then each deployment only differs by a config value, set from a tiny Tutor plugin that patches openedx-common-settings:
MFE_CONFIG_OVERRIDES.setdefault("catalog", {})["HOMEPAGE_SUBTITLE"] = "Courses for Acme Corp"
Same plugin code, same image build, one setting per client. Note the title is already config-driven, since it interpolates SITE_NAME.
On the styling side, keep the Paragon utility classes (display-1, lead, text-white) instead of inline styles, and leave the banner itself alone: it reads --catalog-home-page-banner-background-image and --catalog-home-page-banner-background-color, so per-site background and colors belong in your brand override CSS (PARAGON_THEME_URLS), not in the plugin.