Skip to content

Content Management System

Overview

The Content Management System applet is a set of five flat editors over the CMS tables that Customer Portal (CP Commerce) storefronts read: Theme (colour and font presets), Content Category (a hierarchy of content labels), Widgets (named instances of the platform’s widget catalogue), Menu (navigation items inside a menu list) and Pages (rich-text posts). Each editor is a listing with create, edit and delete; there is no website selector, no preview and no publishing step — a row is live for the storefront as soon as its status is ACTIVE.

It is the older, generic view of content that the CP Commerce Admin applet now edits per website, tab by tab. Both applets write the same tables (see Lifecycle and effects), so a menu item or content category saved here appears in CP Commerce Admin and vice versa — with one important difference: this applet cannot say which website a post or theme belongs to (see Troubleshooting). It writes nothing to stock or the General Ledger.

Where it fits

PositionApplet / systemWhy
ModuleE-Commerce, CRM & DigitalStorefront content; the applet’s route prefix is crm/cms
Same tables, richer screensCP Commerce AdminIts Website › Menu List, Posts, Label List and Content Category tabs write bl_cms_menu_hdr, bl_cms_post_hdr, bl_cms_label_list_hdr and bl_cms_label_hdr scoped to a website. Its Layout Instance tab is what actually places widgets on a storefront page; this applet only names widget instances
Reads what is saved hereCustomer Portal storefront (web and mobile app)Menus, posts, content categories and themes are rendered by the storefront’s widgets
ImagesMedia LibraryPost images uploaded from the Pages editor go to the post’s own image store (cms/posts/add-files), not to a Media Library drive
OrdersShopping Cart (Internal)Not connected: nothing here touches carts or documents; listed because readers arriving from the E-Commerce module expect it

Screens and menus

Sidebar (from shared/menu-items.ts; everything else in that file is commented out): a CMS separator, then Theme, Content Category, Widgets, Menu, Pages, and a Setting entry whose route (setting) does not exist — clicking it falls through to the wildcard redirect and lands on the Theme listing. The applet’s route prefix is applets/tnt/wavelet/crm/cms; opening the prefix with no sub-path redirects to member-listing, which also does not exist, so the practical landing screen is always Theme.

Every editor has the same shape: an ag-grid listing on the left with a + (create) action, a create form, and an edit form that opens from a row. Since the 2026-09-01 build (PR #1, “[FE][Sub Query Remove]”) the listings no longer run raw sub-queries against the entity table; they page through the CMS endpoints with the shared advanced-search component, and the Content Category screens were rebuilt on the two-column container used by the newer applets.

MenuListing columnsCreate / edit formReads and writes
ThemeTitle, Template, Status, Creation Date, Updated DateTitle, Template (one of the platform’s theme templates), Description, Status, then fifteen colour and font-size controls; edit adds an image grid with Add Imagethemes (templates, read only) and theme-instances
Content CategoryName, Category Level, Status, Creation Date, Updated DateName, URL Key, Description, Status, optional Parent Category (nesting toggle)label-lists (read, first list only) and labels
WidgetsTitle, Type, Status, Creation Date, Updated DateTitle, Widget Type (from the widget catalogue), Status; edit adds an image grid with Add Imagewidgets (catalogue, read only) and widget-instances
MenuTitle, Menu Level, Menu List, Sort Number, Link Type, Status, Creation Date, Updated DateTitle, Menu List, Link Type (Component, Page, Content Category, External Link), Link or External URL, Sort Number, Status, optional Parent Menu (nesting toggle), menu icon; Redirect Type is present in the template but commented outmenu-lists (read), menus, and posts / labels to fill the Link picker
PagesTitle, Author Name, Status, Creation Date, Updated DateTitle, URL Key, Status, Content Category, Layout Type, Widget, rich-text Content (Froala editor with inline image upload); edit adds an image grid with Add Imagelabels (categories) and posts

Advanced search per listing (models under models/advanced-search-models/): Pages by Page Title, Author Name, Status; the other four by their title/name and status.

Also in the bundle but reachable from no route: an About Us general-configuration editor, a CSV customer-profile upload dialog, and a marketing landing page inherited from the platform shell. They are declared in app.module.ts only.

Configuration

Before you can use it

  • Theme templates — at least one row in bl_cms_theme_hdr (GET cms/themes). The Theme form’s Template picker is filled from it and a theme cannot be saved without one (CMS_THEME_INSTANCE_HDR_OBJECT_THEME_HDR_GUID_IS_NULL_OR_EMPTY). Templates are platform data; no screen in this applet or in CP Commerce Admin creates them.
  • A label list — the Content Category form silently uses the first label list the tenant has (getLabelList() takes resp.data[0]). If the tenant has none, every category save fails with CMS_LABEL_HDR_OBJECT_LABEL_LIST_GUID_IS_NULL_OR_EMPTY. Label lists are created per website on the CP Commerce Admin Label List tab.
  • A menu list — the Menu form’s Menu List picker reads cms/menu-lists; a menu item needs one (CMS_MENU_HDR_OBJECT_MENU_LIST_GUID_IS_NULL_OR_EMPTY). Menu lists are created on the CP Commerce Admin website Menu List tab.
  • Widget cataloguebl_cms_widget_hdr rows (GET cms/widgets) fill the Widget Type picker.
  • Server-side permissions on the CMS endpoints: API_TNT_DM_ERP_CMS_THEME_INSTANCES_*, API_TNT_DM_ERP_CMS_MENUS_*, API_TNT_DM_CMS_LABEL_*, TNT_API_CMS_POST_* and TNT_API_CMS_WIDGET_INSTANCE_* (CREATE / READ / UPDATE / DELETE, plus ADMIN / OWNER), all in TntCmsPermissions. This applet has no permission screens of its own; assign them from an applet that has (CP Commerce Admin › Settings, or Tenant Admin).

Applet settings

No exposed control found (routes and module checked at commit 3b4e90c4). The applet has no settings container, no field-configuration, default-selection, printables, webhook, feature-visibility or permission routes, and no personalization screen. The Setting sidebar entry points at a route that does not exist. Nothing is read from bl_applet_ext.APPLET_SETTINGS.

Document behaviour settings

Not applicable — the applet creates no documents.

Settings in other applets that control this applet

SettingWhere it is setEffect here
Website › Content Category label list (bl_cms_website_hdr.content_category_label_list_guid)CP Commerce Admin › Website › DetailsDecides which label list the storefront reads categories from. This applet always writes categories into the tenant’s first label list, which is not necessarily the one a website points at
Website › Menu ListCP Commerce Admin › Website › Menu List tabCreates the menu lists offered by the Menu form’s Menu List picker
Website › Layout InstanceCP Commerce Admin › Website › Layout InstanceThe only place widget instances are placed on a page; instances named here do nothing until a layout node references them

Feature visibility / permissions

No client-side permission is read anywhere in the applet’s code (no permission reference in components/), and it ships no bl_applet_client_side_perm_dfn rows that the code would consult. Access is decided entirely by the server-side TntCmsPermissions constants listed above; a login without …_READ on an endpoint sees an empty listing and no error.

Fields

Required-ness below is what the backend validators enforce; the form’s own required markers are listed separately where they differ.

Theme

FieldColumnRequired (backend)Notes
Titlebl_cms_theme_instance_hdr.titleNo (form: yes)Listing column
Templatetheme_hdr_guid (from bl_cms_theme_hdr); the picked title is also stored in typeYes…THEME_HDR_GUID_IS_NULL_OR_EMPTY, …DOES_NOT_EXISTPicker filled from cms/themes
Descriptiondescrption (sic, column name)No
StatusstatusYes…STATUS_IS_NULL_OR_EMPTYACTIVE / INACTIVE
Primary, Secondary, Background, Card Background, Header Background, Header Text, Title Font, Subtitle Font, Normal Text Font, Login/Register Background, Login/Register Text colours; Header, Title, Subtitle, Normal Text font sizesone bl_cms_theme_instance_ext row, param_code = THEME_CONFIG, param_type = JSON, a themeConfig array of {title, value, type}NoColour pickers and text inputs; edit rewrites the matching array entries in place
Websitewebsite_hdr_guidYes…WEBSITE_HDR_GUID_IS_NULL_OR_EMPTY, …DOES_NOT_EXISTNot on the form. Create writes a constant GUID hard-coded in theme-config-create.component.ts; see Troubleshooting

Content Category

FieldColumnRequired (backend)Notes
Namebl_cms_label_hdr.nameYesCMS_LABEL_HDR_OBJECT_NAME_IS_NULL_OR_EMPTYForm: required
URL Keyurl_keyNo (form: yes)
DescriptiondescrNo
StatusstatusYesACTIVE / INACTIVE
Parent Categoryparent_guid; sets level_value 2 (1 when no parent)NoOnly when the nesting toggle is on
code = CMS_CODE, txn_type = CMS_CATEGORY, label_list_guid = the tenant’s first label listYes (code, label list)Fixed by the form; not editable

Widgets

FieldColumnRequired (backend)Notes
Titlebl_cms_widget_instance_hdr.titleNo (form: yes)
Widget Typewidget_hdr_guid and type (the catalogue title)NoPicker from cms/widgets
StatusstatusYes
Thumbnailpix_thumbnail_guidChecked by CmsWidgetInstanceDataConsistencyObject (…PIX_THUMBNAIL_GUID_IS_NULL_OR_EMPTY)Not on the form; the Add Image screen uploads through widget-instances after creation

Menu

FieldColumnRequired (backend)Notes
Titlebl_cms_menu_hdr.titleYesCMS_MENU_HDR_OBJECT_TITLE_IS_NULL_OR_EMPTY
Menu Listmenu_list_guidYes…MENU_LIST_GUID_IS_NULL_OR_EMPTY, …DOES_NOT_EXISTPicker from cms/menu-lists
Link Typemenu_link_typeYes…MENU_LINK_TYPE_IS_NULL_OR_EMPTYCOMPONENT, PAGE, CONTENT CATEGORY, EXTERNAL LINK (Product and Product Category are commented out)
Link / External URLtarget_guid + target_url (Page or Content Category), or target_url only (External Link)NoPage picker from cms/posts, category picker from cms/labels
Sort Numbersort_codeNo (form: yes)Integer
StatusstatusYes
Parent Menuparent_guid; sets menu_level 2 (1 without)Level yes…MENU_LEVEL_IS_NULL_OR_EMPTY; parent must existNesting toggle
Menu iconproperty_json.menu_iconNoChosen on the form; the listing does not show it

Pages

FieldColumnRequired (backend)Notes
Titlebl_cms_post_hdr.titleNo (form: yes)The header validator checks GUID, revision, status and referenced GUIDs only
URL Keyurl_keyNo
StatusstatusYesCMS_POST_HDR_OBJECT_STATUS_IS_NULL_OR_EMPTY
Content Categorypost_category (the label’s GUID as text)NoPicker from cms/labels
Layout Type, Widgetform controls layout, widgetNoNot saved — neither is copied into the container on create or edit
Contentcontent_bodyNoFroala rich text; inline images are PUT to core2/tnt/dm/cms/posts/add-files/{postGuid} (JPEG/PNG)
Authorauthor_name, author_guid, created_by_guid (create), modified_by_guid (edit)NoFrom the signed-in user’s profile
post_type = PAGE, code = CMS_GENERAL_CONFIGURATION, a random pix_thumbnail_guidFixed by the form
Websitewebsite_hdr_guidOnly validated when presentNever set by this applet — see Troubleshooting
Images (edit › Add Image)post image store via posts/add-files with an Image Type of Main Image or Additional ImageJPEG/PNG only

Lifecycle and effects

Endpoints. All through blg-akaun-ts-lib services under core2/tnt/dm/cms/: theme-instances (and themes, read), labels (and label-lists, read), widget-instances (and widgets, read), menus (and menu-lists, read), posts. Create is POST, Save is PUT on the whole container (service.edit), Delete is DELETE /{guid}. Every listing and picker sends the standard paged getByCriteria query.

Statuses. There is no draft/final lifecycle. Each row carries ACTIVE or INACTIVE as chosen on the form; the storefront treats INACTIVE as hidden. Delete is immediate — the edit forms call the service on the first click with no confirmation dialog (the confirmation-dialog references in menu-config-edit and the theme listing are declared but never opened). Deleted rows disappear from every listing (hdr.status != 'DELETED' filters in CmsMenuUow, CmsLabelUow, CmsPostUow, CmsWidgetInstanceUow).

What it writes. bl_cms_theme_instance_hdr + bl_cms_theme_instance_ext (Theme), bl_cms_label_hdr (Content Category), bl_cms_widget_instance_hdr (+ its image extension on upload) (Widgets), bl_cms_menu_hdr (Menu), bl_cms_post_hdr and post images (Pages). It reads bl_cms_theme_hdr, bl_cms_widget_hdr, bl_cms_label_list_hdr, bl_cms_menu_list_hdr.

Shared with CP Commerce Admin. That applet’s Menu List tab creates bl_cms_menu_list_hdr and its menu items write bl_cms_menu_hdr through the same MenuService (link types there include Layout Instance); its Posts tab writes bl_cms_post_hdr with website_hdr_guid set to the open website; its Label List and Content Category tabs write bl_cms_label_list_hdr and bl_cms_label_hdr. CP Commerce Admin does not use theme-instances or widget-instances outside two unused temp services, so Theme and Widgets are edited only here.

Posting proof block. Not a document applet: no ServerDocTypes entry, no JournalPostingTypeHandler handler, no stock processor, no bl_fi_generic_doc_* rows. Amount and quantity signums do not apply; nothing to void.

Related applets

  • CP Commerce Admin — the per-website editor for the same menus, posts and labels, and the only place that creates menu lists, label lists and page layouts; prefer it for anything website-specific.
  • Media Library — drives and categories for storefront media; this applet’s image uploads bypass it.
  • Shopping Cart (Internal) — the document a storefront checkout produces; unrelated to content but the next step in the E-Commerce module.

Troubleshooting

SymptomCauseFix
A theme saved here never appears on your websitetheme-config-create.component.ts writes a constant website_hdr_guid (a GUID hard-coded in the source) on every theme instance; the form has no Website fieldUntil the applet is fixed, themes cannot be assigned to a tenant’s website from this screen
Theme save fails with CMS_THEME_INSTANCE_HDR_OBJECT_WEBSITE_HDR_GUID_DOES_NOT_EXISTThe hard-coded website GUID is not a website on this tenantSame as above
A page created here is not listed on the CP Commerce Admin Posts tabPosts here are saved with no website_hdr_guid; the Posts tab filters by the open websiteCreate website posts from CP Commerce Admin › Website › Posts
Content category save fails with CMS_LABEL_HDR_OBJECT_LABEL_LIST_GUID_IS_NULL_OR_EMPTY, or the category is missing on the storefrontThe form uses the tenant’s first label list; a tenant with none cannot save, and a website that points at another list will not see the categoryCreate a label list on the website first; create website-scoped categories from CP Commerce Admin › Website › Content Category
Menu save fails with CMS_MENU_HDR_OBJECT_MENU_LIST_GUID_IS_NULL_OR_EMPTYMenu List left emptyPick a menu list (created on the CP Commerce Admin website Menu List tab)
Layout Type and Widget on a page are lost after SaveNeither control is copied into the post container on create or editAssign a layout to a post from CP Commerce Admin › Posts › Layout Instance
Theme › Add Image saves nothingThe upload call in theme-config-edit-image-create.component.ts is commented out; the screen only navigates backNo image can be attached to a theme from this applet
Toast Please Select Valid Image format (JPEG or png)!Post or widget image upload with any other typeConvert to JPEG or PNG
Clicking Setting in the sidebar opens the Theme listingThe setting route does not exist; the wildcard redirects to theme-listingThere are no settings; nothing to fix on the tenant
A row vanished after one click on DeleteDelete is immediate; no confirmation dialog is shownRe-create the row; the storefront reflects the change at once
A listing is empty but the CP Commerce Admin tab shows rowsThe login lacks the endpoint’s …_READ permission in TntCmsPermissions; the applet shows no errorGrant the permission set from an applet that has permission screens

The applet repository has one issue, the sub-query removal that produced the 2026-09-01 build (gh:bigledger/blg-applet-akaun-platform-cms-applet#1); no user-reported failures are on record.

Related documentation

Last updated on