CoreMedia Content Cloud v13 Upgrade Guide / Version 2512.0
Table Of ContentsWhile the Workflow App has been replaced by a new implementation based on React instead of ExtJs, the API for custom workflows has largely been kept unchanged. However, there are notable breaking changes:
Localization Based on Resource Bundles
The well-known Studio mechanism for localization based on resource bundles was (and in the Content App still is)
based on ExtJs mechanisms. So to localize your custom workflow labels and texts, you need to apply a new mechanism.
You still have resource bundles as before in different languages. However, you need to register the localized bundles
for "de" and "ja" using the registerLocale() function:
import { registerLocale } from "@coremedia/studio-client.i18n-models";
registerLocale(Gcc_properties, "de", async () => {
await import("./Gcc_de_properties");
});
Following that, when localizing a specific resource bundle key, you need to use the getLocalizer()
function:
import { getLocalizer} from "@coremedia/studio-client.i18n-models";
const localize = await getLocalizer(Gcc_properties);
TextField({
label: localize("TranslationGlobalLink_submission_status_key"),
...
}),WorkflowPlugin API
The type WorkflowPlugin is no longer generic, this is now only the case for its properties startWorkflowFormExtension
and runningWorkflowFormExtension. In addition, for the two form extension, the factory function
StartWorkflowFormExtension<ViewModel>() and RunningWorkflowFormExtension<ViewModel>()
have been introduced respectively. So the registration of a new workflow plugin follows this pattern:
interface GccViewModel {
...
}
const getGccWorkflowPlugin = async (): Promise<TranslationWorkflowPlugin> => {
workflowType: "TRANSLATION",
workflowName: "TranslationGlobalLink",
...
startWorkflowFormExtension: StartWorkflowFormExtension<GccViewModel>({ ... }),
runningWorkflowFormExtension: RunningWorkflowFormExtension<GccViewModel>({ ... }),
...
}
getGccWorkflowPlugin().then((gccWorkflowPlugin) => {
workflowPlugins._.addTranslationWorkflowPlugin(gccWorkflowPlugin);
});For more details, see Section 9.28, “Custom Workflows” in Studio Developer Manual.
ResourceBundleUtil
The utility class ResourceBundleUtil from @jangaroo/runtime/l10n/ResourceBundleUtil
has been deprecated in jangaroo.npm and is not supported inside the workflow app. To replace
ResourceBundleUtil.override please just utilize Web API Object.assign
instead which doesn’t require any import. You can also remove the dependency @jangaroo/runtime
from your package if it was only utilized for that.
To retain code completion and type errors if an overridden resource bundle key does no longer exist in the default
resource bundle, you can utilize satisfies Partial<MyResourceBundle_properties>
(supported by jangaroo.npm 3.3.1+), for example,
import ResourceBundleUtil from "@jangaroo/runtime/l10n/ResourceBundleUtil";
import MyResourceBundle_properties from "./MyResourceBundle_properties";
ResourceBundleUtil.override(MyResourceBundle_properties, {
someKey: "...",
});should be replaced by:
import MyResourceBundle_properties from "./MyResourceBundle_properties";
Object.assign(MyResourceBundle_properties, {
someKey: "...",
} satisfies Partial<MyResourceBundle_properties>);Public API
Whenever utilizing studio-client API you now need to make sure to only utilize public API. In addition, public API needs to be imported from the package export, meaning that deep path imports inside the package will not work. The new plugin build will report corresponding warnings and errors.
Example:
import contentTypeLocalizationRegistry from "@coremedia/studio-client.cap-base-models/content/contentTypeLocalizationRegistry";
now needs to be
import { contentTypeLocalizationRegistry } from "@coremedia/studio-client.cap-base-models";The identifiers are always named after the module file name of the old import.
If you have split your plugin into multiple packages this applies to all packages used inside the runtime code of the plugin. Also be aware that in case you have used packages that did not contain any public API at all, the plugin build may not report any warnings or errors. Those packages will be handled as custom third party packages, so their code is just bundled into your plugin. This could lead to unintended side effects if you rely on shared runtime state or similar in that case.
Extension Mechanism
While the API is mostly the same, there are changes regarding affecting the extension package structure because the new Workflow App is no longer running with ExtJS and though cannot work with the ExtJS based “Dynamic Packages” mechanism.
This has been replaced with a new mechanism based on Module Federation.
package.json Changes
In order to switch an extension for the old workflow app to the new workflow app, you need to make notable changes to the devDependencies and the scripts of the package.json:
Declare the package type as “module” by adding:
"type": "module",
Remove “@jangaroo/core” and “@jangaroo/build” and make sure you have at least these devDependencies
"devDependencies": { "@babel/core": "^7.23.2", "@coremedia/eslint-config-studio-client": "2506.0.0", "@coremedia/studio-client.build-config": "2506.0.0", "@coremedia/studio-client.workflow.shared-modules": "2506.0.0", "eslint": "^8.57.0", "rimraf": "^5.0.7", "typescript": "^5.8.2", "webpack": "^5.98.0", "webpack-cli": "^6.0.1" }Make sure to have at least these scripts:
"scripts": { "clean": "rimraf ./dist", "prebuild": "sync-tsconfig-project-references src --includeDevDependencies", "build": "tsc --project src && webpack build --mode=production", "watch": "webpack watch --mode=development", "lint": "eslint \"src/**/*.ts*\"" }Add a new section “coremedia” with the following entry (replacing the $placeholder with a name containing only letters or underscore [a-z_]+):
"coremedia": { "projectExtensionFor": "studio-client.workflow", "plugins": { "$placeholder": "./dist/appEntry.js" } },
Other Files
Remove
jangaroo.config.jsCreate
.eslintrc.cjsmodule.exports = { extends: ["@coremedia/eslint-config-studio-client"], };Create
babel.config.jsimport { babelConfig } from "@coremedia/studio-client.build-config"; export default babelConfig;Create
webpack.config.jsimport { sharedModules } from "@coremedia/studio-client.workflow.shared-modules"; import { createWorkflowPluginConfig } from "@coremedia/studio-client.build-config"; export default createWorkflowPluginConfig({ name: "$placeholder", sharedModules, });Where $placeholder must be the same identifier that you have used in your
package.jsonfile.Create
src/index.ts// empty, must be there for webpack...
Create
src/tsconfig.json(the new prebuild script will automatically modify thistsconfig.jsonlater):{ "extends": "@coremedia/studio-client.build-config/tsconfig-shared.json", "compilerOptions": { "rootDir": ".", "outDir": "../dist/src" } }Create
src/plugin.tsexport const initPlugin = async () => { // add your plugin code here, e.g. start utilizing the custom workflow api };
Now you have a base skeleton for the new plugin mechanism. You can start adding your own code to the
src/plugin.ts file.
Migrating Content Type Localization for Content App and Workflow App
You usually want to have Content Type Localization only once in a shared packages. If you have sticked to the examples for Content Type Localization provided in the Blueprint, there is a migration path for the new plugin mechanism. While all examples in the Blueprint are adjusted, the general approach looks as follows.
Add the initialization code to the src/plugin.ts file of your plugin.
export const initPlugin = async () => {
const module = await import("@coremedia-blueprint/studio-client.my-doctypes");
await module.initMyDocTypes();
};
For the shared package itself (in the example this is @coremedia-blueprint/studio-client.my-doctypes)
you now need to create and export the corresponding init method. This can be as simple
as just exporting it in their index.ts file:
import { contentTypeLocalizationRegistry } from "@coremedia/studio-client.cap-base-models";
import MyDocTypes_properties from "./MyDocTypes_properties";
export const initMyDocTypes = async (): Promise<void> => {
contentTypeLocalizationRegistry.addLocalization(MyDocTypes_properties);
};
For more complex examples (including different locales), check the packages @coremedia-blueprint/studio-client.workflow.blueprint-doctypes-plugin
and @coremedia-blueprint/studio-client.blueprint-doctypes in the Blueprint workspace.
Customization via ExtJS Plugins
The ExtJS Plugin mechanism was never supported in the old Workflow App. However, it was possible to ignore that and just utilize the API in order to make customizations. As we switched to React, there is no replacement for that and though we cannot offer a migration path here.
Customization for the Workflow App can now only be done via the provided CustomWorkflowApi and
additional APIs like the contentLocalizationRegistry.


