WebCenter Portal

Building a custom page style for WebCenter Portal

Building a custom page style for WebCenter Portal | Blog

Building a custom page style for WebCenter Portal

The starting place

This blog post is incredibly niche, for me at least. I have a product that I am responsible for, it kind of ticks along just fine, but the application owner and the application users have voiced a desire for a bit of a facelift.

MVC

Oracle WebCenter Portal uses an enhanced Model, View, Control (MVC) framework, allowing presentation to be distinct from content. Of course this is Oracle, so they do approach it from a unique direction, but it basically follows rules that any web developer should be aware of, or should be able to get on top of, without too much fuss.

However, in my place, it seems that the people that built the template we have come to rely on are no longer available to us. The product is fairly well documented from Oracle’s viewpoint (the quality of that documentation isn’t necessarily low, it’s just written in a style that takes some effort to understand), but we don’t seem to have the avaialable resources internally to work on the facelift. We certainly have the knowledge, we just don’t have the capacity for that extra work.

An old product, but New to me

Oracle WebCenter Portal has been around probably longer than I’ve been trying to make websites. However the product uses technologies that I am not very familiar with, so in order for me to build something new, I first need to understand how an existing skin was built. I do this by opening a shared asset using JDeveloper which is an IDE. Compared to something like VS Code, this is about the uggliest and least user-friendly IDE that I’ve ever seen. However, that opinion may be the result of limited exposure, perhaps I have a different opinion at the end of this exercise.

Breaking down an existing skin

I am looking at a WebCenter Portal (12c) page template, built using Oracle ADF Faces and Apache Trinidad (JSF). This defines the visual layout structure of portal pages, and customising it is both how we build a custom skin or user experience in WebCenter Portal.

An example WebCenter Portal Page Template:

<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (c) 2011, 2015, Oracle and/or its affiliates. 
All rights reserved.-->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:c="http://java.sun.com/jsp/jstl/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:tr="http://myfaces.apache.org/trinidad"
          xmlns:rah="http://xmlns.oracle.com/webcenter/resourcehandler"
          xmlns:wcdc="http://xmlns.oracle.com/webcenter/spaces/taglib">
  <!--
    - This template uses a flat list of vertical panelGroupLayouts (DIVs)
    - for each of the major sections of the page template.  It relies on
    - CSS to position each of the sections.  The header and footer are
    - fixed (they do not scroll).
    -
    - WCPortalFixedWidth is used to constrain the width of the page.
    -->
  <af:pageTemplateDef var="attrs">
    <af:xmlContent>
      <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
        <display-name>SKIN-NAME</display-name>
        <facet>
          <description>The content of the page goes here</description>
          <display-name>Page Content</display-name>
          <facet-name>content</facet-name>
        </facet>
        <attribute>
          <attribute-name>showGlobalNav</attribute-name>
          <attribute-class>boolean</attribute-class>
          <default-value>true</default-value>
        </attribute>        
        <attribute>
          <attribute-name>showOracleLogo</attribute-name>
          <attribute-class>boolean</attribute-class>
          <default-value>false</default-value>
        </attribute>         
        <attribute>
          <attribute-name>pageTitle</attribute-name>
          <attribute-class>String</attribute-class>
        </attribute>        
        <attribute>
          <attribute-name>showFooter</attribute-name>
          <attribute-class>boolean</attribute-class>
          <default-value>true</default-value>
        </attribute>
      </component>
    </af:xmlContent>
    <!--
     - Begin template.  There are 6 sections:
     - 1) Preamble - required
     - 2) Banner Top - page title, search, global navigation
     - 3) Banner Bottom - portal navigation, portal actions
     - 4) Navigation and Content - the embedded page
     - 5) Footer - links
     - 6) Postamble - required
     -->
    <af:panelGroupLayout id="ptlbody" layout="vertical"
                         styleClass="#{wcpContent.isContributionMode ? 'WCPortalCC' : ''} WCPortalBody WCPortalStickyFooter WCNonEditableArea WCSiteTemplateRoot">
    <af:panelGroupLayout id="ptlsbox" layout="vertical" inlineStyle="min-height:100%;position:relative;overflow:auto">
      <!-- 1) Preamble -->
      <af:panelGroupLayout styleClass="WCPortalPreamble"
                           inlineStyle="display:none;" id="pt_pre">
        <wcdc:siteTemplateMetadata type="start"/>
      </af:panelGroupLayout>
      <!-- Portal Toolbar -->
      <af:panelGroupLayout id="pt_tb" styleClass="WCEditableArea">
      <wcdc:portalToolbar id="ptbdc"/>
      </af:panelGroupLayout>
      <!-- 2) Banner Top (black) -->
      <af:panelGroupLayout layout="vertical" id="bantop"
                           styleClass="WCPortalBannerTop">
        <c:set var="trnum" value="#{userPreferences.accessibilityLargeFontProfile == true? (portalToolbarContext.portalToolbar.editMode ? '12':'15'):'30'}"/>
        <af:panelGroupLayout id="globalPanel" layout="vertical">
          <!-- Upper Left area -->
          <af:panelGroupLayout id="portalLogo" rendered="#{!attrs.showOracleLogo}"
                               styleClass="WCPortalGlobalLogo">
            <!-- Logo -->
            <af:link destination="#{WCAppContext.currentScope.default ? boilerBean.globalLogoURI : boilerBean.globalLogoURIInSpace}"
                       id="gtbpgl1"  styleClass="WCPortalLogo" disabled="#{changeModeBean.inEditMode or serviceCtx.scope.spaceTemplate}">
              <wcdc:spacesLogo id="gtbpgl2" type="icon" inlineStyle="height:24px;"/>
            </af:link>
            <!-- Title -->
            <af:spacer width="5" height="10" id="pt_s7"/>
              <af:link destination="#{WCAppContext.currentScope.default ? boilerBean.globalLogoURI : boilerBean.globalLogoURIInSpace}"
                       id="portalTitle" styleClass="WCPortalGlobalText"
                       disabled="#{changeModeBean.inEditMode or serviceCtx.scope.spaceTemplate}">
                <af:outputText id="portalTitleText"
                               value="#{serviceCtx.scope.spaceTemplate ? WCTruncator[spaceTemplateManager.template[WCAppContext.currentScope.name].GSMetadata.displayName][trnum] : !(empty spaceContext.currentSpace) ? WCTruncator[spaceContext.space[serviceCtx.scope.name].displayName][trnum] : WCTruncator[WCAppContext.application.applicationConfig.title][trnum]}"
                               styleClass="WCPortalTitle"
                               shortDesc="#{serviceCtx.scope.spaceTemplate ? WCTruncator[spaceTemplateManager.template[WCAppContext.currentScope.name].GSMetadata.displayName]['30'] : !(empty spaceContext.currentSpace) ? WCTruncator[spaceContext.space[serviceCtx.scope.name].displayName]['30'] : WCTruncator[WCAppContext.application.applicationConfig.title]['30']}"/>
                <af:panelGroupLayout id="gtbppgl2" layout="default" rendered="#{WCAppContext.currentScope.default}">
                  <af:outputText id="spac1" value=" > " styleClass="WCPortalTitleSeparator"/>
                  <af:outputText id="portalTitleSubText" value="#{uib_o_w_w_r_WebCenter.LABEL_HOME_SPACE}"
                                 styleClass="WCPortalSubTitle"/>
                </af:panelGroupLayout>
              </af:link>
            </af:panelGroupLayout>
          <af:panelGroupLayout id="oracleLogo" rendered="#{attrs.showOracleLogo}"
                               styleClass="WCPortalGlobalLogo">
            <!-- Oracle Logo -->
            <af:link destination="#{boilerBean.globalLogoURIInSpace}"
                     id="gtbpgl3" styleClass="WCPortalLogo"
                     disabled="#{changeModeBean.inEditMode}">
              <af:image id="logoimg" source="/adf/images/t.gif"
                        styleClass="WCPortalOracleLogo"
                        shortDesc="#{not empty attrs.pageTitle ? attrs.pageTitle : WCTruncator[spaceContext.space[WCAppContext.currentScope.name].displayName]}"/>
            </af:link>
            <!--  Title -->
            <af:spacer width="5" height="10" id="pt_s8"/>
              <af:link destination="#{WCAppContext.currentScope.default ? boilerBean.globalLogoURI : boilerBean.globalLogoURIInSpace}"
                       id="oracleTitle" styleClass="WCPortalGlobalText" disabled="#{serviceCtx.scope.spaceTemplate}">
                 <af:outputText id="oracleTitleText"
                               value="#{serviceCtx.scope.spaceTemplate ? WCTruncator[spaceTemplateManager.template[WCAppContext.currentScope.name].GSMetadata.displayName][trnum] : !(empty spaceContext.currentSpace) ? WCTruncator[spaceContext.space[serviceCtx.scope.name].displayName][trnum] : WCTruncator[WCAppContext.application.applicationConfig.title][trnum]}"
                               styleClass="WCPortalTitle"
                               shortDesc="#{serviceCtx.scope.spaceTemplate ? WCTruncator[spaceTemplateManager.template[WCAppContext.currentScope.name].GSMetadata.displayName]['30'] : !(empty spaceContext.currentSpace) ? WCTruncator[spaceContext.space[serviceCtx.scope.name].displayName]['30'] : WCTruncator[WCAppContext.application.applicationConfig.title]['30']}"/>                               
              </af:link>
            </af:panelGroupLayout>
          <!-- Upper Right area -->
          <af:panelGroupLayout id="globalArea">
            <!-- Global Links -->
            <af:panelList id="globLinks" styleClass="WCPortalHeaderNav">
              <!-- Search Task Flow -->
              <af:region value="#{bindings.localToolbarSearch.regionModel}"
                         id="searchbox"/>
              <wcdc:spacesSwitcher id="wcCmdLinkGSSwit" immediate="true"
                                   styleClass="WCLinkMenu"
                                   popupContentDelivery="lazy"
                                   inlineStyle="white-space:nowrap;"
                                   text="#{uib_o_w_s_r_Spaces.LABEL_COMMUNITIES}"
                                   shortDesc="#{uib_o_w_s_r_Spaces.LABEL_COMMUNITIES_DESC}"/>
              <wcdc:favoritesMenu id="wcCmdLinkGSFav"
                                  __taskFlowId="favoritesTaskFlow"
                                  immediate="true"
                                  inlineStyle="white-space:nowrap;"
                                  text="#{uib_o_w_w_r_WebCenter.LABEL_FAVORITES}"
                                  rendered="#{security.homeSpaceEnabled or security.webCenterAdministrator}"
                                  shortDesc="#{uib_o_w_w_r_WebCenter.LABEL_FAVORITES_DESC}"/>
              <af:region value="#{bindings.languageSelectorRegion.regionModel}"
                         id="lang" rendered="#{!security.authenticated}"/>
              <af:spacer styleClass="WCGlobalNavSeparator" id="pbtsep"/>
              <!-- Adminstration -->
              <wcdc:spacesAction id="wcAdminLink" type="administration"
                                 immediate="false"
                                 inlineStyle="white-space:nowrap;"
                                 text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_ADMINISTRATION}"
                                 shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_ADMINISTRATION_DESC}"/>
              <af:spacer styleClass="WCGlobalNavSeparator" id="pbtsep2"
                         rendered="#{security.webCenterConfigAllowed and security.authenticated}"/>
              <!-- Global help Menu-->
              <wcdc:spacesAction id="globalHelpmn" type="globalHelp"
                                   text="#{uib_o_w_w_r_WebCenter.LABEL_HELP}"
                                   shortDesc="#{uib_o_w_w_r_WebCenter.LABEL_HELP_DESC}"
                                   inlineStyle="white-space:nowrap"
                                   styleClass="WCLinkMenu"
                                   displayType="menu"/>
              <!-- Login -->
              <wcdc:spacesAction id="wcLoginLink" type="login"
                                 inlineStyle="white-space:nowrap"
                                 text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_LOGIN}"
                                 shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_LOGIN}"/>
              <!-- User Menu-->
                <af:panelGroupLayout id="userpgl" rendered="#{security.authenticated}">
                  <af:commandImageLink iconPosition="trailing"
                                       id="userMenuLink"
                                       inlineStyle="white-space:nowrap;"
                                       shortDesc="#{uib_o_w_w_r_WebCenter.LABEL_USER_MENU}"
                                       styleClass="#{attrs.styleClass} WCLinkMenu"
                                       immediate="true"
                                       text="#{security.userDisplayName}">
                    <af:showPopupBehavior popupId="userMenuPopup"
                                          alignId="userMenuLink"
                                          align="beforeEnd"/>
                  </af:commandImageLink>
                  <af:popup id="userMenuPopup">
                    <af:menu id="pt_m1">
                      <wcdc:userProfile id="currUserWcLink"
                                        styleClass="WCPortalProfileLink"
                                        immediate="true"
                                        text="#{uib_o_w_w_r_WebCenter.TITLE_USER_PROFILE}"
                                        displayType="menuItem"
                                        shortDesc="#{security.userDisplayName}"/>
                      <wcdc:userPreferences id="wcPreferLink"
                                            __taskFlowId="preferenceRegion"
                                            inlineStyle="white-space:nowrap;"
                                            text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_PREFERENCES}"
                                            displayType="menuItem"
                                            shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_PREFERENCES_DESC}"/>
                      <wcdc:spacesAction id="wcLogoutLink" type="logout"
                                         inlineStyle="white-space:nowrap"
                                         text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_LOGOUT}"
                                         displayType="menuItem"
                                         shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_LOGOUT_DESC}"/>
                    </af:menu>
                  </af:popup>
                </af:panelGroupLayout>
                <af:spacer id="sep1" width="5"/>
              <!-- Status Indicator -->
              <af:statusIndicator id="statInd"/>
            </af:panelList>
          </af:panelGroupLayout>
        </af:panelGroupLayout>
      </af:panelGroupLayout>
      <!-- 3) Banner Bottom (blue) -->
      <af:panelGroupLayout layout="vertical" id="banbot" rendered="#{attrs.showGlobalNav}"
                           styleClass="WCPortalBannerBottom">
        <af:switcher facetName="#{requestContext.rightToLeft? 'rtl' : 'ltr'}">
          <f:facet name="ltr">
            <af:panelGroupLayout id="navPanel" layout="vertical">
              <af:region value="#{bindings.portaltopnavigation.regionModel}"
                         id="spnvpn" inlineStyle="margin-right:45px;"/>
              <af:panelGroupLayout layout="vertical" id="pglbl"
                                   inlineStyle="position:absolute;top:0px;right:0px;margin-top:3px;">
                <af:button icon="#{requestContext.rightToLeft ? '/adf/webcenter/agentdropdown_rtl_sm_ena.png' : '/adf/webcenter/agentdropdown_sm_ena.png'}"
                           styleClass="WCActionsButton"
                           id="actionsMenuLink"
                           shortDesc="#{uib_o_w_w_r_WebCenter['NAV_TOOLS_ACTIONS_FOLDER.DESCRIPTION']}"
						   disabled="#{portalToolbarContext.portalToolbar.editMode}"
                           clientComponent="true"
                           rendered="#{!serviceCtx.scope.spaceTemplate and (WCAppContext.currentScope.default ? ((!AdminConfig.fusionAppsMode and security.homeSpaceEnabled) or security.webCenterAdministrator): empty pageFlowScope.contextActionsTaskFlow)}">
                  <af:showPopupBehavior popupId="actnRegion:actionsDropdownPopup"
                                        alignId="actionsMenuLink"
                                        align="afterStart"/>
                </af:button>
                <af:region value="#{bindings.spacesActionSubmenu.regionModel}"
                           id="actnRegion"
                           rendered="#{!serviceCtx.scope.spaceTemplate and (WCAppContext.currentScope.default ? ((!AdminConfig.fusionAppsMode and security.homeSpaceEnabled) or security.webCenterAdministrator): true)}"/>
              </af:panelGroupLayout>
            </af:panelGroupLayout>
          </f:facet>
          <f:facet name="rtl">
            <af:panelGroupLayout id="navPanelRtl" layout="vertical">
              <af:panelGroupLayout layout="vertical" id="pglblRtl"
                                   inlineStyle="position:absolute;top:0px;left:0px;margin-top:3px;">
                <af:button icon="#{requestContext.rightToLeft ? '/adf/webcenter/agentdropdown_rtl_sm_ena.png' : '/adf/webcenter/agentdropdown_sm_ena.png'}"
                           styleClass="WCActionsButton"
                           id="actionsMenuLinkRtl"
                           shortDesc="#{uib_o_w_w_r_WebCenter['NAV_TOOLS_ACTIONS_FOLDER.DESCRIPTION']}"
                           clientComponent="true"
                           rendered="#{!serviceCtx.scope.spaceTemplate and (WCAppContext.currentScope.default ? ((!AdminConfig.fusionAppsMode and security.homeSpaceEnabled) or security.webCenterAdministrator): empty pageFlowScope.contextActionsTaskFlow)}">
                   <af:showPopupBehavior popupId="actnRegionRtl:actionsDropdownPopup"
                                         alignId="actionsMenuLinkRtl"
                                         align="afterStart"/>
                </af:button>
                <af:region value="#{bindings.spacesActionSubmenu.regionModel}"
                           id="actnRegionRtl"
                           rendered="#{!serviceCtx.scope.spaceTemplate and (WCAppContext.currentScope.default ? ((!AdminConfig.fusionAppsMode and security.homeSpaceEnabled) or security.webCenterAdministrator): true)}"/>
              </af:panelGroupLayout>
              <af:region value="#{bindings.portaltopnavigation.regionModel}"
                         id="spnvpnRtl" inlineStyle="margin-left:45px;"/>
            </af:panelGroupLayout>
          </f:facet>
        </af:switcher>
      </af:panelGroupLayout>
      <!-- 4) Content -->
      <af:panelGroupLayout layout="vertical" id="container"
                           styleClass="WCPortalContainer WCContent WCEditableArea">
        <!-- page title/header - keep? -->
<!--
        <af:panelGroupLayout layout="vertical" id="pghdr" inlineStyle="height:16px;background-color:#F0F0F0;padding:2px 5px;">
          <af:outputText id="ot_ph" inlineStyle="font-weight:bold;"
                         value="#{changeModeBean.inEditMode? uib_o_w_w_r_WebCenter.PAGE_HEADER: navigationContext.currentNavigationModel.currentSelection.selected?navigationContext.currentNavigationModel.currentSelection.title:''}"/>
        </af:panelGroupLayout>
-->
        <af:skipLinkTarget/>
        <af:facetRef facetName="content"/>
      </af:panelGroupLayout>
      <!-- 5) Footer -->
      <af:panelGroupLayout id="footer" layout="vertical"
                           rendered="#{attrs.showFooter and (changeModeBean.inEditMode or (WCAppContext.currentScope.default and !WCAppContext.application.applicationConfig.footerHidden) or (!WCAppContext.currentScope.default and boilerBean.footerDisplayedInSpace))}"
                           styleClass="WCPortalFooter">
        <af:switcher facetName="#{empty WCAppContext.currentPageTemplate.attributesMap['footerNavigationFile'].value}">
          <f:facet name="false">
            <!-- Footer links from navigation model -->
            <wcdc:footerNavigation id="footnav1"
                                   __taskFlowId="navigationrenderer1"
                                   navigationModel="modelPath=#{WCAppContext.currentPageTemplate.attributesMap['footerNavigationFile'].value}"/>
          </f:facet>
          <f:facet name="true">
            <af:panelGroupLayout id="pt_pgl1" layout="vertical">
              <!-- Footer standard links -->
              <af:panelList id="footerPl"
                            styleClass="WCPortalFooterNav"
                            rendered="#{empty WCAppContext.currentPageTemplate.attributesMap['footerNavigationFile'].value}">
                <wcdc:spacesAction id="aboutWcLink" type="aboutWebcenter"
                                   text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_ABOUT}"
                                   shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_ABOUT_DESC}"/>
                <wcdc:spacesAction id="wcRssLink" type="rss"
                                   text="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_RSS}"
                                   shortDesc="#{uib_o_w_w_r_WebCenter.GLOBAL_LINK_RSS_DESC}"/>
                <wcdc:spacesAction id="wcconAdminLink" type="contactAdmin"
                                   text="#{uib_o_w_w_r_WebCenter.CONTACT_ADMINISTRATOR}"
                                   shortDesc="#{uib_o_w_w_r_WebCenter.CONTACT_ADMINISTRATOR_DESC}"/>
                <af:link text="#{uib_o_w_w_r_WebCenter.PRIVACY_STMT}"
                         shortDesc="#{uib_o_w_w_r_WebCenter.PRIVACY_STMT_DESC}"
                         destination="#{WCAppContext.currentScope.default ? boilerBean.privacyURL : boilerBean.privacyURLInSpace}"
                         rendered="#{WCAppContext.currentScope.default ? not empty boilerBean.privacyURL : not empty boilerBean.privacyURLInSpace}"
                         targetFrame="_blank" id="wcPriLink"/>
              </af:panelList>
              <!-- Footer copyright -->
              <af:panelGroupLayout id="cprtpgl" layout="vertical" styleClass="WCPortalFooterNav ">
                <af:outputFormatted id="cpyrght"
                                    rendered="#{WCAppContext.currentScope.default ? not empty boilerBean.copyrightMessage : not empty boilerBean.copyrightMessageInSpace}"
                                    value="#{WCAppContext.currentScope.default ? boilerBean.copyrightMessage : boilerBean.copyrightMessageInSpace}"/>
              </af:panelGroupLayout>
            </af:panelGroupLayout>
          </f:facet>
        </af:switcher>
      </af:panelGroupLayout>
      <!-- 6) Postamble -->
      <af:panelGroupLayout layout="vertical" styleClass="WCPortalPostamble"
                           inlineStyle="display:none;" id="pt_post">
        <wcdc:siteTemplateMetadata type="end"/>
      </af:panelGroupLayout>
    </af:panelGroupLayout>
    </af:panelGroupLayout>
  </af:pageTemplateDef>
</jsp:root>

To add to this alphabet soup so far, this is a JSPX-based ADF Page Template. Thanks Oracle, look at how many abbreviations I can stuff onto my CV as a result of this…

  • Defines layout containers using af:panelGroupLayout, a key layout tag in ADF.
  • Declares facets and attributes using af:pageTemplateDef.
  • Uses ADF Faces tags (af), WebCenter tags (wcdc), and JSP/EL for dynamic logic. What does that even mean?
  • Can be reused across multiple pages to provide consistent structure.

Oracle does document, it’s just that it always seems to require so much pre-existing knowledge to be able to get to grips with the documentation. It assumes everyone that is working on this has been working on it for the last 25 years and all of this stuff makes sense, well, at the start of this blog post, I say it does not make sense…

Root & Template Declaration

af:pageTemplateDef var="attrs"

Defines a template where attrs represents a map of parameters (custom attributes like showFooter, pageTitle, etc.) that users can pass when using this template. Okay, that makes sense.

Template Metadata

<af:xmlContent>
  <component>
    <display-name>SKIN-NAME</display-name>
    <facet>...</facet>
    <attribute>...</attribute>
  </component>
</af:xmlContent>
  • Facets: Areas users will populate (like content).

  • Attributes: Customisable options for this template like:

    • showFooter: show/hide footer
    • showOracleLogo: show Oracle logo or your own
    • pageTitle: optional page title

Main Page Layout

<af:panelGroupLayout id="ptlbody" layout="vertical" ...>

This is the container for the entire body of the template. It holds:

  • Header
  • Navigation
  • Content area
  • Footer

Each of these is nested within panel groups (which are div-like containers).

From what I can tell, so far, you don’t typically modify the structure much for a skin. You mostly modify CSS, images, and icons but knowing the structure helps target the right elements, which is true for most web-pages to be fair, especially for things like Content Management Systems where you were unlikely to be involved in building the initial system and what you have is a tool that is fit for many purposes, therefore you keep digging away at it, trying things, until you understand which element does what.

Logo Area

<af:panelGroupLayout id="portalLogo" rendered="#{!attrs.showOracleLogo}">
  <af:link ...>
    <wcdc:spacesLogo ... />
  </af:link>

So, to use your own custom logo, you’d Override the default CSS class (WCPortalLogo) and provide your own image through the bean or even hardcode the URL for dev/testing.

Page Title

<af:outputText id="portalTitleText" value="#{...}" styleClass="WCPortalTitle" />

This is what displays the title of the current portal or space. Customise style with the WCPortalTitle class.

Rendered with various wcdc: tags. You can hide or reorder them by changing rendered=”#{…}” logic, or modifying or overriding styles like WCLinkMenu, WCPortalHeaderNav.