Dynamic Feed Component Catalog — Reference

Generated from the ALPAMobile.Catalog package, catalog version 2.1.2. Do not edit by hand: change the catalog and regenerate. A test fails when this page and the catalog disagree.

TL;DR — This page lists everything an author can put in a dynamic-feed page: the content types a template can name, the keys each one reads, the values it accepts, the item types and containers they produce, and how a template value is translated into what the member sees. Every key, value, type and default in the tables is checked against the app's code by automated tests, apart from the points listed under How far to trust this page. For worked examples and the reasoning behind individual keys, see the Item Template JSON — Admin Reference.

1. How a template becomes a card

  1. A page is an ordered list of containers. A container's containerType chooses its layout (section 7) and holds an ordered list of items.
  2. An item with no template is static: it is shown as written. A bare page key in its link or ctaLink is expanded into the in-app route.
  3. An item with a template is resolved in this order:
    1. No contentType in the template: the item is dropped.
    2. The visibility rules run (hidden, visibleMecs, hiddenMecs, hiddenUserTypes; section 3). An item that fails any of them is removed.
    3. The app looks for an adapter for the contentType (section 2). If there is one, it fetches the data, applies the template's keys and builds rows. The rows it builds take the template's renderType as their itemType. The two sectioned content types are the exception for their headings: the hotel directory's filter bar and airport headers, and the multi-roster's committee headings, have fixed item types, and only the hotel and person rows take renderType. If the adapter needs a renderType and none is given, or a required key is missing or malformed, or nothing comes back, the item produces no rows. The page still renders.
    4. If there is no adapter (a styling-only content type, or any content type the app does not know), the item is kept only if it has something to show: on the item, a title, text, label, image or link; or in the template, a title, description, eyebrow or image. A link or action in the template alone does not count. The template's keys are then copied onto the item (section 4).
    5. Values containing {placeholders} are filled in for the signed-in member, and route fields are expanded (section 5).
  4. Each row's itemType chooses the component that draws it (section 6).
  5. Anything unknown is skipped, never fatal. An unknown itemType or containerType removes that one item or container, and never breaks the page. An unknown contentType is a content type with no adapter, so by step 3d the item is dropped unless it has something to show; if it does, it still appears as a plain card.
  6. Case. contentType, itemType, containerType and renderType must match exactly, including case: documentitem is not DocumentItem and finds no adapter. Values such as filterType, parentFilterType and hiddenUserTypes are matched ignoring case.

2. Content types

The value of template.contentType. Produces is what it turns into on the page. renderType shows whether the key is required, the default used when it is left out, and the item types it is authored with today.

Content typeStatusProducesrenderTypeWhat it does
ButtonCardStyling only (no fetch)Nothing new: restyles the item it is onoptionalNo fetch. Attach it to a plain Button item to draw it as the branded stripe button. The item keeps its own itemType unless renderType is set. It is kept only if the item has a title, text, label, image or link of its own, or the template has a title, description, eyebrow or image (a link or action in the template alone does not count).
CommitteeLiveA row per recordoptional; default CardSmall; authored with CardSmallThe MEC's committees, one row each. Only parent committees are listed: the per-station LEC variants are removed. Sorted alphabetically by name unless featuredCommittees sets the order.
ContactItemLiveA row per recordrequired; authored with ContactCardPeople as contact rows: one committee's volunteers, or the signed-in pilot's own LEC reps or MEC officers. A grouping key is accepted in existing content but nothing reads it.
DocumentItemLiveA row per recordrequired; authored with HeroCard, CardSmall, CardTextDocuments from the document library, filtered by category or grouping. One row per document, and a document filed under several categories still shows once.
DynamicListNot registered: do not useA row per recordrequiredA server-driven list read from the items query. The adapter exists and is tested but is not registered in the app, so this content type has no adapter. An item that uses it is dropped unless it has something to show of its own (a title, text, label, image or link on the item, or a title, description, eyebrow or image in the template), in which case it shows as a plain card with no list rows. Do not author it.
HeroCardStyling only (no fetch)Nothing new: restyles the item it is onoptionalNo fetch. Attach it to a HeroCard item to type the title, image and action into the template instead of on the item. The item keeps its own itemType unless renderType is set. It is kept only if the item has a title, text, label, image or link of its own, or the template has a title, description, eyebrow or image (a link or action in the template alone does not count).
LecLinkLiveOne rowoptional; default CardSmall; authored with CardSmallOne link row to the signed-in pilot's own LEC page, titled with their station code. Nothing in the template chooses the LEC: it is always the pilot's own.
MecHotelDirectoryLiveHeaders and rows in sectionsoptional; default MecHotelRow; authored with MecHotelRowThe signed-in pilot's MEC crew-hotel directory: a search field, then for each airport a header followed by that airport's hotel rows. It reads no template keys, and it ignores isFavoritable; the pilot's MEC decides what shows.
PilotCardLiveOne rowoptional; default PilotCard; authored with PilotCardThe signed-in pilot's greeting card: a station header and a contract link. It fetches nothing; it reads the pilot's own sign-in. A signed-out visitor gets a plain welcome, and a French page gets the French greeting.
PodcastEpisodeLiveA row per recordrequired; authored with HeroCard, CardSmallEpisodes from an RSS podcast feed, newest first. Episodes carry no artwork of their own, so the card draws its placeholder art.
RosterItemLiveHeaders and rows in sectionsoptional; default ContactCard; authored with ContactCardSeveral committees' rosters at once: a heading per committee followed by that committee's people, in the order the codes are listed. The app picks the roster by this content type, so attach it to an item whose itemType is MultiCommitteeRoster.

ButtonCard

No fetch. Attach it to a plain Button item to draw it as the branded stripe button. The item keeps its own itemType unless renderType is set. It is kept only if the item has a title, text, label, image or link of its own, or the template has a title, description, eyebrow or image (a link or action in the template alone does not count).

KeyTypeRequiredAllowed valuesWhat it does
variantstringnoalpa, alpa-diagonalThe button look: alpa and alpa-diagonal draw the pointed full-width treatments. Leave it out for the standard icon button. This is how most live Button items get their look. It applies to an item whose type is Button.

Committee

The MEC's committees, one row each. Only parent committees are listed: the per-station LEC variants are removed. Sorted alphabetically by name unless featuredCommittees sets the order.

KeyTypeRequiredAllowed valuesWhat it does
actionstringnoanyThe route each committee row opens, filled in per row. {Id} is the committee's code and {Title} its name, as well as {mec} and {lec}. Without action a row opens the committee's own link.
searchFilterstringnoanySort and limit, written like a query string. The list is ascending by name by default. The only way to reverse it is sort_by=name together with order=desc; order alone does nothing. limit caps the count. Example: ?sort_by=name&order=desc&limit=10.
featuredCommitteesobject of stringsnoanyA curated subset in exactly the order listed. Each key is a committee code or name and each value is that row's icon URL. When present it replaces searchFilter and the alphabetical order. A key that matches nothing is skipped. An empty icon is allowed: the committee is listed with no image, and a map whose icons are all empty is still the curated list.
featuredCommitteePagesobject of stringsnoanyEach key is a committee code or name and each value is the content page key for that committee's page. It takes effect only when action is also set, because the page key is added to the action route as ?pageKey=. A committee with no entry falls back to a page key guessed from its name, which is wrong whenever the short name differs.

ContactItem

People as contact rows: one committee's volunteers, or the signed-in pilot's own LEC reps or MEC officers. A grouping key is accepted in existing content but nothing reads it.

KeyTypeRequiredAllowed valuesWhat it does
filterTypestringyesRosterCode, LecReps, MecRepsWhat to list. RosterCode lists one committee's volunteers. LecReps lists the pilot's own LEC reps. MecReps lists the pilot's own MEC officers. Any other value, or none, skips the item.
filterValuestringwhen filterType is RosterCodeanyFor RosterCode, the committee's code (comm_cd); with a blank value nothing shows. It is ignored for LecReps and MecReps. The codes live content uses follow a convention (seen in 994 live codes): the page's MEC code, then 2 to 4 letters, digits or &, then 5 digits. That is a habit of the content, not a rule the app checks.
grouping (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.

DocumentItem

Documents from the document library, filtered by category or grouping. One row per document, and a document filed under several categories still shows once.

KeyTypeRequiredAllowed valuesWhat it does
filterTypestringyesCategory, GroupingCategory filters by one category name. Grouping filters by a grouping name, which spans categories. Any other value, or none, skips the item.
filterValuestringwhen filterValues is not givenanyThe category name, or the grouping name (for example LOA or MOU). With neither this nor filterValues the item shows nothing.
filterValuesarray of stringswhen filterValue is not givenanySeveral categories or groupings in place of filterValue. Their documents are merged before docType and searchFilter apply, so a limit counts across all of them.
categorystringnoanyWith filterType Grouping, an explicit category to read. Without it the grouping is filtered across all categories.
parentFilterTypestringnoMEC, LECReads the signed-in member's own MEC or LEC documents instead of the national ones. It applies only when parentFilterValue is also given; with one but not the other, the national documents are read, with no error.
parentFilterValuestringwhen parentFilterType is setanyAny non-blank value, for example ual. It switches parentFilterType on. It is not sent as the document scope: the app reads the signed-in member's own MEC or LEC set.
docTypestringnoanyNarrows the result to documents of one type. Give one value; the comparison ignores case, and the app accepts any string. Live content uses the values in knownValues.
searchFilterstringnoanySort and limit, written like a query string. Only sort_by=date sorts: with order=desc newest first, otherwise oldest first, and undated documents last. Any other sort_by, or none, keeps the order the documents came in, and order alone does nothing. limit caps the count. Example: ?sort_by=date&order=desc&limit=3. Live content uses limits of 3, 5, 10, 20 and 25. Other spellings, such as by:date-direction:desc-top:20, are not read: the list gets no sort and no limit.

DynamicList

Not registered. The app has no adapter wired for this content type, so it is treated as one with no adapter (step 3d). Do not author it.

A server-driven list read from the items query. The adapter exists and is tested but is not registered in the app, so this content type has no adapter. An item that uses it is dropped unless it has something to show of its own (a title, text, label, image or link on the item, or a title, description, eyebrow or image in the template), in which case it shows as a plain card with no list rows. Do not author it.

KeyTypeRequiredAllowed valuesWhat it does
scopestringnoanyThe items scope to read.
categorystringnoanyThe category to read.
filterValuestringnoanyThe filter value to read.
searchFilterstringnoanyOnly limit is used. sort_by and order are ignored.
actionstringnoanyThe route each row would open, filled in per row ({Id} and the other row properties, as well as {mec} and {lec}).

HeroCard

No fetch. Attach it to a HeroCard item to type the title, image and action into the template instead of on the item. The item keeps its own itemType unless renderType is set. It is kept only if the item has a title, text, label, image or link of its own, or the template has a title, description, eyebrow or image (a link or action in the template alone does not count).

No keys of its own beyond the common ones.

One link row to the signed-in pilot's own LEC page, titled with their station code. Nothing in the template chooses the LEC: it is always the pilot's own.

KeyTypeRequiredAllowed valuesWhat it does
imagestringnoanyThe seal image path. It may contain only {airport} (the member's base airport, lower-case), {lec} (their LEC code) and {mec} (their MEC, upper-case here, unlike elsewhere), for example .../sb2-{airport}{lec}.jpg. Any other token, such as a property of the row, leaves the item with no image. Most sites use one shared icon, a plain URL with no placeholder (https://shared.alpa.org/Portals/27/alpa-app/icons/lec-icon.svg), which the card draws on its icon tile.
cornerRadiusTokenstringnoanyTheme token for the card's corner radius.
parentFilterType (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
parentFilterValue (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
filterType (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
filterValue (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
iconBackgroundToken (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.

MecHotelDirectory

The signed-in pilot's MEC crew-hotel directory: a search field, then for each airport a header followed by that airport's hotel rows. It reads no template keys, and it ignores isFavoritable; the pilot's MEC decides what shows.

No keys of its own beyond the common ones.

PilotCard

The signed-in pilot's greeting card: a station header and a contract link. It fetches nothing; it reads the pilot's own sign-in. A signed-out visitor gets a plain welcome, and a French page gets the French greeting.

KeyTypeRequiredAllowed valuesWhat it does
variantstringnoalpaalpa draws the ALPA-branded always-pointed card. Leave it out for the standard card.
actionstringnoanyWhere the contract link goes. Used only when the member has a contract link.
ctaLinkstringnoanyThe call-to-action target, under the same condition as action.
filterType (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
filterValue (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.
iconColorToken (ignored)stringnoanySent by live content, but the adapter does not read it. Accepted so existing content stays valid; do not offer it for editing.

PodcastEpisode

Episodes from an RSS podcast feed, newest first. Episodes carry no artwork of their own, so the card draws its placeholder art.

KeyTypeRequiredAllowed valuesWhat it does
filterTypestringyesFeedUrlMust be FeedUrl. Anything else skips the item.
filterValuestringyesanyThe feed's URL.
searchFilterstringnoanyOnly limit is used, to cap the number of episodes. The feed is already newest first, so sort_by and order are ignored.

RosterItem

Several committees' rosters at once: a heading per committee followed by that committee's people, in the order the codes are listed. The app picks the roster by this content type, so attach it to an item whose itemType is MultiCommitteeRoster.

KeyTypeRequiredAllowed valuesWhat it does
rosterCodesstringyesanyCommittee roster codes separated by commas, in the order the sections should appear. A repeated code shows once. An unknown code, or a committee with no volunteers, is skipped. The app needs at least one code; asking for two or more is the admin tool's rule, not the app's. The codes live content uses follow a convention (seen in 994 live codes): the page's MEC code, then 2 to 4 letters, digits or &, then 5 digits. That is a habit of the content, not a rule the app checks.

3. Keys any templated item can carry

These apply whatever the content type. The visibility rules run before the adapter does.

KeyTypeRequiredAllowed valuesWhat it does
hiddentrue or falsenoanytrue hides the item and shows nothing in its place. A hidden item can still supply its container's heading or View All link (see Container heading keys), because those are read before the visibility rules run.
visibleMecsstringnoanyMEC codes separated by commas, case-insensitive; the group tokens USA and CAN also work (template/mec-groups.json lists the MECs in each). The item shows only to members of those MECs. A signed-out member, or one with no MEC, never sees it.
hiddenMecsstringnoanyMEC codes separated by commas, or the group tokens USA and CAN (template/mec-groups.json lists the MECs in each). The item is hidden from members of those MECs and shown to everyone else, signed-out members included. Use it for a general option that some MECs replace with their own.
hiddenUserTypesarray of stringsnoMember, Staff, GuestAccount types the item is hidden from, case-insensitive. When the account type is not known the item stays visible.
isFavoritabletrue or falsenoanyfalse removes the favorite heart from the item and its rows. MecHotelDirectory ignores it: its hotel rows set their own hearts. DynamicList applies it only when it is set, and otherwise keeps what its source returned.

Container heading keys

An item's template can supply its container's heading and View All link, but only when the container has none of its own. The first item in the container whose template provides one is used. This is read before the visibility rules run, so an item that is hidden, or not shown to this member, can still set the heading.

KeyTypeRequiredAllowed valuesWhat it does
containerTitlestringnoanyText for the container's heading, used only when the container has no title of its own. It wins over title when both are present. Placeholders are allowed and {mec} is upper-case. The first item in the container whose template provides a heading is used, even if that item is hidden or not shown to this member.
titlestringnoanyTwo jobs. On an item it is always the item's own title. It also becomes the container's heading, but only when containerTitle is absent and the container has no title of its own; when both title and containerTitle are present, title belongs to the card alone and containerTitle is the heading.
viewAllLinkstringnoanyThe container's View All route, used only when the container has none of its own. The first item whose template provides one is used, even if that item is hidden. A bare page key is expanded into the in-app route.

4. Keys copied onto an item with no adapter

For a styling-only content type, the template's keys are copied onto the item. Route values are filled in and then expanded to an in-app route; text values are filled in; value keys are copied as they are.

Template keyTreated asWritten to the item'sWhat it is for
renderTypevalueitemTypeBecomes the item type of the item or rows, which decides the component that draws them.
titletexttitleThe item's title. Placeholders are substituted.
eyebrowtexteyebrowThe small label above the title. Placeholders are substituted.
descriptiontextdescriptionThe item's body text. Placeholders are substituted.
imagetextimageThe image path or URL. Placeholders are substituted.
actionroutelink, ctaLinkWhere the item goes. Written to both the card link and the call-to-action link, replacing any ctaLink.
linkroutelink, ctaLinkSame as action.
ctaLinkroutectaLinkThe call-to-action button's target. If action or link is also given, they set the call-to-action target too and win, because they are applied after it.
variantvaluevariantSelects a sub-style of the component, for example alpa.
isFavoritablevalueisFavoritableTurns the favorite heart off with false.
clampTitlevalueclampTitlefalse shows a hero card's whole title; missing or true keeps the two-line clamp.

5. Placeholders and routes

A value can contain a {token}, filled in for the signed-in member when the page is built.

TokenWhat it becomes
{mec}The signed-in member's MEC. Lower-case in routes and in the image of a styling-only item, upper-case in title, eyebrow and description text. The LecLink image keeps it upper-case.
{lec}The member's LEC code, a raw number such as 012.
{airport}The member's base airport, lower-case. Only the LecLink image takes it; in any other field it is left as written. Not used by live content.
{Property}Any property of the item the value belongs to, by name and ignoring case, for example {Id} or {Title}. Adapters that build rows fill these in per row; for a committee row {Id} is the committee code. Only {mec} and {lec} read the member's profile.
{{mec}-committees-hotel}A compound group: the outer braces only group, and the nested token is substituted. With MEC ual this becomes ual-committees-hotel.
{{mec}-{lec}}A compound group with two nested tokens: the outer braces only group, and both tokens are substituted. With MEC ual and LEC 012 this becomes ual-012, the page key of that MEC's LEC page. Use it where a field takes a page key; a host that does not know the member (the admin tool) can only show it as a placeholder.
{page-key} or page-keyIn a route field, a value that is not already a path, an http(s) link, tel: or mailto: is taken as a dynamic-feed page key and expanded to /dynamic-feed-orchestrator?page=<key>. A full path or URL passes through unchanged. Braces around a key that contains a hyphen, such as {ual-media}, are dropped; a single word in braces, such as {media}, is read as a token, so leave the braces off a one-word key.

Placeholders in an item with no template

An item with no template gets placeholders filled in too, in exactly these fields. In any other field a {token} is shown as written.

FieldHow it is filled inWhat it is
titletext, {mec} upper-caseThe item's title. Placeholders are substituted; {mec} is upper-case here.
headerTexttext, {mec} upper-caseThe heading line (a ButtonCard's text). Placeholders are substituted; {mec} is upper-case here.
descriptiontext, {mec} upper-caseBody text. Placeholders are substituted; {mec} is upper-case here.
blurbtext, {mec} upper-caseSecondary body text. Placeholders are substituted; {mec} is upper-case here.
eyebrowtext, {mec} upper-caseThe small label above the title. Placeholders are substituted; {mec} is upper-case here.
labeltext, {mec} upper-caseA short label. Placeholders are substituted; {mec} is upper-case here.
ctaTexttext, {mec} upper-caseThe button text. Placeholders are substituted; {mec} is upper-case here.
imagepath, {mec} lower-caseThe image path or URL. Placeholders are substituted; {mec} is lower-case here, as in a file name.
iconpath, {mec} lower-caseThe icon name or path. Placeholders are substituted; {mec} is lower-case here.
linkrouteWhere the item goes. Placeholders are substituted, then a page key is expanded to its route.
ctaLinkrouteThe button's target. Placeholders are substituted, then a page key is expanded to its route.

6. Item types

The value of itemType, which is also what renderType sets on a resolved row. Reads lists the item keys the component uses; the ones marked as theme tokens name a design token from the active theme. Also accepted are older names the app still understands. Ignored keys are ones live content sends that the app does not read: they are accepted so existing content stays valid, and are not offered for editing. Use says whether the app's own content uses the type today, and whether an author places it directly, sets it only as a renderType, or attaches a template to it.

Item typeUseWhat it isAlso acceptedReadsTheme tokensIgnored
ButtonAction; in the app's contentIcon button with a label. The alpa and alpa-diagonal variants draw the pointed full-width treatments.SingleButton1ctaText, title, image, icon, ctaLink, link, variant, tokenOverridesbackgroundToken, ctaTextToken, cornerRadiusTokenisSortable, sortOrder
ButtonCardCard; in the app's contentCard with an embedded call-to-action button. Without ctaText the whole card is the tap target.—headerText, title, description, blurb, image, link, ctaText, ctaLink, tokenOverridesbackgroundToken, headerTextToken, iconSizeToken, iconColorToken, ctaTextToken, cornerRadiusTokenisSortable, sortOrder
CardSmallCard; in the app's contentCompact list row with an icon, title and subtitle.—title, image, icon, iconMaskUrl, link, ctaLink, label, description, blurb, tokenOverridesbackgroundToken, titleToken, eyebrowToken, descriptionToken, cornerRadiusToken, iconBackgroundToken, iconSizeToken, iconColorTokenisSortable, sortOrder
CardTextCard; not in the app's contentText card: label, title, description and link.—label, title, description, blurb, image, link, ctaLink, tokenOverrideseyebrowToken, titleToken, descriptionToken—
ContactCardCard; in the app's content; set only as a renderTypeA person: name, role, email and phone. It draws a committee volunteer, an LEC rep or an MEC officer, and is what the ContactItem and RosterItem content types produce. The role line and the favorite heart come from the member's records, not from the template.—title, headerText, email, phonerosterTitleToken, rosterNameToken, rosterEmailToken, rosterTelTokenisSortable, sortOrder
EmergencyButtonAction; not in the app's contentEmergency hotline button.—ctaText, ctaLink, link, tokenOverridesbackgroundToken, ctaTextToken, cornerRadiusToken—
HeroCardCard; in the app's contentContent card with an eyebrow, title, description and image.SingleButtonLarge, DocumentHerotitle, description, blurb, eyebrow, image, icon, link, ctaLink, useDesignPlaceholder, accentOnLeft, tokenOverridesbackgroundToken, eyebrowToken, titleToken, descriptionTokencornerRadiusToken, isSortable, sortOrder
ListCard; in the app's content; a placeholder an adapter replacesA plain list row, drawn exactly like CardSmall. It is the itemType placeholder on templated items whose rows an adapter builds (ContactItem, DocumentItem, MecHotelDirectory, PodcastEpisode). The adapter replaces the placeholder, so its own fields rarely matter.—title, image, icon, iconMaskUrl, link, ctaLink, label, description, blurb, tokenOverridesbackgroundToken, titleToken, eyebrowToken, descriptionToken, cornerRadiusToken, iconBackgroundToken, iconSizeToken, iconColorToken, rosterTitleToken, rosterNameToken, rosterEmailToken, rosterTelTokenisSortable, sortOrder
MecHotelRowCard; in the app's content; set only as a renderTypeOne crew hotel under its airport's header. The MecHotelDirectory content type produces it and sets the airport code (variant) itself; it is not meant to be authored by hand.—title, description, blurb, link, ctaLink, varianttitleToken—
MultiCommitteeRosterCard; in the app's content; a placeholder an adapter replacesPlaceholder for several committees' rosters: attach a RosterItem template and the app replaces it with a heading per committee followed by that committee's people. The item draws nothing itself; its roster tokens style the contact rows.—rosterTitleToken, rosterNameToken, rosterEmailToken, rosterTelTokenisSortable, sortOrder
PilotCardCard; in the app's contentWelcome card: pilot identity heading and a contract link. The alpa variant draws the always-pointed treatment.—headerText, title, linkText, ctaText, link, ctaLink, variant, tokenOverridesbackgroundToken, identityToken, contractLinkTokenisSortable, sortOrder

Item types authors should not use

The app draws these too, but they are not for authors, so this catalog does not describe their keys. Use the item types in the table above.

Names the app owns

These can appear in live content, but they belong to the app (like its settings and profile pages), so the admin portal never authors them and this catalog defines no item, content type or key for them. Show one read-only; it is not an unknown name.

NameKindWhy it is not authored
PacCardItem typeApp-native item: the app draws it itself. It is not a feed component an author places, so a host shows it read-only.
PacContributionsContent typeApp-native content type: the app's own Advocacy and Profile pages handle the PAC contributions, not a feed adapter, so a host shows it read-only.
CallToActionContent typeApp-native content type: the app's Advocacy page loads its call-to-action links itself, not through a feed adapter, so a host shows it read-only.
requiresMenuItemTemplate keyApp-native template key: the app reads it itself. It is not an authoring option, so a host leaves it as written.
secondaryLinkTemplate keyApp-native template key: the app reads it itself. It is not an authoring option, so a host leaves it as written.

Fields by item type

Each table lists the fields a component reads, most important first. Required: nearly all live content sets it. Shown: most do. Advanced: some do. Available: the app reads it but no bundled content sets it. Not offered: the app reads it, but authors should not set it. Parity: live content sends it and the app ignores it. A style token takes its allowed values from the active theme, so none are listed here. The tiers rest on a dated count of the app's bundled content (catalog/snapshots/live-usage.json).

Button

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
ctaTextButton textRequiredText——The button text. Shown in preference to title.862 of 862
ctaLinkButton linkRequiredRoute——Where the button goes. Read before link.861 of 862
backgroundTokenBackgroundRequiredSurface—Surface/Secondary—859 of 862
ctaTextTokenButton text styleRequiredTypography—ButtonText—859 of 862
tokenOverridesToken overridesAdvanced————35 of 862
cornerRadiusTokenCorner radiusAdvancedRadius—BorderRadius/M—91 of 862
imageImageAvailableImage———0 of 862
titleTitleNot offeredText——Shown only when ctaText is blank.0 of 862
iconIconNot offeredIcon———0 of 862
linkLinkNot offeredRoute——Where the button goes when ctaLink is blank.0 of 862
variantStyleNot offeredEnumalpa, alpa-diagonalThe standard style.—2 of 862
isSortableSortableParityBoolean———0 of 862
sortOrderSort orderParityNumber———0 of 862

ButtonCard

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
headerTextHeadingRequiredText——The card text. Shown in preference to title.281 of 281
ctaLinkButton linkRequiredRoute——Where the button goes, read before link. With no button text (ctaText) there is no button and the whole card goes to link, then this.281 of 281
headerTextTokenHeading styleRequiredTypography—ButtonCardTitle—281 of 281
imageImageShownImage———265 of 281
backgroundTokenBackgroundShownSurface—Surface/Default—266 of 281
iconColorTokenIcon colourShownColor—Icon/Active—190 of 281
iconSizeTokenIcon sizeAdvancedIconSize—IconSize/M—67 of 281
descriptionDescriptionAvailableMultiline———0 of 281
ctaTextButton textAvailableText——The card text is headerText or title; this is not shown as that text.0 of 281
tokenOverridesToken overridesAvailable————0 of 281
ctaTextTokenButton text styleAvailableTypography———0 of 281
cornerRadiusTokenCorner radiusAvailableRadius———0 of 281
titleTitleNot offeredText——Shown only when headerText is blank.0 of 281
blurbBlurbNot offeredMultiline———0 of 281
linkLinkNot offeredRoute——Where the button goes when ctaLink is blank. With no button text (ctaText) the whole card goes here, read before ctaLink.0 of 281
isSortableSortableParityBoolean———0 of 281
sortOrderSort orderParityNumber———0 of 281

CardSmall

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
titleTitleRequiredText———1358 of 1360
imageImageRequiredImage———1357 of 1360
ctaLinkButton linkRequiredRoute——Where the item goes when link is blank.1347 of 1360
titleTokenTitle styleRequiredTypography—CardSmallTitle—1354 of 1360
cornerRadiusTokenCorner radiusRequiredRadius—BorderRadius/M—1331 of 1360
iconBackgroundTokenIcon backgroundRequiredSurface—Surface/Secondary—1326 of 1360
iconColorTokenIcon colourRequiredColor—Icon/OnBrand—1325 of 1360
linkLinkAdvancedRoute——Where the item goes. Read before ctaLink.11 of 1360
tokenOverridesToken overridesAdvanced————61 of 1360
backgroundTokenBackgroundAdvancedSurface—Surface/Brand—61 of 1360
iconSizeTokenIcon sizeAdvancedIconSize—IconSize/L—3 of 1360
labelLabelAvailableText———0 of 1360
descriptionDescriptionAvailableMultiline———0 of 1360
eyebrowTokenEyebrow styleAvailableTypography———0 of 1360
descriptionTokenDescription styleAvailableTypography———0 of 1360
iconIconNot offeredIcon———0 of 1360
iconMaskUrlIcon maskNot offeredImage———0 of 1360
blurbBlurbNot offeredMultiline———0 of 1360
isSortableSortableParityBoolean———0 of 1360
sortOrderSort orderParityNumber———0 of 1360

ContactCard

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
rosterTitleTokenRole styleAdvancedTypography—RosterTitle——
rosterNameTokenName styleAdvancedTypography—RosterName——
rosterEmailTokenEmail styleAdvancedTypography—RosterEmail——
rosterTelTokenPhone styleAdvancedTypography—RosterTel——
titleTitleNot offeredText————
headerTextHeadingNot offeredText————
emailEmailNot offeredText————
phonePhoneNot offeredText————
isSortableSortableParityBoolean————
sortOrderSort orderParityNumber————

HeroCard

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
titleTitleRequiredText———198 of 199
eyebrowTokenEyebrow styleRequiredTypography—HeroEyebrow—197 of 199
titleTokenTitle styleRequiredTypography—HeroTitle—197 of 199
descriptionTokenDescription styleRequiredTypography—HeroParagraph—197 of 199
eyebrowEyebrowShownText———135 of 199
imageImageShownImage——Optional. Without one the card hides its image area instead of showing a placeholder.133 of 199
linkLinkShownRoute——Where the item goes. Read before ctaLink.173 of 199
ctaLinkButton linkShownRoute——Where the item goes when link is blank.116 of 199
descriptionDescriptionAdvancedMultiline———50 of 199
accentOnLeftAccent on the leftAdvancedBoolean———3 of 199
useDesignPlaceholderDesign placeholderAvailableBoolean———0 of 199
blurbBlurbNot offeredMultiline———0 of 199
iconIconNot offeredIcon———0 of 199
tokenOverridesToken overridesNot offered————0 of 199
backgroundTokenBackgroundNot offeredSurface———0 of 199
cornerRadiusTokenCorner radiusParityRadius———1 of 199
isSortableSortableParityBoolean———0 of 199
sortOrderSort orderParityNumber———0 of 199

List

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
rosterTitleTokenRole styleShownTypography—RosterTitle—821 of 1269
rosterNameTokenName styleShownTypography—RosterName—821 of 1269
rosterEmailTokenEmail styleShownTypography—RosterEmail—821 of 1269
rosterTelTokenPhone styleShownTypography—RosterTel—821 of 1269
titleTitleAdvancedText———23 of 1269
titleTokenTitle styleAdvancedTypography—CarouselListTitle—449 of 1269
eyebrowTokenEyebrow styleAdvancedTypography—CarouselListEyebrow—449 of 1269
descriptionTokenDescription styleAdvancedTypography—CarouselListParagraph—449 of 1269
imageImageAvailableImage———0 of 1269
linkLinkAvailableRoute——Where the item goes. Read before ctaLink.0 of 1269
ctaLinkButton linkAvailableRoute——Where the item goes when link is blank.0 of 1269
labelLabelAvailableText———0 of 1269
descriptionDescriptionAvailableMultiline———0 of 1269
tokenOverridesToken overridesAvailable————0 of 1269
backgroundTokenBackgroundAvailableSurface———0 of 1269
iconIconNot offeredIcon———0 of 1269
iconMaskUrlIcon maskNot offeredImage———0 of 1269
blurbBlurbNot offeredMultiline———0 of 1269
cornerRadiusTokenCorner radiusNot offeredRadius———0 of 1269
iconBackgroundTokenIcon backgroundNot offeredSurface———0 of 1269
iconSizeTokenIcon sizeNot offeredIconSize———0 of 1269
iconColorTokenIcon colourNot offeredColor———0 of 1269
isSortableSortableParityBoolean———0 of 1269
sortOrderSort orderParityNumber———0 of 1269

MultiCommitteeRoster

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
rosterTitleTokenRole styleRequiredTypography—RosterTitle—22 of 22
rosterNameTokenName styleRequiredTypography—RosterName—22 of 22
rosterEmailTokenEmail styleRequiredTypography—RosterEmail—22 of 22
rosterTelTokenPhone styleRequiredTypography—RosterTel—22 of 22
isSortableSortableParityBoolean———0 of 22
sortOrderSort orderParityNumber———0 of 22

PilotCard

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
identityTokenIdentity styleRequiredTypography—PilotCardIdentity—41 of 41
contractLinkTokenContract link styleRequiredTypography—PilotCardLink—41 of 41
backgroundTokenBackgroundShownSurface—Surface/Default—38 of 41
tokenOverridesToken overridesAdvanced————1 of 41
headerTextHeadingNot offeredText———0 of 41
titleTitleNot offeredText———0 of 41
linkTextLink textNot offeredText———0 of 41
ctaTextButton textNot offeredText———0 of 41
linkLinkNot offeredRoute——Where the item goes. Read before ctaLink.0 of 41
ctaLinkButton linkNot offeredRoute——Where the item goes when link is blank.0 of 41
variantStyleNot offeredEnumalpaThe standard style.—0 of 41
isSortableSortableParityBoolean———0 of 41
sortOrderSort orderParityNumber———0 of 41

7. Containers

The value of containerType. A container with a value the app does not know is skipped.

Container typeUseWhat it isReadsTheme tokensIgnored
ButtonGroupLayout; not in the app's contentHorizontal row of tile buttons with no section header. Only button items are kept; they render as tiles.itemsbackgroundTokenisSortable, sortOrder
CarouselLayout; in the app's contentHorizontal scrolling feed: section header plus cards, typically HeroCard.title, viewAllText, viewAllLink, itemsbackgroundToken, titleToken, viewAllLinkTokencolumns, paddingToken, isSortable, sortOrder
GridLayout; in the app's contentFixed-column grid of mixed items; columns defaults to 3. Title and View All are optional.title, viewAllText, viewAllLink, columns, itemsbackgroundToken, titleToken, viewAllLinkTokenisSortable, sortOrder
StackLayout; in the app's contentSurface-neutral vertical stack: quick-list rows, or a single-item wrapper for a standalone widget. Title and View All are optional.title, viewAllText, viewAllLink, itemsbackgroundToken, titleToken, viewAllLinkTokencolumns, paddingToken, isSortable, sortOrder

Fields by container

ButtonGroup

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
itemsItemsRequired—————
backgroundTokenBackgroundAvailableSurface————
isSortableSortableParityBoolean————
sortOrderSort orderParityNumber————
FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
titleTitleRequiredText———201 of 207
itemsItemsRequired————all
titleTokenTitle styleRequiredTypography—ContainerHeaderTitle—207 of 207
viewAllLinkTokenView All styleRequiredTypography—ContainerViewAllLink—207 of 207
viewAllTextView All textShownText———179 of 207
viewAllLinkView All linkShownRoute———179 of 207
backgroundTokenBackgroundAvailableSurface———0 of 207
columnsColumnsParityNumber———1 of 207
paddingTokenPaddingParity————108 of 207
isSortableSortableParityBoolean———0 of 207
sortOrderSort orderParityNumber———0 of 207

Grid

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
itemsItemsRequired————all
titleTokenTitle styleRequiredTypography—ContainerHeaderTitle—87 of 87
viewAllLinkTokenView All styleRequiredTypography—ContainerViewAllLink—87 of 87
columnsColumnsShownNumber2, 3, 43—81 of 87
titleTitleAdvancedText———10 of 87
viewAllTextView All textAvailableText———0 of 87
viewAllLinkView All linkAvailableRoute———0 of 87
backgroundTokenBackgroundAvailableSurface———0 of 87
isSortableSortableParityBoolean———0 of 87
sortOrderSort orderParityNumber———0 of 87

Stack

FieldLabelTierControlAllowed valuesDefaultReads asSet in bundled content
itemsItemsRequired————all
titleTokenTitle styleRequiredTypography—ContainerHeaderTitle—2309 of 2320
viewAllLinkTokenView All styleRequiredTypography—ContainerViewAllLink—2309 of 2320
titleTitleAdvancedText———896 of 2320
viewAllTextView All textAdvancedText———11 of 2320
viewAllLinkView All linkAdvancedRoute———10 of 2320
backgroundTokenBackgroundAvailableSurface———0 of 2320
columnsColumnsParityNumber———699 of 2320
paddingTokenPaddingParity————1 of 2320
isSortableSortableParityBoolean———0 of 2320
sortOrderSort orderParityNumber———0 of 2320

What the editor offers

The palette lists what an author can add, with the item or container and the template each entry saves as. Entries the live sites use come first. Fill in names the keys the author has to complete; they are saved blank.

EntryGroupUseSaves asTemplateFill in
List row
A small row with an icon tile, a title and a destination.
Itemsin the app's contentitem CardSmall——
Button
An icon button with a label.
Itemsin the app's contentitem Button——
Branded button
The pointed full-width button most live pages use: a Button drawn with the ButtonCard look.
Itemsin the app's contentitem Button{"contentType":"ButtonCard","variant":"alpa"}—
Button card
A tile with a heading and a button.
Itemsin the app's contentitem ButtonCard——
Hero card
A content card with an eyebrow, title, description and image.
Itemsin the app's contentitem HeroCard——
Pilot card
The signed-in pilot's greeting card with a contract link.
Itemsin the app's contentitem PilotCard{"contentType":"PilotCard"}—
Documents
A list of documents, filtered by category or grouping.
DataListsin the app's contentitem List{"contentType":"DocumentItem","renderType":"HeroCard","filterType":"Category","filterValue":""}filterValue
Podcast
The episodes of a podcast feed.
DataListsin the app's contentitem List{"contentType":"PodcastEpisode","renderType":"HeroCard","filterType":"FeedUrl","filterValue":""}filterValue
Hotel directory
The MEC hotel directory, grouped by airport.
DataListsin the app's contentitem List{"contentType":"MecHotelDirectory","renderType":"MecHotelRow"}—
One committee
The volunteers of one committee.
Contactsin the app's contentitem List{"contentType":"ContactItem","renderType":"ContactCard","filterType":"RosterCode","filterValue":""}filterValue
Several committees
A heading per committee followed by its volunteers.
Contactsin the app's contentitem MultiCommitteeRoster{"contentType":"RosterItem","rosterCodes":""}rosterCodes
My LEC reps
The signed-in pilot's own LEC representatives.
Contactsin the app's contentitem List{"contentType":"ContactItem","renderType":"ContactCard","filterType":"LecReps"}—
My MEC officers
The signed-in pilot's own MEC officers.
Contactsin the app's contentitem List{"contentType":"ContactItem","renderType":"ContactCard","filterType":"MecReps"}—
LEC link
A row linking to the signed-in pilot's own LEC page, with the shared LEC icon on the card's icon tile.
LecLinkin the app's contentitem CardSmall{"contentType":"LecLink","renderType":"CardSmall","image":"https://shared.alpa.org/Portals/27/alpa-app/icons/lec-icon.svg"}—
Stack
A vertical stack of rows, or a wrapper for one widget.
Containersin the app's contentcontainer Stack——
Carousel
A horizontal scrolling row of cards.
Containersin the app's contentcontainer Carousel——
Grid
A fixed-column grid of tiles.
Containersin the app's contentcontainer Grid——
Text card
A card with a label, title and description.
Availablenot in the app's contentitem CardText——
Emergency button
The emergency hotline button.
Availablenot in the app's contentitem EmergencyButton——
Button group
A row of tile buttons with no section header.
Availablenot in the app's contentcontainer ButtonGroup——
Committee list
The committees list, with featured committees.
Availablenot in the app's contentitem List{"contentType":"Committee"}—
Hero card with styling
A hero card restyled by a template instead of by its own fields.
Availablenot in the app's contentitem HeroCard{"contentType":"HeroCard"}—

What the app fills in from the member

Some fields are never set by an author: the app fills them in from the signed-in member. The editor cannot read the member, so these are the worked examples it previews with. A test runs the real adapter for every example below.

title: The row's title is the member's own LEC, built from their base airport and LEC code (for example "ORD 012"). It differs for every member, and the admin tool never knows a member's LEC, so the editor shows one generic label instead of an example. The app fills in the title and the link to the member's own LEC page when it draws the row.

Previewed as the label Link to your LEC; no examples.

PilotCard

headerText: The greeting. English: "Welcome {rank} {last name}", or "Welcome {first name} {last name}" when the member record has no rank. A French page: "Bienvenue, {rank} {last name}" (a comma; the rank stays in English). A visitor who is not signed in gets just "Welcome", on English and French pages alike.

Sample memberPageTemplate assumesShows
Captain, short nameEnglish—Welcome Captain Ng
Captain, short nameFrench—Bienvenue, Captain Ng
First Officer, short nameEnglish—Welcome First Officer Li
First Officer, short nameFrench—Bienvenue, First Officer Li
Captain, long nameEnglish—Welcome Captain Vandersteenhoven-Kowalczyk
Captain, long nameFrench—Bienvenue, Captain Vandersteenhoven-Kowalczyk
First Officer, long name, no contractEnglish—Welcome First Officer Lefèvre-Desrosiers
First Officer, long name, no contractFrench—Bienvenue, First Officer Lefèvre-Desrosiers
No rank on recordEnglish—Welcome Jordan O'Brien
No rank on recordFrench—Bienvenue, Jordan O'Brien
No rank, accented name, no contractEnglish—Welcome Élodie Lefèvre-Desrosiers
No rank, accented name, no contractFrench—Bienvenue, Élodie Lefèvre-Desrosiers
First Officer at DAL (a second US MEC)English—Welcome First Officer Okafor
First Officer at DAL (a second US MEC)French—Bienvenue, First Officer Okafor
Captain at ACA (Canadian MEC)English—Welcome Captain Tremblay
Captain at ACA (Canadian MEC)French—Bienvenue, Captain Tremblay
Signed outeither—Welcome

linkText: The contract link: "View Contract", or "Convention collective" on a French page. It shows only when a contract document exists for the member's MEC; otherwise there is no link.

Sample memberPageTemplate assumesShows
Captain, short nameEnglish—View Contract
Captain, short nameFrench—Convention collective
First Officer, short nameEnglish—View Contract
First Officer, short nameFrench—Convention collective
Captain, long nameEnglish—View Contract
Captain, long nameFrench—Convention collective
First Officer, long name, no contractEnglish—nothing
First Officer, long name, no contractFrench—nothing
No rank on recordEnglish—View Contract
No rank on recordFrench—Convention collective
No rank, accented name, no contractEnglish—nothing
No rank, accented name, no contractFrench—nothing
First Officer at DAL (a second US MEC)English—View Contract
First Officer at DAL (a second US MEC)French—Convention collective
Captain at ACA (Canadian MEC)English—View Contract
Captain at ACA (Canadian MEC)French—Convention collective
Signed outeither—nothing

What data-fed content shows

Contacts, documents and podcast episodes come from data, not from the page. Each example is a template an author could save and the rows the app shows for it against the sample contacts, documents and episodes below. A test runs the real adapter against those samples for every example. Dates are written in the language of the member's device; the examples show English.

ContactItem

One committee. The volunteers of the Safety committee, one card each.

{
  "contentType": "ContactItem",
  "renderType": "ContactCard",
  "filterType": "RosterCode",
  "filterValue": "UALSAFE00001"
}
EyebrowTitleRoleDescriptionEmailPhone
card—Wei NgChair—wei.ng@example.org5555550101
card—Mei LiVice Chair—mei.li@example.org5555550102
card—Bob O'BrienSecretary—bob.obrien@example.org5555550104
card—Claire Lefèvre-DesrosiersMember—claire.lefevre@example.org—

My LEC reps. The signed-in member's own LEC representatives.

{
  "contentType": "ContactItem",
  "renderType": "ContactCard",
  "filterType": "LecReps"
}
EyebrowTitleRoleDescriptionEmailPhone
card—Pat MoreauChair—pat.moreau@example.org5555550106
card—Sam OkaforVice Chair—sam.okafor@example.org—

My MEC officers. The signed-in member's own MEC officers.

{
  "contentType": "ContactItem",
  "renderType": "ContactCard",
  "filterType": "MecReps"
}
EyebrowTitleRoleDescriptionEmailPhone
card—Pat MoreauChair—pat.moreau@example.org5555550106
card—Dana WhitfieldSecretary-Treasurer—dana.whitfield@example.org5555550108

A code no committee has. A well-formed code that no committee uses shows nothing, with no message.

{
  "contentType": "ContactItem",
  "renderType": "ContactCard",
  "filterType": "RosterCode",
  "filterValue": "UALNONE00000"
}

Shows nothing.

DocumentItem

Newest three in a category. The three most recent documents filed under Communications, newest first. A document has no image, so each HeroCard row draws without its picture area.

{
  "contentType": "DocumentItem",
  "renderType": "HeroCard",
  "filterType": "Category",
  "filterValue": "Communications",
  "searchFilter": "sort_by=date&order=desc&limit=3"
}
EyebrowTitleRoleDescriptionEmailPhone
card10/02/2026Negotiating committee report—A summary of this month's sessions.——
card09/30/2026LEC officer elections open—How to stand for office and when ballots are due.——
card09/14/2026Scheduling update for October—What changes in the October bid and when it takes effect.——

Only PDFs. Every Communications document that is a PDF, in the order the library returns them. A document has no image, so each HeroCard row draws without its picture area.

{
  "contentType": "DocumentItem",
  "renderType": "HeroCard",
  "filterType": "Category",
  "filterValue": "Communications",
  "docType": "pdf"
}
EyebrowTitleRoleDescriptionEmailPhone
card10/02/2026Negotiating committee report—A summary of this month's sessions.——
card—Annual member survey results, including participation by domicile and a comparison with the previous three years—The full results, with the questions as asked and the number of members who answered each.——

A grouping. The documents in one grouping, across categories, newest first. A document has no image, so each HeroCard row draws without its picture area.

{
  "contentType": "DocumentItem",
  "renderType": "HeroCard",
  "filterType": "Grouping",
  "filterValue": "MEC Communications",
  "searchFilter": "sort_by=date&order=desc"
}
EyebrowTitleRoleDescriptionEmailPhone
card10/02/2026Negotiating committee report—A summary of this month's sessions.——
card09/14/2026Scheduling update for October—What changes in the October bid and when it takes effect.——
card08/21/2026Recognizing our retiring members————
card—Annual member survey results, including participation by domicile and a comparison with the previous three years—The full results, with the questions as asked and the number of members who answered each.——

UAL MEC updates. The three newest MEC updates in UAL's own document set, newest first. UAL's documents have no description, so each HeroCard row shows its date and title only.

{
  "contentType": "DocumentItem",
  "renderType": "HeroCard",
  "parentFilterType": "MEC",
  "parentFilterValue": "ual",
  "filterType": "Category",
  "filterValue": "MEC Updates and Weekly",
  "searchFilter": "sort_by=date&order=desc&limit=3"
}
EyebrowTitleRoleDescriptionEmailPhone
card10/23/2026MEC Weekly Update: October 23————
card10/16/2026MEC Weekly Update: October 16————
card10/09/2026MEC Weekly Update: October 9————

PodcastEpisode

Latest three episodes. The three most recent episodes of a feed. The feed is already newest first, so only limit is used. An episode has no image or description, so a HeroCard row shows its date and title only.

{
  "contentType": "PodcastEpisode",
  "renderType": "HeroCard",
  "filterType": "FeedUrl",
  "filterValue": "https://podcast.example.org/feed/",
  "searchFilter": "sort_by=date&order=desc&limit=3"
}
EyebrowTitleRoleDescriptionEmailPhone
cardOctober 6, 2026Contract talks: what happens next————
cardSeptember 22, 2026Safety at the table: a conversation with the committee chair————
cardSeptember 8, 2026Understanding your October bid, with a walkthrough of preferential bidding, reserve rules and how seniority affects each round of awards————

The whole feed. With no limit, every episode the feed lists, in the feed order. An episode with no publish date has no date line.

{
  "contentType": "PodcastEpisode",
  "renderType": "HeroCard",
  "filterType": "FeedUrl",
  "filterValue": "https://podcast.example.org/feed/"
}
EyebrowTitleRoleDescriptionEmailPhone
cardOctober 6, 2026Contract talks: what happens next————
cardSeptember 22, 2026Safety at the table: a conversation with the committee chair————
cardSeptember 8, 2026Understanding your October bid, with a walkthrough of preferential bidding, reserve rules and how seniority affects each round of awards————
cardAugust 25, 2026Member question: reserve availability————
card—Welcome to the pilot podcast————

A feed that cannot be read. A feed address the app cannot read shows nothing, with no message.

{
  "contentType": "PodcastEpisode",
  "renderType": "HeroCard",
  "filterType": "FeedUrl",
  "filterValue": "https://podcast.example.org/missing/"
}

Shows nothing.

RosterItem

Two committees. A heading per committee, in the order the codes are listed, with that committee's people under it.

{
  "contentType": "RosterItem",
  "renderType": "ContactCard",
  "rosterCodes": "UALSAFE00001,UALSCHD00002"
}
EyebrowTitleRoleDescriptionEmailPhone
heading—Safety————
card—Wei NgChair—wei.ng@example.org5555550101
card—Mei LiVice Chair—mei.li@example.org5555550102
card—Bob O'BrienSecretary—bob.obrien@example.org5555550104
card—Claire Lefèvre-DesrosiersMember—claire.lefevre@example.org—
heading—Scheduling————
card—Mei LiChair—mei.li@example.org5555550102
card—Alex RiveraMember—alex.rivera@example.org5555550105

Sample contacts

ListCodeNameTitleSeatEmailPhone
Committee: SafetyUALSAFE00001Claire Lefèvre-DesrosiersMember—claire.lefevre@example.org—
Committee: SafetyUALSAFE00001Bob O'BrienTreasurer—bob.obrien@example.org5555550104
Committee: SafetyUALSAFE00001Wei NgChair—wei.ng@example.org5555550101
Committee: SafetyUALSAFE00001Mei LiVice Chair—mei.li@example.org5555550102
Committee: SafetyUALSAFE00001Bob O'BrienSecretary—bob.obrien@example.org5555550104
Committee: SchedulingUALSCHD00002Alex RiveraMember—alex.rivera@example.org5555550105
Committee: SchedulingUALSCHD00002Mei LiChair—mei.li@example.org5555550102
My LEC reps—Pat MoreauChairCaptain Representativepat.moreau@example.org5555550106
My LEC reps—Sam OkaforVice ChairFirst Officer Representativesam.okafor@example.org—
My MEC officers—Pat MoreauChair—pat.moreau@example.org5555550106
My MEC officers—Dana WhitfieldSecretary-Treasurer—dana.whitfield@example.org5555550108

Sample podcast episodes

Feed https://podcast.example.org/feed/, newest first.

PublishedTitle
2026-10-06Contract talks: what happens next
2026-09-22Safety at the table: a conversation with the committee chair
2026-09-08Understanding your October bid, with a walkthrough of preferential bidding, reserve rules and how seniority affects each round of awards
2026-08-25Member question: reserve availability
undatedWelcome to the pilot podcast

Sample documents

CategoryGroupingTypePublishedTitleDescription
CommunicationsMEC Communicationswebpage2026-09-14Scheduling update for OctoberWhat changes in the October bid and when it takes effect.
CommunicationsMEC Communicationspdf2026-10-02Negotiating committee reportA summary of this month's sessions.
CommunicationsMEC Communicationswebpage2026-08-21Recognizing our retiring members—
CommunicationsMEC CommunicationspdfundatedAnnual member survey results, including participation by domicile and a comparison with the previous three yearsThe full results, with the questions as asked and the number of members who answered each.
CommunicationsLEC Communicationswebpage2026-09-30LEC officer elections openHow to stand for office and when ballots are due.
Letter of AgreementMEC Documentspdf2026-07-08Letter of Agreement 26-03: reserve availabilityReplaces the interim language on reserve availability.
MEC Updates and Weekly—pdf2026-10-23MEC Weekly Update: October 23—
MEC Updates and Weekly—pdf2026-10-16MEC Weekly Update: October 16—
MEC Updates and Weekly—pdf2026-10-09MEC Weekly Update: October 9—

Sample members

SampleSigned inNameRankMECLECBaseHas a contract
Captain, short nameyesWei NgCaptainUAL012ORDyes
First Officer, short nameyesMei LiFirst OfficerUAL012ORDyes
Captain, long nameyesAnneke Vandersteenhoven-KowalczykCaptainUAL012ORDyes
First Officer, long name, no contractyesClaire Lefèvre-DesrosiersFirst OfficerUAL012ORDno
No rank on recordyesJordan O'Brien—UAL012ORDyes
No rank, accented name, no contractyesÉlodie Lefèvre-Desrosiers—UAL012ORDno
First Officer at DAL (a second US MEC)yesSam OkaforFirst OfficerDAL044ORDyes
Captain at ACA (Canadian MEC)yesLuc TremblayCaptainACA030YYZyes
Signed outno—————no

8. Examples

Each example is checked against this catalog by a test: the content type exists, required keys are present, and every key and render type is valid.

A carousel of the latest documents

A container with one templated item. The item's own itemType is only a placeholder; the template decides what appears. The container's View All link is a bare page key, which the app expands into the in-app route.

{
  "containerType": "Carousel",
  "title": "Latest updates",
  "viewAllText": "View All",
  "viewAllLink": "{ual-media}",
  "items": [
    {
      "itemType": "List",
      "template": {
        "contentType": "DocumentItem",
        "renderType": "HeroCard",
        "filterType": "Category",
        "filterValue": "MEC Updates and Weekly",
        "searchFilter": "?sort_by=date&order=desc&limit=3"
      }
    }
  ]
}

The pilot's greeting card

One row, no parameters needed: the content comes from the pilot's own sign-in. The renderType is optional and defaults to PilotCard.

{
  "containerType": "Stack",
  "items": [
    {
      "itemType": "PilotCard",
      "template": { "contentType": "PilotCard" }
    }
  ]
}

A multi-committee roster

A heading per committee followed by its people, in the order the codes are listed. Replace the two codes with real roster codes.

{
  "containerType": "Stack",
  "items": [
    {
      "itemType": "MultiCommitteeRoster",
      "template": {
        "contentType": "RosterItem",
        "rosterCodes": "COMMITTEE_CODE_ONE,COMMITTEE_CODE_TWO"
      }
    }
  ]
}

In a page payload, template may be a JSON object, as written here, or the same object written as an escaped JSON string. The app reads both. The tests check the object form against this catalog, not the escaped one.

9. How far to trust this page

Tests compare this page's data with the app's code, and fail when they differ, for these points:

Tests do not check: a key's type, whether it is required (or required when), what a content type produces, the descriptions, or the section 1 walk-through. The key lists are checked loosely: a listed key must appear in its adapter's code, and a key the adapter reads must be listed, but a key the adapter reads for a different purpose can pass. When something here surprises you, the app's code decides; report the difference so this page can be fixed.

10. Machine-readable form

The same data, plus JSON Schemas for a page, container and item and a preview fixture for every component, ships as the ALPAMobile.Catalog package. Use it to build pickers and validation in the authoring tool instead of copying values from this page.