@aglyn/aglyn 1.0.0-beta.246 → 1.0.0-beta.249

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 (55) hide show
  1. package/package.json +11 -11
  2. package/src/lib/app-utils/contact-custom-fields.d.ts +23 -1
  3. package/src/lib/app-utils/contact-custom-fields.js +84 -2
  4. package/src/lib/app-utils/contact-custom-fields.js.map +1 -1
  5. package/src/lib/app-utils/crm.d.ts +7 -1
  6. package/src/lib/app-utils/crm.js.map +1 -1
  7. package/src/lib/app-utils/default-site.js +21 -33
  8. package/src/lib/app-utils/default-site.js.map +1 -1
  9. package/src/lib/app-utils/docs-help-sections.generated.js +8 -8
  10. package/src/lib/app-utils/docs-help-sections.generated.js.map +1 -1
  11. package/src/lib/app-utils/docs-help.generated.d.ts +8 -8
  12. package/src/lib/app-utils/docs-help.generated.js +9 -5
  13. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  14. package/src/lib/app-utils/docs-index.generated.js +129 -59
  15. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  16. package/src/lib/app-utils/element-pick-protocol.d.ts +54 -0
  17. package/src/lib/app-utils/element-pick-protocol.js +41 -0
  18. package/src/lib/app-utils/element-pick-protocol.js.map +1 -0
  19. package/src/lib/app-utils/element-pick-target.d.ts +32 -0
  20. package/src/lib/app-utils/element-pick-target.js +47 -0
  21. package/src/lib/app-utils/element-pick-target.js.map +1 -0
  22. package/src/lib/app-utils/error-beacon.d.ts +19 -0
  23. package/src/lib/app-utils/error-beacon.js +31 -5
  24. package/src/lib/app-utils/error-beacon.js.map +1 -1
  25. package/src/lib/app-utils/form-contract.js +13 -6
  26. package/src/lib/app-utils/form-contract.js.map +1 -1
  27. package/src/lib/app-utils/forms.d.ts +31 -0
  28. package/src/lib/app-utils/forms.js +213 -16
  29. package/src/lib/app-utils/forms.js.map +1 -1
  30. package/src/lib/app-utils/node-definition-sanitizer.js +12 -0
  31. package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
  32. package/src/lib/app-utils/seo-locale.d.ts +14 -0
  33. package/src/lib/app-utils/seo-locale.js +15 -0
  34. package/src/lib/app-utils/seo-locale.js.map +1 -1
  35. package/src/lib/app-utils/seo-site-scan.js +18 -3
  36. package/src/lib/app-utils/seo-site-scan.js.map +1 -1
  37. package/src/lib/app-utils/site-live-url.d.ts +24 -0
  38. package/src/lib/app-utils/site-live-url.js +60 -0
  39. package/src/lib/app-utils/site-live-url.js.map +1 -0
  40. package/src/lib/app-utils/starter-template-nodes.d.ts +13 -0
  41. package/src/lib/app-utils/starter-template-nodes.js +40 -0
  42. package/src/lib/app-utils/starter-template-nodes.js.map +1 -1
  43. package/src/lib/app-utils/starter-templates.d.ts +1 -1
  44. package/src/lib/app-utils/starter-templates.js +19 -31
  45. package/src/lib/app-utils/starter-templates.js.map +1 -1
  46. package/src/lib/plugin-manager/feature-plugins.d.ts +74 -3
  47. package/src/lib/plugin-manager/feature-plugins.js +9 -0
  48. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  49. package/src/lib/plugin-manager/plugin-ai-capabilities.d.ts +11 -0
  50. package/src/lib/plugin-manager/plugin-ai-capabilities.js.map +1 -1
  51. package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +23 -0
  52. package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -1
  53. package/src/lib/plugin-manager/stock-photo-provider.d.ts +67 -0
  54. package/src/lib/plugin-manager/stock-photo-provider.js +14 -1
  55. package/src/lib/plugin-manager/stock-photo-provider.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/starter-templates.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Leaf imports only, deliberately (AGL-687). This module is imported from\n// BOTH graphs — the console's client gallery renders virtual starters from\n// it, the console's seed route materializes them, and the AI plugin's server\n// shows them to a model — and neither barrel works in both: the full\n// `@aglyn/aglyn` barrel breaks the RSC/server-route graph, while the server\n// entry drags `node:fs` into the client bundle. The starter kit imports only\n// the canvas constants, a leaf with no imports of their own; the compiled\n// plugin starters are data behind a type-only import; and `screen-route`\n// imports only a TYPE from foundation — so all three are safe on either side.\nimport { PLUGIN_STARTER_TEMPLATES } from './plugin-starter-templates.generated'\nimport { normalizeScreenSlug } from './screen-route'\nimport {\n buildStarterNodes as buildNodes,\n starterHeroSection as heroSection,\n starterSection as section,\n starterText as text,\n type StarterNodeSpec as NodeSpec,\n type StarterTemplate,\n} from './starter-template-nodes'\n\nexport type {\n StarterNodeSpec,\n StarterSectionWidth,\n StarterTemplate,\n StarterTemplateScreen,\n} from './starter-template-nodes'\nexport {\n buildStarterNodes,\n starterHeroSection,\n starterSection,\n starterText,\n} from './starter-template-nodes'\n\n/**\n * First-party starter definitions (AGL-78/79), SEED INPUT (AGL-687).\n *\n * These used to be rendered straight into the gallery and instantiated from\n * code, which made a starter a second kind of template: no version history,\n * no placeholders, no editor, changeable only by shipping a release. Now\n * they are seeded into each host's own template library as ordinary\n * `hosts/{hostId}/templates` documents (see the console's\n * `utils/server/seed-starter-templates.ts` for why copy-on-use rather than a\n * global read-only collection), and nothing reads this file at render time.\n *\n * They are also the page examples the AI plugin's template generator shows a\n * model (AGL-2909), which is why they live in the core package rather than\n * beside the console gallery that renders them.\n *\n * Node ids stay template-local (unique within each screen's version doc);\n * `createPageFromTemplate` re-keys screen and version ids at instantiation.\n *\n * PERSISTED IDENTIFIERS: `StarterTemplate.id`, `StarterTemplateScreen.key`\n * and every node id below appear in stored documents (seeded template doc\n * ids are derived from the first two). They must never be renamed.\n */\nexport interface StarterTemplateDoc {\n id: string\n /** Which starter this page belongs to — lets one starter be selected. */\n starterId: string\n data: Record<string, unknown>\n}\n\n/**\n * Deterministic document id for a seeded starter screen (AGL-687).\n *\n * Derived from the starter id and the screen key — never randomly generated\n * — so re-running the seed addresses the same documents instead of stacking\n * duplicate copies of every starter on every run.\n */\nexport function starterTemplateDocId(\n starterId: string,\n screenKey: string,\n): string {\n return `starter-${starterId}-${screenKey}`\n}\n\n/**\n * Expands one starter into the template documents it seeds as.\n *\n * One page template per screen, matching what a marketplace install of a\n * multi-screen site template already produces (AGL-669) — the alternative,\n * a bespoke multi-page template shape, would be a third lifecycle on top of\n * the two this issue exists to merge. The bundle's name/description/order\n * ride `source` so the gallery can still present the starter as one card.\n */\nexport function buildStarterTemplateDocs(\n starter: StarterTemplate,\n): StarterTemplateDoc[] {\n return starter.screens.map((screen, index) => {\n // Normalized on the way into the document so the persisted address is in\n // the routing-map format the tenant matches against — in particular the\n // root, which the previous `screen.slug ? …` guard dropped entirely when\n // home was spelled `''` (AGL-1575). A slug that sanitizes away carries no\n // field, and the apply path derives one from the display name.\n const slug = normalizeScreenSlug(screen.slug)\n return {\n id: starterTemplateDocId(starter.id, screen.key),\n starterId: starter.id,\n data: {\n kind: 'page',\n displayName: screen.displayName,\n // Only the screen's own description, never the starter blurb: a\n // template's `description` is carried onto the page it creates, and a\n // screen description is the live site's meta-description fallback.\n // The bundle blurb lives on `source.starterDescription` instead.\n ...(screen.description ? { description: screen.description } : {}),\n category: starter.category,\n ...(slug ? { slug } : {}),\n ...(screen.seo ? { seo: screen.seo } : {}),\n nodes: screen.nodes,\n source: {\n type: 'starter',\n starterId: starter.id,\n starterName: starter.displayName,\n starterDescription: starter.description,\n starterOrder: index,\n },\n },\n }\n })\n}\n\n/** Every document a starter COULD materialize as, in bundle order. */\nexport function buildAllStarterTemplateDocs(): StarterTemplateDoc[] {\n return STARTER_TEMPLATES.flatMap(buildStarterTemplateDocs)\n}\n\nconst featureColumn = (id: string, title: string, body: string): NodeSpec => ({\n id,\n componentId: 'muiStack',\n props: { spacing: 1 },\n // `flex: 1` is a column's share of its row, not a width cap — it survives\n // the sweep deliberately. Only `maxWidth` in raw pixels was the violation.\n sx: {\n flex: 1,\n paddingTop: 2,\n paddingRight: 2,\n paddingBottom: 2,\n paddingLeft: 2,\n },\n children: [text(`${id}T`, 'h5', title), text(`${id}B`, 'body1', body)],\n})\n\nconst contactForm = (prefix: string): NodeSpec => ({\n id: `${prefix}form`,\n componentId: 'form',\n props: {\n formName: 'Contact',\n submitLabel: 'Send message',\n successMessage: 'Thanks — we will get back to you soon.',\n },\n children: [\n {\n id: `${prefix}fName`,\n componentId: 'formField',\n props: { fieldName: 'name', label: 'Name', required: true },\n },\n {\n id: `${prefix}fEmail`,\n componentId: 'formField',\n props: {\n fieldName: 'email',\n label: 'Email',\n fieldType: 'email',\n required: true,\n },\n },\n {\n id: `${prefix}fMessage`,\n componentId: 'formField',\n props: {\n fieldName: 'message',\n label: 'Message',\n fieldType: 'textarea',\n required: true,\n },\n },\n ],\n})\n\n\n/**\n * The home page every new site is born with now lives with the rest of the\n * site it is born into — layout, theme and SEO — in `default-site.ts`\n * (AGL-3497). Re-exported so the name keeps its home here.\n */\nexport { buildDefaultHomeScreen } from './default-site'\n\n/** The platform's own starters, which name no plugin's elements. */\nconst PLATFORM_STARTER_TEMPLATES: StarterTemplate[] = [\n {\n id: 'landing',\n displayName: 'Landing Page',\n description:\n 'One-page launch site: hero, three selling points, and a contact form.',\n category: 'Marketing',\n screens: [\n {\n key: 'landing',\n displayName: 'Landing',\n slug: 'landing',\n seo: {\n title: 'Welcome',\n description: 'Everything you need to know, on one page.',\n },\n nodes: buildNodes([\n heroSection(\n 'l_',\n 'A headline that sells your idea',\n 'One clear sentence about the value you deliver.',\n ),\n section('l_featuresSection', 'xl', 6, [\n {\n id: 'l_features',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n featureColumn(\n 'l_f1',\n 'Fast',\n 'Explain the first reason customers pick you.',\n ),\n featureColumn(\n 'l_f2',\n 'Simple',\n 'Explain the second reason customers pick you.',\n ),\n featureColumn(\n 'l_f3',\n 'Reliable',\n 'Explain the third reason customers pick you.',\n ),\n ],\n },\n ]),\n // Was `maxWidth: 560`. A band, not an inner measure: it sat at the\n // top level carrying the section's own gutters and rhythm, so the\n // pixel value was capping the BAND. MD is the stock width for a\n // narrow, form-led column.\n section('l_contactSection', 'md', 6, [\n {\n id: 'l_contact',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('l_contactTitle', 'h4', 'Get in touch'),\n contactForm('l_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n {\n id: 'business',\n displayName: 'Business',\n description:\n 'Company site: home with services, an about page, and a contact page.',\n category: 'Business',\n screens: [\n {\n key: 'home',\n displayName: 'Business Home',\n slug: 'home',\n seo: { title: 'Home' },\n nodes: buildNodes([\n heroSection(\n 'b_',\n 'Your business, done right',\n 'Tell visitors what you do and who you do it for.',\n ),\n section('b_servicesSection', 'xl', 6, [\n {\n id: 'b_services',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n featureColumn('b_s1', 'Service one', 'Describe this service.'),\n featureColumn('b_s2', 'Service two', 'Describe this service.'),\n featureColumn(\n 'b_s3',\n 'Service three',\n 'Describe this service.',\n ),\n ],\n },\n ]),\n ]),\n },\n {\n key: 'about-us',\n displayName: 'About Us',\n slug: 'about-us',\n seo: { title: 'About us' },\n nodes: buildNodes([\n // Was `maxWidth: 720` — the one unambiguous PROSE band in the set,\n // and the case the Prose Container preset exists for. MD (900px)\n // lands near the 65–75 characters a line that reads comfortably.\n section('a_wrapSection', 'md', 8, [\n {\n id: 'a_wrap',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('a_title', 'h3', 'About us'),\n text(\n 'a_body',\n 'body1',\n 'Share your story: how you started, what you believe, and ' +\n 'why customers trust you.',\n ),\n ],\n },\n ]),\n ]),\n },\n {\n key: 'contact-us',\n displayName: 'Contact Us',\n slug: 'contact-us',\n seo: { title: 'Contact' },\n nodes: buildNodes([\n // Was `maxWidth: 560`. Same reading as the landing page's contact\n // band: text plus a form column, so MD.\n section('c_wrapSection', 'md', 8, [\n {\n id: 'c_wrap',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('c_title', 'h3', 'Contact us'),\n text(\n 'c_body',\n 'body1',\n 'Questions or quotes — send a message and we reply within ' +\n 'one business day.',\n ),\n contactForm('c_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n {\n id: 'portfolio',\n displayName: 'Portfolio',\n description: 'Personal portfolio: intro, work grid, and contact form.',\n category: 'Personal',\n screens: [\n {\n key: 'portfolio',\n displayName: 'Portfolio',\n slug: 'portfolio',\n seo: { title: 'Portfolio' },\n nodes: buildNodes([\n heroSection(\n 'p_',\n 'Hi, I make things',\n 'Designer / developer / photographer — introduce yourself here.',\n ),\n section('p_gridSection', 'xl', 6, [\n {\n id: 'p_grid',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n {\n id: 'p_img1',\n componentId: 'image',\n // `height` is an image's own intrinsic sizing prop, not a\n // band cap — out of scope for the container standard.\n props: { alt: 'Project one', height: '220px' },\n },\n {\n id: 'p_img2',\n componentId: 'image',\n props: { alt: 'Project two', height: '220px' },\n },\n {\n id: 'p_img3',\n componentId: 'image',\n props: { alt: 'Project three', height: '220px' },\n },\n ],\n },\n ]),\n // Was `maxWidth: 560`, the third of the three contact bands.\n section('p_contactSection', 'md', 6, [\n {\n id: 'p_contact',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('p_contactTitle', 'h4', 'Work with me'),\n contactForm('p_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n]\n\n/**\n * Every starter in this build, in gallery order: the platform's own, then\n * each plugin's in config order (AGL-3080). A plugin whose elements a starter\n * is built around — a storefront's product grid and cart — declares it under\n * `starterTemplates` in plugins.config.json, and the manifest generator\n * compiles what it returns, so the gallery, the seed route and a model\n * shown examples all read one list without loading any plugin.\n */\nexport const STARTER_TEMPLATES: StarterTemplate[] = [\n ...PLATFORM_STARTER_TEMPLATES,\n ...PLUGIN_STARTER_TEMPLATES,\n]\n"],"names":["PLUGIN_STARTER_TEMPLATES","normalizeScreenSlug","buildStarterNodes","buildNodes","starterHeroSection","heroSection","starterSection","section","starterText","text","starterTemplateDocId","starterId","screenKey","buildStarterTemplateDocs","starter","screens","map","screen","index","slug","id","key","data","kind","displayName","description","category","seo","nodes","source","type","starterName","starterDescription","starterOrder","buildAllStarterTemplateDocs","STARTER_TEMPLATES","flatMap","featureColumn","title","body","componentId","props","spacing","sx","flex","paddingTop","paddingRight","paddingBottom","paddingLeft","children","contactForm","prefix","formName","submitLabel","successMessage","fieldName","label","required","fieldType","buildDefaultHomeScreen","PLATFORM_STARTER_TEMPLATES","direction","alt","height"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/starter-templates.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Leaf imports only, deliberately (AGL-687). This module is imported from\n// BOTH graphs — the console's client gallery renders virtual starters from\n// it, the console's seed route materializes them, and the AI plugin's server\n// shows them to a model — and neither barrel works in both: the full\n// `@aglyn/aglyn` barrel breaks the RSC/server-route graph, while the server\n// entry drags `node:fs` into the client bundle. The starter kit imports only\n// the canvas constants, a leaf with no imports of their own; the compiled\n// plugin starters are data behind a type-only import; and `screen-route`\n// imports only a TYPE from foundation — so all three are safe on either side.\nimport { PLUGIN_STARTER_TEMPLATES } from './plugin-starter-templates.generated'\nimport { normalizeScreenSlug } from './screen-route'\nimport {\n buildStarterNodes as buildNodes,\n starterHeroSection as heroSection,\n starterSection as section,\n starterText as text,\n starterTextField,\n type StarterNodeSpec as NodeSpec,\n type StarterTemplate,\n} from './starter-template-nodes'\n\nexport type {\n StarterNodeSpec,\n StarterSectionWidth,\n StarterTemplate,\n StarterTemplateScreen,\n} from './starter-template-nodes'\nexport {\n buildStarterNodes,\n starterHeroSection,\n starterSection,\n starterText,\n starterTextField,\n} from './starter-template-nodes'\n\n/**\n * First-party starter definitions (AGL-78/79), SEED INPUT (AGL-687).\n *\n * These used to be rendered straight into the gallery and instantiated from\n * code, which made a starter a second kind of template: no version history,\n * no placeholders, no editor, changeable only by shipping a release. Now\n * they are seeded into each host's own template library as ordinary\n * `hosts/{hostId}/templates` documents (see the console's\n * `utils/server/seed-starter-templates.ts` for why copy-on-use rather than a\n * global read-only collection), and nothing reads this file at render time.\n *\n * They are also the page examples the AI plugin's template generator shows a\n * model (AGL-2909), which is why they live in the core package rather than\n * beside the console gallery that renders them.\n *\n * Node ids stay template-local (unique within each screen's version doc);\n * `createPageFromTemplate` re-keys screen and version ids at instantiation.\n *\n * PERSISTED IDENTIFIERS: `StarterTemplate.id`, `StarterTemplateScreen.key`\n * and every node id below appear in stored documents (seeded template doc\n * ids are derived from the first two). They must never be renamed.\n */\nexport interface StarterTemplateDoc {\n id: string\n /** Which starter this page belongs to — lets one starter be selected. */\n starterId: string\n data: Record<string, unknown>\n}\n\n/**\n * Deterministic document id for a seeded starter screen (AGL-687).\n *\n * Derived from the starter id and the screen key — never randomly generated\n * — so re-running the seed addresses the same documents instead of stacking\n * duplicate copies of every starter on every run.\n */\nexport function starterTemplateDocId(\n starterId: string,\n screenKey: string,\n): string {\n return `starter-${starterId}-${screenKey}`\n}\n\n/**\n * Expands one starter into the template documents it seeds as.\n *\n * One page template per screen, matching what a marketplace install of a\n * multi-screen site template already produces (AGL-669) — the alternative,\n * a bespoke multi-page template shape, would be a third lifecycle on top of\n * the two this issue exists to merge. The bundle's name/description/order\n * ride `source` so the gallery can still present the starter as one card.\n */\nexport function buildStarterTemplateDocs(\n starter: StarterTemplate,\n): StarterTemplateDoc[] {\n return starter.screens.map((screen, index) => {\n // Normalized on the way into the document so the persisted address is in\n // the routing-map format the tenant matches against — in particular the\n // root, which the previous `screen.slug ? …` guard dropped entirely when\n // home was spelled `''` (AGL-1575). A slug that sanitizes away carries no\n // field, and the apply path derives one from the display name.\n const slug = normalizeScreenSlug(screen.slug)\n return {\n id: starterTemplateDocId(starter.id, screen.key),\n starterId: starter.id,\n data: {\n kind: 'page',\n displayName: screen.displayName,\n // Only the screen's own description, never the starter blurb: a\n // template's `description` is carried onto the page it creates, and a\n // screen description is the live site's meta-description fallback.\n // The bundle blurb lives on `source.starterDescription` instead.\n ...(screen.description ? { description: screen.description } : {}),\n category: starter.category,\n ...(slug ? { slug } : {}),\n ...(screen.seo ? { seo: screen.seo } : {}),\n nodes: screen.nodes,\n source: {\n type: 'starter',\n starterId: starter.id,\n starterName: starter.displayName,\n starterDescription: starter.description,\n starterOrder: index,\n },\n },\n }\n })\n}\n\n/** Every document a starter COULD materialize as, in bundle order. */\nexport function buildAllStarterTemplateDocs(): StarterTemplateDoc[] {\n return STARTER_TEMPLATES.flatMap(buildStarterTemplateDocs)\n}\n\nconst featureColumn = (id: string, title: string, body: string): NodeSpec => ({\n id,\n componentId: 'muiStack',\n props: { spacing: 1 },\n // `flex: 1` is a column's share of its row, not a width cap — it survives\n // the sweep deliberately. Only `maxWidth` in raw pixels was the violation.\n sx: {\n flex: 1,\n paddingTop: 2,\n paddingRight: 2,\n paddingBottom: 2,\n paddingLeft: 2,\n },\n children: [text(`${id}T`, 'h5', title), text(`${id}B`, 'body1', body)],\n})\n\nconst contactForm = (prefix: string): NodeSpec => ({\n id: `${prefix}form`,\n componentId: 'form',\n props: {\n formName: 'Contact',\n submitLabel: 'Send message',\n successMessage: 'Thanks — we will get back to you soon.',\n },\n children: [\n starterTextField(`${prefix}fName`, { name: 'name', label: 'Name', required: true }),\n starterTextField(`${prefix}fEmail`, {\n name: 'email',\n label: 'Email',\n type: 'email',\n required: true,\n }),\n starterTextField(`${prefix}fMessage`, {\n name: 'message',\n label: 'Message',\n multiline: true,\n required: true,\n }),\n ],\n})\n\n\n/**\n * The home page every new site is born with now lives with the rest of the\n * site it is born into — layout, theme and SEO — in `default-site.ts`\n * (AGL-3497). Re-exported so the name keeps its home here.\n */\nexport { buildDefaultHomeScreen } from './default-site'\n\n/** The platform's own starters, which name no plugin's elements. */\nconst PLATFORM_STARTER_TEMPLATES: StarterTemplate[] = [\n {\n id: 'landing',\n displayName: 'Landing Page',\n description:\n 'One-page launch site: hero, three selling points, and a contact form.',\n category: 'Marketing',\n screens: [\n {\n key: 'landing',\n displayName: 'Landing',\n slug: 'landing',\n seo: {\n title: 'Welcome',\n description: 'Everything you need to know, on one page.',\n },\n nodes: buildNodes([\n heroSection(\n 'l_',\n 'A headline that sells your idea',\n 'One clear sentence about the value you deliver.',\n ),\n section('l_featuresSection', 'xl', 6, [\n {\n id: 'l_features',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n featureColumn(\n 'l_f1',\n 'Fast',\n 'Explain the first reason customers pick you.',\n ),\n featureColumn(\n 'l_f2',\n 'Simple',\n 'Explain the second reason customers pick you.',\n ),\n featureColumn(\n 'l_f3',\n 'Reliable',\n 'Explain the third reason customers pick you.',\n ),\n ],\n },\n ]),\n // Was `maxWidth: 560`. A band, not an inner measure: it sat at the\n // top level carrying the section's own gutters and rhythm, so the\n // pixel value was capping the BAND. MD is the stock width for a\n // narrow, form-led column.\n section('l_contactSection', 'md', 6, [\n {\n id: 'l_contact',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('l_contactTitle', 'h4', 'Get in touch'),\n contactForm('l_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n {\n id: 'business',\n displayName: 'Business',\n description:\n 'Company site: home with services, an about page, and a contact page.',\n category: 'Business',\n screens: [\n {\n key: 'home',\n displayName: 'Business Home',\n slug: 'home',\n seo: { title: 'Home' },\n nodes: buildNodes([\n heroSection(\n 'b_',\n 'Your business, done right',\n 'Tell visitors what you do and who you do it for.',\n ),\n section('b_servicesSection', 'xl', 6, [\n {\n id: 'b_services',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n featureColumn('b_s1', 'Service one', 'Describe this service.'),\n featureColumn('b_s2', 'Service two', 'Describe this service.'),\n featureColumn(\n 'b_s3',\n 'Service three',\n 'Describe this service.',\n ),\n ],\n },\n ]),\n ]),\n },\n {\n key: 'about-us',\n displayName: 'About Us',\n slug: 'about-us',\n seo: { title: 'About us' },\n nodes: buildNodes([\n // Was `maxWidth: 720` — the one unambiguous PROSE band in the set,\n // and the case the Prose Container preset exists for. MD (900px)\n // lands near the 65–75 characters a line that reads comfortably.\n section('a_wrapSection', 'md', 8, [\n {\n id: 'a_wrap',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('a_title', 'h3', 'About us'),\n text(\n 'a_body',\n 'body1',\n 'Share your story: how you started, what you believe, and ' +\n 'why customers trust you.',\n ),\n ],\n },\n ]),\n ]),\n },\n {\n key: 'contact-us',\n displayName: 'Contact Us',\n slug: 'contact-us',\n seo: { title: 'Contact' },\n nodes: buildNodes([\n // Was `maxWidth: 560`. Same reading as the landing page's contact\n // band: text plus a form column, so MD.\n section('c_wrapSection', 'md', 8, [\n {\n id: 'c_wrap',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('c_title', 'h3', 'Contact us'),\n text(\n 'c_body',\n 'body1',\n 'Questions or quotes — send a message and we reply within ' +\n 'one business day.',\n ),\n contactForm('c_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n {\n id: 'portfolio',\n displayName: 'Portfolio',\n description: 'Personal portfolio: intro, work grid, and contact form.',\n category: 'Personal',\n screens: [\n {\n key: 'portfolio',\n displayName: 'Portfolio',\n slug: 'portfolio',\n seo: { title: 'Portfolio' },\n nodes: buildNodes([\n heroSection(\n 'p_',\n 'Hi, I make things',\n 'Designer / developer / photographer — introduce yourself here.',\n ),\n section('p_gridSection', 'xl', 6, [\n {\n id: 'p_grid',\n componentId: 'muiStack',\n props: { direction: 'row', spacing: 2 },\n children: [\n {\n id: 'p_img1',\n componentId: 'image',\n // `height` is an image's own intrinsic sizing prop, not a\n // band cap — out of scope for the container standard.\n props: { alt: 'Project one', height: '220px' },\n },\n {\n id: 'p_img2',\n componentId: 'image',\n props: { alt: 'Project two', height: '220px' },\n },\n {\n id: 'p_img3',\n componentId: 'image',\n props: { alt: 'Project three', height: '220px' },\n },\n ],\n },\n ]),\n // Was `maxWidth: 560`, the third of the three contact bands.\n section('p_contactSection', 'md', 6, [\n {\n id: 'p_contact',\n componentId: 'muiStack',\n props: { spacing: 2 },\n children: [\n text('p_contactTitle', 'h4', 'Work with me'),\n contactForm('p_'),\n ],\n },\n ]),\n ]),\n },\n ],\n },\n]\n\n/**\n * Every starter in this build, in gallery order: the platform's own, then\n * each plugin's in config order (AGL-3080). A plugin whose elements a starter\n * is built around — a storefront's product grid and cart — declares it under\n * `starterTemplates` in plugins.config.json, and the manifest generator\n * compiles what it returns, so the gallery, the seed route and a model\n * shown examples all read one list without loading any plugin.\n */\nexport const STARTER_TEMPLATES: StarterTemplate[] = [\n ...PLATFORM_STARTER_TEMPLATES,\n ...PLUGIN_STARTER_TEMPLATES,\n]\n"],"names":["PLUGIN_STARTER_TEMPLATES","normalizeScreenSlug","buildStarterNodes","buildNodes","starterHeroSection","heroSection","starterSection","section","starterText","text","starterTextField","starterTemplateDocId","starterId","screenKey","buildStarterTemplateDocs","starter","screens","map","screen","index","slug","id","key","data","kind","displayName","description","category","seo","nodes","source","type","starterName","starterDescription","starterOrder","buildAllStarterTemplateDocs","STARTER_TEMPLATES","flatMap","featureColumn","title","body","componentId","props","spacing","sx","flex","paddingTop","paddingRight","paddingBottom","paddingLeft","children","contactForm","prefix","formName","submitLabel","successMessage","name","label","required","multiline","buildDefaultHomeScreen","PLATFORM_STARTER_TEMPLATES","direction","alt","height"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,qEAAqE;AACrE,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,yEAAyE;AACzE,8EAA8E;AAC9E,SAASA,wBAAwB,QAAQ,0CAAsC;AAC/E,SAASC,mBAAmB,QAAQ,oBAAgB;AACpD,SACEC,qBAAqBC,UAAU,EAC/BC,sBAAsBC,WAAW,EACjCC,kBAAkBC,OAAO,EACzBC,eAAeC,IAAI,EACnBC,gBAAgB,QAGX,8BAA0B;AAQjC,SACER,iBAAiB,EACjBE,kBAAkB,EAClBE,cAAc,EACdE,WAAW,EACXE,gBAAgB,QACX,8BAA0B;AA+BjC;;;;;;CAMC,GACD,OAAO,SAASC,qBACdC,SAAiB,EACjBC,SAAiB;IAEjB,OAAO,CAAC,QAAQ,EAAED,UAAU,CAAC,EAAEC,WAAW;AAC5C;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASC,yBACdC,OAAwB;IAExB,OAAOA,QAAQC,OAAO,CAACC,GAAG,CAAC,CAACC,QAAQC;QAClC,yEAAyE;QACzE,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,+DAA+D;QAC/D,MAAMC,OAAOnB,oBAAoBiB,OAAOE,IAAI;QAC5C,OAAO;YACLC,IAAIV,qBAAqBI,QAAQM,EAAE,EAAEH,OAAOI,GAAG;YAC/CV,WAAWG,QAAQM,EAAE;YACrBE,MAAM;gBACJC,MAAM;gBACNC,aAAaP,OAAOO,WAAW;eAK3BP,OAAOQ,WAAW,GAAG;gBAAEA,aAAaR,OAAOQ,WAAW;YAAC,IAAI,CAAC;gBAChEC,UAAUZ,QAAQY,QAAQ;eACtBP,OAAO;gBAAEA;YAAK,IAAI,CAAC,GACnBF,OAAOU,GAAG,GAAG;gBAAEA,KAAKV,OAAOU,GAAG;YAAC,IAAI,CAAC;gBACxCC,OAAOX,OAAOW,KAAK;gBACnBC,QAAQ;oBACNC,MAAM;oBACNnB,WAAWG,QAAQM,EAAE;oBACrBW,aAAajB,QAAQU,WAAW;oBAChCQ,oBAAoBlB,QAAQW,WAAW;oBACvCQ,cAAcf;gBAChB;;QAEJ;IACF;AACF;AAEA,oEAAoE,GACpE,OAAO,SAASgB;IACd,OAAOC,kBAAkBC,OAAO,CAACvB;AACnC;AAEA,MAAMwB,gBAAgB,CAACjB,IAAYkB,OAAeC,OAA4B,CAAA;QAC5EnB;QACAoB,aAAa;QACbC,OAAO;YAAEC,SAAS;QAAE;QACpB,0EAA0E;QAC1E,2EAA2E;QAC3EC,IAAI;YACFC,MAAM;YACNC,YAAY;YACZC,cAAc;YACdC,eAAe;YACfC,aAAa;QACf;QACAC,UAAU;YAACzC,KAAK,GAAGY,GAAG,CAAC,CAAC,EAAE,MAAMkB;YAAQ9B,KAAK,GAAGY,GAAG,CAAC,CAAC,EAAE,SAASmB;SAAM;IACxE,CAAA;AAEA,MAAMW,cAAc,CAACC,SAA8B,CAAA;QACjD/B,IAAI,GAAG+B,OAAO,IAAI,CAAC;QACnBX,aAAa;QACbC,OAAO;YACLW,UAAU;YACVC,aAAa;YACbC,gBAAgB;QAClB;QACAL,UAAU;YACRxC,iBAAiB,GAAG0C,OAAO,KAAK,CAAC,EAAE;gBAAEI,MAAM;gBAAQC,OAAO;gBAAQC,UAAU;YAAK;YACjFhD,iBAAiB,GAAG0C,OAAO,MAAM,CAAC,EAAE;gBAClCI,MAAM;gBACNC,OAAO;gBACP1B,MAAM;gBACN2B,UAAU;YACZ;YACAhD,iBAAiB,GAAG0C,OAAO,QAAQ,CAAC,EAAE;gBACpCI,MAAM;gBACNC,OAAO;gBACPE,WAAW;gBACXD,UAAU;YACZ;SACD;IACH,CAAA;AAGA;;;;CAIC,GACD,SAASE,sBAAsB,QAAQ,oBAAgB;AAEvD,kEAAkE,GAClE,MAAMC,6BAAgD;IACpD;QACExC,IAAI;QACJI,aAAa;QACbC,aACE;QACFC,UAAU;QACVX,SAAS;YACP;gBACEM,KAAK;gBACLG,aAAa;gBACbL,MAAM;gBACNQ,KAAK;oBACHW,OAAO;oBACPb,aAAa;gBACf;gBACAG,OAAO1B,WAAW;oBAChBE,YACE,MACA,mCACA;oBAEFE,QAAQ,qBAAqB,MAAM,GAAG;wBACpC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEoB,WAAW;gCAAOnB,SAAS;4BAAE;4BACtCO,UAAU;gCACRZ,cACE,QACA,QACA;gCAEFA,cACE,QACA,UACA;gCAEFA,cACE,QACA,YACA;6BAEH;wBACH;qBACD;oBACD,mEAAmE;oBACnE,kEAAkE;oBAClE,gEAAgE;oBAChE,2BAA2B;oBAC3B/B,QAAQ,oBAAoB,MAAM,GAAG;wBACnC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEC,SAAS;4BAAE;4BACpBO,UAAU;gCACRzC,KAAK,kBAAkB,MAAM;gCAC7B0C,YAAY;6BACb;wBACH;qBACD;iBACF;YACH;SACD;IACH;IACA;QACE9B,IAAI;QACJI,aAAa;QACbC,aACE;QACFC,UAAU;QACVX,SAAS;YACP;gBACEM,KAAK;gBACLG,aAAa;gBACbL,MAAM;gBACNQ,KAAK;oBAAEW,OAAO;gBAAO;gBACrBV,OAAO1B,WAAW;oBAChBE,YACE,MACA,6BACA;oBAEFE,QAAQ,qBAAqB,MAAM,GAAG;wBACpC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEoB,WAAW;gCAAOnB,SAAS;4BAAE;4BACtCO,UAAU;gCACRZ,cAAc,QAAQ,eAAe;gCACrCA,cAAc,QAAQ,eAAe;gCACrCA,cACE,QACA,iBACA;6BAEH;wBACH;qBACD;iBACF;YACH;YACA;gBACEhB,KAAK;gBACLG,aAAa;gBACbL,MAAM;gBACNQ,KAAK;oBAAEW,OAAO;gBAAW;gBACzBV,OAAO1B,WAAW;oBAChB,mEAAmE;oBACnE,iEAAiE;oBACjE,iEAAiE;oBACjEI,QAAQ,iBAAiB,MAAM,GAAG;wBAChC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEC,SAAS;4BAAE;4BACpBO,UAAU;gCACRzC,KAAK,WAAW,MAAM;gCACtBA,KACE,UACA,SACA,8DACE;6BAEL;wBACH;qBACD;iBACF;YACH;YACA;gBACEa,KAAK;gBACLG,aAAa;gBACbL,MAAM;gBACNQ,KAAK;oBAAEW,OAAO;gBAAU;gBACxBV,OAAO1B,WAAW;oBAChB,kEAAkE;oBAClE,wCAAwC;oBACxCI,QAAQ,iBAAiB,MAAM,GAAG;wBAChC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEC,SAAS;4BAAE;4BACpBO,UAAU;gCACRzC,KAAK,WAAW,MAAM;gCACtBA,KACE,UACA,SACA,8DACE;gCAEJ0C,YAAY;6BACb;wBACH;qBACD;iBACF;YACH;SACD;IACH;IACA;QACE9B,IAAI;QACJI,aAAa;QACbC,aAAa;QACbC,UAAU;QACVX,SAAS;YACP;gBACEM,KAAK;gBACLG,aAAa;gBACbL,MAAM;gBACNQ,KAAK;oBAAEW,OAAO;gBAAY;gBAC1BV,OAAO1B,WAAW;oBAChBE,YACE,MACA,qBACA;oBAEFE,QAAQ,iBAAiB,MAAM,GAAG;wBAChC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEoB,WAAW;gCAAOnB,SAAS;4BAAE;4BACtCO,UAAU;gCACR;oCACE7B,IAAI;oCACJoB,aAAa;oCACb,0DAA0D;oCAC1D,sDAAsD;oCACtDC,OAAO;wCAAEqB,KAAK;wCAAeC,QAAQ;oCAAQ;gCAC/C;gCACA;oCACE3C,IAAI;oCACJoB,aAAa;oCACbC,OAAO;wCAAEqB,KAAK;wCAAeC,QAAQ;oCAAQ;gCAC/C;gCACA;oCACE3C,IAAI;oCACJoB,aAAa;oCACbC,OAAO;wCAAEqB,KAAK;wCAAiBC,QAAQ;oCAAQ;gCACjD;6BACD;wBACH;qBACD;oBACD,6DAA6D;oBAC7DzD,QAAQ,oBAAoB,MAAM,GAAG;wBACnC;4BACEc,IAAI;4BACJoB,aAAa;4BACbC,OAAO;gCAAEC,SAAS;4BAAE;4BACpBO,UAAU;gCACRzC,KAAK,kBAAkB,MAAM;gCAC7B0C,YAAY;6BACb;wBACH;qBACD;iBACF;YACH;SACD;IACH;CACD;AAED;;;;;;;CAOC,GACD,OAAO,MAAMf,oBAAuC;OAC/CyB;OACA7D;CACJ,CAAA"}
@@ -23,7 +23,7 @@ import type { ComponentSchema, MdiIconProps, PresetSchema } from '../types/nodes
23
23
  import type { Plugin, PluginId } from './plugin-manager';
24
24
  import type { HostThemeSource } from '../app-utils/site-theme';
25
25
  import type { HostTheme, HostThemeScheme } from '@aglyn/shared-data-types';
26
- import type { ComponentType } from 'react';
26
+ import type { ComponentType, ReactNode } from 'react';
27
27
  export type { ConsoleImportMappingZoneProps, ConsoleRecordEmailZoneProps, ConsoleRecordInsightsZoneProps, } from './record-zone-props';
28
28
  /** The mui bundle id every UI feature bundle depends on. */
29
29
  export declare const MUI_BUNDLE_ID: PluginId;
@@ -727,6 +727,15 @@ export declare const CONSOLE_WIDGET_SLOTS: {
727
727
  * is `startBlank`, because a takeover somebody can only dismiss BACK INTO is
728
728
  * the funnel this zone exists to refuse, and nothing here is a half-answered
729
729
  * state worth returning to.
730
+ *
731
+ * ── Or drawn before the site exists (AGL-3761) ───────────────────────────
732
+ *
733
+ * "Create site" draws this zone first, with `pendingSite` and no site: the
734
+ * name and address are asked inside the widget's own first step, and the
735
+ * site is created only by a choice that needs it — the starter, Skip, or a
736
+ * start the widget begins. A dismissal there is `leave`, and creates
737
+ * nothing. A zone with no widget, or a widget that answers `ready(false)`,
738
+ * gets the shell's plain name-and-address dialog instead.
730
739
  */
731
740
  readonly hostFirstRun: "hostFirstRun";
732
741
  /**
@@ -1095,9 +1104,62 @@ export interface ConsoleOrgSitesZoneProps {
1095
1104
  /** The sites page's own path, for the links a widget builds. */
1096
1105
  basePath: string;
1097
1106
  }
1107
+ /**
1108
+ * A site that does not exist yet (AGL-3761): what the `hostFirstRun` zone
1109
+ * hands its widget when it is drawn by "Create site" rather than on a site
1110
+ * that was just created.
1111
+ *
1112
+ * Nothing is created while the widget asks its questions. The site comes into
1113
+ * being only when the person makes a choice that needs it: the starter (the
1114
+ * zone's `startBlank`), or a start the widget begins with {@link create}.
1115
+ * Dismissing the widget before then is the zone's `leave`, and leaves nothing
1116
+ * behind.
1117
+ */
1118
+ export interface ConsolePendingSite {
1119
+ /**
1120
+ * The site's name and address, as the shell asks for them, with their own
1121
+ * validation and availability check. The widget draws them where it asks
1122
+ * its first question, before any choice that creates the site.
1123
+ */
1124
+ fields: ReactNode;
1125
+ /**
1126
+ * Whether the name and address can be used, showing what is wrong with them
1127
+ * when they cannot. A widget asks before moving past the step that draws
1128
+ * {@link fields}.
1129
+ */
1130
+ check: () => boolean;
1131
+ /** Something has been typed into {@link fields}. */
1132
+ dirty: boolean;
1133
+ /**
1134
+ * Creates the site now, with nothing on it, for a start the widget is about
1135
+ * to begin. Resolves to the site, or to why it was not created; `address`
1136
+ * marks a refusal the person fixes in {@link fields}. A second call after a
1137
+ * success answers the same site and creates nothing.
1138
+ */
1139
+ create: () => Promise<ConsoleCreatedSite | {
1140
+ error: string;
1141
+ address?: boolean;
1142
+ }>;
1143
+ /** The site {@link create} made, once it has. */
1144
+ created: ConsoleCreatedSite | null;
1145
+ /**
1146
+ * The widget's answer to whether it draws anything here. A widget that
1147
+ * will not (a release it is not part of, a route that refused it) says
1148
+ * `false`, and the shell asks for the site its own way instead.
1149
+ */
1150
+ ready: (shown: boolean) => void;
1151
+ }
1152
+ /** A site the pending flow created (AGL-3761). */
1153
+ export interface ConsoleCreatedSite {
1154
+ hostId: string;
1155
+ /** Its subdomain, which is what a console URL names a site by. */
1156
+ host: string;
1157
+ orgSlug: string;
1158
+ }
1098
1159
  /** What the `hostFirstRun` zone hands each widget (AGL-2918). */
1099
1160
  export interface ConsoleHostFirstRunZoneProps {
1100
- hostId: string;
1161
+ /** The site; `null` while it does not exist yet, with {@link pendingSite} set. */
1162
+ hostId: string | null;
1101
1163
  /** The org the page names; `undefined` while it resolves. */
1102
1164
  orgId: string | undefined;
1103
1165
  /** Path slug for building `/[orgSlug]/…` links. */
@@ -1115,7 +1177,7 @@ export interface ConsoleHostFirstRunZoneProps {
1115
1177
  * every way of dismissing it does BEFORE it has started anything. See
1116
1178
  * `hostFirstRun` in {@link CONSOLE_WIDGET_SLOTS}.
1117
1179
  */
1118
- startBlank: () => void;
1180
+ startBlank: () => void | Promise<boolean>;
1119
1181
  /**
1120
1182
  * Closes the zone after its widget STARTED the site some other way — a
1121
1183
  * guided start whose job is running (AGL-3594). The shell records that the
@@ -1123,8 +1185,17 @@ export interface ConsoleHostFirstRunZoneProps {
1123
1185
  * site's pages are the job's to build. A widget that started nothing calls
1124
1186
  * `startBlank` instead. Optional, so a shell that predates it still closes
1125
1187
  * the zone through `startBlank`.
1188
+ *
1189
+ * With {@link pendingSite} and no site created yet, it is also how every
1190
+ * dismissal leaves: nothing has been made, so nothing is written.
1126
1191
  */
1127
1192
  leave?: () => void;
1193
+ /**
1194
+ * Present when the zone is drawn by "Create site" before the site exists
1195
+ * (AGL-3761). `startBlank` then CREATES the site with the starter, and
1196
+ * resolves `false` when it could not, with the reason shown.
1197
+ */
1198
+ pendingSite?: ConsolePendingSite;
1128
1199
  }
1129
1200
  /**
1130
1201
  * Something a console page holds that somebody may want to publish
@@ -264,6 +264,15 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
264
264
  * is `startBlank`, because a takeover somebody can only dismiss BACK INTO is
265
265
  * the funnel this zone exists to refuse, and nothing here is a half-answered
266
266
  * state worth returning to.
267
+ *
268
+ * ── Or drawn before the site exists (AGL-3761) ───────────────────────────
269
+ *
270
+ * "Create site" draws this zone first, with `pendingSite` and no site: the
271
+ * name and address are asked inside the widget's own first step, and the
272
+ * site is created only by a choice that needs it — the starter, Skip, or a
273
+ * start the widget begins. A dismissal there is `leave`, and creates
274
+ * nothing. A zone with no widget, or a widget that answers `ready(false)`,
275
+ * gets the shell's plain name-and-address dialog instead.
267
276
  */ hostFirstRun: 'hostFirstRun',
268
277
  /**
269
278
  * The host setup Theme section, between the Theme picker and the editor