Dynamic Content Admin and Mobile Architecture

Status: Proposed

Date: 2026-09-15

Related plan: Dynamic Feed Orchestrator Refactor Plan

1. Purpose

This document defines the boundary between the web-based CMS/admin tool and the ALPA Mobile application for authoring, previewing, publishing, resolving, and rendering dynamic content.

The central decision is:

The admin tool authors, previews, and compiles content contracts. The mobile app consumes the published contract, executes its existing runtime behavior, and renders content through its RCL component library. The mobile app does not know about the admin placeholder package or syntax.

The systems share schemas, component metadata, resolver capabilities, theme tokens, and compatibility information. They do not share mobile authentication code, member-specific runtime logic, or compiled mobile RCL implementations.

2. System Overview

Versioned Component Catalog Admin CMS Admin Content Adapter Gateway Dynamic Content Store ALPA Mobile Dynamic Page Loader Dynamic Page Orchestrator published contract catalog Mobile Content Resolvers Item Component Factory Blazor RCL Components Theme and Token Runtime

The admin tool and mobile app are two clients of the same published content contract:

Admin tool
  -> author content
  -> preview content
  -> validate compatibility
  -> publish content

Mobile app
  -> load published content
  -> resolve runtime data
  -> apply member context
  -> map to ViewModels
  -> render RCL components

3. Responsibilities

3.1 Admin CMS

The admin tool owns:

The admin tool does not own:

3.2 Admin adapter gateway

The admin tool needs adapter logic to retrieve data for authoring and preview. Those adapters must run behind an admin backend or controlled gateway.

The gateway owns:

Browser code must not call arbitrary administrator-supplied URLs or receive mobile/API credentials.

3.3 Mobile application

The mobile app owns:

4. Shared Contract Package

The admin tool should consume a versioned component catalog package. The package is a public authoring contract, not a copy of the mobile source code.

The package contains:

The package does not contain:

The package also includes an admin-only placeholder module. This module is an authoring, preview, and publication dependency for the CMS. It is not a mobile dependency and is not shipped to the mobile application.

4.1 Catalog definition

Each component or resolver should have an explicit definition similar to:

{
  "key": "HeroCard",
  "packageVersion": "1.0.0",
  "wireType": "HeroCard",
  "category": "Content",
  "propertiesSchema": "schemas/components/hero-card.json",
  "allowedContainers": ["Stack", "Grid", "Carousel"],
  "themeTokens": ["HeroEyebrow", "HeroTitle", "HeroParagraph"],
  "dataCapabilities": ["documents"],
  "favoriteSupport": "optional",
  "previewFixture": "fixtures/hero-card-document.json",
  "deprecatedAliases": ["DocumentHero"]
}

The registry is the source of truth for the admin authoring surface. It must not be inferred from Razor filenames because filenames do not describe schemas, capabilities, compatibility, or security requirements.

5. Component, Container, and Resolver Model

The catalog separates four concepts:

Concept Responsibility Example
Container Arranges child content Stack, Grid, Carousel
Visual component Defines the rendered presentation shape HeroCard, CardSmall, ButtonCard
Data resolver Obtains or hydrates content documents, podcasts, pilotProfile
Content template Connects a resolver to a visual component Document resolver rendered as HeroCard

A committee or document adapter is therefore not a visual component. It is a data capability that can supply data to a reusable visual component.

The wire contract uses contentType for the data resolver and renderType for the visual component. These are separate fields:

contentType: DocumentItem  -> data resolver
renderType: HeroCard       -> visual component

Example:

Carousel
  -> contentType: DocumentItem
  -> parameters: category = "MEC Updates and Weekly", limit = 3
  -> renderType: HeroCard

This allows the same HeroCard to be used by:

6. Adapter Ownership

There are two adapter layers with separate implementations.

6.1 Admin authoring adapters

Admin adapters provide safe data for the CMS editor and preview canvas.

An admin adapter definition includes:

Initial candidates include:

6.2 Mobile runtime resolvers

Mobile resolvers execute when the app consumes published content. They may use:

The mobile resolver maps its result into ItemDto, which then follows the normal component pipeline:

Mobile resolver
  -> ItemDto
  -> ItemComponentFactory
  -> ComponentView
  -> RCL component

The implementations share the contentType value and normalized schema, but remain separate where their security, caching, or member-context behavior differs.

7. Shared Resolver Capability

The same contentType can be used by both systems, but each system uses its own adapter and context. There is no separate resolver field, execution, or executionOwner field in the published content contract.

contentType + parameters + normalized schema
          |
          +--> Admin adapter + synthetic preview context -> CMS result
          |
          +--> Mobile resolver + member/device context   -> Mobile result

Examples:

contentType Admin preview Mobile result
documents Documents returned by the admin API adapter Documents returned through mobile document queries/cache
podcasts Public feed preview Mobile feed result and mobile navigation
pilotProfile Synthetic pilot fixture Signed-in pilot profile
lecLink Synthetic LEC fixture Current member's LEC
favorites Synthetic favorite state, if needed for preview Current member's favorite state
committeeList Neutral or synthetic committee data MEC/member-filtered committee data
contractAvailability Synthetic capability fixture Current member's actual document availability

The contentType and parameters identify the requested content. The adapter implementation and context determine the result. The CMS must use synthetic or approved admin data; the mobile app uses its normal authenticated and device-aware services.

8. Published JSON and Template Compatibility

The existing persisted format stores template as an escaped JSON string:

{
  "itemType": "CardSmall",
  "template": "{\"renderType\":\"CardSmall\",\"contentType\":\"LecLink\",\"filterValue\":\"SELF\"}"
}

This storage format remains supported. It is a wire/storage concern, not the internal authoring or runtime model.

The processing boundary is:

Persisted escaped string
  -> deserialize once
  -> TemplateDto
  -> orchestrator and resolver pipeline

The CMS may expose structured fields such as:

renderType: CardSmall
contentType: LecLink
parameters:
  filterValue: SELF

When publishing, the admin backend serializes that structured model back into the existing escaped string format. The mobile app continues to deserialize the string into TemplateDto.

Required compatibility behavior:

The admin tool should not force a storage migration merely to provide a structured editing experience.

9. Admin Placeholder Package

Profile-aware placeholders should be handled by a dedicated package inside the admin system rather than by copying mobile profile or authentication logic into the CMS. The mobile app does not reference this package and does not parse its placeholder syntax.

The package should provide:

Its responsibility is:

Admin placeholder package
  -> reads SELF/{mec}/{lec}/profile placeholders
  -> validates them against the component catalog
  -> substitutes synthetic preview values in the canvas
  -> compiles them into the existing mobile runtime contract

It must not:

The package maintains separate representations:

Authored value:
  {lec}

Preview value:
  005

Published runtime contract:
  existing mobile resolver instruction

The preview value is a rendering input only. It must never be serialized as the administrator's value. The admin package emits whatever existing runtime contract the mobile app already supports.

10. Profile-Aware Placeholders

Profile-dependent values need to be authorable without placing a real member account in the CMS. The admin package provides a separate, typed preview context for profile-aware authoring. The placeholder expression is an admin authoring value; it is compiled away before publication. The mobile app receives its existing typed runtime contract, not the admin expression.

10.1 Admin placeholder expression

SELF is an admin authoring value that means "use the member-aware runtime behavior associated with this resolver." The admin package validates and compiles it into the existing mobile resolver contract. The mobile app does not need to know that the author used SELF.

For example:

{
  "contentType": "LecLink",
  "parameters": {
    "filterValue": "SELF"
  }
}

The published content must contain the existing mobile resolver contract. The admin package must not replace SELF with the administrator's profile or a single concrete member value.

10.2 Preview context

The CMS should offer a named, non-production preview context for member-aware content. A preview context is a bundle of safe representative values, not a member identity:

{
  "previewContext": {
    "profile": {
      "firstName": "Preview",
      "lastName": "Pilot",
      "userType": "Member"
    },
    "site": {
      "mec": "UAL",
      "lec": "005"
    },
    "capabilities": {
      "hasContract": true,
      "isFavorited": false
    }
  }
}

The preview context may be selected by label, such as UAL member with LEC 005, but it must not contain an ALPA ID, email address, access token, favorite record, or any other real member identifier.

10.3 Placeholder classes

The catalog should declare which placeholders a resolver accepts:

Placeholder Meaning Preview behavior Runtime behavior
SELF Authoring instruction for member-aware content Use selected synthetic preview context Mobile consumes its existing member-aware resolver contract
{mec} Authoring token for current MEC/site Use preview context MEC Mobile consumes its existing site/context contract
{lec} Authoring token for current LEC Use preview context LEC Mobile consumes its existing member-aware resolver contract
{profile.firstName} Authoring display value Use synthetic name Mobile receives its existing profile-aware content contract
{profile.hasContract} Authoring capability value Use declared preview capability Mobile receives its existing authenticated capability result
{favorite.isFavorited} Authoring preview state Use preview boolean only Mobile handles favorites through its existing runtime state

Each placeholder must have a declared type, allowed locations, and fallback behavior. The CMS should not support arbitrary reflection expressions or arbitrary object paths.

10.4 Resolution phases

Admin placeholder processing and mobile rendering are separate phases:

CMS preview
  -> validate placeholder against catalog
  -> apply synthetic preview context
  -> render preview only

Publish
  -> validate placeholder and required runtime capability
  -> compile placeholders into the existing mobile runtime contract

Mobile runtime
  -> load published JSON
  -> consume its normal typed values and resolver contracts
  -> apply member visibility and data policy
  -> render final RCL component

The CMS must never replace SELF with the administrator's profile. The administrator's identity and organization membership are not a valid representation of an end user's mobile experience. The mobile app must not need to know whether a value originated from an admin placeholder; it only consumes the published contract it already understands.

10.5 Preview limitations

Preview must visibly distinguish synthetic values from live values. When a capability cannot be represented safely, the CMS should show a controlled placeholder state, for example:

This content is resolved for the signed-in member in the mobile app.
Preview uses the selected synthetic member context.

This is preferable to silently showing an administrator's documents, LEC, favorites, or contract availability and presenting that result as universal content.

11. Runtime Rendering Pipeline

PageDto
  -> DynamicPageLoader
  -> optional localized page selection
  -> DynamicPageOrchestrator
  -> template visibility and token resolution (ContentResolutionContext-aware where a resolver needs it)
  -> mobile content resolver
  -> ItemDto
  -> ContainerFactory / ItemComponentFactory
  -> ComponentView
  -> RCL component

Most dynamic pages render the result through the shared DynamicContentHost component rather than owning their own loading/error/favorite-context markup; a page keeps its own hosting shell only when it has real page-specific behavior the shared host doesn't model (see the Dynamic Feed Orchestrator Refactor Plan, Phase 4, for current examples).

The shared rendering boundary is the RCL/ViewModel pipeline, not the feature adapter.

For example, a document carousel can be rendered as:

DocumentItem resolver
  -> document rows
  -> ItemDto.ItemType = HeroCard
  -> CardHeroViewModel
  -> CardHero.razor

A search result for the same document should produce the same CardHeroViewModel where the content contract is compatible.

12. Styling and Assets

The admin tool should not receive the complete alpa-components.css file. The style contract should be layered:

  1. Runtime component CSS: owned by the mobile RCL and shipped with the app.
  2. Design tokens: published to the admin tool as colors, typography, spacing, radii, icon sizes, and approved states.
  3. Site theme values: selected or authored through approved token values.
  4. Assets: managed through validated image and icon references.

The CMS may choose:

The CMS may not inject arbitrary selectors, positioning rules, or CSS that can break component layout and interaction.

The mobile app continues to own:

The admin preview should implement equivalent component styles using the same token values and component metadata, but it does not need to consume the mobile stylesheet wholesale.

13. Security Rules

14. Versioning and Compatibility

Version independently:

Published content should record the catalog version it was authored against. The mobile runtime should advertise supported catalog versions and capabilities.

Publishing must fail when content requires an unsupported:

Compatibility metadata should define:

15. Example: UAL Home Page

A dynamic UAL page can contain:

Site: ual
  Page: ual-home
    Stack
      PilotCard
        contentType: PilotCard

    Stack
      CardSmall
        contentType: LecLink
        parameters: filterValue = SELF

    Grid
      ButtonCard: PDR
      ButtonCard: Documents
      ButtonCard: Committees

    Carousel: LATEST UPDATES
      HeroCard
        contentType: DocumentItem
        renderType: HeroCard
        parameters: category = MEC Updates and Weekly, sort = date descending, limit = 3
        admin preview: documents adapter
        mobile runtime: documents resolver

The CMS can author the composition, preview the document carousel through its admin adapter, and publish the site. At runtime, mobile resolves the pilot and LEC content using the current member, while the document resolver produces items for the same reusable HeroCard component.

16. Decisions Summary

  1. The CMS consumes a versioned component catalog, not the mobile source tree or compiled RCL.
  2. Admin authoring adapters and mobile runtime resolvers are separate implementations.
  3. Public/admin-resolvable data can be previewed through a controlled admin gateway.
  4. Profile, MEC, LEC, favorites, contract availability, and personalized visibility remain mobile-only.
  5. The existing escaped template-string storage format remains supported.
  6. Templates are deserialized once into typed models before orchestration.
  7. Containers, visual components, and data resolvers are separate catalog concepts.
  8. Styles are shared through tokens and metadata, not by packaging the entire mobile stylesheet.
  9. Published content declares its catalog and capability requirements.
  10. The mobile app remains responsible for security-sensitive runtime behavior and final rendering.
  11. Admin placeholders are authoring-only and are not part of the mobile runtime contract.
  12. The CMS uses synthetic preview contexts for profile-aware content and never substitutes real member identity.
  13. Placeholder handling is packaged in the admin system as an authoring/preview/compilation dependency, not a mobile dependency.
  14. Preview substitutions are ephemeral; publication emits only the existing mobile runtime contract.