@aglyn/aglyn 1.0.0-beta.200 → 1.0.0-beta.202

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.
Files changed (85) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/activity-presenter.d.ts +29 -3
  3. package/src/lib/app-utils/activity-presenter.js +32 -4
  4. package/src/lib/app-utils/activity-presenter.js.map +1 -1
  5. package/src/lib/app-utils/api-plugins.d.ts +20 -0
  6. package/src/lib/app-utils/api-plugins.js +9 -0
  7. package/src/lib/app-utils/api-plugins.js.map +1 -1
  8. package/src/lib/app-utils/artifact-list-keys.js +10 -0
  9. package/src/lib/app-utils/artifact-list-keys.js.map +1 -1
  10. package/src/lib/app-utils/card-payment-velocity.d.ts +57 -0
  11. package/src/lib/app-utils/card-payment-velocity.js +90 -0
  12. package/src/lib/app-utils/card-payment-velocity.js.map +1 -0
  13. package/src/lib/app-utils/crm-digest.d.ts +6 -0
  14. package/src/lib/app-utils/crm-digest.js +1 -0
  15. package/src/lib/app-utils/crm-digest.js.map +1 -1
  16. package/src/lib/app-utils/crm-task-reminders.d.ts +6 -0
  17. package/src/lib/app-utils/crm-task-reminders.js +1 -0
  18. package/src/lib/app-utils/crm-task-reminders.js.map +1 -1
  19. package/src/lib/app-utils/crm.d.ts +19 -0
  20. package/src/lib/app-utils/crm.js +27 -1
  21. package/src/lib/app-utils/crm.js.map +1 -1
  22. package/src/lib/app-utils/docs-help.generated.d.ts +4 -4
  23. package/src/lib/app-utils/docs-help.generated.js +12 -0
  24. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  25. package/src/lib/app-utils/docs-index.generated.js +85 -64
  26. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  27. package/src/lib/app-utils/email-state.d.ts +7 -3
  28. package/src/lib/app-utils/email-state.js +22 -6
  29. package/src/lib/app-utils/email-state.js.map +1 -1
  30. package/src/lib/app-utils/forms.d.ts +101 -9
  31. package/src/lib/app-utils/forms.js +137 -7
  32. package/src/lib/app-utils/forms.js.map +1 -1
  33. package/src/lib/app-utils/health-report.d.ts +3 -3
  34. package/src/lib/app-utils/health-report.js +9 -9
  35. package/src/lib/app-utils/health-report.js.map +1 -1
  36. package/src/lib/app-utils/host-naming.d.ts +12 -7
  37. package/src/lib/app-utils/host-naming.js +18 -3
  38. package/src/lib/app-utils/host-naming.js.map +1 -1
  39. package/src/lib/app-utils/lockdown.d.ts +19 -0
  40. package/src/lib/app-utils/lockdown.js +21 -0
  41. package/src/lib/app-utils/lockdown.js.map +1 -1
  42. package/src/lib/app-utils/marketplace-listing-visibility.js +5 -5
  43. package/src/lib/app-utils/marketplace-listing-visibility.js.map +1 -1
  44. package/src/lib/app-utils/media-embedded-fields.d.ts +40 -0
  45. package/src/lib/app-utils/media-embedded-fields.js +77 -0
  46. package/src/lib/app-utils/media-embedded-fields.js.map +1 -1
  47. package/src/lib/app-utils/media-metadata.d.ts +17 -1
  48. package/src/lib/app-utils/media-metadata.js +22 -2
  49. package/src/lib/app-utils/media-metadata.js.map +1 -1
  50. package/src/lib/app-utils/notifications.d.ts +35 -0
  51. package/src/lib/app-utils/notifications.js +57 -1
  52. package/src/lib/app-utils/notifications.js.map +1 -1
  53. package/src/lib/app-utils/payment-risk.d.ts +75 -0
  54. package/src/lib/app-utils/payment-risk.js +139 -0
  55. package/src/lib/app-utils/payment-risk.js.map +1 -0
  56. package/src/lib/app-utils/platform-brand.d.ts +8 -2
  57. package/src/lib/app-utils/platform-brand.js +9 -3
  58. package/src/lib/app-utils/platform-brand.js.map +1 -1
  59. package/src/lib/app-utils/plugin-api-request-host.d.ts +29 -0
  60. package/src/lib/app-utils/plugin-api-request-host.js +90 -0
  61. package/src/lib/app-utils/plugin-api-request-host.js.map +1 -0
  62. package/src/lib/app-utils/plugin-bundle-checks.d.ts +4 -2
  63. package/src/lib/app-utils/plugin-bundle-checks.js +111 -5
  64. package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
  65. package/src/lib/app-utils/site-return-url.d.ts +55 -0
  66. package/src/lib/app-utils/site-return-url.js +129 -0
  67. package/src/lib/app-utils/site-return-url.js.map +1 -0
  68. package/src/lib/app-utils/webhook-delivery.js +4 -1
  69. package/src/lib/app-utils/webhook-delivery.js.map +1 -1
  70. package/src/lib/plugin-manager/billing-webhook-hooks.d.ts +18 -0
  71. package/src/lib/plugin-manager/billing-webhook-hooks.js +9 -1
  72. package/src/lib/plugin-manager/billing-webhook-hooks.js.map +1 -1
  73. package/src/lib/plugin-manager/plugin-activity-actions.d.ts +9 -1
  74. package/src/lib/plugin-manager/plugin-activity-actions.js +11 -1
  75. package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
  76. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +8 -0
  77. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  78. package/src/lib/plugin-manager/plugin-events.d.ts +22 -0
  79. package/src/lib/plugin-manager/plugin-events.js.map +1 -1
  80. package/src/lib/plugin-manager/plugin-jobs.d.ts +8 -4
  81. package/src/lib/plugin-manager/plugin-jobs.js +8 -4
  82. package/src/lib/plugin-manager/plugin-jobs.js.map +1 -1
  83. package/src/lib/plugin-manager/plugin-recurring-charges.d.ts +39 -0
  84. package/src/lib/plugin-manager/plugin-recurring-charges.js +49 -0
  85. package/src/lib/plugin-manager/plugin-recurring-charges.js.map +1 -0
@@ -583,7 +583,7 @@ export const ASSIST_DOCS_INDEX = [
583
583
  title: 'Product copy and catalogs with AI',
584
584
  heading: 'Write copy for many products',
585
585
  anchor: '#write-copy-for-many-products',
586
- text: 'On the products page, Build your catalog with AI has Write copy for products. Pick up to 50 products and press Write copy. The copy is written one product at a time, and each row appears in the review table as it is ready.\n- Apply saves one product\'s copy. Apply to all saves every row still waiting.\n- Applying changes only the description, search listing, tags, categories and option names. A price, stock count or anything else changed since the table loaded is kept.\n- A product that was deleted, or whose copy could not be held to the rules below, is marked Skipped and the rest carry on.\n- If your AI credits run out partway, the job waits and carries on from the product where it stopped once credits are available.\nWhen you import products\nIn the Import products (CSV) dialog, tick Write descriptions, search listings and tags with AI as they land. Once the import has created your products, their copy is written as above and waits in the review table on the products page. Copy is written for the first 50 products of a larger import.'
586
+ text: 'On the products page, Build your catalog with AI has Write copy for products. Pick up to 50 products and press Write copy. The picker offers the page of products the products table is showing, so filter, search or page that table first to reach others. The copy is written one product at a time, and each row appears in the review table as it is ready.\n- Apply saves one product\'s copy. Apply to all saves every row still waiting.\n- Applying changes only the description, search listing, tags, categories and option names. A price, stock count or anything else changed since the table loaded is kept.\n- A product that was deleted, or whose copy could not be held to the rules below, is marked Skipped and the rest carry on.\n- If your AI credits run out partway, the job waits and carries on from the product where it stopped once credits are available.\nWhen you import products\nIn the Import products (CSV) dialog, tick Write descriptions, search listings and tags with AI as they land. Once the import has created your products, their copy is written as above and waits in the review table on the products page. Copy is written for the first 50 products of a larger import.'
587
587
  },
588
588
  {
589
589
  path: '/ai/products-with-ai',
@@ -1500,7 +1500,7 @@ export const ASSIST_DOCS_INDEX = [
1500
1500
  title: 'Reusable components',
1501
1501
  heading: 'Manage',
1502
1502
  anchor: '#manage',
1503
- text: 'From the site\'s Components page you can rename, edit the description, open the besigner, or delete a reusable component. The component\'s ID is persisted inside every screen that places it and never changes.\nYou can also give a component its own icon, from the same picker the besigner uses for icon elements — either in the Edit component dialog on the Components page, or on the component\'s detail page. Every instance is then marked with it: in the hierarchy, on the canvas badge, and in the element drawer under Your components. A page assembled from promoted sections becomes readable at a glance. Components without an icon keep the generic package glyph.\nFilters in the Components table\'s toolbar narrows the list by name (a word of it, or the whole name), Used in (page or email), ID, or the date it was last updated, and Search finds a component by the start of any word of its name. Every filter and the search word are part of the list\'s query, so they look through every component on the site, not only the page on screen. Each filter in force shows as a chip above the table. A combination that cannot be asked at once — a name "contains" filter beside a search, or a second date range — is left out, and the table says which one and why. See Filter and search a list.'
1503
+ text: 'From the site\'s Components page you can rename, edit the description, open the besigner, or delete a reusable component. The component\'s ID is persisted inside every screen that places it and never changes.\nYou can also give a component its own icon, from the same picker the besigner uses for icon elements — either in the Edit component dialog on the Components page, or on the component\'s detail page. Every instance is then marked with it: in the hierarchy, on the canvas badge, and in the element drawer under Your components. A page assembled from promoted sections becomes readable at a glance. Components without an icon keep the generic package glyph.\nFilters in the Components table\'s toolbar narrows the list by name (a word of it, or the whole name), Used in (page or email), ID, or the date it was last updated, and Search finds a component by the start of any word of its name. Every filter and the search word are part of the list\'s query, so they look through every component on the site, not only the page on screen. The table lists components by ID and its column headers do not re-sort it; an Updated filter lists the matches most recently updated first. Each filter in force shows as a chip above the table. A combination that cannot be asked at once — a name "contains" filter beside a search, or an ID "starts with" beside an Updated filter (one range at a time) — is left out, and the table says which one and why. See Filter and search a list.'
1504
1504
  },
1505
1505
  {
1506
1506
  path: '/building-sites/besigner/reusable-components',
@@ -2263,7 +2263,7 @@ export const ASSIST_DOCS_INDEX = [
2263
2263
  title: 'Layouts',
2264
2264
  heading: 'Find a layout',
2265
2265
  anchor: '#find-a-layout',
2266
- text: 'The site\'s Layouts page lists every layout. Filters in the table\'s toolbar narrows it by display name (a word of it, or the whole name), ID, or the date it was last updated, and Search finds a layout by the start of any word of its name. Every filter and the search word are part of the list\'s query, so they look through every layout on the site, not only the page on screen, and the pager turns through the matches. Each filter in force shows as a chip above the table; remove a chip to drop it. Some combinations cannot be asked at once — a name "contains" filter beside a search, or a second date range — and the table says which filter it left out and why rather than applying it to part of the list. See Filter and search a list.'
2266
+ text: 'The site\'s Layouts page lists every layout. Filters in the table\'s toolbar narrows it by display name (a word of it, or the whole name), ID, or the date it was last updated, and Search finds a layout by the start of any word of its name. Every filter and the search word are part of the list\'s query, so they look through every layout on the site, not only the page on screen, and the pager turns through the matches. The table lists layouts by ID and its column headers do not re-sort it; an Updated filter lists the matches most recently updated first. Each filter in force shows as a chip above the table; remove a chip to drop it. Some combinations cannot be asked at once — a name "contains" filter beside a search, or an ID "starts with" beside an Updated filter (one range at a time) — and the table says which filter it left out and why rather than applying it to part of the list. See Filter and search a list.'
2267
2267
  },
2268
2268
  {
2269
2269
  path: '/building-sites/screens-and-layouts/layouts',
@@ -2774,7 +2774,7 @@ export const ASSIST_DOCS_INDEX = [
2774
2774
  title: 'Build a blog',
2775
2775
  heading: '2. Write entries',
2776
2776
  anchor: '#2-write-entries',
2777
- text: 'Add rich blog entries with images, a live preview, and scheduling so posts publish at the right time.\nNew entry, or clicking any row in the entries table, opens that entry on its own page. The page has its own address, so you can bookmark an entry you\'re mid-way through or paste the link to a colleague and they land on the same one. Back to entries — or your browser\'s Back button — returns to the list; if the entry has edits you haven\'t saved, you\'re asked before they\'re dropped.\nThe table opens with the most recently Published entries first. A scheduled entry sorts by the date it\'s due to go out, so the next posts in your queue open the list, and when you reverse the column they come last among the dated entries. Click the Title, Status, Updated or Published header to sort by that column, and again to reverse it. Entries with nothing in the sorted column, such as a draft with no published date, follow the rest in either direction rather than dropping out. Filters in the table\'s toolbar narrows the list by Title (a word of it), Status, Category, Author, or the Published or Updated date, and Search finds an entry by the start of any word of its title. Every filter and the search word are part of the list\'s query, so they look through the whole collection, not only the page you\'re on, and each filter in force shows as a chip above the table. While the list is filtered or searched it sorts by Published or Updated, and a date filter sorts by the date it filters; a note above the table says when the order moved. A combination that cannot be asked at once — a Title filter beside a search, or two date ranges — is left out, and the table says which one and why. See Filter and search a list.\nEach entry carries, besides the title, excerpt, cover image, and markdown body:\n- Catego'
2777
+ text: 'Add rich blog entries with images, a live preview, and scheduling so posts publish at the right time.\nNew entry, or clicking any row in the entries table, opens that entry on its own page. The page has its own address, so you can bookmark an entry you\'re mid-way through or paste the link to a colleague and they land on the same one. Back to entries — or your browser\'s Back button — returns to the list; if the entry has edits you haven\'t saved, you\'re asked before they\'re dropped.\nThe table opens with the most recently Published entries first. A scheduled entry sorts by the date it\'s due to go out, so the next posts in your queue open the list, and when you reverse the column they come last among the dated entries. Click the Title, Status, Updated or Published header to sort by that column, and again to reverse it. Entries with nothing in the sorted column, such as a draft with no published date, follow the rest in either direction rather than dropping out. Filters in the table\'s toolbar narrows the list by Title (a word of it), Status, Category, Author, or the Published or Updated date, and Search finds an entry by the start of any word of its title. Every filter and the search word are part of the list\'s query, so they look through the whole collection, not only the page you\'re on, and each filter in force shows as a chip above the table. While the list is filtered or searched it sorts by Published or Updated, and a date filter sorts by the date it filters; a note above the table says when the order moved. A combination that cannot be asked at once — a Title filter beside a search, two date ranges, or is any of picks that multiply past thirty combinations — is left out, and the table says which one and why. See Filter and search a list.\nEach entry carries, besides the '
2778
2778
  },
2779
2779
  {
2780
2780
  path: '/building-sites/site-templates/build-a-blog',
@@ -2858,7 +2858,7 @@ export const ASSIST_DOCS_INDEX = [
2858
2858
  title: 'Save & share a template',
2859
2859
  heading: 'Start from a template',
2860
2860
  anchor: '#start-from-a-template',
2861
- text: 'Open the starter template gallery and install a template. It lands in your templates library as one page template per page — publishing nothing until you choose which pages you want. Aglyn\'s own starter templates still create their pages straight away, since you pick those when a site is empty.\nWhere to find it\nTemplates sits next to the create button on three lists, and each one offers templates of its own kind:\n| List | What the picker offers |\n| Screens | Page templates, plus Aglyn\'s starter sites and marketplace templates |\n| Layouts | Layout templates |\n| Components | Component templates |\nStarter sites and marketplace templates are whole-site page bundles, so they appear only on Screens — a layout or component picker would have nothing to do with them.\nThe picker\'s search box finds a template, a starter or a marketplace listing by the start of any word of its name. Each shelf asks its own query, so the search looks through your whole library and the whole marketplace, not only the cards on screen, and your templates and the marketplace templates page through what matched.\nUse the filter icon in the dialog\'s header to search by name, description or category.'
2861
+ text: 'Open the starter template gallery and install a template. It lands in your templates library as one page template per page — publishing nothing until you choose which pages you want. Aglyn\'s own starter templates still create their pages straight away, since you pick those when a site is empty.\nWhere to find it\nTemplates sits next to the create button on three lists, and each one offers templates of its own kind:\n| List | What the picker offers |\n| Screens | Page templates, plus Aglyn\'s starter sites and marketplace templates |\n| Layouts | Layout templates |\n| Components | Component templates |\nStarter sites and marketplace templates are whole-site page bundles, so they appear only on Screens — a layout or component picker would have nothing to do with them.\nThe filter icon in the dialog\'s header opens the picker\'s search box, which finds a template, a starter or a marketplace listing by the start of any word of its name — its name only, not its description or category. It reads the first word you type. Each shelf asks its own query, so the search looks through your whole library and the whole marketplace, not only the cards on screen, and your templates and the marketplace templates page through what matched.'
2862
2862
  },
2863
2863
  {
2864
2864
  path: '/building-sites/site-templates/save-a-template',
@@ -2886,7 +2886,7 @@ export const ASSIST_DOCS_INDEX = [
2886
2886
  title: 'Your templates library',
2887
2887
  heading: '',
2888
2888
  anchor: '',
2889
- text: 'Your templates library\nTemplates are saved starting points. A template is inert: nothing in your library is on your live site until you deliberately use it. That is the whole point of the library — it means installing something from the marketplace can never publish pages to a site you are running.\nFind it at Templates in a site\'s navigation, alongside Screens, Layouts and Components — the three things a template can produce.\nA template is a copy, not a live link: once you use one, the result is yours outright and editing the template never changes what you already made. If you want one edit to update every place a thing appears, you want a reusable component. If you want one frame around many pages, you want a layout.\nFilters in the library\'s toolbar narrows it by Kind (page, component, or layout), Source (marketplace, starter, or saved here), name (a word of it, or the whole name), or the date it was last updated, and Search finds a template by the start of any word of its name — a starter by its starter\'s name. Every filter and the search word are part of the library\'s query, so they look through every template on the site, and the library pages through the matches. Each filter in force shows as a chip above the table; a combination that cannot be asked at once is left out, and the table says which one and why. See Filter and search a list.'
2889
+ text: 'Your templates library\nTemplates are saved starting points. A template is inert: nothing in your library is on your live site until you deliberately use it. That is the whole point of the library — it means installing something from the marketplace can never publish pages to a site you are running.\nFind it at Templates in a site\'s navigation, alongside Screens, Layouts and Components — the three things a template can produce.\nA template is a copy, not a live link: once you use one, the result is yours outright and editing the template never changes what you already made. If you want one edit to update every place a thing appears, you want a reusable component. If you want one frame around many pages, you want a layout.\nFilters in the library\'s toolbar narrows it by Kind (page, component, or layout), Source (marketplace, starter, or saved here), name (a word of it, or the whole name), or the date it was last updated, and Search finds a template by the start of any word of its name — a starter by its starter\'s name. Every filter and the search word are part of the library\'s query, so they look through every template on the site, and the library pages through the matches. Each filter in force shows as a chip above the table. A name "contains" filter cannot be asked beside a search: while a search is typed it is left out, and the table says which one and why. The library lists templates by ID, and an Updated filter lists the matches most recently updated first. See Filter and search a list.'
2890
2890
  },
2891
2891
  {
2892
2892
  path: '/building-sites/site-templates/templates-library',
@@ -3117,7 +3117,7 @@ export const ASSIST_DOCS_INDEX = [
3117
3117
  title: 'Product catalog',
3118
3118
  heading: 'Collections',
3119
3119
  anchor: '#collections',
3120
- text: 'Collections group products for landing pages and storefront blocks:\n- Manual collections are an ordered, hand-picked list.\n- Smart collections define rules — match by tag, category, price, name, or product type, with all or any semantics — and membership updates automatically as products change. Draft and archived products never appear. A smart collection lists every product that matches, however large the catalog. Saving or deleting one updates which products it holds right away. On a big catalog that can take a few seconds after Collection saved appears.\nOn a Product grid scoped to a smart collection whose rules use any, is not, a name, or a price above, the grid\'s search box and its category and tag chips can\'t be combined with the collection. Using one shows a notice above the grid instead of narrowing it. The type, In stock and price controls still work.'
3120
+ text: 'Collections group products for landing pages and storefront blocks:\n- Manual collections are an ordered, hand-picked list.\n- Smart collections define rules — match by tag, category, price, name, or product type, with all or any semantics — and membership updates automatically as products change. Draft and archived products never appear. A smart collection lists every product that matches, however large the catalog. Saving or deleting one updates which products it holds right away. On a big catalog that can take a few seconds after Collection saved appears.\nOn a Product grid scoped to a smart collection, the grid\'s search box and its category and tag chips can\'t be combined with the collection when a rule says a product\'s tag or category is something, or when the rules are ones a single query cannot ask: any across two or more rules, a tag or category that is not, a name, a price above or is, or more than one tag or category. Using one of those controls shows a notice above the grid instead of narrowing it. The type, In stock and price controls still work, and a collection built only from type is or is not rules and a price below keeps every control. A price below rule is a price range, so that collection\'s grid is in price order — high to low if that is the sort chosen, low to high otherwise.'
3121
3121
  },
3122
3122
  {
3123
3123
  path: '/commerce-and-bookings/commerce/catalog',
@@ -3371,6 +3371,13 @@ export const ASSIST_DOCS_INDEX = [
3371
3371
  anchor: '#four-kinds-of-history',
3372
3372
  text: 'A contact\'s timeline is one newest-first stream drawn from four sources, and every entry says which it is:\n| Entry | Where it comes from | Who can change it |\n| Captured | The platform recorded it — a form submission, an order, a booking, a member sign-up, a newsletter opt-in, an API or import create, or a contact added by hand. Each carries the door it came through and, for a form, the page the person was on. | Nobody. It is a record of what happened. |\n| Logged | A member of your team logged it — a call, an email, a meeting, a note, or something else. | Its author, or an org-wide member. |\n| Sent | An email the platform sent to this person from their record — by a teammate with Send email, or by an automation\'s Send an email step. It carries its subject, the address it went to, and where delivery got to. See Sending an email. | Nobody edits what was sent; its author or an org-wide member may delete it. |\n| Campaign | A campaign email the platform delivered to the person — which email, when it went out, and what became of it. See Campaign email on the timeline. | Nobody. It is the delivery record. |\nA captured entry from this site carries a link to its record: Open submission lands on the Inbox with the reader open on that submission, Open order on the orders list with the order\'s dialog open, and a booking or a sign-up on the Bookings or Users page. An entry from another site in your workspace — read on that site\'s console — or one written before the site was stamped on it is shown without a link.\nCaptured history lives on the contact and is kept to the most recent fifty entries. Logged activity is a collection of its own, bounded at 5,000 entries per record — a call a day for fourteen years, so nobody working a real relationship reaches it, and an automation logging '
3373
3373
  },
3374
+ {
3375
+ path: '/content-and-data/crm/activities',
3376
+ title: 'Activities & the timeline',
3377
+ heading: 'Reading the timeline',
3378
+ anchor: '#reading-the-timeline',
3379
+ text: 'Every entry — on a contact\'s Timeline, and on the Activity card of a lead, a company or a deal — is a collapsed row, newest first:\n- Collapsed, a row shows its kind and its chips (Logged, Received, Sent, the delivery state, how a call went and how long it took), then its subject, or a note\'s first line, and under it who logged it, to or from whom, and when. An email reads as its subject, its recipient and its time.\n- Opened with the chevron at its start, a row shows the rest: an email\'s body, a note\'s every line. A row with nothing more to show has no chevron.\n- Expand all in the card header opens every row; Collapse all closes them again.\n- Edit and Delete stay on the row they act on.\nThe list is paged ten at a time by the footer under it, the same footer as every list in the console, with a menu for how many rows a page holds.\nA logged or sent Email activity and a Campaign entry are different things and are drawn differently: the first is a message somebody on your team wrote, sent or recorded, the second is a mailing the platform sent to an audience the person was in.\nA few Note entries are bookkeeping rather than something a person typed, and each is signed by what did it: Filed under and Removed from a campaign, by the member who changed the record\'s filing — or by Lead conversion, when a lead\'s campaigns were carried onto the contact it became — and Enrolled in a sequence and stopped, by Sequences. They read on the lead and the contact alike, above the emails they explain.'
3380
+ },
3374
3381
  {
3375
3382
  path: '/content-and-data/crm/activities',
3376
3383
  title: 'Activities & the timeline',
@@ -3383,7 +3390,7 @@ export const ASSIST_DOCS_INDEX = [
3383
3390
  title: 'Activities & the timeline',
3384
3391
  heading: 'Logging an activity',
3385
3392
  anchor: '#logging-an-activity',
3386
- text: 'Open the record — a contact\'s page under CRM › Contacts, a company\'s under Companies, a deal\'s under Deals, or a lead\'s under Leads — and choose Log activity. The activity is filed against that record; there is no picker, because what you are looking at is what the activity is about.\nLogging an activity is part of the CRM, included from Starter. On Free the CRM is shown locked, so there is no record page to log from.\n| Field | What it is |\n| Kind | Call, Email, Meeting, Note or Other. |\n| When | When it happened, which is not always when you are logging it. Defaults to now. |\n| What happened | The body of the entry. |\n| Outcome | For a call or a meeting: how it ended — "left a voicemail", "agreed to a trial". |\n| Minutes | For a call or a meeting: how long it took. |\nEach entry shows who logged it and how long ago. The author can edit or delete their own entries; an org-wide member can edit or delete anyone\'s. A colleague with access to only some of your sites can read an entry they did not write, and cannot change it.\nA meeting from a booking {#meeting-from-a-booking}\nA confirmed booking files a meeting on its record\'s timeline without anyone logging it — titled with the service and the slot, and linked to the booking. The record is the one the booking link was dropped from (a contact\'s, a lead\'s or a deal\'s Book a meeting, or Insert booking link in Send email), which wins even when the person books with another address; a booking taken from the widget with no record attached is matched to a contact by the booker\'s address. When the service asks for it, a Follow up after <service> task is filed beside the meeting, due one business day after the slot. Nothing is filed on a site where the CRM is switched off, or for a workspace whose plan does not include the CRM.'
3393
+ text: 'Open the record — a contact\'s page under CRM › Contacts, a company\'s under Companies, a deal\'s under Deals, or a lead\'s under Leads — and choose Log activity in the header of the Timeline or Activity card. The activity is filed against that record; there is no picker, because what you are looking at is what the activity is about.\nLogging an activity is part of the CRM, included from Starter. On Free the CRM is shown locked, so there is no record page to log from.\n| Field | What it is |\n| Kind | Call, Email, Meeting, Note or Other. |\n| When | When it happened, which is not always when you are logging it. Defaults to now. |\n| What happened | The body of the entry. |\n| Outcome | For a call or a meeting: how it ended — "left a voicemail", "agreed to a trial". |\n| Minutes | For a call or a meeting: how long it took. |\nEach entry shows who logged it and how long ago. The author can edit or delete their own entries; an org-wide member can edit or delete anyone\'s. A colleague with access to only some of your sites can read an entry they did not write, and cannot change it.\nA meeting from a booking {#meeting-from-a-booking}\nA confirmed booking files a meeting on its record\'s timeline without anyone logging it — titled with the service and the slot, and linked to the booking. The record is the one the booking link was dropped from (a contact\'s, a lead\'s or a deal\'s Book a meeting, or Insert booking link in Send email), which wins even when the person books with another address; a booking taken from the widget with no record attached is matched to a contact by the booker\'s address. When the service asks for it, a Follow up after <service> task is filed beside the meeting, due one business day after the slot. Nothing is filed on a site where the CRM is switched off, or for a '
3387
3394
  },
3388
3395
  {
3389
3396
  path: '/content-and-data/crm/activities',
@@ -3418,7 +3425,7 @@ export const ASSIST_DOCS_INDEX = [
3418
3425
  title: 'Activities & the timeline',
3419
3426
  heading: 'The recent activity feed',
3420
3427
  anchor: '#the-recent-activity-feed',
3421
- text: 'The Contacts section shows the newest activity logged across the CRM under the list — the last few calls, emails, meetings and notes anyone on the team filed against any record — each linking to the record it is about. It is a glance at what the team has been doing; the record\'s own page is where the whole log lives.'
3428
+ text: 'The Contacts section shows the newest activity logged across the CRM in a Recent activity card of its own under the contacts list — the calls, emails, meetings and notes anyone on the team filed against any record — each linking to the record it is about. Its rows are collapsed like the timeline\'s and open the same way, Expand all is in its header, and it is paged ten at a time. The card appears once something has been logged. It is a glance at what the team has been doing; the record\'s own page is where the whole log lives.'
3422
3429
  },
3423
3430
  {
3424
3431
  path: '/content-and-data/crm/activities',
@@ -3530,7 +3537,7 @@ export const ASSIST_DOCS_INDEX = [
3530
3537
  title: 'Bulk actions',
3531
3538
  heading: 'Tasks',
3532
3539
  anchor: '#tasks',
3533
- text: '| Action | What happens |\n| Complete | Each open selected task is completed through the server, one at a time, so every one fires its taskCompleted event. Tasks already done are left alone. |\n| Assign | Pick a team member, or Nobody to clear the assignee. Each task is saved through the server, so the new assignee gets the same notification the drawer sends — assigning to yourself sends nothing. |\n| Set due | Pick a date and time for every selected task, or leave it empty to clear the due date. |\n| Export CSV | Download the selected tasks as tasks-selected.csv — the same file the list\'s Export CSV writes for the view on screen: title, kind, priority, status, the due date and the completion as timestamps, the assignee by email address, the contact, company and deal by name, and notes. |\n| Delete | After a confirmation, the selected tasks are deleted for everyone who can see them. A finished task is better ticked done, which keeps it in the Done view. |'
3540
+ text: '| Action | What happens |\n| Complete | Each open selected task is completed through the server, one at a time, so every one fires its taskCompleted event. Tasks already done are left alone. |\n| Assign | Pick a team member, or Nobody to clear the assignee. Each task is saved through the server, so the new assignee gets the same notification the drawer sends — assigning to yourself sends nothing. |\n| Set due | Pick a date and time for every selected task, or leave it empty to clear the due date. |\n| Export CSV | Download the selected tasks as tasks-selected.csv — the same file the list\'s Export CSV writes for the page on screen: title, kind, priority, status, the due date and the completion as timestamps, the assignee by email address, the contact, company and deal by name, and notes. |\n| Delete | After a confirmation, the selected tasks are deleted for everyone who can see them. A finished task is better ticked done, which keeps it in the Done view. |'
3534
3541
  },
3535
3542
  {
3536
3543
  path: '/content-and-data/crm/bulk-actions',
@@ -3579,7 +3586,7 @@ export const ASSIST_DOCS_INDEX = [
3579
3586
  title: 'Companies',
3580
3587
  heading: 'The companies list',
3581
3588
  anchor: '#the-companies-list',
3582
- text: 'The list shows every company your site may see, most recently changed first, with its domain, how many contacts are linked to it, its owner, when it was last changed and its next activity — when the earliest open task against it is due. The table\'s Search box finds a company by a word of its name or its domain. Filters › Company finds one whose name is exactly what you type, or starts with it — which orders the list by name — Filters › Owner shows one teammate\'s accounts, or any of several, and Next activity › is empty keeps only the companies with nothing scheduled.\nEvery filter and the search are answered by the list\'s query, so they reach every company, a page at a time, not only the page on screen, and filters on different columns add up. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under a site, a member whose access is limited to particular sites searches by the start of a company\'s name, and a notice says so. When a combination cannot be answered by one query, the list does not apply that filter, and a notice above the table names it and says why; see Filter and search a list. Clicking a row opens the company\'s page.\nThe Contacts column is a count kept on the company and moved with every link and unlink, so a page of companies costs no lookup per row. A company linked before the count existed can read lower than its page shows; the company\'s own page counts live, and is the figure to trust when the two differ.'
3589
+ text: 'The list shows every company your site may see, most recently changed first, with its domain, how many contacts are linked to it, its owner, when it was last changed and its next activity — when the earliest open task against it is due. The table\'s Search box finds a company by a word of its name or its domain. Filters › Company finds one whose name equals what you type, or starts with it — which orders the list by name — Filters › Owner shows one teammate\'s accounts, or any of several, and Next activity › is empty keeps only the companies with nothing scheduled.\nEvery filter and the search are answered by the list\'s query, so they reach every company, a page at a time, not only the page on screen, and filters on different columns add up. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under a site, a member whose access is limited to particular sites searches by the start of a company\'s name, and a notice says so. When a combination cannot be answered by one query, the list does not apply that filter, and a notice above the table names it and says why; see Filter and search a list. The Company column\'s header sorts only the rows of the page on screen; the pages keep the list\'s own order. Clicking a row opens the company\'s page.\nThe Contacts column is a count kept on the company and moved with every link and unlink, so a page of companies costs no lookup per row. A company linked before the count existed can read lower than its page shows; the company\'s own page counts live, and is the figure to trust when the two differ.'
3583
3590
  },
3584
3591
  {
3585
3592
  path: '/content-and-data/crm/companies',
@@ -3614,14 +3621,14 @@ export const ASSIST_DOCS_INDEX = [
3614
3621
  title: 'Companies',
3615
3622
  heading: 'Import from CSV',
3616
3623
  anchor: '#import-from-csv',
3617
- text: 'Import CSV, above the list, takes a spreadsheet of companies — an export from another CRM, an account list — and files each one. A company already in your list is updated rather than added twice: a row is matched to an existing company by its domain first, and by its name when the row has no domain or no company carries it. Importing needs the same Manage data permission as creating a company.\nThe three steps are the ones the contacts import walks: choose the file (up to 5,000 rows), match its columns — Aglyn proposes a match from the header names and shows the first row\'s value beside each — check the ten-row preview, then import in batches of 200 with a progress bar and a result that says how many were added, updated and skipped, with the skipped rows downloadable as a CSV that says why. Download template hands you the export\'s own header over no rows, so a sheet filled in against it maps itself.\n| Field | What is read |\n| Company name | Required. A row without one is skipped. |\n| Domain | The bare hostname (acme.com); a URL or www. is stripped. What a row is matched on first. A cell that is not a hostname is dropped and reported. |\n| Website, phone, industry, notes | As on the company form; a phone that cannot be read is dropped and reported. |\n| Owner | The email address of a member of your organization. An address that matches nobody leaves the company without an owner, and the result names those addresses. |\n| Address line 1, line 2, city, state, postal code, country | The postal address. Country must be a two-letter code. |\n| Tags | Separated by , or \\|, lowercased. Added to any tags the company already has. |\n| Custom fields | Every field defined on the Companies tab of Fields is offered as a target, and a header that matches a field\'s label or key is proposed f'
3624
+ text: 'Import CSV, in the card\'s header, takes a spreadsheet of companies — an export from another CRM, an account list — and files each one. A company already in your list is updated rather than added twice: a row is matched to an existing company by its domain first, and by its name when the row has no domain or no company carries it. Importing needs the same Manage data permission as creating a company.\nThe three steps are the ones the contacts import walks: choose the file (up to 5,000 rows), match its columns — Aglyn proposes a match from the header names and shows the first row\'s value beside each — check the ten-row preview, then import in batches of 200 with a progress bar and a result that says how many were added, updated and skipped, with the skipped rows downloadable as a CSV that says why. Download template hands you the export\'s own header over no rows, so a sheet filled in against it maps itself.\n| Field | What is read |\n| Company name | Required. A row without one is skipped. |\n| Domain | The bare hostname (acme.com); a URL or www. is stripped. What a row is matched on first. A cell that is not a hostname is dropped and reported. |\n| Website, phone, industry, notes | As on the company form; a phone that cannot be read is dropped and reported. |\n| Owner | The email address of a member of your organization. An address that matches nobody leaves the company without an owner, and the result names those addresses. |\n| Address line 1, line 2, city, state, postal code, country | The postal address. Country must be a two-letter code. |\n| Tags | Separated by , or \\|, lowercased. Added to any tags the company already has. |\n| Custom fields | Every field defined on the Companies tab of Fields is offered as a target, and a header that matches a field\'s label or key is prop'
3618
3625
  },
3619
3626
  {
3620
3627
  path: '/content-and-data/crm/companies',
3621
3628
  title: 'Companies',
3622
3629
  heading: 'Export CSV',
3623
3630
  anchor: '#export-csv',
3624
- text: 'Export CSV, above the list, downloads the companies on screen as companies.csv; the bulk bar\'s Export CSV downloads the selected rows as companies-selected.csv. Both write the same file: every column above plus the contacts count, with the owner written as their email address, under the header the import reads — so an export re-imports without a hand mapping, and the count maps to nothing.'
3631
+ text: 'Export CSV, in the card\'s header, downloads the companies on screen as companies.csv; the bulk bar\'s Export CSV downloads the selected rows as companies-selected.csv. Both write the same file: every column above plus the contacts count, with the owner written as their email address, under the header the import reads — so an export re-imports without a hand mapping, and the count maps to nothing.'
3625
3632
  },
3626
3633
  {
3627
3634
  path: '/content-and-data/crm/companies',
@@ -3670,7 +3677,7 @@ export const ASSIST_DOCS_INDEX = [
3670
3677
  title: 'The contact record',
3671
3678
  heading: 'The record page',
3672
3679
  anchor: '#the-record-page',
3673
- text: 'Clicking a row in the list opens the person\'s own page at …/crm/contacts/{id} — an address you can paste and that every other CRM record links to. The page opens with the person\'s name, their lifecycle stage, their owner, when they last engaged with one of your campaigns, and — for a buyer — how many orders they have placed and what they have spent; the order count is a link to the site\'s orders list narrowed to the person\'s address. When a sender has given a verdict on the address — a bounce, a gateway block, an unsubscribe, a spam complaint, a do-not-contact mark — it leads the chip row, with the date and the server\'s words on hover, and Send email is disabled with the reason; the Contacts list carries the same verdict in its Email column and filter. It is the lead\'s email state, on the contact the lead became or was always. Beside Send email it carries Call, which dials the person\'s number, and Log a call — see click to call. Under it, one card per aspect of the record:\n- Properties — the editable profile: name, phone (with a dial button beside it, see click to call), job title, company, lifecycle stage, owner, tags, address and an About box for your team\'s notes. One Save writes everything at once. The email is shown but cannot be edited here, because it is the shared identity. The Company field is the same picker the New contact drawer has: search the companies your site may see, create one by typing its name, or clear the field to unlink the person. A record that carries a company name with no link — an import, or a save from before the picker — shows the name as a note beneath the field, with one click to link the company of that name or create it. Changing the company here moves the count on the companies list with it.\n- Relationship — the sources that created t'
3680
+ text: 'Clicking a row in the list opens the person\'s own page at …/crm/contacts/{id} — an address you can paste and that every other CRM record links to. The page opens with the person\'s name, their lifecycle stage, their owner, when they last engaged with one of your campaigns, and — for a buyer — how many orders they have placed and what they have spent; the order count is a link to the site\'s orders list narrowed to the person\'s address. When a sender has given a verdict on the address — a bounce, a gateway block, an unsubscribe, a spam complaint, a do-not-contact mark — it leads the chip row, with the date and the server\'s words on hover, and Send email is disabled with the reason; the Contacts list carries the same verdict in its Email column and filter. It is the lead\'s email state, on the contact the lead became or was always. Beside Send email it carries Call, which dials the person\'s number, and Log a call — see click to call. Under it, one card per aspect of the record:\n- Properties — the editable profile: name, phone (with a dial button beside it, see click to call), job title, company, lifecycle stage, owner, tags, address and an About box for your team\'s notes, then under More fields one control per custom field your organization has defined. One Save, in the card\'s header, writes everything at once, and Discard changes beside it puts back what you had not saved. The email is shown but cannot be edited here, because it is the shared identity. The Company field is the same picker the New contact drawer has: search the companies your site may see, create one by typing its name, or clear the field to unlink the person. A record that carries a company name with no link — an import, or a save from before the picker — shows the name as a note beneath the field, with one'
3674
3681
  },
3675
3682
  {
3676
3683
  path: '/content-and-data/crm/contact-record',
@@ -3698,7 +3705,7 @@ export const ASSIST_DOCS_INDEX = [
3698
3705
  title: 'The contact record',
3699
3706
  heading: 'Owner',
3700
3707
  anchor: '#owner',
3701
- text: 'The Owner is the team member responsible for the relationship. The contacts list has an Owner column and an Assigned to me toggle that narrows the list to the people assigned to you; the record page shows the owner beside the heading and lets you reassign.'
3708
+ text: 'The Owner is the team member responsible for the relationship. The contacts list has an Owner column, and its Filters › Owner offers Me first, which narrows the list to the people assigned to you; the record page shows the owner beside the heading and lets you reassign.'
3702
3709
  },
3703
3710
  {
3704
3711
  path: '/content-and-data/crm/contact-record',
@@ -3719,7 +3726,7 @@ export const ASSIST_DOCS_INDEX = [
3719
3726
  title: 'The contact record',
3720
3727
  heading: 'Finding a contact',
3721
3728
  anchor: '#finding-a-contact',
3722
- text: 'The list\'s filters and its search box reach every contact, page by page; the search finds a person by a word of their name or email addresses — see Filters on the Contacts list. The console\'s search (the magnifying glass in the top bar) finds contacts too — by name, email, phone number or company name — and opens the person\'s page. Contacts appear in that search only for members who can manage data on the site, and only while the CRM is available to them.\nThe phone number and company name are kept on the record itself for that lookup, as this site last saved them; the values you see on a person\'s page are always your own site\'s.'
3729
+ text: 'The list\'s filters and its search box reach every contact, page by page; the search finds a person by the start of a word of their name, their email addresses or their company, or by their phone number\'s digits — see Filters on the Contacts list. The console\'s search (the magnifying glass in the top bar) finds contacts too — by name, email, phone number or company name — and opens the person\'s page. Contacts appear in that search only for members who can manage data on the site, and only while the CRM is available to them.\nThe phone number and company name are kept on the record itself for that lookup, as this site last saved them; the values you see on a person\'s page are always your own site\'s.'
3723
3730
  },
3724
3731
  {
3725
3732
  path: '/content-and-data/crm/contact-record',
@@ -3747,21 +3754,21 @@ export const ASSIST_DOCS_INDEX = [
3747
3754
  title: 'Custom fields',
3748
3755
  heading: 'Define a field',
3749
3756
  anchor: '#define-a-field',
3750
- text: 'Open CRM → Fields, pick the tab for the record the field describes — Contacts, Companies, Deals or Leads — and choose New field.\n- Label — how the field reads everywhere it shows.\n- Key — derived from the label as you type (Annual revenue becomes annualrevenue); edit it to choose your own. A key starts with a letter and uses lowercase letters, digits and underscores, up to 40 characters. Values are stored under the key, so it cannot change once the field exists — a rename is a new field and a retirement of the old one.\n- Type — Text, Number, Date, Choice, Checkbox or Link. Every value is read by its type, so the type is fixed once the field exists.\n- Choices — for a Choice field, one per line. A stored value has to be one of them.\n- Required on the … form — the record\'s page will not save the field empty. It does not make a website form field required; that is set on the form itself.\nFields are listed in the order they appear on a record and in the list\'s columns; the arrows on each row move a field up or down.\nHow many records carry a value under each field is not counted. That would read every record in the organization each time the page opened, so the list says so rather than showing a number it cannot keep true.'
3757
+ text: 'Open CRM → Fields, pick the tab for the record the field describes — Contacts, Companies, Deals or Leads — and choose New field.\n- Label — how the field reads everywhere it shows.\n- Key — derived from the label as you type (Annual revenue becomes annualrevenue); edit it to choose your own. A key starts with a letter and uses lowercase letters, digits and underscores, up to 40 characters. Values are stored under the key, so it cannot change once the field exists — a rename is a new field and a retirement of the old one.\n- Type — Text, Number, Date, Choice, Checkbox or Link. Every value is read by its type, so the type is fixed once the field exists.\n- Choices — for a Choice field, one per line. A stored value has to be one of them.\n- Required on the … form — the record\'s page will not save the field empty. It does not make a website form field required; that is set on the form itself.\nEach tab is the console\'s list table: it pages, sorts by Field, Key or Type, filters by Type and Required from its Filters panel, and searches a field\'s name and key. It opens in the order fields appear on a record and in the list\'s columns, numbered under Order; the arrows on each row move a field up or down. The order is the record\'s, not a view of the list, so the arrows are live only while the list shows it — with a sort, a filter or a search in force they wait, and say Clear sorting and filters to reorder.\nHow many records carry a value under each field is not counted. That would read every record in the organization each time the page opened, so the list says so rather than showing a number it cannot keep true.'
3751
3758
  },
3752
3759
  {
3753
3760
  path: '/content-and-data/crm/custom-fields',
3754
3761
  title: 'Custom fields',
3755
3762
  heading: 'Fields per record',
3756
3763
  anchor: '#fields-per-record',
3757
- text: 'Each tab of the Fields section is its own list: a field belongs to contacts, to companies, to deals or to leads, and never to more than one. Keys are unique within a tab, so a company field and a contact field may both be called region — they are two fields, each read by its own type.\n| Record | Where its fields show |\n| Contacts | The Custom fields card on a contact\'s page, optional columns and filters on the contacts list, the CSV import, a form field\'s destination, and custom on /v1/contacts. |\n| Companies | Rows on a company\'s page and controls on its Edit form, optional columns on the companies list, the companies CSV import, and custom on /v1/companies. |\n| Deals | Rows on a deal\'s page and controls on its Edit form, optional columns on the deals table, and custom on /v1/deals. |\n| Leads | Controls on a lead\'s page beside its profile and in the New lead drawer, optional columns on the leads list, and custom on /v1/leads. |\nOnly a contact field can be the destination of a website form field, because a submission is a fact about a person; the drawer on the other tabs says so. Company, deal and lead columns show values and are not filterable, for the reason the contact columns are not: the value lives in a map no index covers.\nA lead\'s values stay on the lead when it converts. A lead field and a contact field are two fields even when they share a key, so nothing is copied across; the converted lead is still on record and still shows what was written on it.\nFields defined before companies, deals and leads could carry them are contact fields, and need nothing done to them.'
3764
+ text: 'Each tab of the Fields section is its own list: a field belongs to contacts, to companies, to deals or to leads, and never to more than one. Keys are unique within a tab, so a company field and a contact field may both be called region — they are two fields, each read by its own type.\n| Record | Where its fields show |\n| Contacts | More fields in the Properties card on a contact\'s page, optional columns and filters on the contacts list, the CSV import, a form field\'s destination, and custom on /v1/contacts. |\n| Companies | More fields on a company\'s page and controls on its Edit form, optional columns on the companies list, the companies CSV import, and custom on /v1/companies. |\n| Deals | More fields in the Properties card on a deal\'s page and controls on its Edit form, optional columns on the deals table, and custom on /v1/deals. |\n| Leads | More fields in the Details card on a lead\'s page and in the New lead drawer, optional columns on the leads list, and custom on /v1/leads. |\nOnly a contact field can be the destination of a website form field, because a submission is a fact about a person; the drawer on the other tabs says so. Company, deal and lead columns show values and are not filterable: the value lives in a map no index covers. A contact field is the exception — each site\'s record of the person carries a key for it that the list\'s query can ask — see Filters on the Contacts list.\nA lead\'s values stay on the lead when it converts. A lead field and a contact field are two fields even when they share a key, so nothing is copied across; the converted lead is still on record and still shows what was written on it.\nFields defined before companies, deals and leads could carry them are contact fields, and need nothing done to them.'
3758
3765
  },
3759
3766
  {
3760
3767
  path: '/content-and-data/crm/custom-fields',
3761
3768
  title: 'Custom fields',
3762
3769
  heading: 'Where values show',
3763
3770
  anchor: '#where-values-show',
3764
- text: '- A contact\'s page carries a Custom fields card with one control per field — a text box, a number box, a date picker, a choice list, a checkbox or a link box. Save writes only the fields you changed; clearing a control clears the value.\n- The contacts list offers one optional column per field. The columns show the value as it reads — a date as a day, a checkbox as Yes or No, a link as a link — and are not sortable or filterable.\n- A lead\'s page carries its fields under Custom fields, below the profile and saved with it by the same Save. The New lead drawer offers the same controls, so a lead can be entered complete. A converted lead\'s are read-only with the rest of the record. The leads list offers one optional column per field.\n- Exports and the API carry the values under their keys.\nA value belongs to the site that recorded it. Two sites in one organization that both know a person each see their own values, never each other\'s.'
3771
+ text: '- A contact\'s page carries its fields in the Properties card, under More fields after the built-in properties, with one control per field — a text box, a number box, a date picker, a choice list, a checkbox or a link box. The card\'s one Save, in its header, writes the profile and only the fields you changed; clearing a control clears the value. With no field defined, there is no More fields at all.\n- The contacts list offers one optional column per field. The columns show the value as it reads — a date as a day, a checkbox as Yes or No, a link as a link. They do not sort; each is a field in the table\'s Filters panel — see Filters on the Contacts list.\n- A lead\'s page carries its fields in the Details card, under More fields after the profile and saved with it by the same Save in the card\'s header. The New lead drawer offers the same controls, so a lead can be entered complete. A converted lead\'s are read-only with the rest of the record. The leads list offers one optional column per field.\n- A company\'s page and a deal\'s list their fields under More fields, after the built-in properties; Edit changes them.\n- Exports and the API carry the values under their keys.\nA value belongs to the site that recorded it. Two sites in one organization that both know a person each see their own values, never each other\'s.'
3765
3772
  },
3766
3773
  {
3767
3774
  path: '/content-and-data/crm/custom-fields',
@@ -3775,7 +3782,7 @@ export const ASSIST_DOCS_INDEX = [
3775
3782
  title: 'Custom fields',
3776
3783
  heading: 'Lead source values',
3777
3784
  anchor: '#lead-source-values',
3778
- text: 'Lead source is a standard lead field — Salesforce\'s Lead Source — and its choices are your organization\'s own. They are kept on the Leads tab, below the custom lead fields, under Lead source values. Every lead\'s page, the New lead drawer and every contact\'s page offer them as a select, and the leads list filters and sorts by them.\n| Action | What it does |\n| Add value | Adds a value at the end of the list. A value the list already holds, in any capitalization, is refused. |\n| Drag, or the arrows | Reorders the list. The order is the order every select offers, and the order the leads list sorts in. |\n| Sort A–Z | Puts the whole list in alphabetical order. |\n| Rename | Renames the value, and every lead and contact holding it is updated to the new name in the same step, so a report grouped by lead source follows the rename. |\n| Make default | New leads start with this value — in the New lead drawer, over the API, and from a CSV row that names none. Clear default removes it. |\n| Deactivate | Takes the value out of every select without touching the records that hold it. They show it as (inactive) and keep it until someone changes it. Activate brings it back. |\n| Delete… | Removes the value for good. You pick another active value to move its leads and contacts to, or clear it from them. To keep it on those records, deactivate it instead. |\nAn organization that has never edited the list starts from a short starter list; your first change makes it your own.\nThe list is enforced. A lead source typed into a CSV import or sent over /v1/leads must be one of the active values, matched without regard to case and stored as the list spells it. Anything else is refused, with the values the list allows named in the error — the import skips that row and says so, and warns before the file '
3785
+ text: 'Lead source is a standard lead field — Salesforce\'s Lead Source — and its choices are your organization\'s own. They are kept on the Leads tab, below the custom lead fields, under Lead source values. Every lead\'s page, the New lead drawer and every contact\'s page offer them as a select, and the leads list filters by them.\n| Action | What it does |\n| Add value | Adds a value at the end of the list. A value the list already holds, in any capitalization, is refused. |\n| Drag, or the arrows | Reorders the list. The order is the order every select offers. |\n| Sort A–Z | Puts the whole list in alphabetical order. |\n| Rename | Renames the value, and every lead and contact holding it is updated to the new name in the same step, so a report grouped by lead source follows the rename. |\n| Make default | New leads start with this value — in the New lead drawer, over the API, and from a CSV row that names none. Clear default removes it. |\n| Deactivate | Takes the value out of every select without touching the records that hold it. They show it as (inactive) and keep it until someone changes it. Activate brings it back. |\n| Delete… | Removes the value for good. You pick another active value to move its leads and contacts to, or clear it from them. To keep it on those records, deactivate it instead. |\nAn organization that has never edited the list starts from a short starter list; your first change makes it your own.\nThe list is enforced. A lead source typed into a CSV import or sent over /v1/leads must be one of the active values, matched without regard to case and stored as the list spells it. Anything else is refused, with the values the list allows named in the error — the import skips that row and says so, and warns before the file is sent. A lead or contact that already holds a v'
3779
3786
  },
3780
3787
  {
3781
3788
  path: '/content-and-data/crm/custom-fields',
@@ -3824,14 +3831,14 @@ export const ASSIST_DOCS_INDEX = [
3824
3831
  title: 'Deals pipeline',
3825
3832
  heading: 'The board and the table',
3826
3833
  anchor: '#the-board-and-the-table',
3827
- text: 'The section opens as a board of the chosen pipeline: one column per open stage, with Won and Lost folded away at the end until you expand them. Each card shows the deal\'s title, amount, the contact and company it is with, its owner, and how many days it has sat in its current stage. Drag a card between columns to move it, or use the card\'s menu to move it, mark it won, or mark it lost from the keyboard.\nAbove the board, three figures summarize what is open: the open count, the pipeline value (every open deal\'s amount, per currency) and the weighted value (each amount multiplied by its stage\'s probability).\nSwitch to the table for a paged list with the title, stage, amount, owner, expected close date, status and next activity of every deal in the chosen pipeline, including the closed ones, most recently changed first. The table\'s Filters panel narrows it by Status (open, won or lost — one, or any of them), and Next activity › is empty keeps only the deals with no open task scheduled against them — the ones the reports page counts as stuck. Search finds a deal by any word of its title.\nEvery filter and the search are answered by the table\'s query, so they reach every deal in the pipeline, a page at a time, not only the page on screen, and filters on different columns add up. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under a site, a member whose access is limited to particular sites searches by the start of a deal\'s title, and a notice says so. When a combination cannot be answered by one query, the table does not apply that filter, and a notice above it names the filter and says why; see Filter and search a list. The board ha'
3834
+ text: 'The section opens as a board of the chosen pipeline: one column per open stage, with Won and Lost folded away at the end until you expand them. Each card shows the deal\'s title, amount, the contact and company it is with, its owner, and how many days it has sat in its current stage. Drag a card between columns to move it, or use the card\'s menu to move it, mark it won, or mark it lost from the keyboard.\nAbove the board, three figures summarize what is open: the open count, the pipeline value (every open deal\'s amount, per currency) and the weighted value (each amount multiplied by its stage\'s probability).\nSwitch to the table for a paged list with the title, stage, amount, owner, expected close date, status and next activity of every deal in the chosen pipeline, including the closed ones, most recently changed first. The table\'s Filters panel narrows it by Status (open, won or lost — one, or any of them), and Next activity › is empty keeps only the deals with no open task scheduled against them — the ones the reports page counts as stuck. Search finds a deal by any word of its title.\nEvery filter and the search are answered by the table\'s query, so they reach every deal in the pipeline, a page at a time, not only the page on screen, and filters on different columns add up. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under a site, a member whose access is limited to particular sites searches by the start of a deal\'s title, and a notice says so. When a combination cannot be answered by one query, the table does not apply that filter, and a notice above it names the filter and says why; see Filter and search a list. A column hea'
3828
3835
  },
3829
3836
  {
3830
3837
  path: '/content-and-data/crm/deals',
3831
3838
  title: 'Deals pipeline',
3832
3839
  heading: 'Import from CSV',
3833
3840
  anchor: '#import-from-csv',
3834
- text: 'Import CSV beside the table\'s status filter takes a spreadsheet of deals — an export from another CRM, a forecast sheet — and files each row as a new deal. A deal has no key the way a contact has an address, so nothing is merged: importing a file twice files it twice. Importing needs the same Manage data permission as creating a deal.\nThe three steps are the ones the contacts import walks: choose the file (up to 5,000 rows), match its columns — Aglyn proposes a match from the header names and shows the first row\'s value beside each — check the ten-row preview, then import in batches of 200 with a progress bar and a result that says how many were added and skipped, with the skipped rows downloadable as a CSV that says why. Download template hands you the export\'s own header over no rows, so a sheet filled in against it maps itself.\n| Field | What is read |\n| Title | Required. A row without one is skipped. |\n| Pipeline | By name, as it appears in Pipelines, spelled either way. Left empty, the row lands in the default pipeline. A name your workspace has no pipeline for skips the row as No pipeline by that name. |\n| Stage | By name within that pipeline. Left empty, the pipeline\'s first open stage. A name the pipeline has no stage for skips the row as No stage by that name in that pipeline. A row filed into Won or Lost is closed on arrival; no dealWon or dealLost event fires for it. |\n| Amount | In major units (1250.00, $1,250); the currency symbol and separators are ignored. A cell that is not a number is dropped and reported. |\n| Currency | A three-letter code (USD, EUR); USD when empty. Anything else is dropped and reported. |\n| Owner | The email address of a member of your organization. An address that matches nobody leaves the deal without an owner, and the result names'
3841
+ text: 'Import CSV in the card\'s header takes a spreadsheet of deals — an export from another CRM, a forecast sheet — and files each row as a new deal. A deal has no key the way a contact has an address, so nothing is merged: importing a file twice files it twice. Importing needs the same Manage data permission as creating a deal.\nThe three steps are the ones the contacts import walks: choose the file (up to 5,000 rows), match its columns — Aglyn proposes a match from the header names and shows the first row\'s value beside each — check the ten-row preview, then import in batches of 200 with a progress bar and a result that says how many were added and skipped, with the skipped rows downloadable as a CSV that says why. Download template hands you the export\'s own header over no rows, so a sheet filled in against it maps itself.\n| Field | What is read |\n| Title | Required. A row without one is skipped. |\n| Pipeline | By name, as it appears in Pipelines, spelled either way. Left empty, the row lands in the default pipeline. A name your workspace has no pipeline for skips the row as No pipeline by that name. |\n| Stage | By name within that pipeline. Left empty, the pipeline\'s first open stage. A name the pipeline has no stage for skips the row as No stage by that name in that pipeline. A row filed into Won or Lost is closed on arrival; no dealWon or dealLost event fires for it. |\n| Amount | In major units (1250.00, $1,250); the currency symbol and separators are ignored. A cell that is not a number is dropped and reported. |\n| Currency | A three-letter code (USD, EUR); USD when empty. Anything else is dropped and reported. |\n| Owner | The email address of a member of your organization. An address that matches nobody leaves the deal without an owner, and the result names those addre'
3835
3842
  },
3836
3843
  {
3837
3844
  path: '/content-and-data/crm/deals',
@@ -3971,7 +3978,7 @@ export const ASSIST_DOCS_INDEX = [
3971
3978
  title: 'Leads',
3972
3979
  heading: '',
3973
3980
  anchor: '',
3974
- text: 'Leads\nA lead is somebody you have heard of but not yet qualified: a visitor who booked or wrote in through a form that routes leads, a person from a list you imported, or one you added by hand. It is a record of its own — the way it is in Salesforce — and it becomes a contact only when you convert it. The Leads section of the CRM is where the team works them — decides who owns each one, keeps notes, and either converts the lead into a contact or closes it with a reason.\nLeads live under the site that captured them, so each site\'s list is its own. Open CRM → Leads in the console, or use Open in CRM on a row of the Leads list in the Inbox\'s Site Members & Leads section.\nPlan availability Leads are part of the CRM, included from Starter. On Free the section is shown locked, with the rest of the CRM. Leads are still filed on Free, exactly as described below, and kept; workspace owners and admins can export every lead, or erase a person, from Settings → Privacy. See What each plan includes.'
3981
+ text: 'Leads\nA lead is somebody you have heard of but not yet qualified: a visitor who booked or wrote in through a form that routes leads, a person from a list you imported, or one you added by hand. It is a record of its own — the way it is in Salesforce — and it becomes a contact only when you convert it. The Leads section of the CRM is where the team works them — decides who owns each one, keeps notes, and either converts the lead into a contact or closes it with a reason.\nLeads live under the site that captured them, so each site\'s list is its own. Open CRM → Leads in the console, or open one lead from the Inbox: its Site Members & Leads section shows members or leads, one at a time, by the Members | Leads toggle above the table. Choose Leads, and a row\'s menu (⋮) has Open in CRM. Each side is its own list with its own filters and search, so a person who left their address and later signed up appears under both. On the organization\'s Inbox the section is Leads alone, every site\'s. See Filter the Inbox tables.\nPlan availability Leads are part of the CRM, included from Starter. On Free the section is shown locked, with the rest of the CRM. Leads are still filed on Free, exactly as described below, and kept; workspace owners and admins can export every lead, or erase a person, from Settings → Privacy. See What each plan includes.'
3975
3982
  },
3976
3983
  {
3977
3984
  path: '/content-and-data/crm/leads',
@@ -3999,7 +4006,7 @@ export const ASSIST_DOCS_INDEX = [
3999
4006
  title: 'Leads',
4000
4007
  heading: 'A lead\'s page',
4001
4008
  anchor: '#a-leads-page',
4002
- text: 'Click a row to open the lead. The page has three cards.\nLead holds what the team decides: the status, the owner, the lead\'s profile — company, job title, phone, website, lead source, tags and address, with any custom lead fields under it, all edited together under one Save — and free-text notes with a Save notes button. It also shows the identity the capture recorded — email and name — and the person\'s marketing consent: whether they opted in (and when), declined, or never recorded a choice. Once the lead converts, the profile is read-only here: the contact is the record then. A lead with no recorded consent cannot be sent marketing email, which is worth knowing before you promise them a newsletter. The card\'s header carries Call and Log a call beside Send email — see click to call. Beside the status, the header names every campaign the lead is filed under.\nCampaigns is the filing: Filed under campaigns offers the site\'s campaigns by name, and Save filing writes the pick. It is your own grouping — it never adds anyone to a send, because a campaign mails its lists — and it is the same picker the contact\'s Relationship card carries, so a lead and the contact it becomes are filed the same way.\nCaptured history is read-only: when the person was first and last seen, how many times your site captured them, every source that did, and — under Where this lead came from — the campaign the capture is credited to, when there is one. That is attribution, which campaign\'s link brought the person; the filing above is separate, and the card says so.\nEmail state {#email-state}\nBeside the status, a lead carries the last verdict on its address, when a sender has given one: Bounced (the mailbox does not exist), Blocked by their mail gateway (the company\'s mail filter refused the sender), U'
4009
+ text: 'Click a row to open the lead.\nLead holds what the team decides: the status and the owner. It also shows the identity the capture recorded — email and name — and the person\'s marketing consent: whether they opted in (and when), declined, or never recorded a choice. A lead with no recorded consent cannot be sent marketing email, which is worth knowing before you promise them a newsletter. The card\'s header carries Convert, Call and Log a call beside Send email — see click to call — and, once the lead converts, Open contact, Open company and Open deal in place of Convert. Beside the status, the header names every campaign the lead is filed under.\nDetails is the lead\'s profile — company, job title, phone, website, lead source, tags and address — with any custom lead fields under More fields, and free-text notes, all saved together by the one Save in the card\'s header. Once the lead converts, the profile is read-only here, because the contact is the record then; the notes can still be written.\nCampaigns is the filing: Filed under campaigns offers the site\'s campaigns by name, and Save filing in the card\'s header writes the pick. It is your own grouping — it never adds anyone to a send, because a campaign mails its lists — and it is the same picker the contact\'s Relationship card carries, so a lead and the contact it becomes are filed the same way.\nCaptured history is read-only: when the person was first and last seen, how many times your site captured them, every source that did, and — under Where this lead came from — the campaign the capture is credited to, when there is one. That is attribution, which campaign\'s link brought the person; the filing above is separate, and the card says so.\nEmail state {#email-state}\nBeside the status, a lead carries the last verdict on its '
4003
4010
  },
4004
4011
  {
4005
4012
  path: '/content-and-data/crm/leads',
@@ -4069,7 +4076,7 @@ export const ASSIST_DOCS_INDEX = [
4069
4076
  title: 'CRM',
4070
4077
  heading: 'The contacts page',
4071
4078
  anchor: '#the-contacts-page',
4072
- text: 'The Contacts section is the list the rest of the CRM is built on. It lets you:\n- Browse the list, with Owner and Stage columns and one optional column per custom field, and narrow it by stage, owner (Me included) and the rest through the table\'s Filters — see Filters on the Contacts list.\n- Add a contact by hand with New contact — see The contact record.\n- Open a contact\'s own page to edit their profile, see where they came from, and read their history.\n- Add tags and notes.\n- Log calls, emails, meetings and notes against a person, and read them in one timeline with everything the platform captured — see Activities & the timeline.\n- Tick rows and act on all of them at once — tag them, set their owner or stage, add them to an email audience, export them, or remove them from this site; see Bulk actions.\n- Export to CSV, and Import CSV — see below.\nThe Contacts section is part of the CRM, included from Starter. On Free it is shown locked in the rail with the rest of the CRM; the people your sites capture are still kept, and can be exported from Settings → Privacy.\nUnder the list, a Recent activity feed shows the newest calls, emails, meetings and notes anyone on the team has logged against any record.'
4079
+ text: 'The Contacts section is the list the rest of the CRM is built on. It lets you:\n- Browse the list, with Owner and Stage columns and one optional column per custom field, and narrow it by stage, owner (Me included) and the rest through the table\'s Filters — see Filters on the Contacts list.\n- Add a contact by hand with New contact — see The contact record.\n- Open a contact\'s own page to edit their profile, see where they came from, and read their history.\n- Add tags and notes.\n- Log calls, emails, meetings and notes against a person, and read them in one timeline with everything the platform captured — see Activities & the timeline.\n- Tick rows and act on all of them at once — tag them, set their owner or stage, add them to an email audience, export them, or remove them from this site; see Bulk actions.\n- Export to CSV, and Import CSV — see below.\nThe Contacts section is part of the CRM, included from Starter. On Free it is shown locked in the rail with the rest of the CRM; the people your sites capture are still kept, and can be exported from Settings → Privacy.\nUnder the list, a Recent activity card shows the newest calls, emails, meetings and notes anyone on the team has logged against any record, each collapsed to one row that opens to the rest. Import CSV, Export CSV and New contact are in the header of the Contacts card.'
4073
4080
  },
4074
4081
  {
4075
4082
  path: '/content-and-data/crm/overview',
@@ -4083,14 +4090,14 @@ export const ASSIST_DOCS_INDEX = [
4083
4090
  title: 'CRM',
4084
4091
  heading: 'Segments',
4085
4092
  anchor: '#segments',
4086
- text: 'Group contacts into segments — saved filters over tags and sources, kept from the Contacts list\'s filter bar through Save as segment… in the views menu — and target them directly in email campaigns. A saved view keeps more than a segment — every filter, the columns and the sort — and a contacts view can be an audience in its own right, picked beside a segment when an audience is built from a rule. An audience built from a rule can also read a contact\'s owner, lifecycle stage, company and custom fields; see email audiences.'
4093
+ text: 'Group contacts into segments — saved filters over tags and sources, kept from the Contacts list\'s filters through Save as segment… in the views menu — and target them directly in email campaigns. A saved view keeps more than a segment — every filter, the columns and the sort — and a contacts view can be an audience in its own right, picked beside a segment when an audience is built from a rule. An audience built from a rule can also read a contact\'s owner, lifecycle stage, company and custom fields; see email audiences.'
4087
4094
  },
4088
4095
  {
4089
4096
  path: '/content-and-data/crm/overview',
4090
4097
  title: 'CRM',
4091
4098
  heading: 'Everywhere the CRM shows up',
4092
4099
  anchor: '#everywhere-the-crm-shows-up',
4093
- text: 'The CRM is wired into the rest of the console rather than standing beside it. Every place a person\'s record is met links into the CRM, and the CRM links back out to the record that put the person there.\n| Where | Into the CRM | Out of the CRM |\n| Search (the top bar) | Contacts by name, email, phone or company; leads by name or email; companies by name or domain; deals by title. Each result opens the record. The CRM groups appear only for members who may open the CRM. | — |\n| Inbox | A submission row\'s ⋮ → Open contact in CRM; a member or lead row\'s Open in CRM. | A contact\'s timeline opens the submission that captured them, in the Inbox reader. |\n| Forms | A form\'s page: See the contacts this form captured in the CRM, and the CRM routing card. | — |\n| Products → Orders | An order\'s dialog: View customer in CRM. | The contact header\'s order count opens the orders list narrowed to the person\'s address; a timeline entry opens the order itself. |\n| Bookings | Each upcoming booking: View in CRM. | A timeline entry for a booking opens the Bookings page. |\n| Users | A site user\'s row menu: Open in CRM. | A timeline entry for a sign-up opens the Users page. |\n| Dashboard | The Inbox card counts the site\'s open leads and links to Leads; the CRM at a glance card\'s figures open Contacts, Deals and Tasks. The organization\'s Sites page carries CRM at a glance and Tasks due above the site grid, totaling every site and opening the organization-level hub. | — |\n| Marketing | — | The Relationship card\'s campaign attribution opens the campaign\'s page. |\n| Setup → Activity | — | Adding, deleting or converting a contact, company, deal or lead is logged, and each entry opens the record. |\nA link that arrives by a person\'s address — from an order, a booking or a site user — opens the Contac'
4100
+ text: 'The CRM is wired into the rest of the console rather than standing beside it. Every place a person\'s record is met links into the CRM, and the CRM links back out to the record that put the person there.\n| Where | Into the CRM | Out of the CRM |\n| Search (the top bar) | Contacts by name, email, phone or company; leads by name or email; companies by name or domain; deals by title. Each result opens the record. The CRM groups appear only for members who may open the CRM. | — |\n| Inbox | A submission row\'s ⋮ → Open contact in CRM; with the Site Members & Leads section\'s toggle on Leads, a lead row\'s ⋮ → Open in CRM. A member row has no CRM link. | A contact\'s timeline opens the submission that captured them, in the Inbox reader. |\n| Forms | A form\'s page: See the contacts this form captured in the CRM, and the CRM routing card. | — |\n| Products → Orders | An order\'s dialog: View customer in CRM. | The contact header\'s order count opens the orders list narrowed to the person\'s address; a timeline entry opens the order itself. |\n| Bookings | Each upcoming booking: View in CRM. | A timeline entry for a booking opens the Bookings page. |\n| Users | A site user\'s row menu: Open in CRM. | A timeline entry for a sign-up opens the Users page. |\n| Dashboard | The Inbox card counts the site\'s open leads and links to Leads; the CRM at a glance card\'s figures open Contacts, Deals and Tasks. The organization\'s Sites page carries CRM at a glance and Tasks due above the site grid, totaling every site and opening the organization-level hub. | — |\n| Marketing | — | The Relationship card\'s campaign attribution opens the campaign\'s page. |\n| Setup → Activity | — | Adding, deleting or converting a contact, company, deal or lead is logged, and each entry opens the record. |\nA link that arrives b'
4094
4101
  },
4095
4102
  {
4096
4103
  path: '/content-and-data/crm/overview',
@@ -4132,7 +4139,7 @@ export const ASSIST_DOCS_INDEX = [
4132
4139
  title: 'Reports',
4133
4140
  heading: 'Choosing a period',
4134
4141
  anchor: '#choosing-a-period',
4135
- text: 'A picker at the top of the page selects the window the flow reports measure: Last 7 days, Last 30 days (the default), Last 90 days or This month. A day period counts back from the moment you pick it; "This month" starts on the first of your calendar month. Each period is compared to the one before it of the same length — thirty days against the thirty before them, this month against last month — which is what the percentage next to a figure is measured against.\nThree cards ignore the period on purpose. The Pipeline, Forecast by close month and Tasks cards describe what is open now; "the pipeline over the last 30 days" would be a different question.\nEvery card with a table carries an Export CSV button — see Exporting a table.'
4142
+ text: 'A picker at the top of the page selects the window the flow reports measure: Last 7 days, Last 30 days (the default), Last 90 days or This month. A day period counts back from the moment you pick it; "This month" starts on the first of your calendar month. Each period is compared to the one before it of the same length — thirty days against the thirty before them, this month against last month — which is what the percentage next to a figure is measured against.\nThree cards ignore the period on purpose. The Pipeline, Forecast by close month and Tasks cards describe what is open now; "the pipeline over the last 30 days" would be a different question.\nEvery card with a table carries an Export CSV button in its header — see Exporting a table.'
4136
4143
  },
4137
4144
  {
4138
4145
  path: '/content-and-data/crm/reports',
@@ -4209,7 +4216,7 @@ export const ASSIST_DOCS_INDEX = [
4209
4216
  title: 'Reports',
4210
4217
  heading: 'Exporting a table',
4211
4218
  anchor: '#exporting-a-table',
4212
- text: 'Every card with a table — activity by teammate, conversion by source, the lead funnel, open tasks by assignee and the top open deals — has an Export CSV button beneath the table. The file holds exactly the rows on screen, in the same order with the same names and counts, so you can check it against the page; it is written in your browser from what the card has already read and costs no further reads.\nBecause the file is the loaded window, it has the window\'s limits: when a card is grouped from a bounded read — the 1,000 most recent activities, say — the caption beside the button says so, and the file holds the rows grouped from that window rather than from every record. The tiles above the table remain the server\'s count. Files are named for the card and the period, such as crm-activity-30d.csv; the two cards that have no period name none.'
4219
+ text: 'Every card with a table — activity by teammate, conversion by source, the lead funnel, open tasks by assignee and the top open deals — has an Export CSV button in the card\'s header. The file holds exactly the rows on screen, in the same order with the same names and counts, so you can check it against the page; it is written in your browser from what the card has already read and costs no further reads.\nBecause the file is the loaded window, it has the window\'s limits: when a card is grouped from a bounded read — the 1,000 most recent activities, say — the caption beside the button says so, and the file holds the rows grouped from that window rather than from every record. The tiles above the table remain the server\'s count. Files are named for the card and the period, such as crm-activity-30d.csv; the two cards that have no period name none.'
4213
4220
  },
4214
4221
  {
4215
4222
  path: '/content-and-data/crm/reports',
@@ -4279,7 +4286,7 @@ export const ASSIST_DOCS_INDEX = [
4279
4286
  title: 'Sequences',
4280
4287
  heading: 'Sequences',
4281
4288
  anchor: '#sequences',
4282
- text: 'A sequence is the emails, and the tasks between them, one person gets from one rep. Sequences → All sequences lists each one with its mailbox, its status, and how many people it has enrolled, and how many of them are still active, replied, bounced or opted out.\nThe list is newest first, a page at a time. The table\'s toolbar filters it. Filters narrows it by Status or Mailbox (pick one or several), by the name (a word in it, or the whole name), or by the day it was Created (on, before or after a date). Search finds a sequence by the start of any word of its name. Every filter and the search are answered by the database across all your sequences, not only the page on screen, and each filter in force shows as a chip above the table; remove a chip to drop its filter. The Filters panel edits one filter at a time, and filters on different columns add up. A combination the database cannot answer at once — a name word together with a search, for example — is named above the table rather than applied to some rows. See Filter and search a list.\nBuild a sequence {#build-a-sequence}\nSelect New sequence, name it, and choose the site whose CRM the people you enroll are contacts of and the mailbox it sends from. A sequence sends as the member who connected its mailbox, so only that member, or an organization owner or admin, can edit or activate it.\nThe Mailbox list offers the mailboxes you connected, and an owner or admin every mailbox in the organization. A disconnected mailbox is never offered. When exactly one of your own mailboxes is active, a new sequence starts on it. With none, connect one first.\nA sequence holds up to eight steps, of which up to four are emails:\n- Email — a subject and a body, or a CRM email template whose body is sent. Insert merge fields — the contact\'s firs'
4289
+ text: 'A sequence is the emails, and the tasks between them, one person gets from one rep. Sequences → All sequences lists each one with its mailbox, its status, and how many people it has enrolled, and how many of them are still active, replied, bounced or opted out.\nThe list is newest first, a page at a time. The table\'s toolbar filters it. Filters narrows it by Status or Mailbox (pick one or several), by Name (a word in it, or the whole name), or by the day it was Created (on, before or after a date). Search finds a sequence by the start of any word of its name. Every filter and the search are answered by the database across all your sequences, not only the page on screen, and each filter in force shows as a chip above the table; remove a chip to drop its filter. The Filters panel edits one filter at a time, and filters on different columns add up. A combination the database cannot answer at once — a name word together with a search, for example — is named above the table rather than applied to some rows. See Filter and search a list.\nBuild a sequence {#build-a-sequence}\nSelect New sequence, name it, and choose the site whose CRM the people you enroll are contacts of and the mailbox it sends from. A sequence sends as the member who connected its mailbox, so only that member, or an organization owner or admin, can edit or activate it.\nThe Mailbox list offers the mailboxes you connected, and an owner or admin every mailbox in the organization. A disconnected mailbox is never offered. When exactly one of your own mailboxes is active, a new sequence starts on it. With none, connect one first.\nA sequence holds up to eight steps, of which up to four are emails:\n- Email — a subject and a body, or a CRM email template whose body is sent. Insert merge fields — the contact\'s first na'
4283
4290
  },
4284
4291
  {
4285
4292
  path: '/content-and-data/crm/sequences',
@@ -4293,7 +4300,14 @@ export const ASSIST_DOCS_INDEX = [
4293
4300
  title: 'Sequences',
4294
4301
  heading: 'Enrollments',
4295
4302
  anchor: '#enrollments',
4296
- text: 'A sequence\'s Enrollments tab lists everyone in it: their status, the step they\'re on, when the next one is due in the mailbox\'s timezone, when the last one went, and why they stopped when they have. A person enrolled as a lead is marked Lead until the lead converts. For each one you can:\n- Pause and Resume — nothing is sent while they\'re paused. An enrollment the engine held because its mail gateway refused you twice is paused the same way, and Resume on it sends the email anyway.\n- Stop — they get nothing more from this sequence.\n- Mark do-not-contact — puts the address on your organization\'s do-not-contact list, which every sequence checks before every send, and stops them in every other sequence too.\nThe tab lists the people newest enrolled first, a page at a time, and its toolbar filters them. Filters narrows them by Status, Enrolled as (contact or lead) and Stop reason (pick one or several), by the whole Email address, or by the day they were Enrolled (on, before or after a date). Search finds a person by the start of any word of their name or of their address — casey, morgan or example.com all find casey.morgan@example.com. Every filter and the search are answered by the database across everyone in the sequence, not only the page on screen; a combination it cannot answer at once is named above the table instead of being applied to some rows. See Filter and search a list.'
4303
+ text: 'A sequence\'s Enrollments tab lists everyone in it: their status, the step they\'re on, when the next one is due in the mailbox\'s timezone, when the last one went, and why they stopped when they have. A person enrolled as a lead is marked Lead until the lead converts. For each one you can:\n- Pause and Resume — nothing is sent while they\'re paused. An enrollment the engine held because its mail gateway refused you twice is paused the same way, and Resume on it sends the email anyway.\n- Stop — they get nothing more from this sequence.\n- Mark do-not-contact — puts the address on your organization\'s do-not-contact list, which every sequence checks before every send, and stops them in every other sequence too.\nThe tab lists the people newest enrolled first, a page at a time, and its toolbar filters them. Filters narrows them by Status or Stop reason (pick one or several), by Enrolled as (contact or lead), by the whole Email address, or by the day they were Enrolled (on, before or after a date). Search finds a person by the start of any word of their name or of their address — casey, morgan or example.com all find casey.morgan@example.com. Every filter and the search are answered by the database across everyone in the sequence, not only the page on screen; a combination it cannot answer at once is named above the table instead of being applied to some rows. See Filter and search a list.\nOn a sequence that counts link clicks, the Clicks column shows how many times the person clicked and how many different links they followed — 2 · 1 link. Clicks made by security scanners aren\'t in it. Filters adds Clicked and Link followed, and the column chooser adds Links followed, Last click and Scanner clicks, which the export then includes. Stop reason shows the short reason; hover it for t'
4304
+ },
4305
+ {
4306
+ path: '/content-and-data/crm/sequences',
4307
+ title: 'Sequences',
4308
+ heading: 'See one person\'s history',
4309
+ anchor: '#person-history',
4310
+ text: 'Select a person\'s row — or focus it and press Enter — to open their page. Its address is theirs alone, so you can paste it into a comment or a message to point a teammate at one person. The page has three parts:\n- The header — their name and address, a Lead or Contact chip that opens their CRM record, their status, the step they\'re on and when the next one sends, with the same actions as the row\'s menu. A person held because their mail gateway refused you shows why, and Resume and send sends the email anyway. Under it, five numbers: emails sent, clicks, links followed, scanner clicks (which aren\'t counted) and replies.\n- Activity — everything that happened to them, newest first: when they were enrolled and by whom, each email with its subject as sent (and whether it was their curated copy), each link they followed with the full address and the email it came from, scanner visits with why they were read as a scanner, replies, bounces with what the receiving server said, holds, pauses, resumes and stops with who did it and why. Open thread in Gmail opens the conversation in the sending mailbox.\n- Details — closed until you open it: the personal line, the attestations, the mailbox, the campaigns, what your mail has met at their domain, each curated email in full, the Gmail threads and the enrollment\'s id.\nClicks are listed one at a time from the release that added this page. Clicks before it were kept only as a count, the times of the first and last, and the last link followed, so the page shows them as one line saying exactly that rather than guessing at the rest. Someone enrolled but not yet emailed shows Nothing yet and when their first step sends.'
4297
4311
  },
4298
4312
  {
4299
4313
  path: '/content-and-data/crm/sequences',
@@ -4412,7 +4426,7 @@ export const ASSIST_DOCS_INDEX = [
4412
4426
  title: 'Tasks & follow-ups',
4413
4427
  heading: 'The tasks page',
4414
4428
  anchor: '#the-tasks-page',
4415
- text: 'The Tasks section is one list with six views, chosen under Show in the table\'s Filters panel — My tasks unless you choose another:\n| View | What it shows |\n| My tasks | Open tasks assigned to you, soonest due first. Tasks with no due date come last. |\n| Overdue | Open tasks whose due date is before today. |\n| Today | Open tasks due at any time today. |\n| Upcoming | Open tasks due tomorrow or later. |\n| All open | Every open task, whoever it is assigned to. |\n| Done | Completed tasks, most recently due first. |\n"Overdue" and "today" are not stored on the task — nothing runs at midnight to stamp them. Each view is a window over the due date computed from your own clock and time zone when you look, and a tab left open across midnight repaints yesterday\'s work as overdue on its own.\nEach row shows a checkbox that completes or reopens the task, the title (with the first line of notes under it), the kind, the priority, the due date colored by where it stands — red when overdue, amber when due today — with a snooze beside it, the assignee, and the record it is for, as a link into that record\'s page. The list shows a view a page at a time, with the usual footer to pick how many rows a page holds and to turn to the next page.\nBeside Show, the Filters panel narrows a view by Kind (call, email, meeting, to-do), Priority (low, normal, high) and Assignee, and Search finds a task by a word of its title. The view, the filters and the search are all answered by the list\'s query, so they reach every task in the view, page by page, and add up with each other. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under a site, a member whose access is li'
4429
+ text: 'The Tasks section is one list with six views, chosen under Show in the table\'s Filters panel — My tasks unless you choose another:\n| View | What it shows |\n| My tasks | Open tasks assigned to you, soonest due first. Tasks with no due date come last. |\n| Overdue | Open tasks whose due date is before today. |\n| Today | Open tasks due at any time today. |\n| Upcoming | Open tasks due tomorrow or later. |\n| All open | Every open task, whoever it is assigned to. |\n| Done | Completed tasks, most recently due first. |\n"Overdue" and "today" are not stored on the task — nothing runs at midnight to stamp them. Each view is a window over the due date computed from your own clock and time zone when you look, and a tab left open across midnight repaints yesterday\'s work as overdue on its own.\nEach row shows a checkbox that completes or reopens the task, the title (with the first line of notes under it), the kind, the priority, the due date colored by where it stands — red when overdue, amber when due today — with a snooze beside it, the assignee, and the record it is for, as a link into that record\'s page. The list shows a view a page at a time, with the usual footer to pick how many rows a page holds and to turn to the next page.\nBeside Show, the Filters panel narrows a view by Kind (call, email, meeting, to-do), Priority (low, normal, high) and Assignee — each is one or is any of several — and Search finds a task by a word of its title. The view, the filters and the search are all answered by the list\'s query, so they reach every task in the view, page by page, and add up with each other. The search matches whole words from their start — "cof" finds Coffee, a fragment from the middle of a word does not — one word at a time: type several and it searches the first, and says so. Under'
4416
4430
  },
4417
4431
  {
4418
4432
  path: '/content-and-data/crm/tasks',
@@ -4503,21 +4517,21 @@ export const ASSIST_DOCS_INDEX = [
4503
4517
  title: 'Saved views',
4504
4518
  heading: 'Filters on the Contacts list',
4505
4519
  anchor: '#filters-on-the-contacts-list',
4506
- text: 'On the Contacts list the fields are the list\'s columns and a few that are not — owner, stage, source, company, tags, form, site, orders, lifetime value, the updated date, email verdict, next activity, and one field per custom field your organization has defined.\nEach field offers what the list\'s query can answer:\n| Field | Filter by |\n| Contact | The name contains a word, is exactly a name, starts with or ends with some letters. |\n| Email | is an address, or starts with some letters. |\n| Tags | contains a tag, any of several, or is not empty. |\n| Form ID | contains a form\'s ID — the form\'s own page links here with it. |\n| Site ID | is a site\'s ID, or any of several. |\n| Orders, Lifetime value | is not empty — the person has bought, or is worth something. Each site keeps its own figures on its own record of the person, where no range reaches, so there are no numeric ranges. |\n| Created | on, after or before a date. |\n| Updated | on, after or before a date. |\n| Next activity | is empty — no next activity scheduled. |\n| Owner, Stage | is one, any of several, or is not empty. |\n| Source | is one, or any of several. |\n| Company | is one, or is not empty. |\n| Email verdict | is one verdict, any of several, is empty (nothing known) or is not empty. |\n| A custom field | equals a choice, or any of several, for a choice field; equals for text or a number; is or is not ticked for a checkbox; is not empty for any. |\nSearch finds a person by a word of their name, their email addresses or their company, or by the digits of their phone number — the whole number, or its last seven or last four digits, typed without spaces or brackets. Tags have their own filter.\nCreated, and a name or address that starts with or ends with some letters, each order the list by their own field, so each st'
4520
+ text: 'On the Contacts list the fields are the list\'s columns and a few that are not — the address, source, company, form, site, orders, lifetime value, the created date, and one field per custom field your organization has defined.\nEach field offers what the list\'s query can answer:\n| Field | Filter by |\n| Contact | The name contains a word, equals a whole name, starts with or ends with some letters. |\n| Email (the address) | equals an address, or starts with some letters. |\n| Email (the verdict column) | is one verdict, or is any of several. |\n| Tags | contains a tag, is any of several, or is not empty. |\n| Form ID | contains a form\'s ID — the form\'s own page links here with it. |\n| Site ID | equals a site\'s ID, or is any of several. |\n| Orders, Lifetime value (cents) | is not empty — the person has bought, or is worth something. Each site keeps its own figures on its own record of the person, where no range reaches, so there are no numeric ranges. |\n| Created | is, is after, is on or after, is before or is on or before a date. |\n| Last activity | The same five date conditions, asked of when the contact\'s record last changed; its chip reads Updated. |\n| Next activity | is empty — no next activity scheduled. |\n| Owner, Stage | is one, or is any of several. Owner offers Me first. |\n| Source | is one, or is any of several. |\n| Company | is one. |\n| A custom field | is a choice, or is any of several, for a choice field; equals and is not empty for text; = and is not empty for a number; is not empty for a date; is ticked or not for a checkbox. |\nSearch finds a person by a word of their name, their email addresses or their company, or by the digits of their phone number — the whole number, or its last seven or last four digits, typed without spaces or brackets. Tags have their own'
4507
4521
  },
4508
4522
  {
4509
4523
  path: '/content-and-data/crm/views',
4510
4524
  title: 'Saved views',
4511
4525
  heading: 'Filters on the other lists',
4512
4526
  anchor: '#filters-on-the-other-lists',
4513
- text: '- Leads — Status, Email, Owner, Lead source and Campaign; the search finds a lead by a word of its name, email address, company, title or tags. Campaign and the search cannot be combined. See the leads list.\n- Companies — Company (is exactly, or starts with, which orders the list by name), Owner (one teammate, or any of several) and Next activity; the search finds a company by a word of its name or domain. See the companies list.\n- Deals (the table) — Status (open, won or lost; one, or any of them) and Next activity; the search finds a deal by any word of its title. See the board and the table.\n- Tasks — Show is the task view (My tasks, Overdue, Today, Upcoming, All open, Done); Kind, Priority and Assignee filter it, and the search finds a task by a word of its title.\nOn the contacts, companies and deals lists, Next activity › is empty keeps only the records with no open task scheduled against them (see next activity). Like every other filter, it is answered by the query and adds up with the rest.'
4527
+ text: '- Leads — Status, Email, Owner and Lead source (one, or any of several) and Campaign (one); the search finds a lead by a word of its name, email address, company, title or tags. Campaign and the search cannot be combined. See the leads list.\n- Companies — Company (equals, or starts with, which orders the list by name), Owner (one teammate, or any of several) and Next activity; the search finds a company by a word of its name or domain. See the companies list.\n- Deals (the table) — Status (open, won or lost; one, or any of them) and Next activity; the search finds a deal by any word of its title. See the board and the table.\n- Tasks — Show is the task view (My tasks, Overdue, Today, Upcoming, All open, Done); Kind, Priority and Assignee (one, or any of several) filter it, and the search finds a task by a word of its title. See the tasks page.\nOn the contacts, companies and deals lists, Next activity › is empty keeps only the records with no open task scheduled against them (see next activity). Like every other filter, it is answered by the query and adds up with the rest.'
4514
4528
  },
4515
4529
  {
4516
4530
  path: '/content-and-data/crm/views',
4517
4531
  title: 'Saved views',
4518
4532
  heading: 'Columns and sort',
4519
4533
  anchor: '#columns-and-sort',
4520
- text: 'Manage columns in any list\'s column menu chooses what shows, and Move left / Move right in the same menu put a column where you want it. A view keeps both — the choice and the order — and a view saved before a column existed shows the new column too, after the ones it names. On the Leads and Contacts lists the column headers do not sort: those lists keep their newest-first order.'
4534
+ text: 'Manage columns in any list\'s column menu chooses what shows, and Move left / Move right in the same menu put a column where you want it. A view keeps both — the choice and the order — and a view saved before a column existed shows the new column too, after the ones it names. On the Leads, Contacts and Tasks lists the column headers do not sort: each keeps its query\'s order — newest first, or for tasks soonest due first (Done: most recently due first). On the Companies and Deals tables a column header sorts the rows of the page on screen only; the pages themselves keep the list\'s own order.'
4521
4535
  },
4522
4536
  {
4523
4537
  path: '/content-and-data/crm/views',
@@ -4636,7 +4650,7 @@ export const ASSIST_DOCS_INDEX = [
4636
4650
  title: 'Datasets & Dynamic Content',
4637
4651
  heading: 'Filter and search the records',
4638
4652
  anchor: '#filter-records',
4639
- text: 'The records table filters through its own toolbar: Filters opens the filter panel, where each filterable field of the dataset\'s model is a column, and Search finds records by the words in their text. Each filter shows as a chip above the table, and removing the chip removes the filter. The panel and chips work as on every console list — see Filter and search a list.\nEvery filter and the search reach the whole dataset. They are answered by the database across every record, and the table pages through the matches exactly as it pages through the unfiltered dataset — nothing is matched only against the records already on screen. What each field type offers:\n| Field | Filters |\n| -- | -- |\n| Text with a fixed list of options | is, is any of — picked from the options |\n| True/false | is — picked |\n| Number | = |\n| Plain text | equals and is any of, ignoring case; contains a word |\n| List | contains one of its entries, spelled exactly as stored |\nDates, references, maps, bytes, coordinates and null fields are not filterable, and no field offers ranges (greater than, before, after), is not, or is empty — the panel does not show what the database cannot answer this way.\nContains and search match the start of a word. kett finds Kettle; ttle finds nothing. The search looks at every text field, option field and list of the record. Each asks for one word: type several and the table uses the first and says so above the records. A word is matched on its first 12 characters, a text value\'s first 40 words are searchable, and equals compares the first 64 characters of a text value.\nCombine as many is, equals, is any of and = filters as you like, but only one contains or search at a time. A second one — a contains while a search word is typed, or a contains on a second field — is not appl'
4653
+ text: 'The records table filters through its own toolbar: Filters opens the filter panel, where each filterable field of the dataset\'s model is a column, and Search finds records by the words in their text. Each filter shows as a chip above the table, and removing the chip removes the filter. The panel and chips work as on every console list — see Filter and search a list.\nEvery filter and the search reach the whole dataset. They are answered by the database across every record, and the table pages through the matches exactly as it pages through the unfiltered dataset — nothing is matched only against the records already on screen. The records run in one stable order, by each record\'s ID — the same on every load, though not the order they were added in — and the column headers don\'t re-sort them. What each field type offers:\n| Field | Filters |\n| -- | -- |\n| Text with a fixed list of options | is, is any of — picked from the options |\n| True/false | is — picked |\n| Number | = |\n| Plain text | equals and is any of, ignoring case; contains a word |\n| List | contains one of its entries, spelled exactly as stored |\nDates, references, maps, bytes, coordinates and null fields are not filterable, and no field offers ranges (greater than, before, after), is not, or is empty — the panel does not show what the database cannot answer this way.\nContains and search match the start of a word. kett finds Kettle; ttle finds nothing. The search looks at every text field, option field and list of the record. Each asks for one word: type several and the table uses the first and says so above the records. A word is matched on its first 12 characters, a text value\'s first 40 words are searchable, and equals compares the first 64 characters of a text value. A record keeps at most 500 filter terms; '
4640
4654
  },
4641
4655
  {
4642
4656
  path: '/content-and-data/datasets/overview',
@@ -4734,7 +4748,7 @@ export const ASSIST_DOCS_INDEX = [
4734
4748
  title: 'Events Calendar',
4735
4749
  heading: 'Manage events',
4736
4750
  anchor: '#manage-events',
4737
- text: 'The console Events page lists your site\'s events, newest start first. Add event opens the editor; each event has:\n- Title — required.\n- Starts and Ends — a start time is required; leaving the end blank (or setting it before the start) gives the event one hour.\n- Location and Organizer — both optional, and both shown next to the date.\n- Cover image URL — optional thumbnail, shown beside the event.\n- Description — optional detail paragraph.\nSet published / Set to draft flips an event\'s status, shown as a chip in the list. Delete removes an event from your site.\nDrafts never leave the console The public listing filters to published events on the server, so a draft is never sent to a visitor\'s browser — it\'s a safe place to stage next month\'s schedule.'
4751
+ text: 'The console Events page lists your site\'s events, newest start first. It has no filters or search, and it reads the newest 200 events: a site with more says so above Add event, and the older ones are not reachable from the list. Add event opens the editor; each event has:\n- Title — required.\n- Starts and Ends — a start time is required; leaving the end blank (or setting it before the start) gives the event one hour.\n- Location and Organizer — both optional, and both shown next to the date.\n- Cover image URL — optional thumbnail, shown beside the event.\n- Description — optional detail paragraph.\nSet published / Set to draft flips an event\'s status, shown as a chip in the list. Delete removes an event from your site.\nDrafts never leave the console The public listing filters to published events on the server, so a draft is never sent to a visitor\'s browser — it\'s a safe place to stage next month\'s schedule.'
4738
4752
  },
4739
4753
  {
4740
4754
  path: '/content-and-data/events/overview',
@@ -4811,7 +4825,7 @@ export const ASSIST_DOCS_INDEX = [
4811
4825
  title: 'Forms & Lead Capture',
4812
4826
  heading: 'Find a form in the list',
4813
4827
  anchor: '#find-a-form',
4814
- text: 'The Forms table filters through its toolbar by every column it shows:\n- Display name, by a word in it: contains "audit" finds "Multi-brand site audit".\n- Slug, exactly.\n- Submissions, as a number: equal to, over or under a number, or empty. A form that hasn\'t had a submission shows a dash, and is empty finds it.\n- Leads, equal to a number, or empty. A form counts a lead only once it files one, so a form that doesn\'t route to leads, or hasn\'t filed its first, shows a dash. Is empty finds those forms. No form stores a zero, so Leads = 0 finds none.\n- Last submission and Updated, as days: on, before or after a date. Last submission is set finds every form that has had a submission.\nTwo more columns stay hidden until you show them from Columns, and the Filters panel offers them either way: Status (active or retired) and Lead routing (on or off, the switch on the form\'s CRM routing card). Campaign finds the forms filed under any of the campaigns you pick. The panel lists the site\'s campaigns once you open it.\nSearch finds a form by a word of its name or slug, or by its ID. It looks for one word, the first you type, and says so when you type more.\nEvery filter and the search look through the whole catalog, not just the page on screen, and the pager turns through the matches. Filters on different columns add up, with one limit: one range at a time, meaning a number over or under, or a date before or after. A second range isn\'t applied, and the list says which one it left out. Retired forms stay out of the list until you ask for them: choose Status in the Filters panel and pick Retired to find one and restore it. See Filter and search a list.'
4828
+ text: 'The Forms table filters through its toolbar by every column it shows:\n- Display name, by the start of a word in it: contains "audit" finds "Multi-brand site audit".\n- Slug, equals the whole slug.\n- Submissions, as a number: =, !=, >, >=, < or <= a number, is empty or is not empty. A form that hasn\'t had a submission shows a dash, and is empty finds it.\n- Leads, = a number, or is empty. Leads counts the people the form filed as leads that are still in CRM → Leads: a visitor who submits twice is one lead. A form with the lead switch on shows 0 until its first lead, so Leads = 0 finds the lead forms that haven\'t filed one yet. A form that has never routed to leads shows a dash, and is empty finds it.\n- Last submission and Updated, as days: is, is after, is on or after, is before or is on or before a date. Last submission is not empty finds every form that has had a submission.\nThree more columns stay hidden until you show them from Columns, and the Filters panel offers them either way: Status (Active or Retired), Lead routing (On or Off, the switch on the form\'s CRM routing card) and In a campaign (Yes or No; No finds the forms filed under no campaign). Campaign finds the forms filed under any of the campaigns you pick, up to 30. The panel lists the site\'s campaigns once you open it.\nSubmissions, Leads and Last submission are recounted from what\'s left whenever a submission is deleted from the Inbox or a lead is erased, so they never count something you removed. Retiring or restoring a form, and taking it out of a deleted campaign, moves its Updated date.\nSearch finds a form by the start of a word of its name or slug, or the start of its ID. It looks for one word, the first you type, and says so when you type more.\nEvery filter and the search look through the whole catalog'
4815
4829
  },
4816
4830
  {
4817
4831
  path: '/content-and-data/forms/overview',
@@ -4846,7 +4860,7 @@ export const ASSIST_DOCS_INDEX = [
4846
4860
  title: 'Media Library & CDN',
4847
4861
  heading: 'Organize',
4848
4862
  anchor: '#organize',
4849
- text: '- Arrange media in a folder hierarchy. Folders appear as cards in the grid (folders first, before files) as well as in a side rail — open one to browse into it, and use the breadcrumb to step back out.\n- Drag and drop to reorganize: drag a file (or a whole selection) onto a folder to move it in, drag a folder onto another to nest it, or drop onto a breadcrumb to move items up and out. Nesting depth and name-collision rules are enforced automatically.\n- Move to folder… shows the full path, not just the folder name — Blog / Covers and Press / Covers are two different destinations and the menu says so. The same paths appear in the detail drawer\'s Folder field.\n- Big moves are safe to interrupt. Moving a large selection relocates the stored objects one at a time, so the library keeps working through it and tells you how far it has got. If it cannot finish everything, it reports the real split — Moved 7 of 19 — 12 could not be moved — and leaves the files that did not move selected, so clicking Move again picks up exactly where it stopped. Nothing is lost either way: a file is only ever in one folder, its URL keeps working, and a repeat move of a file that already arrived does nothing.\n- Filter, search and sort through the same toolbar as every other list in the console, in either of two views — see Filter and search and Grid and List views below.\n- Search finds a file by any word of its name — banner finds hero-banner2x.png, because a file name\'s words are split at dashes, dots and underscores as well as spaces. Results come from the whole library, however large, and ✕ (or Esc) clears the box.\n- Capture and edit metadata in a detail drawer — file name, alt text, description, tags, and your own custom key/value metadata (mirrored onto the delivered object\'s storage metadata)'
4863
+ text: '- Arrange media in a folder hierarchy. Folders appear as cards in the grid (folders first, before files) as well as in a side rail — open one to browse into it, and use the breadcrumb to step back out.\n- Drag and drop to reorganize: drag a file (or a whole selection) onto a folder to move it in, drag a folder onto another to nest it, or drop onto a breadcrumb to move items up and out. Nesting depth and name-collision rules are enforced automatically.\n- Move to folder… shows the full path, not just the folder name — Blog / Covers and Press / Covers are two different destinations and the menu says so. The same paths appear in the detail drawer\'s Folder field.\n- Big moves are safe to interrupt. Moving a large selection relocates the stored objects one at a time, so the library keeps working through it and tells you how far it has got. If it cannot finish everything, it reports the real split — Moved 7 of 19 — 12 could not be moved — and leaves the files that did not move selected, so clicking Move again picks up exactly where it stopped. Nothing is lost either way: a file is only ever in one folder, its URL keeps working, and a repeat move of a file that already arrived does nothing.\n- Filter, search and sort through the same toolbar as every other list in the console, in either of two views — see Filter and search and Grid and List views below.\n- Search finds a file by the start of any word of its name — banner finds hero-banner2x.png, because a file name\'s words are split at dashes, dots and underscores as well as spaces. Results come from the whole library, however large, and ✕ (or Esc) clears the box.\n- Capture and edit metadata in a detail drawer — file name, alt text, description, tags, and your own custom key/value metadata (mirrored onto the delivered object\'s stor'
4850
4864
  },
4851
4865
  {
4852
4866
  path: '/content-and-data/media/overview',
@@ -4860,7 +4874,7 @@ export const ASSIST_DOCS_INDEX = [
4860
4874
  title: 'Media Library & CDN',
4861
4875
  heading: 'Deliver over CDN',
4862
4876
  anchor: '#deliver-over-cdn',
4863
- text: 'Every plan serves media via a CDN with automatic WebP variants, so images load fast and cache well.\nURLs are stable\nA media URL is keyed to the asset, not to its bytes or its location. That means the link you copied stays correct when you:\n- Replace the file — every screen, layout, and content entry that embeds it serves the new file immediately, with no re-linking. A replaced video also drops the poster frame and any encoded versions of the old footage, so nothing left over is served under the new file\'s link.\n- Move it between folders — organizing your library never breaks a live page.\nSo replacing a logo across a whole site is one upload, not a hunt for every reference. Links copied before this behavior shipped keep working too.\nPage elements point at the asset, not at a link\nWhen you place an image with Browse media, the element records which asset you chose rather than a link to it. You never have to copy or paste a path, and the element keeps working through folder moves, file replacements, and any future change to how we deliver media. Copy URL is still there for pasting a link somewhere outside Aglyn.\nYou can also type any external image URL into the field by hand — useful for hotlinking an image hosted elsewhere. Images placed before this shipped keep rendering exactly as they did.\nWhat hotlinking means for your visitors {#hotlinking-and-your-visitors}\nHotlinking is a supported feature and we do not intend to remove it, but it has a consequence worth knowing before you rely on it: your visitor\'s browser fetches that file from that host directly, and we do not proxy it. Aglyn never sits in the middle of the request, so the host you named receives the visitor\'s IP address, their browser user-agent and the address of the page they are reading, and it can set its o'
4877
+ text: 'Every plan serves media via a CDN with automatic WebP variants, so images load fast and cache well.\nURLs are stable\nA media URL is keyed to the asset, not to its bytes or its location. That means the link you copied stays correct when you:\n- Replace the file — every screen, layout, and content entry that embeds it serves the new file immediately, with no re-linking. A replaced video also drops the poster frame and any encoded versions of the old footage, so nothing left over is served under the new file\'s link. The file\'s details are read from the new file, and your custom fields stay with the asset.\n- Move it between folders — organizing your library never breaks a live page.\nSo replacing a logo across a whole site is one upload, not a hunt for every reference. Links copied before this behavior shipped keep working too.\nPage elements point at the asset, not at a link\nWhen you place an image with Browse media, the element records which asset you chose rather than a link to it. You never have to copy or paste a path, and the element keeps working through folder moves, file replacements, and any future change to how we deliver media. Copy URL is still there for pasting a link somewhere outside Aglyn.\nYou can also type any external image URL into the field by hand — useful for hotlinking an image hosted elsewhere. Images placed before this shipped keep rendering exactly as they did.\nWhat hotlinking means for your visitors {#hotlinking-and-your-visitors}\nHotlinking is a supported feature and we do not intend to remove it, but it has a consequence worth knowing before you rely on it: your visitor\'s browser fetches that file from that host directly, and we do not proxy it. Aglyn never sits in the middle of the request, so the host you named receives the visitor\'s IP address, '
4864
4878
  },
4865
4879
  {
4866
4880
  path: '/content-and-data/media/overview',
@@ -4888,7 +4902,7 @@ export const ASSIST_DOCS_INDEX = [
4888
4902
  title: 'Media Library & CDN',
4889
4903
  heading: 'Reference',
4890
4904
  anchor: '#reference',
4891
- text: 'The details behind the screens above, for anyone wiring media into their own code.\nVariant widths {#variant-widths}\nAglyn generates WebP variants at 320, 640 and 1280 pixels wide when an image is uploaded. Those three are the whole set — there is no arbitrary resizing service behind the CDN URL.\nAdd ?w= to a CDN URL to ask for one: …/api/media/cdn/org:{orgId}/{mediaId}?w=640. A width the asset does not have generated is not an error and not a resize — the original bytes are served instead, so a ?w=200 request answers with the full-size file. Check the drawer\'s delivery line to see which widths a given file has.\n?download=1 on the same URL makes the response save rather than open in a tab. Both parameters are read after every access check, so neither widens what is served, and both are part of the cache key, so they cannot bleed into each other.\nTag limits {#tag-limits}\nTags are stored lower-cased and de-duplicated. A tag longer than 40 characters is dropped, and a file keeps at most 20 tags — entries past the twentieth are dropped rather than replacing an earlier one.\nOver the API\nMedia is read-only over the REST API: file names, sizes, dimensions, tags, folders, and both URL forms. See the Media API resource, including what it does not return.'
4905
+ text: 'The details behind the screens above, for anyone wiring media into their own code.\nVariant widths {#variant-widths}\nAglyn generates WebP variants at 320, 640 and 1280 pixels wide when an image is uploaded. Those three are the whole set — there is no arbitrary resizing service behind the CDN URL.\nAdd ?w= to a CDN URL to ask for one: …/api/media/cdn/org:{orgId}/{mediaId}?w=640. A width the asset does not have generated is not an error and not a resize — the original bytes are served instead, so a ?w=200 request answers with the full-size file. Check the drawer\'s delivery line to see which widths a given file has.\n?download=1 on the same URL makes the response save rather than open in a tab. Both parameters are read after every access check, so neither widens what is served, and both are part of the cache key, so they cannot bleed into each other.\nTag limits {#tag-limits}\nTags are stored lower-cased and de-duplicated. A tag longer than 40 characters is dropped, and a file keeps at most 20 tags — entries past the twentieth are dropped rather than replacing an earlier one.\nOver the API\nThe REST API lists and reads media — file names, sizes, dimensions, tags, folders, both URL forms, your custom fields and the details inside each file — and uploads new files. The same fields come back through Aglyn\'s MCP server. See the Media API resource, including what it does not return.'
4892
4906
  },
4893
4907
  {
4894
4908
  path: '/content-and-data/media/overview',
@@ -5441,7 +5455,7 @@ export const ASSIST_DOCS_INDEX = [
5441
5455
  title: 'Publisher handbook',
5442
5456
  heading: 'How installs work (the buyer side)',
5443
5457
  anchor: '#how-installs-work-the-buyer-side',
5444
- text: 'Browse is a catalog — cards link to the detail page, which is the only place an install happens. The buyer picks targets (all sites, selected sites, or org-wide for plugins), confirms a dialog that names exactly where the install lands, and the pin is written: your exact {version, sha256} pinned to the site or org, the plugin enabled for the workspace, loaded on their next visit. Buyers can uninstall from the listing\'s own detail page (Uninstall, or Uninstall org-wide for an org-scope pin) as well as from Marketplace → Installed — removing the pin and disabling it. Data your plugin created stays, so reinstalls resume cleanly. Paid listings require purchase before install; you see sales in your publisher ledger.\nThe detail page shows two install figures side by side: installs is the cumulative all-time total and only ever grows, while active counts the organizations and sites that currently hold a pin — it goes down when someone uninstalls. A big gap between the two is churn worth investigating.\nA purchase licenses the buyer\'s organization, and Marketplace → Licenses lists what the workspace holds and what the buyer bought across every workspace, one table each. Each table filters through its own toolbar: Search finds a license by a word of its listing\'s name, and Filters offers who bought it (You) on the workspace\'s table, and which workspace a purchase landed in — or Every workspace you belong to, for a purchase that names none — on the buyer\'s own. Both answer over every license, not the page on screen, and each filter in force shows as a chip above it; a word that more than 30 listing names share is refused with a note asking for more of it. See Filter and search a list.\nEvery listing shows its artifact type as a chip — Plugin, Component, Site template, Layout, Datas'
5458
+ text: 'Browse is a catalog — cards link to the detail page, which is the only place an install happens. The buyer picks targets (all sites, selected sites, or org-wide for plugins), confirms a dialog that names exactly where the install lands, and the pin is written: your exact {version, sha256} pinned to the site or org, the plugin enabled for the workspace, loaded on their next visit. Buyers can uninstall from the listing\'s own detail page (Uninstall, or Uninstall org-wide for an org-scope pin) as well as from Marketplace → Installed — removing the pin and disabling it. Data your plugin created stays, so reinstalls resume cleanly. Paid listings require purchase before install; you see sales in your publisher ledger.\nThe detail page shows two install figures side by side: installs is the cumulative all-time total and only ever grows, while active counts the organizations and sites that currently hold a pin — it goes down when someone uninstalls. A big gap between the two is churn worth investigating.\nA purchase licenses the buyer\'s organization, and Marketplace → Licenses lists what the workspace holds and what the buyer bought across every workspace, one table each. Each table filters through its own toolbar: Search finds a license by the start of a word of its listing\'s name, and Filters offers Bought by (You) on the workspace\'s table, and Licensed to — which workspace a purchase landed in, or Every workspace you belong to for a purchase that names none — on the buyer\'s own. Both answer over every license, not the page on screen, and each filter in force shows as a chip above it; the tables keep their own order and their column headers do not re-sort them. A word that more than 30 listing names share is refused with a note asking for more of it. See Filter and search a list'
5445
5459
  },
5446
5460
  {
5447
5461
  path: '/developers/plugins/publishing/publisher-handbook',
@@ -5644,7 +5658,7 @@ export const ASSIST_DOCS_INDEX = [
5644
5658
  title: 'Plugin-manager API reference',
5645
5659
  heading: 'Billing — `billing-webhook-hooks` (`/server`)',
5646
5660
  anchor: '#billing--billing-webhook-hooks-server',
5647
- text: 'registerBillingWebhookHandler(eventTypePrefix, handler) — receives the platform Stripe events. Handler errors propagate to a 500; make handlers idempotent. Handlers run sequentially with no error isolation, deliberately: isolating them would trade a duplicated side effect for a dropped one, which is the worse trade on a money path.\nA handler may return { claimed: true } to tell the platform it recognized the event as its own — it found the order, the purchase, the booking. Returning nothing keeps the previous meaning ("not mine"), so existing handlers need no change. Every registered handler still runs after one has claimed; the claim is a report, never a dispatch rule.\nClaim your chargebacks The one event where this matters today is charge.dispute.. A dispute carries no metadata, so plugins self-select by joining on the payment intent — and a plugin that finds nothing looks identical to a plugin that failed. The console route raises a staff alert for any dispute nothing claimed, because that is money moving with no record of it anywhere. If your plugin owns disputes, claim the ones it handles, or every one of them will be reported as a platform fault.\nA 500 does not always mean a redelivery A throw that reaches the route after any dispatch has begun makes the platform hold its Stripe-event idempotency claim instead of releasing it, so the redelivery short-circuits as a duplicate and your handler is not run again — the failure is recorded on the claim and escalated to staff to reconcile by hand. Releasing the claim would let a redelivery re-apply whatever the failed dispatch had already committed (an inventory decrement, a gift-card balance, a coupon redemption), and those cannot be un-applied.\nA throw raised before any dispatch began still releases the claim and is red'
5661
+ text: 'registerBillingWebhookHandler(eventTypePrefix, handler) — receives the platform Stripe events. Handler errors propagate to a 500; make handlers idempotent. Handlers run sequentially with no error isolation, deliberately: isolating them would trade a duplicated side effect for a dropped one, which is the worse trade on a money path.\nA handler may return { claimed: true } to tell the platform it recognized the event as its own — it found the order, the purchase, the booking. Returning nothing keeps the previous meaning ("not mine"), so existing handlers need no change. Every registered handler still runs after one has claimed; the claim is a report, never a dispatch rule.\nA claiming handler may also return the site the record belongs to, { claimed: true, hostId }. The platform reads it on a card\'s fraud signals (radar.earlyfraudwarning.created, review.opened, charge.dispute.created): the seller\'s fraud-pattern row names the sites the charges were for, whatever plugin sold them. To show a fraud signal on your own record, use paymentRiskEventFrom from @aglyn/aglyn/app-utils/payment-risk to read the event and recordPaymentRiskOnRecord from @aglyn/tenant-data-admin/server/payment-risk-record to stamp the shared paymentRisk field and notify the site\'s managers once. Render it with describePaymentRisk. Never refund or cancel on a signal; the merchant decides.\nClaim your chargebacks The one event where this matters today is charge.dispute.. A dispute carries no metadata, so plugins self-select by joining on the payment intent — and a plugin that finds nothing looks identical to a plugin that failed. The console route raises a staff alert for any dispute nothing claimed, because that is money moving with no record of it anywhere. If your plugin owns disputes, claim the ones it ha'
5648
5662
  },
5649
5663
  {
5650
5664
  path: '/developers/plugins/reference/plugin-manager-api',
@@ -5688,6 +5702,13 @@ export const ASSIST_DOCS_INDEX = [
5688
5702
  anchor: '#the-tenants-tax-rule--plugin-tax-profile-server',
5689
5703
  text: 'More than one plugin takes money, and a merchant has one tax profile. The plugin that keeps it answers what a flat rate adds to a charge and which regime a settled payment was taxed under; any other plugin that charges asks here instead of importing the owner\'s model.\n| API | Semantics |\n| registerPluginTaxProfile(profile, { pluginId? }) | A slot: a workspace has one tax profile, so a second plugin\'s is refused and the incumbent keeps serving. |\n| pluginTaxProfile() | The rule — and it throws when no plugin registered one. |\n| flatTax(rate, chargeCents, fallbackLabel) | { taxCents, label, pct }, exclusive and rounded to the cent. rate is the merchant\'s stored setting passed as read; an absent, zero, negative or out-of-range one answers all-zero and never throws. |\n| taxModeOf(settledPayment, manualTaxCents?) | The regime as the owner records it. manualTaxCents is tax the caller added as a line of its own, which the processor reports as none. |\n| pluginTaxProfileOwner() | The owner\'s plugin id, or null — for a caller that only wants to know who it is. |\nNo profile is a refusal, never a zero. Every other seam here answers null for "nobody home", and this one must not: a caller that read null as "no tax" would charge an untaxed total and record it as untaxed, and the merchant would owe the difference. A refused sale is seen the same day. It cannot happen in a working build — both apps load every plugin\'s server entry before a plugin handler, a cron or the billing webhook runs — and tax-profile-is-registered.spec.ts in each app runs the real registrars and holds the real rule, because a plugin\'s own spec may not import the owner.'
5690
5704
  },
5705
+ {
5706
+ path: '/developers/plugins/reference/plugin-manager-api',
5707
+ title: 'Plugin-manager API reference',
5708
+ heading: 'Recurring charges — `plugin-recurring-charges` (`/server`)',
5709
+ anchor: '#recurring-charges--plugin-recurring-charges-server',
5710
+ text: 'A security lockdown pauses the subscriptions a locked site sells to its own customers. If your plugin sells subscriptions, declare them so a lock can find them:\n| API | Semantics |\n| registerRecurringChargeSource(source, { pluginId? }) | Joins the core.recurring-charge-sources contract (multiple). Register it on the consoleApi surface, where the lockdown route runs. |\n| listRecurringChargeSources() | Every declared source with its plugin id. The lockdown asks each one; a source that throws is reported as a lookup error and the others still run. |\nAnswer from your own records, never by searching the payment provider. The lockdown pauses what you return with pausecollection[behavior]=void, records it, and the lift resumes exactly those. You never pause, resume or cancel anything yourself.'
5711
+ },
5691
5712
  {
5692
5713
  path: '/developers/plugins/reference/plugin-manager-api',
5693
5714
  title: 'Plugin-manager API reference',
@@ -5721,7 +5742,7 @@ export const ASSIST_DOCS_INDEX = [
5721
5742
  title: 'Plugin-manager API reference',
5722
5743
  heading: 'Platform events — `plugin-events` (`/server`)',
5723
5744
  anchor: '#platform-events--plugin-events-server',
5724
- text: 'Core raises the events; a plugin that must react to what a core route did subscribes from its serverDeclarations entry, so the subscription is in place before the first request. Payloads carry the actor and the before / after, never a reference to the plugin.\n| Event | Raised by | Payload |\n| org.seatAddons.changed | the add-on checkout and the billing webhook | { orgId, actor, before, after } — the org.seatAddons maps |\n| org.permissions.changed | the member, role and host-member routes | { orgId, actor, subject: { type, id?, name? }, permission, granted } |\n| billing.invoice.paid | the billing webhook, once the invoice resolves to a workspace | { orgId, invoiceId, amountPaidCents, currency, paidOutOfBand, metadata } |\n| billing.invoice.failed | the billing webhook | { orgId, invoiceId, amountDueCents, metadata } |\n| billing.invoice.closed | the billing webhook, on voided and on markeduncollectible | { orgId, invoiceId, reason: \'voided\' \\| \'uncollectible\', metadata } |\n| billing.dispute.opened | the billing webhook, on a dispute that matched a workspace | { orgId, chargeId, invoiceId, amountCents } |\n| billing.paymentMethod.changed | the billing webhook, after reading the customer\'s default | { orgId, defaultType } |\nThe five billing events carry the Stripe object\'s own metadata, which core does not read. A plugin that stamped its own id on an invoice it created recognizes its own by it; every other handler ignores the event. They are awaited in the route rather than deferred, because a plugin\'s decision about whether a workspace may keep spending must not lag the payment that settled it.'
5745
+ text: 'Core raises the events; a plugin that must react to what a core route did subscribes from its serverDeclarations entry, so the subscription is in place before the first request. Payloads carry the actor and the before / after, never a reference to the plugin.\n| Event | Raised by | Payload |\n| org.seatAddons.changed | the add-on checkout and the billing webhook | { orgId, actor, before, after } — the org.seatAddons maps |\n| org.permissions.changed | the member, role and host-member routes | { orgId, actor, subject: { type, id?, name? }, permission, granted } |\n| host.records.removed | the public API\'s deletes and a person\'s erasure, after the delete lands | { orgId, hostIds, collection, records: [{ id, data }] } — each removed document as it stood |\n| billing.invoice.paid | the billing webhook, once the invoice resolves to a workspace | { orgId, invoiceId, amountPaidCents, currency, paidOutOfBand, metadata } |\n| billing.invoice.failed | the billing webhook | { orgId, invoiceId, amountDueCents, metadata } |\n| billing.invoice.closed | the billing webhook, on voided and on markeduncollectible | { orgId, invoiceId, reason: \'voided\' \\| \'uncollectible\', metadata } |\n| billing.dispute.opened | the billing webhook, on a dispute that matched a workspace | { orgId, chargeId, invoiceId, amountCents } |\n| billing.paymentMethod.changed | the billing webhook, after reading the customer\'s default | { orgId, defaultType } |\nThe five billing events carry the Stripe object\'s own metadata, which core does not read. A plugin that stamped its own id on an invoice it created recognizes its own by it; every other handler ignores the event. They are awaited in the route rather than deferred, because a plugin\'s decision about whether a workspace may keep spending must not lag the payment that se'
5725
5746
  },
5726
5747
  {
5727
5748
  path: '/developers/plugins/reference/plugin-manager-api',
@@ -5791,7 +5812,7 @@ export const ASSIST_DOCS_INDEX = [
5791
5812
  title: 'Plugin-manager API reference',
5792
5813
  heading: 'Activity actions — `plugin-activity-actions`',
5793
5814
  anchor: '#activity-actions--plugin-activity-actions',
5794
- text: 'A plugin whose activity rows are read by more than a person stores a CODE (ai.job.output) and declares what it means:\n| API | Semantics |\n| registerPluginActivityActions({ pluginId, group, actions }) | Idempotent per plugin; a code another plugin declared refuses the registration. Declare it from both entries, in code that is sure to run: the register function your declarations entry calls, or the top level of a file your package.json lists in sideEffects. |\n| pluginActivityActionLabel(action) | What a reader sees for a code — activityActionLabel in the presenter reads it, so every feed, table and card shows the same words. |\n| listPluginActivityFilters() | One chip per group with the codes it keeps: the org feed and the actor table draw their chips from this, and send action isAnyOf …. |\n| pluginStaffAuditActionGroup(action) / pluginStaffAuditActionGroupLabel(group) | The staff audit facet\'s grouping: a registered group by code or by staffAuditPrefixes, else the action\'s leading namespace. |\n| isPluginStaffAuditAccess(action) | Whether a staff audit action is one a plugin\'s group names in staffAuditAccessActions — the actions its staff doors write when staff READ something rather than change it. The audit log files them as accesses. Matched exactly. |\nAn org activity row names its target, { type, id, name }. Core\'s target types are core\'s own resources; a plugin files a row about one of ITS resources under its own namespace, pluginId:noun (PluginActivityTargetType, e.g. outreach:mailbox), which the org log accepts without naming the plugin. The feed labels it by the noun (Mailbox), prefers the target\'s name wherever it has one, and links it nowhere.'
5815
+ text: 'A plugin whose activity rows are read by more than a person stores a CODE (ai.job.output) and declares what it means:\n| API | Semantics |\n| registerPluginActivityActions({ pluginId, group, actions }) | Idempotent per plugin; a code another plugin declared refuses the registration, and so does a group of more than 30 actions (PLUGINACTIVITYGROUPMAXACTIONS). Declare it from both entries, in code that is sure to run: the register function your declarations entry calls, or the top level of a file your package.json lists in sideEffects. |\n| pluginActivityActionLabel(action) | What a reader sees for a code — activityActionLabel in the presenter reads it, so every feed, table and card shows the same words. |\n| listPluginActivityFilters() | One chip per group with the codes it keeps: the org feed and the actor table draw their chips from this, and send action isAnyOf … on the list\'s query — which holds at most 30 values, which is why a group is capped at 30 codes. |\n| pluginStaffAuditActionGroup(action) / pluginStaffAuditActionGroupLabel(group) | The staff audit facet\'s grouping: a registered group by code or by staffAuditPrefixes, else the action\'s leading namespace. |\n| isPluginStaffAuditAccess(action) | Whether a staff audit action is one a plugin\'s group names in staffAuditAccessActions — the actions its staff doors write when staff READ something rather than change it. The audit log files them as accesses. Matched exactly. |\nAn org activity row names its target, { type, id, name }. Core\'s target types are core\'s own resources; a plugin files a row about one of ITS resources under its own namespace, pluginId:noun (PluginActivityTargetType, e.g. outreach:mailbox), which the org log accepts without naming the plugin. The feed labels it by the noun (Mailbox), prefers the targe'
5795
5816
  },
5796
5817
  {
5797
5818
  path: '/developers/plugins/reference/plugin-manager-api',
@@ -6372,7 +6393,7 @@ export const ASSIST_DOCS_INDEX = [
6372
6393
  title: 'Search the console',
6373
6394
  heading: 'What it does not search',
6374
6395
  anchor: '#what-it-does-not-search',
6375
- text: 'Being precise about this matters — an empty result should mean "you do not have one", not "search could not see it".\n- Orders and bookings are not searchable. They are found on their own pages, which have their own filters.\n- Media has its own, richer search on the Media page, including wildcards and searching by tag or custom field. See the media library.\n- Other workspaces. Search only ever covers the workspace named in the page address you are on.\n- Other people\'s sites. You only ever see sites you are a member of.'
6396
+ text: 'Being precise about this matters — an empty result should mean "you do not have one", not "search could not see it".\n- Orders and bookings are not searchable. They are found on their own pages, which have their own filters.\n- Media has its own search and filters on the Media page: search by the start of a word in a file name, and filter by type, tags, upload date and more. See the media library.\n- Other workspaces. Search only ever covers the workspace named in the page address you are on.\n- Other people\'s sites. You only ever see sites you are a member of.'
6376
6397
  },
6377
6398
  {
6378
6399
  path: '/getting-started/console-search',
@@ -6407,7 +6428,7 @@ export const ASSIST_DOCS_INDEX = [
6407
6428
  title: 'The console tour',
6408
6429
  heading: 'Filter and search a list',
6409
6430
  anchor: '#filter-and-search',
6410
- text: 'Most lists in the console are tables with the same toolbar above them: Columns shows and hides columns, Filters narrows the rows, Export downloads the table, and Search finds rows by their words. They work the same way on every list. A list drawn as cards rather than a table — such as All Sites — keeps its cards and has the same Search box, Filters panel and chips above them.\n- Filters opens a panel that edits one filter at a time: pick a column, an operator and a value. Pick another column and set it too, and both apply — filters on different columns add up, and each column holds one filter. Clearing the value, or deleting the panel\'s row, drops that column\'s filter.\n- Chips above the table show every filter in force, each read as a sentence such as "Status is Live". The panel shows one filter at a time; the chips show them all. Remove a chip to drop its filter.\n- Search finds records by the start of a word in the things that list searches — each list\'s page names them. It matches one word at a time: type "acm" and "Acme Coffee" is found; type two words and the list searches the first and says so. A word is read up to its first 12 letters. Search adds to the filters, and an empty box shows the list unfiltered again.\n- The pager at the foot of the table then turns through the matches, not the whole list.\nEvery filter and every search word is answered by the list\'s query, across the whole list — never only the rows already on screen. A record that matches is found whether it would have been on the first page or the fortieth. Two limits follow from asking one query:\n- A filter a query can\'t answer isn\'t offered. The panel lists only the columns and operators the list can look up.\n- A combination one query can\'t hold is refused by name. A note above the list names the filt'
6431
+ text: 'Most lists in the console are tables with the same toolbar above them: Columns shows and hides columns, Filters narrows the rows, Export downloads the table, and Search finds rows by their words. They work the same way on every list. A list drawn as cards rather than a table — such as All Sites — keeps its cards and has the same Search box, Filters panel and chips above them.\n- Filters opens a panel that edits one filter at a time: pick a column, an operator and a value. Pick another column and set it too, and both apply — filters on different columns add up, and each column holds one filter. Clearing the value, or deleting the panel\'s row, drops that column\'s filter.\n- Chips above the table show every filter in force, each read as a sentence such as "Status is Suspended". The panel shows one filter at a time; the chips show them all. Remove a chip to drop its filter.\n- Search finds records by the start of a word in the things that list searches — each list\'s page names them. It matches one word at a time: type "acm" and "Acme Coffee" is found; type two words and the list searches the first and says so. A word is read up to its first 12 letters. Search adds to the filters, and an empty box shows the list unfiltered again.\n- The pager at the foot of the table then turns through the matches, not the whole list.\nEvery filter and every search word is answered by the list\'s query, across the whole list — never only the rows already on screen. A record that matches is found whether it would have been on the first page or the fortieth. Two limits follow from asking one query:\n- A filter a query can\'t answer isn\'t offered. The panel lists only the columns and operators the list can look up.\n- A combination one query can\'t hold is refused by name. A note above the list names the'
6411
6432
  },
6412
6433
  {
6413
6434
  path: '/getting-started/console-tour',
@@ -6428,7 +6449,7 @@ export const ASSIST_DOCS_INDEX = [
6428
6449
  title: 'The console tour',
6429
6450
  heading: 'The Sites list',
6430
6451
  anchor: '#the-sites-list',
6431
- text: 'All Sites is the front door of a workspace: one card per site, for the workspace currently selected in the switcher, in name order. A site you can reach in another organization isn\'t missing — it\'s behind the workspace switcher.\nEach card carries:\n- The site\'s display name as the title, with its hostname underneath as the subheader — the custom domain when the site has one, otherwise its name.aglyn.app address. Both are also listed inside the card, as Aglyn Domain and Custom Domain.\n- A status pill (below).\n- Visit, which opens the live site in a new tab, and Manage, which opens that site\'s dashboard in the console.\nAbove the cards are a Search box and a Filters button — the same controls a table\'s toolbar has, over the cards. Search finds a site by the start of any word of its name, its slug (the name in name.aglyn.app) or its custom domain: harbor, bakery and shop.harbor all find Harbor Bakery at shop.harbor-bakery.com. Filters narrows the cards by Custom domain (Connected or None) and by the date a site was Created (on, before or after a day). Each filter in force shows as a chip above the cards; remove a chip to drop it. A filter on the created date lists the cards newest first.\nThe search and the filters are answered by the query that reads the cards, across every site you have in the workspace, not only the cards on screen. The cards come twelve at a time; Load more adds the next twelve that match. The site count beside the heading always counts every site. Status, plan, owner and the last-updated date are not filters: a site\'s status can change with no save at all (a timed suspension ends on its own), and a site doesn\'t store its plan, owner or template. See Filter and search a list.\nThe status pill {#the-status-pill}\n| Pill | Hover tells you |\n| Live (green) | H'
6452
+ text: 'All Sites is the front door of a workspace: one card per site, for the workspace currently selected in the switcher, in name order. A site you can reach in another organization isn\'t missing — it\'s behind the workspace switcher.\nEach card carries:\n- The site\'s display name as the title, with its hostname underneath as the subheader — the custom domain when the site has one, otherwise its name.aglyn.app address. Both are also listed inside the card, as Aglyn Domain and Custom Domain.\n- A status pill (below).\n- Visit, which opens the live site in a new tab, and Manage, which opens that site\'s dashboard in the console.\nAbove the cards are a Search box and a Filters button — the same controls a table\'s toolbar has, over the cards. Search finds a site by the start of any word of its name, its slug (the name in name.aglyn.app) or its custom domain: harbor, bakery and shop.harbor all find Harbor Bakery at shop.harbor-bakery.com. Filters narrows the cards by Custom domain (Connected or None) and by the day a site was Created — is, after, on or after, before or on or before a day. Each filter in force shows as a chip above the cards; remove a chip to drop it. A filter on the created date lists the cards newest first instead of by name.\nThe search and the filters are answered by the query that reads the cards, across every site you have in the workspace, not only the cards on screen. The cards come twelve at a time; Load more adds the next twelve that match. The site count opposite the heading always counts every site. Status, plan, owner and the last-updated date are not filters: a site\'s status can change with no save at all (a timed suspension ends on its own), and a site doesn\'t store its plan, owner or template. See Filter and search a list.\nThe status pill {#the-status-pill'
6432
6453
  },
6433
6454
  {
6434
6455
  path: '/getting-started/console-tour',
@@ -6449,7 +6470,7 @@ export const ASSIST_DOCS_INDEX = [
6449
6470
  title: 'The console tour',
6450
6471
  heading: 'Workspace settings & notifications',
6451
6472
  anchor: '#workspace-settings--notifications',
6452
- text: 'Organization-wide settings (name, workspace URL) live under Organization → Settings, which also holds Profile, API keys, Branding, Single sign-on, Privacy, Ownership and Delete. Turning plugins on and off for the workspace is its own section, Organization → Plugins — Marketplace is for finding and installing new ones, not for administering what you already run:\nThe notifications feed\nYour in-app notification feed — billing, publishing, workflow failures — lives under Notifications, which has two sections in the rail on the left: All notifications and Settings. The first shows what arrived, newest first, with Mark all read above it. The feed\'s Filters narrows it by Type (one type, or several) and by Status (New or Read), and both can stand together. Each filter in force shows as a chip above the feed; remove the chip to drop it. The filters apply to the whole feed, not just the page on screen, and the pager then turns through the matches; see Filter and search a list. There is no search box, because a notification\'s words are not indexed:\nNotification settings\nEverything about what reaches you lives on the second section, Settings.\nWhat you are told about is a table: one row per category, one column for In console and one for Email. Each row says what arrives in that category, so you are never switching off a bucket you would have to guess the contents of.\n- In console is on for every category. Switching it off stops that category appearing in the feed and in the bell.\n- Email is off for every category. Switch one on and you also get a message in your inbox when one of those notifications arrives. This does not touch the mail Aglyn already sends you — invites, verification, receipts, password resets and dunning are separate, and are not affected by anything on this page.'
6473
+ text: 'Organization-wide settings (name, workspace URL) live under Organization → Settings, which also holds Profile, API keys, Branding, Single sign-on, Privacy, Ownership and Delete. Turning plugins on and off for the workspace is its own section, Organization → Plugins — Marketplace is for finding and installing new ones, not for administering what you already run:\nThe notifications feed\nYour in-app notification feed — billing, publishing, workflow failures — lives under Notifications, which has two sections in the rail on the left: All notifications and Settings. The first shows what arrived, newest first, with Mark all read above it. The feed\'s Filters narrows it by Type (is one type, or is any of up to thirty — a larger pick is refused, with a note above the feed) and by Status (is New or Read), and both can stand together. Each filter in force shows as a chip above the feed; remove the chip to drop it. The filters apply to the whole feed, not just the page on screen, and the pager then turns through the matches; see Filter and search a list. There is no search box, because a notification\'s words are not indexed:\nNotification settings\nEverything about what reaches you lives on the second section, Settings.\nWhat you are told about is a table: one row per category, one column for In console and one for Email. Each row says what arrives in that category, so you are never switching off a bucket you would have to guess the contents of.\n- In console is on for every category. Switching it off stops that category appearing in the feed and in the bell.\n- Email is off for every category. Switch one on and you also get a message in your inbox when one of those notifications arrives. This does not touch the mail Aglyn already sends you — invites, verification, receipts, password res'
6453
6474
  },
6454
6475
  {
6455
6476
  path: '/getting-started/create-a-site',
@@ -6463,7 +6484,7 @@ export const ASSIST_DOCS_INDEX = [
6463
6484
  title: 'Create a site',
6464
6485
  heading: 'Create your first site',
6465
6486
  anchor: '#create-your-first-site',
6466
- text: '1. Sign in to the console.\n2. Open the site switcher in the app bar (top-left) and choose Create site.\n3. Give it a name. Aglyn generates a working subdomain immediately, so the site has a real address from the first moment — you can attach a custom domain later. The address resolves right away, but it has nothing to serve until you publish a screen at the site root, so a brand-new site answers its own URL with a not-found page. Starting from a starter template creates and publishes a home page for you; building by hand, that\'s your first screen.\n4. You land on the new site\'s Setup page (titled Host Setup), with tabs for Basic details, SEO, Theme, Custom Domain, Emails, and Activity. To start building rather than configuring, use the Screens tab in the site navigation — see Publish your first screen.\nName collisions Site names must be unique enough to generate a valid subdomain. If a name is taken, the console suggests an available variation.'
6487
+ text: '1. Sign in to the console.\n2. Open the site switcher in the app bar (top-left) and choose Create site.\n3. Give it a name. Aglyn generates a working subdomain immediately, so the site has a real address from the first moment — you can attach a custom domain later. The address resolves right away, but it has nothing to serve until you publish a screen at the site root, so a brand-new site answers its own URL with a not-found page. Starting from a starter template creates and publishes a home page for you; building by hand, that\'s your first screen.\n4. You land on the new site\'s Setup page (titled Host Setup), with tabs for Basic details, SEO, Tracking, Theme, and Emails; the custom domain and the activity log are under Admin. To start building rather than configuring, use the Screens tab in the site navigation — see Publish your first screen.\nName collisions Site names must be unique enough to generate a valid subdomain. If a name is taken, the console suggests an available variation.'
6467
6488
  },
6468
6489
  {
6469
6490
  path: '/getting-started/create-a-site',
@@ -6533,14 +6554,14 @@ export const ASSIST_DOCS_INDEX = [
6533
6554
  title: 'Build & publish a survey',
6534
6555
  heading: '',
6535
6556
  anchor: '',
6536
- text: 'Build & publish a survey\nThis walkthrough strings together datasets, the Besigner\'s form elements, and publishing into one loop: model the responses → design the survey → publish → collect. By the end you have a live survey page whose submissions land in a typed dataset you can filter, sort, and export.\nPlan availability Forms and the inbox are available on every plan. Writing submissions into a dataset needs the data store, which unlocks on Starter and above.'
6557
+ text: 'Build & publish a survey\nThis walkthrough strings together datasets, the Besigner\'s form elements, and publishing into one loop: model the responses → design the survey → publish → collect. By the end you have a live survey page whose submissions land in a typed dataset you can filter, search, and export.\nPlan availability Forms and the inbox are available on every plan. Writing submissions into a dataset needs the data store, which unlocks on Starter and above.'
6537
6558
  },
6538
6559
  {
6539
6560
  path: '/guides/build-and-publish-a-survey',
6540
6561
  title: 'Build & publish a survey',
6541
6562
  heading: '1. Create the dataset',
6542
6563
  anchor: '#1-create-the-dataset',
6543
- text: 'Datasets belong to your organization, so every site can share them. Open the organization Data page (or any site\'s Data page — both edit the same data).\n1. Choose Add dataset. In the New dataset dialog give it a Name (say Survey responses) and a comma-separated list of Fields (satisfaction, visit, topics, comments) — at least one, or Create stays disabled. Create it.\n2. Select your new dataset in the Dataset dropdown and open Schema. The Schema dialog lists each field with its display name, generated field id, and a type chip.\n3. Use Add field / Edit to type the fields properly:\n- satisfaction → type Integer. A form stores every value as text, so the rating lands as "4"; the Data page\'s filter and sort still compare it as a number.\n- visit → type Text (one radio choice).\n- topics → type Text (ticked checkboxes arrive joined with , ).\n- comments → type Text.\n4. Save schema.\nEach field\'s Display name is what you see in dialogs and table headers; the field id next to it (a slug generated once from the display name) is the stable key records store values under — the key {{item.fieldId}} bindings reference, and what a form field\'s Maps to schema field picker stores. Renaming the display name later never changes the id.\nModel first A clean schema now makes everything downstream typed: the record editor renders the right input per field and imports are validated. Form submissions are the exception — they are stored as text without validation, so a submitted value can disagree with its field\'s type. See the datasets deep-dive for the full type system.'
6564
+ text: 'Datasets belong to your organization, so every site can share them. Open the organization Data page (or any site\'s Data page — both edit the same data).\n1. Choose Add dataset. In the New dataset dialog give it a Name (say Survey responses) and a comma-separated list of Fields (satisfaction, visit, topics, comments) — at least one, or Create stays disabled. Create it.\n2. Select your new dataset in the Dataset dropdown and open Schema. The Schema dialog lists each field with its display name, generated field id, and a type chip.\n3. Use Add field / Edit to type the fields properly:\n- satisfaction → type Integer. A form stores every value as text, so the rating lands as "4"; the Data page\'s = filter still matches it as the number 4.\n- visit → type Text (one radio choice).\n- topics → type Text (ticked checkboxes arrive joined with , ).\n- comments → type Text.\n4. Save schema.\nEach field\'s Display name is what you see in dialogs and table headers; the field id next to it (a slug generated once from the display name) is the stable key records store values under — the key {{item.fieldId}} bindings reference, and what a form field\'s Maps to schema field picker stores. Renaming the display name later never changes the id.\nModel first A clean schema now makes everything downstream typed: the record editor renders the right input per field and imports are validated. Form submissions are the exception — they are stored as text without validation, so a submitted value can disagree with its field\'s type. See the datasets deep-dive for the full type system.'
6544
6565
  },
6545
6566
  {
6546
6567
  path: '/guides/build-and-publish-a-survey',
@@ -6582,7 +6603,7 @@ export const ASSIST_DOCS_INDEX = [
6582
6603
  title: 'Build & publish a survey',
6583
6604
  heading: '7. Watch responses arrive',
6584
6605
  anchor: '#7-watch-responses-arrive',
6585
- text: 'Every submission does three things:\n- appends a record to Survey responses — the Data page updates live;\n- files an inbox copy under the form\'s name (see Forms & lead capture);\n- fires the formSubmission automation event, so workflows and actions can react (send a thank-you alert, notify your team, write other datasets).\nOn the Data page, use Filter (satisfaction >= 4) and Sort (satisfaction desc) over the loaded records, and export everything with the CSV / JSON buttons.\nChart it Bind a container\'s Repeat over dataset to Survey responses and reference {{item.satisfaction}} inside it to render responses back onto a (members-only?) results screen. The deep-dive covers repeatables.'
6606
+ text: 'Every submission does three things:\n- appends a record to Survey responses — the Data page updates live;\n- files an inbox copy under the form\'s name (see Forms & lead capture);\n- fires the formSubmission automation event, so workflows and actions can react (send a thank-you alert, notify your team, write other datasets).\nOn the Data page, use Filters (satisfaction = 5) or Search (a word from the comments) to narrow the records. Both reach every record in the dataset, not only the page on screen; a number field offers = but no ranges, and the column headers don\'t sort. See Filter and search the records. Export everything with the CSV / JSON buttons.\nChart it Bind a container\'s Repeat over dataset to Survey responses and reference {{item.satisfaction}} inside it to render responses back onto a (members-only?) results screen. The deep-dive covers repeatables.'
6586
6607
  },
6587
6608
  {
6588
6609
  path: '/guides/build-and-publish-a-survey',
@@ -6687,7 +6708,7 @@ export const ASSIST_DOCS_INDEX = [
6687
6708
  title: 'Commerce end to end',
6688
6709
  heading: '5. Run orders from the console',
6689
6710
  anchor: '#5-run-orders-from-the-console',
6690
- text: 'The Products hub\'s Orders tab lists every sale with product, period, status, and channel filters plus Export CSV and Draft order (build an order by hand and send a payment link).\nExport CSV writes the orders currently shown — the filters apply — as orders.csv, one row per order: date, product, amountUsd, feeUsd, customerEmail, coupon, orderId, status, channel, refundedUsd, netUsd. amountUsd is the gross charge, so subtract refundedUsd (or read netUsd) when reconciling against a Stripe payout. Orders with several line items name the first and count the rest, e.g. Blue Mug +2 more.\nOpen an order for the detail dialog — customer, line items, totals, timeline, and internal notes:\n- Fulfill… — enter a carrier and tracking number; the order moves to fulfilled and the buyer\'s account page shows the tracking. Mark delivered closes the loop, and Packing slip prints one.\n- Refund — confirms "Refund this order?", then refunds the buyer through Stripe (full or partial) and reverses the platform fee. Site-admin role only.\n- Cancel order — for orders that shouldn\'t proceed (does not auto-refund).\nStatuses move through a guarded machine: pending → paid → fulfilled → delivered, with cancel/refund exits — see the orders reference.'
6711
+ text: 'The Products hub\'s Orders tab lists every sale, newest first. Its Search finds an order by the start of a word in its number, the buyer\'s email or an item\'s name, and Filters narrows it by order number, product, date, status, channel, customer and dispute — across every order in the store, not only the page on screen (see The Orders screen for what combines). Beside it sit Export CSV and Draft order (build an order by hand and send a payment link).\nExport CSV writes every order the filters and the search match, up to 5,000, as orders.csv, one row per order: date, product, amountUsd, feeUsd, customerEmail, coupon, orderId, status, channel, refundedUsd, netUsd. amountUsd is the gross charge, so subtract refundedUsd (or read netUsd) when reconciling against a Stripe payout. Orders with several line items name the first and count the rest, e.g. Blue Mug +2 more.\nOpen an order for the detail dialog — customer, line items, totals, timeline, and internal notes:\n- Fulfill… — enter a carrier and tracking number; the order moves to fulfilled and the buyer\'s account page shows the tracking. Mark delivered closes the loop, and Packing slip prints one.\n- Refund — confirms "Refund this order?", then refunds the buyer through Stripe (full or partial) and reverses the platform fee. Site-admin role only.\n- Cancel order — for orders that shouldn\'t proceed (does not auto-refund).\nStatuses move through a guarded machine: pending → paid → fulfilled → delivered, with cancel/refund exits — see the orders reference.'
6691
6712
  },
6692
6713
  {
6693
6714
  path: '/guides/commerce-end-to-end',
@@ -6960,7 +6981,7 @@ export const ASSIST_DOCS_INDEX = [
6960
6981
  title: 'Member accounts',
6961
6982
  heading: '5. Manage members from the console',
6962
6983
  anchor: '#5-manage-members-from-the-console',
6963
- text: 'The site\'s Users page has two cards: Site users (your members — this guide) and Users (console collaborators). The Site users card is paged, newest first, with Email, Name, Joined, and Status columns. Its search box finds a member by the start of any word of their name or their email address — rae, donovan or example.com all find Rae Donovan at rae@example.com, and a member who never gave a name is found by their address. Filters in the table\'s toolbar narrows it by Email (the whole address), Name (a word of it, or the whole name), Joined (on a day, or before or after a date) and Status (Active or Suspended). The filters and the search add up, and every one is answered by the query that reads the list, across every member rather than the page on screen. Name contains and the search each look for one word, and one query can look for only one: while a search is typed, a Name-contains filter is not applied, and a notice above the table says so. Each filter in force shows as a chip above the table; see Filter and search a list. For members who may open the CRM, each row\'s ⋮ menu holds Open in CRM — the member\'s contact, found by the address they signed up with.\nClick a member to open the member drawer:\n- Profile — email, display name, and join date, with a Suspended chip when applicable.\n- Lifetime purchases — charged order totals minus refunds (pending and canceled orders excluded).\n- Orders — the member\'s payment history, newest first: order number, status, total, date, any refunded amount, and the Stripe payment reference. Needs the editor or admin role on the site.\n- Subscriptions — each with its renewal date and status chip.\n- Addresses — the member\'s saved addresses.\nSuspend & reactivate\nThe drawer\'s action button flips between Suspend member and Reactivate member, ea'
6984
+ text: 'The site\'s Users page has two cards: Site users (your members — this guide) and Users (console collaborators). The Site users card is paged, newest first, with Email, Name, Joined, and Status columns. Its search box finds a member by the start of any word of their name or their email address — rae, donovan or example.com all find Rae Donovan at rae@example.com, and a member who never gave a name is found by their address. Filters in the table\'s toolbar narrows it by Email (equals the whole address), Name (contains a word of it, or equals the whole name), Joined (is, is after, is on or after, is before or is on or before a day) and Status (is Active or Suspended). The filters and the search add up, and every one is answered by the query that reads the list, across every member rather than the page on screen. Name contains and the search each look for one word, and one query can look for only one: while a search is typed, a Name-contains filter is not applied, and a notice above the table says so. Each filter in force shows as a chip above the table; see Filter and search a list. For members who may open the CRM, each row\'s ⋮ menu holds Open in CRM — the member\'s contact, found by the address they signed up with.\nClick a member to open the member drawer:\n- Profile — email, display name, and join date, with a Suspended chip when applicable.\n- Lifetime purchases — charged order totals minus refunds (pending and canceled orders excluded).\n- Orders — the member\'s payment history, newest first: order number, status, total, date, any refunded amount, and the Stripe payment reference. Needs the editor or admin role on the site.\n- Subscriptions — each with its renewal date and status chip.\n- Addresses — the member\'s saved addresses.\nSuspend & reactivate\nThe drawer\'s action button'
6964
6985
  },
6965
6986
  {
6966
6987
  path: '/guides/member-accounts',
@@ -7373,7 +7394,7 @@ export const ASSIST_DOCS_INDEX = [
7373
7394
  title: 'Designed emails',
7374
7395
  heading: 'Find a template',
7375
7396
  anchor: '#find-a-template',
7376
- text: 'The templates table filters through its toolbar by name (it contains a word, it is, or it starts with), and Search matches the start of any word of a template\'s name, up to its first twelve characters. The filters and the search are asked of the site\'s templates themselves, so they reach every template the site holds, a page at a time in name order, not only the page on screen. A name that contains a word and Search both match words of the name, so only one of them applies at a time; a note above the table says which was set aside. The Origin column shows whether a template is yours or installed from a listing, but it is not a filter.\nOn your organization\'s Emails page the same filters and search run on each site\'s templates, and Site chooses which sites are read: any of your sites, wherever it sits in the pages of sites. Without it, the table reads the page of sites the Sites picker shows. It lists up to 50 matching templates from each site; where a site has more, the note under the table says so and links to that site\'s own list. See Filter and search a list.'
7397
+ text: 'The templates table filters through its toolbar by Template, the name (it contains a word, it is, or it starts with), and Search matches the start of any word of a template\'s name, up to its first twelve characters. The filters and the search are asked of the site\'s templates themselves, so they reach every template the site holds, a page at a time in name order, not only the page on screen. A name that contains a word and Search both match words of the name, so only one of them applies at a time; a note above the table says which was set aside. The Origin column shows whether a template is yours or installed from a listing, but it is not a filter.\nOn your organization\'s Emails page the same filters and search run on each site\'s templates, and the Site filter (is, is any of) chooses which sites are read: any of your sites, wherever it sits in the pages of sites. Without it, the table reads the page of sites the Sites picker shows. It lists up to 50 matching templates from each site; where a site has more, the note under the table says so and links to that site\'s own list. See Filter and search a list.'
7377
7398
  },
7378
7399
  {
7379
7400
  path: '/marketing-and-automation/email-campaigns/designed-emails',
@@ -7492,14 +7513,14 @@ export const ASSIST_DOCS_INDEX = [
7492
7513
  title: 'Email Campaigns',
7493
7514
  heading: 'Email lists',
7494
7515
  anchor: '#email-lists',
7495
- text: 'Lists are audiences shared across your organization\'s sites. Create them on the Marketing page and target any of them from the campaign composer. A list is one of two kinds, chosen when you create it.\nThe lists table filters through its toolbar: Filters narrows it by name (it contains a word, or it is) or by Membership (manual or rule), and Search matches the start of any word of a list\'s name. The filters and the search are asked of your organization\'s lists themselves, so they reach every list, a page at a time in name order. A name that contains a word and Search both match words of the name, so only one of them applies at a time, and a note above the table says which was set aside. See Filter and search a list.\nManual lists\nA manual list holds the people you put in it. Grow it with the "Enroll in a list" automation step (e.g. on form completion), popup email capture, the Add to a list card in the Inbox, or by hand from the list itself. Members stay until they are removed.\nSee and manage who is on a list {#list-members}\nPress Members on any list row to open it. You get the membership a page at a time — address, name, when they joined, how they got there, and what their consent record says — plus the controls to change it. Press Close to collapse it again; nothing is read until you open a list.\nHow tells a rule match apart from somebody who was added. A person a rule enrolled leaves when they stop matching; a person who was added stays.\nThe membership table filters through its toolbar by Address (the whole address) and How (rule or added), and Search matches the start of any word of a member\'s name or of any part of their address: the local part, a piece of it such as doe in jane.doe, or the domain, with or without the @, up to the first twelve characters typed. The f'
7516
+ text: 'Lists are audiences shared across your organization\'s sites. Create them on the Marketing page and target any of them from the campaign composer. A list is one of two kinds, chosen when you create it.\nThe lists table filters through its toolbar: Filters narrows it by List, the list\'s name (contains a word, or is), or by Membership (is manual or rule), and Search matches the start of any word of a list\'s name. The filters and the search are asked of your organization\'s lists themselves, so they reach every list, a page at a time in name order. A name that contains a word and Search both match words of the name, so only one of them applies at a time, and a note above the table says which was set aside. See Filter and search a list.\nManual lists\nA manual list holds the people you put in it. Grow it with the "Enroll in a list" automation step (e.g. on form completion), popup email capture, the Add to a list card in the Inbox, or by hand from the list itself. Members stay until they are removed.\nSee and manage who is on a list {#list-members}\nPress Members on any list row to open it. You get the membership a page at a time — address, name, when they joined, how they got there, and what their consent record says — plus the controls to change it. Press Close to collapse it again; nothing is read until you open a list.\nHow tells a rule match apart from somebody who was added. A person a rule enrolled leaves when they stop matching; a person who was added stays.\nThe membership table filters through its toolbar by Address (the whole address) and How (rule or added), and Search matches the start of any word of a member\'s name or of any part of their address: the local part, a piece of it such as doe in jane.doe, or the domain, with or without the @, up to the first twelve characte'
7496
7517
  },
7497
7518
  {
7498
7519
  path: '/marketing-and-automation/email-campaigns/overview',
7499
7520
  title: 'Email Campaigns',
7500
7521
  heading: 'Experiments',
7501
7522
  anchor: '#experiments',
7502
- text: 'Business plans can A/B test screens, sections, and emails from the Experiments card on the Marketing page: weighted variants, deterministic visitor assignment, a conversion goal, and per-variant exposure/conversion rates with a pick-the-winner flow.\nTwo ways to finish a test without watching it:\n- End date — past it, visitors get the default and stats stop accruing until you pick a winner.\n- Auto-declare winner — opt in with a minimum exposure count per variant and a confidence level (90/95/99%); once a challenger clears the bar (or every challenger confidently loses to the control), the experiment completes itself and serves the winner. Auto-completed tests carry a chip in the results dialog.\n- Screens & sections — variants pin a screen version; visitors are split deterministically and the winning version serves to everyone once you pick it. Start a section test straight from the Besigner\'s Interactions panel.\n- Emails — variants override the campaign\'s subject and/or body. Attach a running email experiment in the campaign composer; each recipient deterministically receives one variant (re-sends reach the same variant), sends count as exposures, and once a winner is picked every later send uses the winning copy.\nThe Experiments table filters through its toolbar by Experiment (a name that contains a word, or is exactly a name in either case), Tests (screen, section or email) and Status (draft, running, paused or done; one or several of each). Search finds an experiment by the start of any word in its name: cop finds Hero copy. Every filter and the search are answered by the query, across all of the site\'s experiments, a page at a time and in name order, not only over the page on screen. A combination the query cannot answer together is not applied, and a notice above th'
7523
+ text: 'Business plans can A/B test screens, sections, and emails from the Experiments card on the Marketing page: weighted variants, deterministic visitor assignment, a conversion goal, and per-variant exposure/conversion rates with a pick-the-winner flow.\nTwo ways to finish a test without watching it:\n- End date — past it, visitors get the default and stats stop accruing until you pick a winner.\n- Auto-declare winner — opt in with a minimum exposure count per variant and a confidence level (90/95/99%); once a challenger clears the bar (or every challenger confidently loses to the control), the experiment completes itself and serves the winner. Auto-completed tests carry a chip in the results dialog.\n- Screens & sections — variants pin a screen version; visitors are split deterministically and the winning version serves to everyone once you pick it. Start a section test straight from the Besigner\'s Interactions panel.\n- Emails — variants override the campaign\'s subject and/or body. Attach a running email experiment in the campaign composer; each recipient deterministically receives one variant (re-sends reach the same variant), sends count as exposures, and once a winner is picked every later send uses the winning copy.\nThe Experiments table filters through its toolbar by Experiment (a name that contains a word, or is exactly a name in either case), Tests (screen, section or email) and Status (draft, running, paused or done; one or several of each). Search finds an experiment by the start of any word in its name: cop finds Hero copy. Every filter and the search are answered by the query, across all of the site\'s experiments, a page at a time and in name order, not only over the page on screen. Experiment containing a word and Search both match words of the name, so only one of'
7503
7524
  },
7504
7525
  {
7505
7526
  path: '/marketing-and-automation/email-campaigns/overview',
@@ -7870,14 +7891,14 @@ export const ASSIST_DOCS_INDEX = [
7870
7891
  title: 'Add-ons',
7871
7892
  heading: 'How changes bill',
7872
7893
  anchor: '#how-changes-bill',
7873
- text: '- Adding or removing units shows a prorated preview of today\'s charge before you confirm, and takes effect immediately.\n- Removing an add-on credits the unused time onto your next invoice.\nAdd-ons are not on the plan-switch schedule Add-on changes are always immediate and always prorated, in both directions. Plan switches are not: since Aglyn moved to end-of-cycle downgrades, a plan downgrade waits for your period end and charges $0 today, while only a plan upgrade is immediate and prorated. Removing an add-on still credits you today. See when each change takes effect.\n- Hard caps: seat and dataset add-ons stop at your plan\'s maximum (for example, Starter tops out at 5 workspace managers). Past the cap, the answer is a plan upgrade — the Billing page tells you when you\'re there.'
7894
+ text: '- Adding units shows a prorated preview of today\'s charge before you confirm. It is charged to your card when you confirm, and the units are yours as soon as that payment goes through — if your bank asks you to confirm it, Billing shows the check right there.\n- Removing units charges nothing and refunds nothing: you keep them until the end of the period you already paid for, and they drop off then.\nAdd-ons are not on the plan-switch schedule Adding an add-on works like a plan upgrade: charged today, prorated, and applied once paid. Removing one works like a plan downgrade: nothing today, and it ends at your period end. See when each change takes effect.\n- Hard caps: seat and dataset add-ons stop at your plan\'s maximum (for example, Starter tops out at 5 workspace managers). Past the cap, the answer is a plan upgrade — the Billing page tells you when you\'re there.'
7874
7895
  },
7875
7896
  {
7876
7897
  path: '/workspace-and-billing/billing-and-plans/add-ons',
7877
7898
  title: 'Add-ons',
7878
7899
  heading: 'Plan switches and cancellation',
7879
7900
  anchor: '#plan-switches-and-cancellation',
7880
- text: '- Switching plans keeps your add-on quantities and re-prices them at the new plan\'s rates. If the new plan doesn\'t sell one of your add-ons, it\'s removed and the switch confirmation says so. On an upgrade this happens today, in the same prorated update as the plan change. On a downgrade it happens on the effective date along with the plan — your add-ons keep running, at your current plan\'s rates, for the rest of the period you already paid for.\n- Canceling (or a subscription that dies after failed payments) ends your add-ons with the plan — they bill on that subscription, so entitlement enforcement stops counting them at the same moment the plan downgrades to Free.'
7901
+ text: '- Switching plans keeps your add-on quantities and re-prices them at the new plan\'s rates. If the new plan doesn\'t sell one of your add-ons, it\'s removed and the switch confirmation says so. On an upgrade this happens today, in the same prorated charge as the plan change. On a downgrade it happens on the effective date along with the plan — your add-ons keep running, at your current plan\'s rates, for the rest of the period you already paid for.\n- Canceling (or a subscription that dies after failed payments) ends your add-ons with the plan — they bill on that subscription, so entitlement enforcement stops counting them at the same moment the plan downgrades to Free.'
7881
7902
  },
7882
7903
  {
7883
7904
  path: '/workspace-and-billing/billing-and-plans/add-ons',
@@ -7954,7 +7975,7 @@ export const ASSIST_DOCS_INDEX = [
7954
7975
  title: 'Downgrading, canceling & your data',
7955
7976
  heading: 'When each change takes effect',
7956
7977
  anchor: '#when-changes-take-effect',
7957
- text: 'Plan changes are deliberately asymmetric, and knowing which direction you\'re going tells you what you\'ll be charged — and when. Nothing is taken from your card at the moment you change a plan or an add-on: the adjustment is written onto your next invoice, so a mid-cycle upgrade appears there rather than as a charge today.\n| You\'re doing | When it takes effect | What you are charged, and when |\n| Upgrading to a higher plan | Immediately | Nothing today. A prorated amount for the rest of the current period is added to your next invoice |\n| Downgrading to a lower paid plan | At the end of your current billing period | Nothing |\n| Canceling | At the end of your current billing period | Nothing |\n| Adding or removing an add-on | Immediately | Nothing today. Prorated onto your next invoice — removing one credits you back the same way |\nThe reason downgrades wait is simple: you already paid for the current period, so you keep everything you paid for until it runs out. There is no proration credit on a downgrade because there is nothing to credit — nothing changes today.\nBilling opens on your current plan and the next one up. To see the plans below yours, choose Compare all plans, then Looking for something smaller? — the help tip beside it says when a downgrade takes effect.'
7978
+ text: 'Plan changes are deliberately asymmetric, and knowing which direction you\'re going tells you what you\'ll be charged — and when. Anything that adds to your subscription is charged to your card as soon as you confirm it, and takes effect once that payment goes through. If your bank asks you to confirm the payment, Billing shows its check right there; if the card is declined, nothing changes and you stay on what you already have.\n| You\'re doing | When it takes effect | What you are charged, and when |\n| Upgrading to a higher plan | Immediately, once the payment goes through | Today. The prorated difference for the rest of the current period is charged when you confirm |\n| Downgrading to a lower paid plan | At the end of your current billing period | Nothing |\n| Canceling | At the end of your current billing period | Nothing |\n| Adding an add-on | Immediately, once the payment goes through | Today. Prorated for the rest of the current period and charged when you confirm |\n| Removing an add-on | At the end of your current billing period | Nothing |\nThe reason downgrades wait is simple: you already paid for the current period, so you keep everything you paid for until it runs out. There is no proration credit on a downgrade because there is nothing to credit — nothing changes today.\nBilling opens on your current plan and the next one up. To see the plans below yours, choose Compare all plans, then Looking for something smaller? — the help tip beside it says when a downgrade takes effect.'
7958
7979
  },
7959
7980
  {
7960
7981
  path: '/workspace-and-billing/billing-and-plans/downgrading-and-canceling',
@@ -8388,7 +8409,7 @@ export const ASSIST_DOCS_INDEX = [
8388
8409
  title: 'Invite teammates',
8389
8410
  heading: 'Activity log',
8390
8411
  anchor: '#activity-log',
8391
- text: 'The organization\'s Team page shows a Recent Activity log: what happened at organization level — renames, workspace URL changes, ownership transfers, members added/removed or re-roled, and invites sent, revoked, or accepted — together with the changes made on each of the organization\'s sites, newest first, each with who did it, where and when.\nVisible to members whose role carries the Activity & audit log permission. Owners and admins have it by default; viewers do not, and neither does a custom role until you grant it. Revoking it does not merely hide the card — the feed is served by an API that checks the permission, so a member without it cannot read the log by any route.\nEntries name the thing that changed and link straight to it, so "Saved the screen — Home" takes you to that screen. Entries recorded before this shipped show a plain description instead of a link.\nThe log filters through its table\'s toolbar, across the whole log rather than the page on screen:\n- Filters narrows it by Action — picked from the actions the log records as named entries, such as the AI entries below — by Who (one of the organization\'s members), by Where (the organization itself or one of its sites), and by When (on a day, or before or after a date). They add up, and every one is answered by the log\'s own query.\n- Search finds an entry by the start of a word of the address of the person who made the change (or the API key\'s name, for an entry an integration wrote) and of the name of what changed — ada, example.com or home — across the whole log. It matches one word at a time: type two and the log says it searched the first.\nEvery filter and the search are on the log\'s own query. Anything that query cannot take is not applied, and a notice above the table names it.\nChanging a filter or the '
8412
+ text: 'The organization\'s Team page shows a Recent Activity log: what happened at organization level — renames, workspace URL changes, ownership transfers, members added/removed or re-roled, and invites sent, revoked, or accepted — together with the changes made on each of the organization\'s sites, newest first, each with who did it, where and when.\nVisible to members whose role carries the Activity & audit log permission. Owners and admins have it by default; viewers do not, and neither does a custom role until you grant it. Revoking it does not merely hide the card — the feed is served by an API that checks the permission, so a member without it cannot read the log by any route.\nWho is always someone you can narrow down:\n- a person, by the address they had when they acted — or, for the few entries that recorded only their account (subscription changes made before the log carried the address), the address that account has now;\n- an integration, as API key and the name you gave the key;\n- a workflow run, as Workflow and the workflow\'s name;\n- Aglyn, for what the platform did on its own — a subscription Stripe ended after failed payments, a cancellation made by Aglyn staff, inbound CRM mail, a background AI job.\nEntries name the thing that changed and link straight to it, so "Saved the screen — Home" takes you to that screen. Entries recorded before this shipped show a plain description instead of a link.\nThe log filters through its table\'s toolbar, across the whole log rather than the page on screen:\n- Filters narrows it by Action — is one, or is any of several, picked from the actions the log records as named entries, such as the AI entries below — by Who (is one of the organization\'s members), by Where (is the organization itself or one of its sites), and by When (is, is aft'
8392
8413
  },
8393
8414
  {
8394
8415
  path: '/workspace-and-billing/teams-and-roles/invite-teammates',
@@ -8444,7 +8465,7 @@ export const ASSIST_DOCS_INDEX = [
8444
8465
  title: 'Members-only areas',
8445
8466
  heading: 'Manage your members',
8446
8467
  anchor: '#manage-your-members',
8447
- text: 'The site\'s Users page lists everyone who signed up on your published site — paged, newest first. The search box finds a member by the start of any word of their name or email address, and Filters in the table\'s toolbar narrows the list by email, name, join date or Status (Active or Suspended). They add up, across every member rather than the page on screen, because the query that reads the list answers them all. See Filter and search a list. Click a member to open their detail drawer:\n- Profile — email, display name, join date, and saved addresses.\n- Order history — the member\'s payment records, newest first: order number, status, total, and date, plus the Stripe payment reference and any refunded amount. Order history is visible to site admins and editors.\n- Subscriptions — active and past storefront subscriptions with their renewal date.\n- Lifetime purchases — everything the member actually paid: charged order totals minus refunds (pending and canceled orders don\'t count).\nSuspend or reactivate a member\nFrom the drawer you can suspend a member (with a confirmation). A suspended member:\n- can no longer sign in on your published site — they see a clear "account suspended" message;\n- is signed out the next time their account page loads;\n- keeps all orders, subscriptions, and history — nothing is deleted.\nReactivate restores access with the member\'s existing password. The member list shows each account\'s Active/Suspended status at a glance.'
8468
+ text: 'The site\'s Users page lists everyone who signed up on your published site — paged, newest first. The search box finds a member by the start of any word of their name or email address, and Filters in the table\'s toolbar narrows the list by email, name, join date or Status (Active or Suspended). They add up — except that a Name contains filter and a search can\'t stand together, and the list says which it set aside — across every member rather than the page on screen, because the query that reads the list answers them all. The member guide names each filter\'s operators. See Filter and search a list. Click a member to open their detail drawer:\n- Profile — email, display name, join date, and saved addresses.\n- Order history — the member\'s payment records, newest first: order number, status, total, and date, plus the Stripe payment reference and any refunded amount. Order history is visible to site admins and editors.\n- Subscriptions — active and past storefront subscriptions with their renewal date.\n- Lifetime purchases — everything the member actually paid: charged order totals minus refunds (pending and canceled orders don\'t count).\nSuspend or reactivate a member\nFrom the drawer you can suspend a member (with a confirmation). A suspended member:\n- can no longer sign in on your published site — they see a clear "account suspended" message;\n- is signed out the next time their account page loads;\n- keeps all orders, subscriptions, and history — nothing is deleted.\nReactivate restores access with the member\'s existing password. The member list shows each account\'s Active/Suspended status at a glance.'
8448
8469
  },
8449
8470
  {
8450
8471
  path: '/workspace-and-billing/teams-and-roles/members-only',
@@ -8465,7 +8486,7 @@ export const ASSIST_DOCS_INDEX = [
8465
8486
  title: 'Teams, Roles & Membership',
8466
8487
  heading: '',
8467
8488
  anchor: '',
8468
- text: 'Teams, Roles & Membership\nAglyn has two kinds of people: your team (who build and manage the site) and site members (visitors who sign up to your site). Both are permission-aware.\nPlan availability Paid. Seats are metered per tier; see Billing & plans.\nThe Team page\'s roster filters through its table\'s toolbar: Filters narrows it by Role (one role, or several at once) or Access (team manager or site collaborator), and Search finds a member by the start of any word of their name, email address or job title — ada, lovelace or example.com all find Ada Lovelace at ada@example.com. The filters and the search add up, and they are answered by the query that reads the roster, so the table lists every member who matches, not a narrowing of the rows already on screen. Each filter in force shows as a chip above the table; see Filter and search a list. The role pickers and Permissions in each row work as before.'
8489
+ text: 'Teams, Roles & Membership\nAglyn has two kinds of people: your team (who build and manage the site) and site members (visitors who sign up to your site). Both are permission-aware.\nPlan availability Paid. Seats are metered per tier; see Billing & plans.\nThe Team page\'s roster filters through its table\'s toolbar: Filters narrows it by Role (is one role, or is any of several) or Access (is Team manager or Site collaborator), and Search finds a member by the start of any word of their name, email address or job title — ada, lovelace or example.com all find Ada Lovelace at ada@example.com. The filters and the search add up, and they are answered by the query that reads the roster, so the table lists every member who matches, not a narrowing of the rows already on screen. Each filter in force shows as a chip above the table; see Filter and search a list. The role pickers and Permissions in each row work as before.'
8469
8490
  },
8470
8491
  {
8471
8492
  path: '/workspace-and-billing/teams-and-roles/overview',