@ebitex/content-mcp 0.5.152 → 0.5.159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16,12 +16,12 @@ export const HELP_TOPICS = [
|
|
|
16
16
|
{
|
|
17
17
|
"slug": "components",
|
|
18
18
|
"title": "Authoring Components",
|
|
19
|
-
"body": "# Authoring Components\n\nA Component is one piece of content built from a Contract — for example,\na specific article. This guide covers creating and editing Components,\norganizing them in folders, and the friction the app shows you when a\nContract changes underneath a Component you've already created. See\n[Modeling content with Contracts](contracts.md) first if you haven't\ncreated a Contract yet.\n\n## Creating a Component\n\n1. From the Content page, select **New Component** (optionally after\n opening the folder you want it created in).\n2. Enter a **Name** — the **Id** fills in from it automatically and can\n still be edited by hand.\n3. Choose a **Contract**. If you started from a specific folder that\n restricts which Contracts are allowed there, only those (and their\n descendants) are offered.\n4. Fill in the form that appears — every field from the Contract, laid\n out in order. Fields marked with a red **\\*** are required.\n5. Select **Create**. If a required field is missing or a value doesn't\n match the Contract's rules, the field is highlighted with an\n explanation — fix it and select **Create** again.\n\n## Filling in fields\n\nMost fields are a straightforward text box, number box, or checkbox.\nA few work differently:\n\n- **Reference** and **Nested** are older field types kept working for\n existing Contracts, but no longer offered when adding a new field — new\n Contracts should use **Component** instead (below), which offers the\n same two behaviors plus a third, chosen per value instead of committed\n to for the whole field.\n- **Component** fields ask you to choose, each time you fill one in:\n **Choose…** to link to an existing Component (same search box as\n Reference, with **Change**/**Remove** once chosen); **Create new…** to\n create a brand-new Component and link to it in one step (fill in its\n name, Contract, and any required fields right there); or **Create\n inline…** to embed a value that only ever exists inside this one — pick\n a Contract and an **Edit** panel slides in, exactly like Nested below.\n If the Contract only allows one of these choices, only that one is\n offered. If a linked Component can't be found — most often because it\n was skipped during a promotion into this environment (see\n [content-environments.md](content-environments.md)'s \"Unresolved\n references\" section) — you'll see a distinct **Unresolved** badge\n instead of the usual resolved name, with a link to Component Sync to\n see the full picture and fix it. **Change**/**Remove** still work\n normally on an unresolved value.\n- **Blob** fields (images and other files) show an **Upload** button.\n Once uploaded, you'll see a preview (for images) and a link to download\n the file, plus a **Replace** button.\n- **Nested** fields show a small **Edit** panel once a Contract is chosen\n for them (automatically, if only one is allowed for that field, or via a\n picker if more than one is allowed) — selecting **Edit** opens the\n nested content in its own panel, sliding in over the current one. Any\n unsaved changes you've made — at every level — are kept even if you\n drill several levels deep and back out again; nothing is lost until you\n actually leave the page without saving. A Component field's own **Create\n inline…** choice opens the identical panel.\n- Fields marked **Localizable** always show a small translations icon next\n to their label — select it to add per-locale overrides alongside the\n default value. It's disabled (with an explanation on hover) until your\n organization has a language configured under **Localization** settings\n with at least one language added under it to translate into; once one\n exists, the icon becomes selectable. This works the same way for every\n field type, including Blob, Reference, Nested, Component, and\n Presentation fields: each locale gets its own independent\n **Upload**/**Edit**/**Choose…** affordance, so a Nested value's translated\n content — or a different linked Component or uploaded file per locale —\n is fully separate from the default. The default-locale row in the\n translations panel is always read-only (a reflection of the default\n value, not a second copy of it); translate from the other locale rows.\n- **Presentation** fields let you instantiate a Template inline — pick a\n Template, bind it to a Component, and set contextual values and settings\n for this specific placement. See\n [Presenting content with Templates](templates.md) for the full flow.\n\n## Links to the live page\n\nIf the Contract has **External links**, they appear as buttons under the\nComponent's name, and at the top of the quick-edit panel. A button opens that\nComponent's page on your site in a new tab. If it is greyed out, the reason is\nwritten beside it, usually that the Component has not been published yet. The\nlink always shows what is *published*, not the changes you are typing. See\n[Links to your site](contracts.md) to set them up.\n\n## Status, and what to do next\n\nUnder the Component's name, one **status strip** says whether it can be published and, if not, why. It also\nholds the next step, so you do not have to hunt for it:\n\n- **Draft**, **Published** or **Modified since it was published**, with one line about the live site\n (\"The live site shows an older version\").\n- If your organization uses an [editorial workflow](content-workflow.md) for this folder, the strip shows the\n workflow's state beside the headline. While that state does not allow publishing it reads **Can't be\n published yet**, and the workflow's next step (for example **Approve**) sits beside it. Choose it, add an\n optional comment and confirm, all without leaving the Content tab. **Republish…** stays available, but it is\n no longer the highlighted button; its tooltip gives the reason, and the publish panel explains the block.\n- Once the state allows publishing it reads **Ready to publish** and **Publish…** is highlighted instead.\n- If you have edited since a review was started, the strip says so, and that publishing will use the version\n that was reviewed.\n- A Component that no longer fits its folder's rules gets a **Move it…** row.\n- If the Component has translations in progress, they are listed here too, with **Review…** for one that is\n waiting for you.\n\nThe full workflow panel, with its comment box and **Cancel run**, and the complete translations list stay on the\n**Settings** tab. Where the Component is used (**Used in N places**) and whether it is **Inherited** are in the line\nunder the name.\n\n## Jumping to a field\n\nWhen a Contract has eight or more fields, a **Jump to field** menu appears beside the **Content** and **Settings**\ntabs. Choosing a field scrolls to it and puts the cursor there. A red dot marks a field that needs attention after\na failed save.\n\n## Editing a tree of Components\n\nWhen a Contract is set up to be edited as a tree (see\n[Editing fields as a tree](contracts.md)), its Component editor shows one\nsection, such as **Pedigree**, in place of the separate pickers. The Component\nyou are editing is the root, and each slot is a Component of its own.\n\n- **Chart or outline.** A slot-based tree such as a pedigree is drawn as a chart,\n one column per generation, or as an outline. Choose with the buttons above it;\n the outline is used on narrow screens. **Generations** shows fewer levels\n without changing anything. A list, such as the parts of a product, is always\n an outline you can collapse and expand.\n- **Fill a slot.** Select an empty slot to search for an existing Component, or\n **Create new** to make one on the spot. A slot only lists Components it can\n hold, such as dogs for a sire.\n- **Options you can't choose are greyed out, with the reason.** *Would become its\n own ancestor* or *Would contain itself* means choosing it would make something\n its own ancestor. *Already used elsewhere in this tree* appears when the\n Contract doesn't allow repeats. *Already in this list* means it is there\n already. If the server still refuses a change, the reason is shown above the\n tree.\n- **Edit without leaving.** **Edit** on a filled slot opens that Component in a\n panel over the page. Change it, save it and close the panel, and you are back\n in the tree.\n- **Change or remove.** Point at a filled slot for **Change** and the remove\n button. Removing only empties the slot; the Component itself is kept.\n- **A slot under an empty parent is greyed out**, because there is nothing to\n attach it to yet. Fill the parent first.\n- **A name with ×2 or \"in 2\"** is one Component that appears in more than one\n place. Editing it changes it everywhere.\n\n**A slot can be described inline.** Some fields accept a description written\nin place instead of an existing Component, for example a dam who is not in your\narchive and never will be. Where a field allows it, the picker has an\n**Enter … inline instead** button. An inline slot is drawn with a dashed\noutline and an **Inline** chip, and its own slots (her sire and dam, say) are\ndrawn under it and filled in the same way as any other.\n\n- **Edit** on an inline slot opens its own fields in a panel at the side. The\n slots the tree draws are not repeated there. Choose **Done** to keep your\n changes.\n- **Change** or the remove button on an inline slot replaces or removes it\n *together with everything under it*. The picker says how many entries that\n is before you choose, and a notice with **Undo** appears for a few seconds\n afterwards. Undo puts the whole description back.\n- A field that only accepts an existing Component has no inline button.\n- Nothing else can point at an inline description, so it shows no ×2 count.\n\n**What saves when.** The first level, the slots of the Component you have open,\nis part of that Component: it is saved with **Save**, like any other field.\nSlots deeper down belong to the Components above them, so filling one saves that\nComponent straight away, and a **Saved as you go** note under the tree says so.\nA slot under an inline description belongs to the Component that holds the\ndescription, so it follows the same rule: with **Save** when that Component is\nthe one you have open, at once otherwise.\n\n## Contextual defaults\n\nFields marked Contextual on the Contract appear in a separate\n**\"Defaults for usage sites\"** section, clearly labeled optional — even if\nthe Contract also marks them Mandatory. That's intentional: a Contextual\nfield's real value is supplied wherever the content is *used*, not here;\nwhat you set in this section is only a fallback for places that don't\nsupply their own value.\n\n### Setting per-usage values on a Reference\n\nWhen you link to another Component via a Reference field (or a Component\nfield's **Choose…**/**Create new…** path — both link the same way), select\n**Contextual values** to open a panel listing that target's own Contextual\nfields, each with three distinct states you can switch between:\n\n- **Inheriting the Component's default** — nothing set here; the linked\n Component's own default value is used.\n- **Overridden** — set a value here to use instead of the default, just\n for this one link. This works for every field type the target Contract\n declares as Contextual, not just simple text/number/checkbox fields — a\n Contextual Reference field gets the same **Choose…** picker, a Contextual\n Blob field the same **Upload** button, and a Contextual Nested field the\n same drill-in **Edit** panel you'd see editing that field directly on a\n Component.\n- **Explicitly cleared** — select **Clear** to force \"no value\" at this\n usage, ignoring the default entirely (only available when the field\n isn't required).\n\nSelect **Reset to default** at any time to go back to inheriting. The same\nthree states and the same per-type widgets apply to a Presentation field's\nown contextual-values panel (see\n[Presenting content with Templates](templates.md)).\n\n### Editing the linked Component itself\n\nNext to **Contextual values**, a linked Component also offers **Quick\nedit**, which opens that Component in a layer over the page you're on —\nits own fields, its own **Save**, and a note of everywhere else it's used,\nsince saving changes it there too. How layers stack, and the difference\nbetween a layer that saves on its own and one that's part of your page, is\nexplained in\n[Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\n## Organizing with folders\n\nThe **Authoring** page shows your folder tree on the left. At the top are **All components** (everything in\nthis environment, across every folder) and **Top level** (Components that aren't in any folder). Below them\nare your folders, each with a count; a folder's count includes everything beneath it. A long folder name wraps\nrather than being cut off.\n\nPoint at a folder to see its actions: the **+** icon creates a subfolder inside it, the pencil renames it or\nmoves it (choose where it goes under **Inside**), the trash icon deletes it (only possible once it's empty,\nand it asks first), and the handle drags it. Selecting a folder shows two tabs: **Contents** (the Components\ninside it) and, if you have the right permissions, **Settings** (that folder's **Access rules**, **Allowed\nContracts**, and editorial workflow assignment). The double-arrow at the top of the panel collapses the whole\ntree to a narrow rail of icons with count badges; select one to open that folder, or the arrow to bring the\npanel back.\n\nEach Component is a row with its title (its id underneath), Contract, publish status (**Draft**, **Published**,\n**Changed** or **Unpublished**), and who last updated it and when. Select the **Title** or **Updated** heading\nto sort by it. Above the list, a search box matches a title, id or Contract, and the **Contract**,\n**Category** and **Status** chips narrow further; **Clear filters** resets them. **Status** lets you tick\none or more of Draft, Published, Changed and Unpublished, for example to find everything that has changed since\nit was published. The count under the list follows the filter, so it is the number that match, not the number\non the page. **Import**, beside **New Component**, opens the [bundle import](export-import.md) for bringing\nComponents in from another environment. Beneath the list, **Rows per page** and\n**Previous / Next** page through long folders, and a line says how many of the total you are looking at.\n\n### Moving Components by dragging, or with the menu\n\nDrag a Component by the handle at the start of its row onto a folder in the tree — or onto **Top level** to take\nit out of its folder — to move it. If you've ticked several rows, dragging one drags them all. A message\nconfirms what moved and offers **Undo**, which puts each Component back where it came from.\n\nTo move without dragging, open the row's **⋯** menu and choose **Move to folder…**, then pick the folder. When\nthe row is part of a selection, the menu says \"Move 3 selected to folder…\" and moves all of them. A folder you\ncan't edit is shown but not choosable. A move is not all-or-nothing: if a Component can't go there (the folder\ndoesn't allow its Contract, say, or you can't edit it), the message names it and why, and the rest still move.\nDragging a folder onto another moves the whole folder inside it; a folder can't be dropped into itself or one\nof its own subfolders. Folders are always listed alphabetically, so there is no manual order to drag into.\n\n### Working on several Components at once\n\nTick rows (the box in the heading ticks every row on the page) and a bar replaces the search tools, showing how\nmany are selected and in which publish states:\n\n- **Publish** applies to everything selected, and reads **Republish** when none of the selection is a draft.\n It opens the usual publish dialog, which lists what else would be published with them.\n- **Unpublish** applies only to what is published or changed. It shows \"2 of 5\" when some of the selection\n can't be unpublished, is switched off with the reason when none can, and asks you to confirm, with a breakdown\n of what comes off the live site.\n- **Move to folder…** moves what you can edit and says how many of the selection that is.\n\nUnder **Settings**:\n\n- **Access rules** restrict which roles can view, edit, delete, or publish\n content in that folder and everything below it (until a subfolder sets\n its own, narrower rules). No rules anywhere on a branch means it's open\n to every member. Select **Add Rule** to grant a role access: pick the\n role from the list and check whichever of View/Edit/Delete/Publish it\n should have. Editing, deleting, or publishing all imply viewing, so you\n don't need to check View separately for those.\n- **Allowed Contracts** restrict which Contracts new Components in that\n folder (and its subfolders, unless they set their own) can use — useful\n for keeping a folder focused on one kind of content. Select **Add\n Contract** and search for the Contract to allow; select **Remove** next\n to an already-allowed Contract to take it off the list. This only\n affects *new* or *moved* Components; it never breaks ones already there,\n though they'll show a **Non-conforming** badge as a reminder.\n\nIf you don't have permission to manage a folder's access rules or allowed\nContracts, you can still see what you're allowed to do there — the panel\njust won't let you change it.\n\n### Moving a Component from its own page\n\nOpen the Component, select the **Settings** tab, and select **Move…**\nnext to the **Folder** label. A picker lists every folder (and **Root**);\npick one to move the Component there once you save. A folder you don't\nhave edit access to is shown but disabled, with an explanation. A folder\nwhose **Allowed Contracts** don't include this Component's Contract is\ndisabled too — unlike an *existing* Component whose folder's rules later\nchange (the **Non-conforming** badge case above), a move that would\nviolate the target folder's rules is rejected outright, so the picker\nwon't offer it as an option in the first place.\n\n### Finding your way back to a folder\n\nThe Component editor shows a breadcrumb above its title (**Content** /\nthe folder it's in / the Component's name) — select the folder name to\nreturn straight to that folder's Contents tab, rather than using your\nbrowser's back button.\n\n## The upgrade badge\n\nIf a Contract changes after a Component was created from it, that\nComponent keeps working exactly as it did — nothing breaks automatically.\nInstead:\n\n- If the Component still satisfies the Contract's latest version, you'll\n see a badge offering **Upgrade to v_N_** — select it to move the\n Component onto the latest version immediately.\n- If it no longer satisfies the latest version, you'll see a\n **Not valid against latest** badge listing exactly what's wrong. Select\n **Start guided upgrade** to switch into editing against the latest\n version, fix the listed issues, and save — the Component moves onto the\n new version as part of that save.\n\nYou're never forced to upgrade; an older Component keeps validating against\nthe version it was created with until you choose to move it forward.\n\n## Asking the assistant to edit this Component\n\nThe help panel's question box (open it from the **?** icon) can see and edit the Component you have\nopen, not only answer questions about it — see **When the assistant can read and edit** in\n[Getting help](../general/getting-help.md). A field edit it makes saves immediately with the same\nversion history a manual edit gets; anything bigger, like deleting the Component, is proposed for\nyou to review first.\n"
|
|
19
|
+
"body": "# Authoring Components\n\nA Component is one piece of content built from a Contract — for example,\na specific article. This guide covers creating and editing Components,\norganizing them in folders, and the friction the app shows you when a\nContract changes underneath a Component you've already created. See\n[Modeling content with Contracts](contracts.md) first if you haven't\ncreated a Contract yet.\n\n## Creating a Component\n\n1. From the Content page, select **New Component** (optionally after\n opening the folder you want it created in).\n2. Enter a **Name** — the **Id** fills in from it automatically and can\n still be edited by hand.\n3. Choose a **Contract**. If you started from a specific folder that\n restricts which Contracts are allowed there, only those (and their\n descendants) are offered.\n4. Fill in the form that appears — every field from the Contract, laid\n out in order. Fields marked with a red **\\*** are required.\n5. Select **Create**. If a required field is missing or a value doesn't\n match the Contract's rules, the field is highlighted with an\n explanation — fix it and select **Create** again.\n\n## Filling in fields\n\nMost fields are a straightforward text box, number box, or checkbox.\nA few work differently:\n\n- **Reference** and **Nested** are older field types kept working for\n existing Contracts, but no longer offered when adding a new field — new\n Contracts should use **Component** instead (below), which offers the\n same two behaviors plus a third, chosen per value instead of committed\n to for the whole field.\n- **Component** fields ask you to choose, each time you fill one in:\n **Choose…** to link to an existing Component (same search box as\n Reference, with **Change**/**Remove** once chosen); **Create new…** to\n create a brand-new Component and link to it in one step (fill in its\n name, Contract, and any required fields right there); or **Create\n inline…** to embed a value that only ever exists inside this one — pick\n a Contract and an **Edit** panel slides in, exactly like Nested below.\n If the Contract only allows one of these choices, only that one is\n offered. If a linked Component can't be found — most often because it\n was skipped during a promotion into this environment (see\n [content-environments.md](content-environments.md)'s \"Unresolved\n references\" section) — you'll see a distinct **Unresolved** badge\n instead of the usual resolved name, with a link to Component Sync to\n see the full picture and fix it. **Change**/**Remove** still work\n normally on an unresolved value.\n- **Blob** fields (images and other files) show an **Upload** button.\n Once uploaded, you'll see a preview (for images) and a link to download\n the file, plus a **Replace** button.\n- **Nested** fields show a small **Edit** panel once a Contract is chosen\n for them (automatically, if only one is allowed for that field, or via a\n picker if more than one is allowed) — selecting **Edit** opens the\n nested content in its own panel, sliding in over the current one. Any\n unsaved changes you've made — at every level — are kept even if you\n drill several levels deep and back out again; nothing is lost until you\n actually leave the page without saving. A Component field's own **Create\n inline…** choice opens the identical panel.\n- Fields marked **Localizable** always show a small translations icon next\n to their label — select it to add per-locale overrides alongside the\n default value. It's disabled (with an explanation on hover) until your\n organization has a language configured under **Localization** settings\n with at least one language added under it to translate into; once one\n exists, the icon becomes selectable. This works the same way for every\n field type, including Blob, Reference, Nested, Component, and\n Presentation fields: each locale gets its own independent\n **Upload**/**Edit**/**Choose…** affordance, so a Nested value's translated\n content — or a different linked Component or uploaded file per locale —\n is fully separate from the default. The default-locale row in the\n translations panel is always read-only (a reflection of the default\n value, not a second copy of it); translate from the other locale rows.\n- **Presentation** fields let you instantiate a Template inline — pick a\n Template, bind it to a Component, and set contextual values and settings\n for this specific placement. See\n [Presenting content with Templates](templates.md) for the full flow.\n\n## Links to the live page\n\nIf the Contract has **External links**, they appear as buttons under the\nComponent's name, and at the top of the quick-edit panel. A button opens that\nComponent's page on your site in a new tab. If it is greyed out, the reason is\nwritten beside it, usually that the Component has not been published yet. The\nlink always shows what is *published*, not the changes you are typing. See\n[Links to your site](contracts.md) to set them up.\n\n## Status, and what to do next\n\nUnder the Component's name, one **status strip** says whether it can be published and, if not, why. It also\nholds the next step, so you do not have to hunt for it:\n\n- **Draft**, **Published** or **Modified since it was published**, with one line about the live site\n (\"The live site shows an older version\").\n- If your organization uses an [editorial workflow](content-workflow.md) for this folder, the strip shows the\n workflow's state beside the headline. While that state does not allow publishing it reads **Can't be\n published yet**, and the workflow's next step (for example **Approve**) sits beside it. Choose it, add an\n optional comment and confirm, all without leaving the Content tab. **Republish…** stays available, but it is\n no longer the highlighted button; its tooltip gives the reason, and the publish panel explains the block.\n- Once the state allows publishing it reads **Ready to publish** and **Publish…** is highlighted instead.\n- If you have edited since a review was started, the strip says so, and that publishing will use the version\n that was reviewed.\n- A Component that no longer fits its folder's rules gets a **Move it…** row.\n- If the Component has translations in progress, they are listed here too, with **Review…** for one that is\n waiting for you.\n\nThe full workflow panel, with its comment box and **Cancel run**, and the complete translations list stay on the\n**Settings** tab. Where the Component is used (**Used in N places**) and whether it is **Inherited** are in the line\nunder the name.\n\n## Jumping to a field\n\nWhen a Contract has eight or more fields, a **Jump to field** menu appears beside the **Content** and **Settings**\ntabs. Choosing a field scrolls to it and puts the cursor there. A red dot marks a field that needs attention after\na failed save.\n\n## Editing a tree of Components\n\nWhen a Contract is set up to be edited as a tree (see\n[Editing fields as a tree](contracts.md)), its Component editor shows one\nsection, such as **Pedigree**, in place of the separate pickers. The Component\nyou are editing is the root, and each slot is a Component of its own.\n\n- **Chart or outline.** A slot-based tree such as a pedigree is drawn as a chart,\n one column per generation, or as an outline. Choose with the buttons above it;\n the outline is used on narrow screens. **Generations** shows fewer levels\n without changing anything. A list, such as the parts of a product, is always\n an outline you can collapse and expand.\n- **Fill a slot.** Select an empty slot to search for an existing Component, or\n **Create new** to make one on the spot. A slot only lists Components it can\n hold, such as dogs for a sire.\n- **Options you can't choose are greyed out, with the reason.** *Would become its\n own ancestor* or *Would contain itself* means choosing it would make something\n its own ancestor. *Already used elsewhere in this tree* appears when the\n Contract doesn't allow repeats. *Already in this list* means it is there\n already. If the server still refuses a change, the reason is shown above the\n tree.\n- **Edit without leaving.** **Edit** on a filled slot opens that Component in a\n panel over the page. Change it, save it and close the panel, and you are back\n in the tree.\n- **Change or remove.** Point at a filled slot for **Change** and the remove\n button. Removing only empties the slot; the Component itself is kept.\n- **A slot under an empty parent is greyed out**, because there is nothing to\n attach it to yet. Fill the parent first.\n- **A name with ×2 or \"in 2\"** is one Component that appears in more than one\n place. Editing it changes it everywhere.\n\n**A slot can be described inline.** Some fields accept a description written\nin place instead of an existing Component, for example a dam who is not in your\narchive and never will be. Where a field allows it, the picker has an\n**Enter … inline instead** button. An inline slot is drawn with a dashed\noutline and an **Inline** chip, and its own slots (her sire and dam, say) are\ndrawn under it and filled in the same way as any other.\n\n- **Edit** on an inline slot opens its own fields in a panel at the side. The\n slots the tree draws are not repeated there. Choose **Done** to keep your\n changes.\n- **Change** or the remove button on an inline slot replaces or removes it\n *together with everything under it*. The picker says how many entries that\n is before you choose, and a notice with **Undo** appears for a few seconds\n afterwards. Undo puts the whole description back.\n- A field that only accepts an existing Component has no inline button.\n- Nothing else can point at an inline description, so it shows no ×2 count.\n\n**What saves when.** The first level, the slots of the Component you have open,\nis part of that Component: it is saved with **Save**, like any other field.\nSlots deeper down belong to the Components above them, so filling one saves that\nComponent straight away, and a **Saved as you go** note under the tree says so.\nA slot under an inline description belongs to the Component that holds the\ndescription, so it follows the same rule: with **Save** when that Component is\nthe one you have open, at once otherwise.\n\n## Contextual defaults\n\nFields marked Contextual on the Contract appear in a separate\n**\"Defaults for usage sites\"** section, clearly labeled optional — even if\nthe Contract also marks them Mandatory. That's intentional: a Contextual\nfield's real value is supplied wherever the content is *used*, not here;\nwhat you set in this section is only a fallback for places that don't\nsupply their own value.\n\n### Setting per-usage values on a Reference\n\nWhen you link to another Component via a Reference field (or a Component\nfield's **Choose…**/**Create new…** path — both link the same way), select\n**Contextual values** to open a panel listing that target's own Contextual\nfields, each with three distinct states you can switch between:\n\n- **Inheriting the Component's default** — nothing set here; the linked\n Component's own default value is used.\n- **Overridden** — set a value here to use instead of the default, just\n for this one link. This works for every field type the target Contract\n declares as Contextual, not just simple text/number/checkbox fields — a\n Contextual Reference field gets the same **Choose…** picker, a Contextual\n Blob field the same **Upload** button, and a Contextual Nested field the\n same drill-in **Edit** panel you'd see editing that field directly on a\n Component.\n- **Explicitly cleared** — select **Clear** to force \"no value\" at this\n usage, ignoring the default entirely (only available when the field\n isn't required).\n\nSelect **Reset to default** at any time to go back to inheriting. The same\nthree states and the same per-type widgets apply to a Presentation field's\nown contextual-values panel (see\n[Presenting content with Templates](templates.md)).\n\n### Editing the linked Component itself\n\nNext to **Contextual values**, a linked Component also offers **Quick\nedit**, which opens that Component in a layer over the page you're on —\nits own fields, its own **Save**, and a note of everywhere else it's used,\nsince saving changes it there too. How layers stack, and the difference\nbetween a layer that saves on its own and one that's part of your page, is\nexplained in\n[Editing something from where it's used](content-authoring.md#editing-something-from-where-its-used).\n\n## Organizing with folders\n\nThe **Authoring** page shows your folder tree on the left. At the top are **All components** (everything in\nthis environment, across every folder) and **Top level** (Components that aren't in any folder). Below them\nare your folders, each with a count; a folder's count includes everything beneath it. A long folder name wraps\nrather than being cut off.\n\nPoint at a folder to see its actions: the **+** icon creates a subfolder inside it, the pencil renames it or\nmoves it (choose where it goes under **Inside**), the trash icon deletes it (only possible once it's empty,\nand it asks first), and the handle drags it. Selecting a folder shows two tabs: **Contents** (the Components\ninside it) and, if you have the right permissions, **Settings** (that folder's **Access rules**, **Allowed\nContracts**, and editorial workflow assignment). The double-arrow at the top of the panel collapses the whole\ntree to a narrow rail of icons with count badges; select one to open that folder, or the arrow to bring the\npanel back.\n\nEach Component is a row with its title (its id underneath), Contract, publish status (**Draft**, **Published**,\n**Changed** or **Unpublished**), and who last updated it and when. Select the **Title** or **Updated** heading\nto sort by it. Above the list, a search box matches a title, id or Contract, and the **Contract**,\n**Category** and **Status** chips narrow further; **Clear filters** resets them. **Status** lets you tick\none or more of Draft, Published, Changed and Unpublished, for example to find everything that has changed since\nit was published. The count under the list follows the filter, so it is the number that match, not the number\non the page. **Import**, beside **New Component**, opens the [bundle import](export-import.md) for bringing\nComponents in from another environment. Beneath the list, **Rows per page** and\n**Previous / Next** page through long folders, and a line says how many of the total you are looking at.\n\n### Moving Components by dragging, or with the menu\n\nDrag a Component by the handle at the start of its row onto a folder in the tree — or onto **Top level** to take\nit out of its folder — to move it. If you've ticked several rows, dragging one drags them all. A message\nconfirms what moved and offers **Undo**, which puts each Component back where it came from.\n\nTo move without dragging, open the row's **⋯** menu and choose **Move to folder…**, then pick the folder. When\nthe row is part of a selection, the menu says \"Move 3 selected to folder…\" and moves all of them. A folder you\ncan't edit is shown but not choosable. A move is not all-or-nothing: if a Component can't go there (the folder\ndoesn't allow its Contract, say, or you can't edit it), the message names it and why, and the rest still move.\nDragging a folder onto another moves the whole folder inside it; a folder can't be dropped into itself or one\nof its own subfolders. Folders are always listed alphabetically, so there is no manual order to drag into.\n\n### Working on several Components at once\n\nTick rows (the box in the heading ticks every row on the page) and a bar replaces the search tools, showing how\nmany are selected and in which publish states:\n\n- **Publish** applies to everything selected, and reads **Republish** when none of the selection is a draft.\n It opens the usual publish dialog, which lists what else would be published with them.\n- **Unpublish** applies only to what is published or changed. It shows \"2 of 5\" when some of the selection\n can't be unpublished, is switched off with the reason when none can, and asks you to confirm, with a breakdown\n of what comes off the live site.\n- **Move to folder…** moves what you can edit and says how many of the selection that is.\n\nUnder **Settings**:\n\n- **Access rules** restrict which roles can view, edit, delete, or publish\n content in that folder and everything below it (until a subfolder sets\n its own, narrower rules). No rules anywhere on a branch means it's open\n to every member. Select **Add Rule** to grant a role access: pick the\n role from the list and check whichever of View/Edit/Delete/Publish it\n should have. Editing, deleting, or publishing all imply viewing, so you\n don't need to check View separately for those.\n- **Allowed Contracts** restrict which Contracts new Components in that\n folder (and its subfolders, unless they set their own) can use — useful\n for keeping a folder focused on one kind of content. Select **Add\n Contract** and search for the Contract to allow; select **Remove** next\n to an already-allowed Contract to take it off the list. This only\n affects *new* or *moved* Components; it never breaks ones already there,\n though they'll show a **Non-conforming** badge as a reminder.\n\nIf you don't have permission to manage a folder's access rules or allowed\nContracts, you can still see what you're allowed to do there — the panel\njust won't let you change it.\n\n### Moving a Component from its own page\n\nOpen the Component, select the **Settings** tab, and select **Move…**\nnext to the **Folder** label. A picker lists every folder (and **Root**);\npick one to move the Component there once you save. A folder you don't\nhave edit access to is shown but disabled, with an explanation. A folder\nwhose **Allowed Contracts** don't include this Component's Contract is\ndisabled too — unlike an *existing* Component whose folder's rules later\nchange (the **Non-conforming** badge case above), a move that would\nviolate the target folder's rules is rejected outright, so the picker\nwon't offer it as an option in the first place.\n\n### Making copies of a Component\n\nWhen you need several near-identical records (a litter, a series of events,\nproduct variants), build one and **duplicate** it. Open the Component and\nselect **Duplicate…** next to **Preview…**. The button is there whenever you\ncould create a Component in the same folder, and absent when you couldn't.\n\nChoose a **number of copies** (1 to 25) and a **name**. Each copy is named\nwith a number after it (`Puppy A 1`, `Puppy A 2`, …), and the dialog previews\nthe first three, with their external ids, before you start.\n\n- **Values are copied, references are shared.** A copy gets its own\n copy of every value in the document. A Component it *references* is not\n copied: every copy points at the same one, so changing that referenced\n Component changes it in all of them.\n- **Copies are drafts.** They are not published, and carry none of the\n original's published state, history, workflow state, or where it is used.\n They sit in the same folder and use the same Contract as the original.\n- **Copies are made from the saved version.** If you have unsaved edits, the\n dialog says so; save first if you want them included.\n- **External ids** follow the original's (`puppy-a-copy-1`) and move to the\n next free number if one is taken, so a batch never fails over a clash.\n\nCopies are created one at a time. If your plan only has room for some of them,\nthe dialog says how many fit and won't start until the number is lowered. If\nsomething goes wrong part-way, it lists which copies exist, which failed and\nwhich were never attempted, and offers **Create the remaining N**, which\ncarries on from where it stopped instead of making extras. If the original no\nlonger matches the latest version of its Contract, nothing is created and the\ndialog names the field to fix first.\n\n### Finding your way back to a folder\n\nThe Component editor shows a breadcrumb above its title (**Content** /\nthe folder it's in / the Component's name) — select the folder name to\nreturn straight to that folder's Contents tab, rather than using your\nbrowser's back button.\n\n## The upgrade badge\n\nIf a Contract changes after a Component was created from it, that\nComponent keeps working exactly as it did — nothing breaks automatically.\nInstead:\n\n- If the Component still satisfies the Contract's latest version, you'll\n see a badge offering **Upgrade to v_N_** — select it to move the\n Component onto the latest version immediately.\n- If it no longer satisfies the latest version, you'll see a\n **Not valid against latest** badge listing exactly what's wrong. Select\n **Start guided upgrade** to switch into editing against the latest\n version, fix the listed issues, and save — the Component moves onto the\n new version as part of that save.\n\nYou're never forced to upgrade; an older Component keeps validating against\nthe version it was created with until you choose to move it forward.\n\n## Asking the assistant to edit this Component\n\nThe help panel's question box (open it from the **?** icon) can see and edit the Component you have\nopen, not only answer questions about it — see **When the assistant can read and edit** in\n[Getting help](../general/getting-help.md). A field edit it makes saves immediately with the same\nversion history a manual edit gets; anything bigger, like deleting the Component, is proposed for\nyou to review first.\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"slug": "content-adapters",
|
|
23
23
|
"title": "Bridging Contracts with Adapters",
|
|
24
|
-
"body": "# Bridging Contracts with Adapters\n\nWhen you bind a Component to a Template (see [Authoring a presentation](content-authoring.md)), the\nComponent's Contract normally has to be exactly what the Template needs, or a more specific kind of\nit. Sometimes the Component you want to use has a *different* Contract entirely — an **Adapter**\nbridges that gap by mapping the mismatched Contract's fields onto the ones the Template expects.\n\n## When the wizard offers one\n\nIn the Presentation wizard's **Select existing** tab, a Component whose Contract the Template\ndoesn't recognize at all lands in the **Needs an Adapter** group. Selecting one shows why it doesn't\nfit, and three buttons appear:\n\n- **Use existing Adapter** — pick an already-created Adapter that maps this Component's Contract onto\n something the Template accepts.\n- **Create Adapter** — build a new, reusable, named Adapter right there in the wizard, for this\n Contract pairing. It's saved to the **Adapters** page (under Configure) so anyone can reuse it\n later.\n- **Connect manually** — build a one-off mapping that's saved directly on this Presentation only,\n never listed on the Adapters page. Useful for a mapping you don't expect to need again. A **Save as\n Adapter…** action turns it into a named one later, without redoing the mapping.\n\nEither way, once a mapping is attached the field-by-field connections are drawn between the\nComponent's fields and the Template's, Complete becomes available, and the banner reads \"Mapped via\n*Adapter name*\" (or \"Mapped manually\" for a one-off).\n\nA Component that's already Compatible can still get an Adapter attached deliberately — useful when\nyou want to reshape its content on the way into this particular Template, even though it didn't\nstrictly need mapping.\n\n## After it's mapped\n\nOnce a mapping is attached, the set-value card offers a few more actions beside the Adapter's name:\n\n- **Edit mapping** — reopens the same field-by-field canvas, already filled in with the current\n mapping, so you can adjust it without starting over. This never changes *which* Component is\n bound, and editing a named Adapter's mapping this way never touches the shared Adapter itself (so\n every other Presentation using it is unaffected) — it becomes this Presentation's own one-off\n mapping instead, which you can turn back into a named Adapter with **Save as Adapter…** if you\n want to reuse it elsewhere.\n- **Change** — picks a different Component for this Presentation entirely. If the new Component's\n Contract still works with the mapping that was already in place, it's kept automatically; if not,\n it's dropped and the reason is explained right there, so you can map fresh.\n- **Save as Adapter…** — only shown for a one-off (\"manual mapping\") — turns it into a named,\n reusable Adapter without redoing any of the mapping work.\n\n## The four rule kinds, in plain language\n\nEvery field the Template needs gets exactly one rule saying where its value comes from:\n\n- **Copy** — take the value straight from one of the Component's own fields (the field types have to\n be compatible — see below).\n- **Compute** — build the value from a small set of building blocks: one of the Component's fields, a\n fixed piece of text, joining a few things together with an optional separator, falling back\n through a list of options until one isn't empty, converting a value from one field type to a\n compatible one (e.g. plain text into rich text), taking just the first item of a list, reading a\n field out of a referenced/nested item, mapping every item of a list, dispatching on which kind of\n item you have, or a simple condition/comparison — see **Logic and structure blocks** below for all\n of these. There's no free-text formula box — you build the computation visually, block by block, on\n the canvas.\n- **Map inner content** — for a field that holds another whole piece of content inside it (a nested\n or embedded Component), apply a second, smaller Adapter to that inner content: pick an existing\n named Adapter, or **Connect manually** to name that inner content's own two Contracts and map them\n right there, the same way you'd map the outer fields. (This is also available as the **For each\n item** block's own \"Adapt to another Contract\" mode — see below — which is the way to reach it when\n you're adding a fresh block rather than mapping a whole field.)\n- **Look up a fixed item** — instead of taking a value from the Component being mapped, always pull it\n from one specific, chosen Component or item.\n\n## Field compatibility\n\nTwo fields need to either already match, or be *coercible*, to connect — you can't map a text field\nstraight onto a number field, for example, but a few kinds of mismatch have a small conversion block\nthe canvas offers to insert for you automatically:\n\n- A single value can feed a field that accepts multiple values (it becomes a one-item list) — no\n extra block needed.\n- A field that accepts multiple values can feed a single-value field by inserting a **Take first\n item** block, which uses the first value and drops the rest.\n- Some field types can be converted into others by inserting a **Convert** block — plain text into\n rich text, plain text into a number (fails at delivery time if the text isn't actually numeric), a\n number into text, or rich text into plain text (its formatting is discarded).\n- A field that isn't translatable can feed a translatable one (it becomes that language's default,\n with no translations yet).\n- A field restricted to certain kinds of related content requires the source to already be\n restricted to the same (or a more specific) set.\n\nWhen you connect two fields that need one of these conversions, a small prompt appears offering to\ninsert the right block between them — accept it and the connection completes with that block already\nwired in place. Everything else — a translatable field into a non-translatable one, a personalizable\nfield into a non-personalizable one (or vice versa), or two field types with no registered\nconversion at all — isn't allowed, and the canvas explains why right there instead of drawing a\nconnection (incompatible fields are also visibly dimmed while you have a source selected).\n\n## What \"unmapped — delivers null\" means\n\nEvery field the Template *requires* needs a rule — the canvas won't let you save until they all do.\nA field that's merely optional can be left unmapped; the card for it reads **unmapped — delivers\nnull**, meaning a person or system reading this content afterward will see that field as empty,\nexactly as if it had no value at all. This is often exactly what you want for a field the source\nContract has no equivalent of.\n\n## The mapping canvas\n\nWhether you're on the standalone **Adapters** page (Configure → Adapters → New Adapter) or inside the\nwizard, mapping works the same way: every building block you add is its own node on one draggable,\nzoomable canvas — the **Input document** card starts on the left, the Template's (or the other\nContract's) fields on the right. Drag a line from one connector to another to connect them, or click a\nname to select it as the starting point and then click the one it should feed — both do exactly\nthe same thing, so use whichever is easier at the time. Click an existing connection, or the field's own\ndelete button, to remove it. `Escape` cancels a pending click-to-connect selection.\n\nThe **Input document** card is everything you're mapping *from*, in one place. It's always there, and\nit has three parts:\n\n- **Fields** — one connector per field of the Contract you're mapping from. This is the everyday\n one: drag a field straight across to the output it should fill.\n- **Input document** — the whole piece of content, as one thing. Use this when the same Adapter runs\n over several *different* kinds of content (a search result over every kind of page, say) and you\n need to branch on which kind each one actually is — connect it to a **Switch on Contract** block.\n- **System** — facts about the run itself rather than about the content: **Source contract external\n id** and **Source contract id**, which tell a consumer *which kind* of content a result came from.\n\nThe **+ Add node** button adds a building block to the canvas — **Join text**, **First non-null**, a\n**Constant value**, **Convert type**, **Take first item**, **Look up in** (a fixed reference to one\nComponent), **Expand fields**, **Build value**, **For each item**, **Switch on Contract**, **If / else**,\n**Equals**, or **Exists** (the last seven are covered in **Logic and structure blocks** below). Drag or click to\nwire fields into and out of it just like any other node; each block has its own small settings right on\nthe node itself (which characters to join with, what to convert into, and so on). Delete a block with\nthe **✕** in its own corner.\n\nA required field the Template needs that's still unconnected is called out in red at the bottom of the\ncanvas, and saving stays disabled until every one of them has a rule.\n\nA **Full screen** button, above the canvas, expands it to fill the whole screen for a more complex\nmapping that needs more room to work in — nothing about the mapping is lost switching in or out, and\n`Escape` exits back to the normal view.\n\nA **Preview** button lets you pick a sample piece of content of the source Contract and see exactly\nwhat the mapped result looks like, using the real mapping engine — no guessing.\n\nThe canvas remembers however you arrange the nodes — drag them into a layout that makes sense to\nyou, save, and it's still that way next time you (or anyone else) open this mapping, whether it's a\nnamed Adapter or a one-off mapping on a single Presentation. Dragging snaps each node to a light\ngrid so things line up cleanly. A node you add but never connect to anything doesn't have its\nposition remembered, since it isn't part of the saved mapping at all yet.\n\n## Logic and structure blocks\n\n**Lists always go through a \"For each item\" block.** None of the other blocks below — Expand fields,\nSwitch on Contract, If/else, Equals, Exists — ever work directly on a list; each expects one item.\nWhen the field you're reading from holds a list, add a **For each item** block first: it's the one\nblock that turns a list into \"one item at a time\" and back into a list again. Everything else you\nconnect after it (an Expand, a Switch, a comparison, whatever the mapping needs for one item) runs\nonce per item automatically.\n\n- **Expand fields** — reads a field out of something that isn't a plain value: a referenced item, a\n nested piece of content, or a component field. Pick which Contract you're expecting (skipped\n automatically when there's only one possibility), and the block grows one output for each of that\n Contract's own fields — connect whichever ones you need onward, just like any other field.\n- **Expand Linked Experience** — for a link field that points at a page in your Experience tree:\n opens the linked page in one step. Its outputs are the page's **Name**, **URL**, **Component** (the\n content it's built from — pick a Contract under \"Read content as…\" to get that content's own fields\n as further outputs) and **Presentation** — the page's own rendering, exactly as it's configured\n (its Template, its content, its settings). Connect **Presentation** to a Presentation-typed output\n to show that page's presentation inline on yours — a \"featured pages\" section that re-hosts each\n page's real rendering rather than rebuilding a card from its fields. An outside link, or a page\n with no presentation of its own, gives nothing here; inside a **For each item**, pair it with\n **Keep item when** (below) to drop those. If the output field only allows certain Templates, a\n relayed presentation built on a different Template comes out empty (with a warning) rather than\n slipping through — widen the field's allowed Templates if that's not what you want.\n- **Build value** — the opposite of Expand fields: assembles a nested piece of content, or a component\n field's inline value, out of other fields in this mapping. Pick which Contract you're building, and\n the block grows one input for each of that Contract's own fields (fields with no separate override —\n the \"context\" ones you'd only ever fill in on a specific usage — never appear here at all). Fields\n marked **Required** need a connection before the mapping can be saved; anything else is optional and\n comes out empty if you leave it unconnected. Pick **Nested** or **Component** to match whatever field\n you're feeding the result into.\n- **For each item** — the only block that crosses a list boundary, as above. Choose one of two modes:\n - **Map each item** — click **Edit mapping** to open a dedicated screen (it takes over the whole\n canvas, with a **Back** button to return) where you build the per-item transformation using an\n **Item** starting point and a **Result** ending point, with any of the other blocks in between —\n including another **For each item**, for a list inside a list. That screen also has a second\n ending point, **Keep item when**: wire a yes/no value into it (an Exists or Equals block,\n usually) and only the items where it comes out *yes* make it into the list — the rest are left\n out entirely, with no empty placeholder and no warning for them. Leave it unconnected to keep\n every item. The typical use is a list of links that mixes pages with outside links: **Expand\n Linked Experience → Component → Exists → Keep item when** drops everything that isn't a real\n page, instead of shipping an empty card for it. One output can feed several blocks at once, so\n the same Expand can supply both the check and the result.\n - **Adapt to another Contract** — apply a whole second, smaller Adapter to each item, exactly like\n **Map inner content** above (pick an existing named Adapter, or **Connect manually**).\n- **Switch on Contract** — for a field that could hold more than one kind of thing (several different\n Contracts), branch the mapping by which one it actually is. Add a case for each Contract you want to\n handle by name; each case gets its own **As *(Contract name)*** output (typically feeding an Expand\n fields block for that specific Contract) and its own **Value for this case** input for what should\n come out when it matches. An optional **Default** input covers any Contract you didn't add a case\n for. See **Reading one page type's fields into several outputs**, below, for the two ways to wire\n it up.\n- **If / else** — picks between two values based on a yes/no condition: wire something into **When**\n (must resolve to yes/no — an Exists or Equals block is the usual source), and one value each into\n **Then** and **Else**.\n- **Equals** — compares two values and outputs yes/no; both sides need to already be the same field\n type (no automatic conversion here — insert a Convert type block first if they aren't).\n- **Exists** — outputs yes unless the value it's checking is completely missing or an empty piece of\n text; useful as the condition for an If/else block (\"only use this if there's actually something\n there\").\n\n## Reading one page type's fields into several outputs\n\nA common shape: the same Adapter runs over several kinds of content, and one of those kinds has a\nhandful of extra fields you want to carry through. A search result over every kind of page, where a\nblog post additionally has a heading, an author, a publish date, an image, topics and an excerpt, is\nthe worked example.\n\nWire it exactly the way you'd draw it:\n\n1. **Input document → Switch on Contract** (its **Value to switch on** connector). Add one case,\n *Blog post*.\n2. **As Blog post → Expand fields.** The Expand grows one output per field a blog post has.\n3. Connect each of those outputs **straight across to the output field it fills** — heading to\n Heading, author to Author, and so on. You do not wire anything back into the Switch.\n\nThat's it. Behind the scenes each of those outputs becomes its own rule, gated on \"only when this\nreally is a blog post\"; anything that isn't a blog post simply leaves those fields empty, which is\nwhat you want. Reopening the Adapter later shows you the same one Switch and one Expand you drew.\n\n**Fields every kind of content has come off the Input document, not through the Switch.** Title and\nDescription exist on every page, so wire them straight from the Input document's **Fields** section.\nRouting them through a case would gain nothing and would leave them empty for anything the Switch\ndoesn't have a case for.\n\n**When one output needs a *different* value per type**, that's the Switch's own arms — \"Title is the\nblog post's heading if it's a blog post, otherwise the page's own title\":\n\n1. **Expand fields → heading → Value for this case** (the *Blog post* arm).\n2. **Input document → Fields → Title → Default.**\n3. **Switch → Result → Title.**\n\nOne connector can feed several places at once, so the same Expand's *heading* output can go to both\nthe Heading output field and the Switch's arm — it's still one Switch and one Expand on the canvas.\n\n**One thing the canvas won't do:** read *two different cases'* fields into a single output without\ngoing through the arms. If you try, that output field shows \"Fields read from different cases of one\nSwitch must go through the case arms and Output\" and saving is blocked until you rewire it — combining\nper-case values is exactly what the arms and **Result** are for. Every other output field keeps\nworking normally in the meantime.\n\n## Suggest rules (Early Access)\n\nFor an organization with this Early Access feature turned on, a **Suggest rules** button appears\nabove the mapping canvas. Describe what you want in plain language — \"map the product's name to the\ncard's title, and its price to the subtitle as a formatted string\" — and it reads the two Contracts\ninvolved, drafts a candidate mapping, and checks its own work against the same validation the canvas\nalready runs, retrying until it's valid or it gives up and says so.\n\n**Nothing is written until you say so.** The panel shows the proposed rules — never the saved\nAdapter — with **Accept** and **Dismiss**. Accept merges the proposal into the mapping you're\ncurrently editing; you still have to press **Save** afterward, exactly as if you'd drawn the\nconnections yourself. Dismiss discards the proposal with no trace. If you already have some of the\nmapping done, describe what's missing — it's told what's already there and builds on it rather than\nstarting over.\n\nIf it can't produce a valid mapping, it says so rather than proposing something broken. If your\norganization has connected its own AI provider credential (see the **AI** section of your\norganization's settings), suggestions run on that provider instead of ebitex's, and a provider-side\nproblem (an expired key, exhausted credit) is reported by name so you know where to look.\n\n## Editing a named Adapter later\n\nAdapters created via **Create Adapter**, or saved via **Save as Adapter…**, live on the **Adapters**\npage (Configure → Adapters), listed with their input and output Contracts. Editing one there updates\nevery Presentation using it — but only once each of those is **published again**. Content that's\nalready published keeps its existing shape until republished, so a mapping change never silently\nchanges something a visitor is looking at right now.\n\nIf a named Adapter is deleted while still bound to a Presentation, the field-by-field connections stop\nresolving correctly — a warning appears on the affected field, and saving is blocked until you either\nrestore the Adapter, pick a different one, or unbind it.\n"
|
|
24
|
+
"body": "# Bridging Contracts with Adapters\n\nWhen you bind a Component to a Template (see [Authoring a presentation](content-authoring.md)), the\nComponent's Contract normally has to be exactly what the Template needs, or a more specific kind of\nit. Sometimes the Component you want to use has a *different* Contract entirely — an **Adapter**\nbridges that gap by mapping the mismatched Contract's fields onto the ones the Template expects.\n\n## When the wizard offers one\n\nIn the Presentation wizard's **Select existing** tab, a Component whose Contract the Template\ndoesn't recognize at all lands in the **Needs an Adapter** group. Selecting one shows why it doesn't\nfit, and three buttons appear:\n\n- **Use existing Adapter** — pick an already-created Adapter that maps this Component's Contract onto\n something the Template accepts.\n- **Create Adapter** — build a new, reusable, named Adapter right there in the wizard, for this\n Contract pairing. It's saved to the **Adapters** page (under Configure) so anyone can reuse it\n later.\n- **Connect manually** — build a one-off mapping that's saved directly on this Presentation only,\n never listed on the Adapters page. Useful for a mapping you don't expect to need again. A **Save as\n Adapter…** action turns it into a named one later, without redoing the mapping.\n\nEither way, once a mapping is attached the field-by-field connections are drawn between the\nComponent's fields and the Template's, Complete becomes available, and the banner reads \"Mapped via\n*Adapter name*\" (or \"Mapped manually\" for a one-off).\n\nA Component that's already Compatible can still get an Adapter attached deliberately — useful when\nyou want to reshape its content on the way into this particular Template, even though it didn't\nstrictly need mapping.\n\n## After it's mapped\n\nOnce a mapping is attached, the set-value card offers a few more actions beside the Adapter's name:\n\n- **Edit mapping** — reopens the same field-by-field canvas, already filled in with the current\n mapping, so you can adjust it without starting over. This never changes *which* Component is\n bound, and editing a named Adapter's mapping this way never touches the shared Adapter itself (so\n every other Presentation using it is unaffected) — it becomes this Presentation's own one-off\n mapping instead, which you can turn back into a named Adapter with **Save as Adapter…** if you\n want to reuse it elsewhere.\n- **Change** — picks a different Component for this Presentation entirely. If the new Component's\n Contract still works with the mapping that was already in place, it's kept automatically; if not,\n it's dropped and the reason is explained right there, so you can map fresh.\n- **Save as Adapter…** — only shown for a one-off (\"manual mapping\") — turns it into a named,\n reusable Adapter without redoing any of the mapping work.\n\n## The four rule kinds, in plain language\n\nEvery field the Template needs gets exactly one rule saying where its value comes from:\n\n- **Copy** — take the value straight from one of the Component's own fields (the field types have to\n be compatible — see below).\n- **Compute** — build the value from a small set of building blocks: one of the Component's fields, a\n fixed piece of text, joining a few things together with an optional separator, falling back\n through a list of options until one isn't empty, converting a value from one field type to a\n compatible one (e.g. plain text into rich text), taking just the first item of a list, reading a\n field out of a referenced/nested item, mapping every item of a list, dispatching on which kind of\n item you have, or a simple condition/comparison — see **Logic and structure blocks** below for all\n of these. There's no free-text formula box — you build the computation visually, block by block, on\n the canvas.\n- **Map inner content** — for a field that holds another whole piece of content inside it (a nested\n or embedded Component), apply a second, smaller Adapter to that inner content: pick an existing\n named Adapter, or **Connect manually** to name that inner content's own two Contracts and map them\n right there, the same way you'd map the outer fields. (This is also available as the **For each\n item** block's own \"Adapt to another Contract\" mode — see below — which is the way to reach it when\n you're adding a fresh block rather than mapping a whole field.)\n- **Look up a fixed item** — instead of taking a value from the Component being mapped, always pull it\n from one specific, chosen Component or item.\n\n## Field compatibility\n\nTwo fields need to either already match, or be *coercible*, to connect — you can't map a text field\nstraight onto a number field, for example, but a few kinds of mismatch have a small conversion block\nthe canvas offers to insert for you automatically:\n\n- A single value can feed a field that accepts multiple values (it becomes a one-item list) — no\n extra block needed.\n- A field that accepts multiple values can feed a single-value field by inserting a **Take first\n item** block, which uses the first value and drops the rest.\n- Some field types can be converted into others by inserting a **Convert** block — plain text into\n rich text, plain text into a number (fails at delivery time if the text isn't actually numeric), a\n number into text, or rich text into plain text (its formatting is discarded).\n- A field that isn't translatable can feed a translatable one (it becomes that language's default,\n with no translations yet).\n- A field restricted to certain kinds of related content requires the source to already be\n restricted to the same (or a more specific) set.\n\nWhen you connect two fields that need one of these conversions, a small prompt appears offering to\ninsert the right block between them — accept it and the connection completes with that block already\nwired in place. Everything else — a translatable field into a non-translatable one, a personalizable\nfield into a non-personalizable one (or vice versa), or two field types with no registered\nconversion at all — isn't allowed, and the canvas explains why right there instead of drawing a\nconnection (incompatible fields are also visibly dimmed while you have a source selected).\n\n## What \"unmapped — delivers null\" means\n\nEvery field the Template *requires* needs a rule — the canvas won't let you save until they all do.\nA field that's merely optional can be left unmapped; the card for it reads **unmapped — delivers\nnull**, meaning a person or system reading this content afterward will see that field as empty,\nexactly as if it had no value at all. This is often exactly what you want for a field the source\nContract has no equivalent of.\n\n## The mapping canvas\n\nWhether you're on the standalone **Adapters** page (Configure → Adapters → New Adapter) or inside the\nwizard, mapping works the same way: every building block you add is its own node on one draggable,\nzoomable canvas — the **Input document** card starts on the left, the Template's (or the other\nContract's) fields on the right. Drag a line from one connector to another to connect them, or click a\nname to select it as the starting point and then click the one it should feed — both do exactly\nthe same thing, so use whichever is easier at the time. Click an existing connection, or the field's own\ndelete button, to remove it. `Escape` cancels a pending click-to-connect selection.\n\nThe **Input document** card is everything you're mapping *from*, in one place. It's always there, and\nit has three parts:\n\n- **Fields** — one connector per field of the Contract you're mapping from. This is the everyday\n one: drag a field straight across to the output it should fill.\n- **Input document** — the whole piece of content, as one thing. Use this when the same Adapter runs\n over several *different* kinds of content (a search result over every kind of page, say) and you\n need to branch on which kind each one actually is — connect it to a **Switch on Contract** block.\n- **System** — facts about the run itself rather than about the content: **Source contract external\n id** and **Source contract id**, which tell a consumer *which kind* of content a result came from.\n\nThe **+ Add node** button opens a menu of building blocks in four groups: **Combine and convert** (**Join text**,\n**First non-null**, **Constant value**, **Convert type**), **Pull in related content** (**Look up in**, **Expand\nfields**, **Expand Linked Experience**, **Build value**), **Work with lists** (**For each item**, **Take first item**)\nand **Decide** (**If / else**, **Switch on Contract**, **Equals**, **Exists**). Type in the search box to filter,\nuse the arrow keys to move, and press Escape to close it. The logic and structure blocks are covered in **Logic and\nstructure blocks** below. Drag or click to\nwire fields into and out of it just like any other node; each block has its own small settings right on\nthe node itself (which characters to join with, what to convert into, and so on). Delete a block with\nthe **✕** in its own corner.\n\nA required field the Template needs that's still unconnected is called out in red at the bottom of the\ncanvas, and saving stays disabled until every one of them has a rule.\n\nWhen something stops the mapping from being saved, a panel above the canvas counts the issues and warnings and lists\neach one with the field it is about. **Show** selects that field on the canvas and brings it into view.\n\nA **Full screen** button, above the canvas, expands it to fill the whole screen for a more complex\nmapping that needs more room to work in — nothing about the mapping is lost switching in or out, and\n`Escape` exits back to the normal view.\n\nA **Preview** button lets you pick a sample piece of content of the source Contract and see exactly\nwhat the mapped result looks like, using the real mapping engine — no guessing.\n\nThe canvas remembers however you arrange the nodes — drag them into a layout that makes sense to\nyou, save, and it's still that way next time you (or anyone else) open this mapping, whether it's a\nnamed Adapter or a one-off mapping on a single Presentation. Dragging snaps each node to a light\ngrid so things line up cleanly. A node you add but never connect to anything doesn't have its\nposition remembered, since it isn't part of the saved mapping at all yet.\n\n## Logic and structure blocks\n\n**Lists always go through a \"For each item\" block.** None of the other blocks below — Expand fields,\nSwitch on Contract, If/else, Equals, Exists — ever work directly on a list; each expects one item.\nWhen the field you're reading from holds a list, add a **For each item** block first: it's the one\nblock that turns a list into \"one item at a time\" and back into a list again. Everything else you\nconnect after it (an Expand, a Switch, a comparison, whatever the mapping needs for one item) runs\nonce per item automatically.\n\n- **Expand fields** — reads a field out of something that isn't a plain value: a referenced item, a\n nested piece of content, or a component field. Pick which Contract you're expecting (skipped\n automatically when there's only one possibility), and the block grows one output for each of that\n Contract's own fields — connect whichever ones you need onward, just like any other field.\n- **Expand Linked Experience** — for a link field that points at a page in your Experience tree:\n opens the linked page in one step. Its outputs are the page's **Name**, **URL**, **Component** (the\n content it's built from — pick a Contract under \"Read content as…\" to get that content's own fields\n as further outputs) and **Presentation** — the page's own rendering, exactly as it's configured\n (its Template, its content, its settings). Connect **Presentation** to a Presentation-typed output\n to show that page's presentation inline on yours — a \"featured pages\" section that re-hosts each\n page's real rendering rather than rebuilding a card from its fields. An outside link, or a page\n with no presentation of its own, gives nothing here; inside a **For each item**, pair it with\n **Keep item when** (below) to drop those. If the output field only allows certain Templates, a\n relayed presentation built on a different Template comes out empty (with a warning) rather than\n slipping through — widen the field's allowed Templates if that's not what you want.\n- **Build value** — the opposite of Expand fields: assembles a nested piece of content, or a component\n field's inline value, out of other fields in this mapping. Pick which Contract you're building, and\n the block grows one input for each of that Contract's own fields (fields with no separate override —\n the \"context\" ones you'd only ever fill in on a specific usage — never appear here at all). Fields\n marked **Required** need a connection before the mapping can be saved; anything else is optional and\n comes out empty if you leave it unconnected. Pick **Nested** or **Component** to match whatever field\n you're feeding the result into.\n- **For each item** — the only block that crosses a list boundary, as above. Choose one of two modes:\n - **Map each item** — click **Edit mapping** to open a dedicated screen (it takes over the whole\n canvas, with a **Back** button to return) where you build the per-item transformation using an\n **Item** starting point and a **Result** ending point, with any of the other blocks in between —\n including another **For each item**, for a list inside a list. That screen also has a second\n ending point, **Keep item when**: wire a yes/no value into it (an Exists or Equals block,\n usually) and only the items where it comes out *yes* make it into the list — the rest are left\n out entirely, with no empty placeholder and no warning for them. Leave it unconnected to keep\n every item. The typical use is a list of links that mixes pages with outside links: **Expand\n Linked Experience → Component → Exists → Keep item when** drops everything that isn't a real\n page, instead of shipping an empty card for it. One output can feed several blocks at once, so\n the same Expand can supply both the check and the result.\n - **Adapt to another Contract** — apply a whole second, smaller Adapter to each item, exactly like\n **Map inner content** above (pick an existing named Adapter, or **Connect manually**).\n- **Switch on Contract** — for a field that could hold more than one kind of thing (several different\n Contracts), branch the mapping by which one it actually is. Add a case for each Contract you want to\n handle by name; each case gets its own **As *(Contract name)*** output (typically feeding an Expand\n fields block for that specific Contract) and its own **Value for this case** input for what should\n come out when it matches. An optional **Default** input covers any Contract you didn't add a case\n for. See **Reading one page type's fields into several outputs**, below, for the two ways to wire\n it up.\n- **If / else** — picks between two values based on a yes/no condition: wire something into **When**\n (must resolve to yes/no — an Exists or Equals block is the usual source), and one value each into\n **Then** and **Else**.\n- **Equals** — compares two values and outputs yes/no; both sides need to already be the same field\n type (no automatic conversion here — insert a Convert type block first if they aren't).\n- **Exists** — outputs yes unless the value it's checking is completely missing or an empty piece of\n text; useful as the condition for an If/else block (\"only use this if there's actually something\n there\").\n\n## Reading one page type's fields into several outputs\n\nA common shape: the same Adapter runs over several kinds of content, and one of those kinds has a\nhandful of extra fields you want to carry through. A search result over every kind of page, where a\nblog post additionally has a heading, an author, a publish date, an image, topics and an excerpt, is\nthe worked example.\n\nWire it exactly the way you'd draw it:\n\n1. **Input document → Switch on Contract** (its **Value to switch on** connector). Add one case,\n *Blog post*.\n2. **As Blog post → Expand fields.** The Expand grows one output per field a blog post has.\n3. Connect each of those outputs **straight across to the output field it fills** — heading to\n Heading, author to Author, and so on. You do not wire anything back into the Switch.\n\nThat's it. Behind the scenes each of those outputs becomes its own rule, gated on \"only when this\nreally is a blog post\"; anything that isn't a blog post simply leaves those fields empty, which is\nwhat you want. Reopening the Adapter later shows you the same one Switch and one Expand you drew.\n\n**Fields every kind of content has come off the Input document, not through the Switch.** Title and\nDescription exist on every page, so wire them straight from the Input document's **Fields** section.\nRouting them through a case would gain nothing and would leave them empty for anything the Switch\ndoesn't have a case for.\n\n**When one output needs a *different* value per type**, that's the Switch's own arms — \"Title is the\nblog post's heading if it's a blog post, otherwise the page's own title\":\n\n1. **Expand fields → heading → Value for this case** (the *Blog post* arm).\n2. **Input document → Fields → Title → Default.**\n3. **Switch → Result → Title.**\n\nOne connector can feed several places at once, so the same Expand's *heading* output can go to both\nthe Heading output field and the Switch's arm — it's still one Switch and one Expand on the canvas.\n\n**One thing the canvas won't do:** read *two different cases'* fields into a single output without\ngoing through the arms. If you try, that output field shows \"Fields read from different cases of one\nSwitch must go through the case arms and Output\" and saving is blocked until you rewire it — combining\nper-case values is exactly what the arms and **Result** are for. Every other output field keeps\nworking normally in the meantime.\n\n## Suggest rules (Early Access)\n\nFor an organization with this Early Access feature turned on, a **Suggest rules** button appears\nabove the mapping canvas. Describe what you want in plain language — \"map the product's name to the\ncard's title, and its price to the subtitle as a formatted string\" — and it reads the two Contracts\ninvolved, drafts a candidate mapping, and checks its own work against the same validation the canvas\nalready runs, retrying until it's valid or it gives up and says so.\n\n**Nothing is written until you say so.** The panel shows the proposed rules — never the saved\nAdapter — with **Accept** and **Dismiss**. Accept merges the proposal into the mapping you're\ncurrently editing; you still have to press **Save** afterward, exactly as if you'd drawn the\nconnections yourself. Dismiss discards the proposal with no trace. If you already have some of the\nmapping done, describe what's missing — it's told what's already there and builds on it rather than\nstarting over.\n\nIf it can't produce a valid mapping, it says so rather than proposing something broken. If your\norganization has connected its own AI provider credential (see the **AI** section of your\norganization's settings), suggestions run on that provider instead of ebitex's, and a provider-side\nproblem (an expired key, exhausted credit) is reported by name so you know where to look.\n\n## Editing a named Adapter later\n\nAdapters created via **Create Adapter**, or saved via **Save as Adapter…**, live on the **Adapters**\npage (Configure → Adapters), listed with their input and output Contracts. Editing one there updates\nevery Presentation using it — but only once each of those is **published again**. Content that's\nalready published keeps its existing shape until republished, so a mapping change never silently\nchanges something a visitor is looking at right now.\n\nIf a named Adapter is deleted while still bound to a Presentation, the field-by-field connections stop\nresolving correctly — a warning appears on the affected field, and saving is blocked until you either\nrestore the Adapter, pick a different one, or unbind it.\n"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"slug": "content-authoring",
|
|
@@ -61,7 +61,7 @@ export const HELP_TOPICS = [
|
|
|
61
61
|
{
|
|
62
62
|
"slug": "content-taxonomy",
|
|
63
63
|
"title": "Taxonomy",
|
|
64
|
-
"body": "# Taxonomy\n\nOrganize your content with named classification trees — usable both as tags on Components,\nExperience pages, and Contracts (for findability and bulk operations) and as a field type your\nContracts can use directly.\n\n## Where the vocabulary lives\n\nThe category groups and categories themselves — the **vocabulary** — belong to your organization, not\nto Content alone: the same \"Topics\" or \"Regions\" that classify a Component can classify an asset in\nAssets. They are managed in **Hub › Taxonomy** (see the Hub guide), where each group shows where it is\nin use.\n\nContent's own **Taxonomy** page, under **Configure**, answers a different question: **which of the\norganization's groups can editors use in this environment?** A group is only visible here once it has\nbeen added, and other environments — including a sub-tenant's — never see a group nobody added to\nthem. The page has two lists:\n\n- **In this environment** — the groups editors can tag with and pick in Category fields here, with\n how many categories each has and whether it carries a metadata Contract here. **Remove from this\n environment** hides a group from pickers again; it is disabled, with the reason, while anything\n here is still tagged with one of its categories, a Category field value still names one, or a\n Category field on a Contract restricts to the group. Removing never deletes the group, its\n categories, or anything already tagged.\n- **Available to add** — the organization's groups not yet in use here. **Add to this environment**\n makes one usable; optionally give it a metadata document here at the same time (below).\n\nAdding and removing needs the **Manage Content taxonomy** permission (`content.taxonomy.manage`).\n**New group** creates a group in the organization vocabulary *and* adds it here in one step; because\nit writes the vocabulary it also needs `platform.taxonomy.manage`.\n\n### Editing the tree from Content\n\nBelow the two lists, the page shows the vocabulary for every group added here — the same tree editor\nHub uses. If you hold `platform.taxonomy.manage` you can add, rename, move and delete categories right\nthere; a change applies in every environment and app at once. Without it the tree is read-only, and\neach button says so.\n\n### Missing a group?\n\nIf the group you expect is not in the category picker, it has not been added to this environment.\nSomeone with `content.taxonomy.manage` sees a **Manage groups in this environment** link at the\nbottom of the picker that goes straight to the Taxonomy page; everyone else simply does not see the\ngroup, which is the point.\n\n## CategoryGroups and Categories\n\nA **CategoryGroup** is the root of one tree — \"Topics,\" \"Regions,\" \"Campaigns.\"\n\nA **Category** is one node in a group's tree. Each category has:\n\n- A **key** (used in paths and safe to keep even if you change the display value)\n- A **display value** — localizable, like any other text in the app\n- **Selectable** — turned off, a category becomes a purely structural branch: something you can\n nest other categories under, but never assign to content directly. Use this for organizing\n headings like \"Seating\" that shouldn't themselves be a tag.\n\nA category can be nested under another category in the same group, to any depth. You can't delete\na category (or turn off its Selectable flag) while anything in any app still references it — the\ndialog lists every usage, per app and environment, so you can decouple them first.\n\n### Metadata\n\nWhen adding a group to an environment (or creating one from Content), you can optionally attach a\n**metadata Contract** — the same kind of structure definition you use for content, but describing\nextra information every category in this group should carry *in this environment* (an icon name, a\ncolor, a short blurb). If a group has a metadata Contract here, every category in it gets a\n**Metadata** editor in the tree. Metadata is Content's and per environment: the organization's\nvocabulary carries none, and removing the group from an environment removes its metadata Contract and\ndocuments there.\n\n## Tagging content\n\nOpen any Component (under its **Settings** tab), Experience page, or Contract (under its\n**General** tab) and find the **Categories** panel. **Add tag…** opens a picker scoped to one\ngroup at a time (or a specific group, if the page only allows one); pick any selectable category\nand it's added. Only groups added to the current environment are offered. Tags are separate from\nany Category field value the item's Contract might also have — think of tags as sticky notes for\nfinding and grouping things, not part of the content itself. Tagging a Contract needs the same\npermission that lets you edit the Contract at all; Templates can't be tagged yet.\n\n## Filtering by category\n\nThe Component library has a **Filter by category** control — pick a category and the list narrows\nto everything tagged with it (or a category nested under it). Select several items from a filtered\nlist and use **Publish N selected…** to publish them all together through the usual publish dialog,\nwhich shows the combined set of everything each selected item depends on.\n\nThe Experience page has the same **Filter by category** control on its site tree. Because the tree\nonly loads a branch's children when you expand it, picking a category automatically expands every\nancestor branch needed to reach each matching page, highlights the matches, and dims everything\nelse that's visible without hiding it — so you can still see where a match sits relative to the\nrest of the site. Clearing the filter leaves the tree as you left it.\n\n## Filtering which Contract you pick\n\nWhen adding new content from an Experience page's payload editor — \"New Component\" or \"Create\ninline\" — the Contract picker offers a **Filter by category** button. Pick a category and the\nchoices narrow to Contracts tagged with it; **Clear** brings back the full list. This is a\nconvenience for a large Contract library — it defaults to showing every eligible Contract, and you\ncan always clear the filter to reach one that isn't tagged.\n\n## Using a Category field on a Contract\n\nWhen building a Contract, add a field with type **Category**. In its settings, you can restrict\nwhich CategoryGroup(s) the field accepts — leave it empty to allow any group. In the Component\neditor, that field shows a **Choose…** button opening the same category picker; the chosen\ncategory displays as its full path (e.g. `topics/tech/ai`).\n\n## What happens when you rename or move a category\n\nRenaming a category, or moving it to a different parent, updates everywhere it's referenced\nimmediately — in every environment and app, no republishing needed. What *does* require\nrepublishing is a **tag added after publish**: a Component's set of published categories is frozen\nat publish time, exactly like its content. If you tag something new and want that reflected in\ndelivered results, publish it again.\n\n## Promotion and inheritance\n\nThe vocabulary exists in every environment already, so promoting tagged content never copies\ncategories. What rides along is the **group's presence**: promoting something tagged with a group\nnot yet added to the target adds it there (with its metadata Contract, if any), so the tags still\nvalidate. Environment inheritance works the same way — a child environment inherits which groups its\nparent has added, and their metadata, as read-only.\n\n## External taxonomy\n\nIf your organization has registered a content provider that also supplies taxonomy, its groups and\ncategories appear in the picker and the Taxonomy page alongside your own — marked **synced** and\nread-only. They belong to the environment the provider is registered in rather than to the\norganization vocabulary, and work identically to your own categories everywhere except editing:\nyou can tag content with them and use them in Category fields, but changing them happens on the\nprovider's own side, refreshed the same way its other content is.\n"
|
|
64
|
+
"body": "# Taxonomy\n\nOrganize your content with named classification trees — usable both as tags on Components,\nExperience pages, and Contracts (for findability and bulk operations) and as a field type your\nContracts can use directly.\n\n## Where the vocabulary lives\n\nThe category groups and categories themselves — the **vocabulary** — belong to your organization, not\nto Content alone: the same \"Topics\" or \"Regions\" that classify a Component can classify an asset in\nAssets. They are managed in **Hub › Taxonomy** (see the Hub guide), where each group shows where it is\nin use.\n\nContent's own **Taxonomy** page, under **Configure**, answers a different question: **which of the\norganization's groups can editors use in this environment?** A group is only visible here once it has\nbeen added, and other environments — including a sub-tenant's — never see a group nobody added to\nthem. The page has two lists:\n\n- **In this environment** — the groups editors can tag with and pick in Category fields here, with\n how many categories each has and whether it carries a metadata Contract here. **Remove from this\n environment** hides a group from pickers again; it is disabled, with the reason, while anything\n here is still tagged with one of its categories, a Category field value still names one, or a\n Category field on a Contract restricts to the group. Removing never deletes the group, its\n categories, or anything already tagged.\n- **Available to add** — the organization's groups not yet in use here. **Add to this environment**\n makes one usable; optionally give it a metadata document here at the same time (below).\n\nWith nothing added yet, the page shows one message with **Choose groups to add** and **New group**; the longer\nexplanation of how categories are shared is behind **How categories work** under the title.\n\nAdding and removing needs the **Manage Content taxonomy** permission (`content.taxonomy.manage`).\n**New group** creates a group in the organization vocabulary *and* adds it here in one step; because\nit writes the vocabulary it also needs `platform.taxonomy.manage`.\n\n### Editing the tree from Content\n\nBelow the two lists, the page shows the vocabulary for every group added here — the same tree editor\nHub uses. If you hold `platform.taxonomy.manage` you can add, rename, move and delete categories right\nthere; a change applies in every environment and app at once. Without it the tree is read-only, and\neach button says so.\n\n### Missing a group?\n\nIf the group you expect is not in the category picker, it has not been added to this environment.\nSomeone with `content.taxonomy.manage` sees a **Manage groups in this environment** link at the\nbottom of the picker that goes straight to the Taxonomy page; everyone else simply does not see the\ngroup, which is the point.\n\n## CategoryGroups and Categories\n\nA **CategoryGroup** is the root of one tree — \"Topics,\" \"Regions,\" \"Campaigns.\"\n\nA **Category** is one node in a group's tree. Each category has:\n\n- A **key** (used in paths and safe to keep even if you change the display value)\n- A **display value** — localizable, like any other text in the app\n- **Selectable** — turned off, a category becomes a purely structural branch: something you can\n nest other categories under, but never assign to content directly. Use this for organizing\n headings like \"Seating\" that shouldn't themselves be a tag.\n\nA category can be nested under another category in the same group, to any depth. You can't delete\na category (or turn off its Selectable flag) while anything in any app still references it — the\ndialog lists every usage, per app and environment, so you can decouple them first.\n\n### Metadata\n\nWhen adding a group to an environment (or creating one from Content), you can optionally attach a\n**metadata Contract** — the same kind of structure definition you use for content, but describing\nextra information every category in this group should carry *in this environment* (an icon name, a\ncolor, a short blurb). If a group has a metadata Contract here, every category in it gets a\n**Metadata** editor in the tree. Metadata is Content's and per environment: the organization's\nvocabulary carries none, and removing the group from an environment removes its metadata Contract and\ndocuments there.\n\n## Tagging content\n\nOpen any Component (under its **Settings** tab), Experience page, or Contract (under its\n**General** tab) and find the **Categories** panel. **Add tag…** opens a picker scoped to one\ngroup at a time (or a specific group, if the page only allows one); pick any selectable category\nand it's added. Only groups added to the current environment are offered. Tags are separate from\nany Category field value the item's Contract might also have — think of tags as sticky notes for\nfinding and grouping things, not part of the content itself. Tagging a Contract needs the same\npermission that lets you edit the Contract at all; Templates can't be tagged yet.\n\n## Filtering by category\n\nThe Component library has a **Filter by category** control — pick a category and the list narrows\nto everything tagged with it (or a category nested under it). Select several items from a filtered\nlist and use **Publish N selected…** to publish them all together through the usual publish dialog,\nwhich shows the combined set of everything each selected item depends on.\n\nThe Experience page has the same **Filter by category** control on its site tree. Because the tree\nonly loads a branch's children when you expand it, picking a category automatically expands every\nancestor branch needed to reach each matching page, highlights the matches, and dims everything\nelse that's visible without hiding it — so you can still see where a match sits relative to the\nrest of the site. Clearing the filter leaves the tree as you left it.\n\n## Filtering which Contract you pick\n\nWhen adding new content from an Experience page's payload editor — \"New Component\" or \"Create\ninline\" — the Contract picker offers a **Filter by category** button. Pick a category and the\nchoices narrow to Contracts tagged with it; **Clear** brings back the full list. This is a\nconvenience for a large Contract library — it defaults to showing every eligible Contract, and you\ncan always clear the filter to reach one that isn't tagged.\n\n## Using a Category field on a Contract\n\nWhen building a Contract, add a field with type **Category**. In its settings, you can restrict\nwhich CategoryGroup(s) the field accepts — leave it empty to allow any group. In the Component\neditor, that field shows a **Choose…** button opening the same category picker; the chosen\ncategory displays as its full path (e.g. `topics/tech/ai`).\n\n## What happens when you rename or move a category\n\nRenaming a category, or moving it to a different parent, updates everywhere it's referenced\nimmediately — in every environment and app, no republishing needed. What *does* require\nrepublishing is a **tag added after publish**: a Component's set of published categories is frozen\nat publish time, exactly like its content. If you tag something new and want that reflected in\ndelivered results, publish it again.\n\n## Promotion and inheritance\n\nThe vocabulary exists in every environment already, so promoting tagged content never copies\ncategories. What rides along is the **group's presence**: promoting something tagged with a group\nnot yet added to the target adds it there (with its metadata Contract, if any), so the tags still\nvalidate. Environment inheritance works the same way — a child environment inherits which groups its\nparent has added, and their metadata, as read-only.\n\n## External taxonomy\n\nIf your organization has registered a content provider that also supplies taxonomy, its groups and\ncategories appear in the picker and the Taxonomy page alongside your own — marked **synced** and\nread-only. They belong to the environment the provider is registered in rather than to the\norganization vocabulary, and work identically to your own categories everywhere except editing:\nyou can tag content with them and use them in Category fields, but changing them happens on the\nprovider's own side, refreshed the same way its other content is.\n"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"slug": "content-workflow",
|
|
@@ -121,7 +121,7 @@ export const HELP_TOPICS = [
|
|
|
121
121
|
{
|
|
122
122
|
"slug": "templates",
|
|
123
123
|
"title": "Presenting content with Templates",
|
|
124
|
-
"body": "# Presenting content with Templates\n\nA Template defines how a piece of content gets shown — for example\n\"Hero banner\" or \"Card grid\" — and which kinds of Component it can present.\nA Presentation is a specific use of a Template: pick a Template, bind it\nto a Component, and optionally fine-tune it with per-placement settings\nand overrides. Templates are the presentation half of the system;\nContracts and Components (see [Modeling content with Contracts](contracts.md)\nand [Authoring Components](components.md)) are the content half — they\nstay deliberately separate, so the same piece of content can be presented\ndifferent ways in different places.\n\n## Creating a Template\n\n1. From the Templates list, select **New Template
|
|
124
|
+
"body": "# Presenting content with Templates\n\nA Template defines how a piece of content gets shown — for example\n\"Hero banner\" or \"Card grid\" — and which kinds of Component it can present.\nA Presentation is a specific use of a Template: pick a Template, bind it\nto a Component, and optionally fine-tune it with per-placement settings\nand overrides. Templates are the presentation half of the system;\nContracts and Components (see [Modeling content with Contracts](contracts.md)\nand [Authoring Components](components.md)) are the content half — they\nstay deliberately separate, so the same piece of content can be presented\ndifferent ways in different places.\n\n## Creating a Template\n\n1. From the Templates list, select **New Template**. A Template has two tabs, **Details** and **Settings**, and\n an existing Template has the same two (plus **Where used** and **History**).\n2. On **Details**, enter a **Name**. The **Id** fills in from it automatically.\n3. Still on **Details**, choose the **Supported Contracts**: the Contracts whose Components this Template can\n present. Select **Add a Contract** and pick from the searchable list. Leave it empty and a Component of any\n Contract can use the Template; constraining it to one Contract (often an abstract one, so several kinds of\n content can share the same Template) is the common case.\n4. On **Settings**, optionally give the Template settings. The settings are a Contract: the fields an editor can\n fill in each time they use this Template, such as a Theme or Padding. A Template with no settings is completely\n normal, and you can add them later. You have two choices:\n - **Define settings for this Template** creates a new Contract that only this Template uses. Add fields the\n same way you would on a Contract (see \"Field types and modifiers\" in\n [Modeling content with Contracts](contracts.md)): the same field types and modifiers, the same generated\n settings form, except a new settings field starts **Contextual** by default (a Template field is almost\n always meant as a per-usage override); you can still switch it off for a field that should live on the\n Component itself. Nothing is added for you: choose **Add a field**, and a row you add but leave empty is\n ignored when you create the Template.\n - **Use an existing Contract** lets you pick an ordinary Contract from your library instead, useful when you\n want two or more Templates to share the same settings shape. A change to that Contract shows on every\n Template that uses it.\n5. Review the change list in the bar at the foot of the page and select\n **Save**. The bar says whether the change is additive or breaking. An\n additive change saves at once; a breaking one asks you to confirm\n first. **Discard** drops your edits, and leaving the page with unsaved\n changes asks before you lose them.\n\n## A Template's settings Contract is an ordinary Contract\n\nA Template's settings fields live on a real Contract, listed in your\nContract library alongside every other Contract — there's nothing hidden\nabout it. Once a Template is saved, its **Settings** tab shows the **Settings Contract** with its name and field\ncount and two actions:\n\n- **Edit Contract** opens its fields in a small side panel without leaving the Template: add, remove, reorder, or\n reconfigure fields, then Save. If the same Contract is used by other Templates too, they all see the change.\n- **Change Contract** points this Template at a different existing Contract\n instead. The Template's Save button still needs to be clicked to commit\n the change — until then it's just a pending pick.\n\nYou can also open and edit a settings Contract directly from the Contract\nlibrary like any other Contract.\n\n## Using a Template on a Component\n\nA Contract field can be given the **Presentation** field type, letting a\nComponent instantiate a Template inline — the common pattern for a page's\nbody is an *enumerable* Presentation field, so the page becomes a list of\npresented sections.\n\nWhen you reach a Presentation field while editing a Component, select\n**+ Add presentation** to open a wizard that walks you through picking a\nTemplate and binding a Component to it — including a preview of whether a\ncandidate Component actually fits before you commit. See\n[Authoring a presentation](content-authoring.md) for the full walkthrough,\nincluding what \"Compatible\" vs. \"Needs an Adapter\" mean and the Contextual\nvalues / Settings / Change / Remove controls on an already-bound field.\n\nIf the Template has been updated to a newer version since this Presentation\nwas created, a small notice appears — **Update to v_N_** moves it onto the\nnew version. Until you do, the existing Presentation keeps working exactly\nas before; a Template change never breaks something already in place.\n\n## Deleting a Template\n\nA Template can't be deleted while any Presentation still uses it, or while\na Presentation field's settings still name it as an allowed Template —\nyou'll see exactly what's blocking the delete so you can address it first.\nDeleting a Template does **not** delete its settings Contract — it stays in\nyour Contract library afterward (in case another Template uses it too, or\nyou want to reuse it later), and you can delete it separately from there if\nyou no longer need it. A Contract still assigned as some Template's\nsettings is itself blocked from deletion until you either delete that\nTemplate or change its settings Contract first.\n"
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"slug": "translation-jobs",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"helpCorpus.generated.js","sourceRoot":"","sources":["../../src/resources/helpCorpus.generated.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AAIpG,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,knWAAknW;KAC3nW;IACD;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,wnGAAwnG;KACjoG;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,ouqBAAouqB;KAC7uqB;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kCAAkC;QAC3C,MAAM,EAAE,06nBAA06nB;KACn7nB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,0BAA0B;QACnC,MAAM,EAAE,6oLAA6oL;KACtpL;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,gCAAgC;QACzC,MAAM,EAAE,k5pBAAk5pB;KAC35pB;IACD;QACE,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,k/qBAAk/qB;KAC3/qB;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,qCAAqC;QAC9C,MAAM,EAAE,q3FAAq3F;KAC93F;IACD;QACE,MAAM,EAAE,yBAAyB;QACjC,OAAO,EAAE,4BAA4B;QACrC,MAAM,EAAE,2jRAA2jR;KACpkR;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,ywKAAywK;KAClxK;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,4CAA4C;QACrD,MAAM,EAAE,22GAA22G;KACp3G;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,moQAAmoQ;KAC5oQ;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,+9XAA+9X;KACx+X;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,iCAAiC;QAC1C,MAAM,EAAE,+wkBAA+wkB;KACxxkB;IACD;QACE,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,+iFAA+iF;KACxjF;IACD;QACE,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,u/JAAu/J;KAChgK;IACD;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,y9FAAy9F;KACl+F;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,mBAAmB;QAC5B,MAAM,EAAE,upIAAupI;KAChqI;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,ugNAAugN;KAChhN;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,w/OAAw/O;KACjgP;IACD;QACE,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,oBAAoB;QAC7B,MAAM,EAAE,i4YAAi4Y;KAC14Y;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,+BAA+B;QACxC,MAAM,EAAE,g2EAAg2E;KACz2E;IACD;QACE,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,i7FAAi7F;KAC17F;IACD;QACE,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,mCAAmC;QAC5C,MAAM,EAAE,g8KAAg8K;KACz8K;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,yvJAAyvJ;KAClwJ;CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebitex/content-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.159",
|
|
4
4
|
"description": "An MCP server for ebitex Content: build and publish a content model from an AI agent.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://developers.ebitex.io/getting-started/content-as-code/",
|