@lucasvu/scope-ui 0.0.8 → 0.1.1

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.
@@ -6,6 +6,44 @@ import process from 'node:process'
6
6
 
7
7
  const PACKAGE_NAME = '@lucasvu/scope-ui'
8
8
  const DEFAULT_THEME_PRESET = 'ocean'
9
+ const DEFAULT_LAYOUT_FILE = 'src/layout-presets/workspace-admin-v1.ts'
10
+
11
+ const LAYOUT_PRESET = {
12
+ id: 'workspace-admin-v1',
13
+ label: 'Workspace Admin v1',
14
+ description:
15
+ 'Shared admin shell with a dark sidebar, gradient topbar, soft intro card, optional segmented tabs, and card-based content blocks inspired by the Campaigns screen.',
16
+ recommendedFor: [
17
+ 'Admin workspaces',
18
+ 'Operations dashboards',
19
+ 'CRUD-heavy backoffice screens that should share one shell',
20
+ ],
21
+ shellRecipe: [
22
+ 'Dark left sidebar with icon + label navigation and one active item',
23
+ 'Gradient workspace topbar with workspace label on the left and timezone/user slots on the right',
24
+ 'Large page intro card with breadcrumb, title, and optional subtitle',
25
+ 'Optional segmented tabs row directly under the intro card',
26
+ 'Toolbar card with search/filters on the left and actions on the right',
27
+ 'Main body rendered as one or more content cards instead of a flat page',
28
+ ],
29
+ requiredFields: [
30
+ 'layoutPreset',
31
+ 'workspaceLabel',
32
+ 'pageKind',
33
+ 'routeUrl',
34
+ 'sidebarItems',
35
+ 'activeSidebarItemId',
36
+ 'pageTitle',
37
+ ],
38
+ askBeforeCoding: [
39
+ 'What workspace label should appear in the topbar?',
40
+ 'What timezone or top-right meta label should appear beside the user badge?',
41
+ 'What sidebar items exist and which one is active on this screen?',
42
+ 'Does this screen need segmented tabs? If yes, what are the tab labels and which tab is active?',
43
+ 'What search placeholder, filters, and primary action belong in the toolbar card?',
44
+ 'What columns, fields, or summary blocks should be rendered in the page body?',
45
+ ],
46
+ }
9
47
 
10
48
  const THEME_PRESETS = {
11
49
  ocean: {
@@ -216,6 +254,7 @@ function parseArgs(argv) {
216
254
  force: false,
217
255
  agentsFile: 'AGENTS.md',
218
256
  themeFile: 'src/styles/ui-theme.css',
257
+ layoutFile: DEFAULT_LAYOUT_FILE,
219
258
  theme: DEFAULT_THEME_PRESET,
220
259
  listThemes: false,
221
260
  }
@@ -248,6 +287,16 @@ function parseArgs(argv) {
248
287
  continue
249
288
  }
250
289
 
290
+ if (arg === '--layout-file') {
291
+ const value = argv[index + 1]
292
+ if (!value || value.startsWith('--')) {
293
+ exitWithMissingValue('--layout-file')
294
+ }
295
+ args.layoutFile = value
296
+ index += 1
297
+ continue
298
+ }
299
+
251
300
  if (arg === '--theme') {
252
301
  const value = argv[index + 1]
253
302
  if (!value || value.startsWith('--')) {
@@ -288,12 +337,13 @@ Usage:
288
337
  Optional: inspect approved presets before choosing one.
289
338
 
290
339
  npx scope-ui-init --theme forest --force
291
- npx scope-ui-init --agents-file AGENTS.md --theme-file src/styles/ui-theme.css
340
+ npx scope-ui-init --agents-file AGENTS.md --theme-file src/styles/ui-theme.css --layout-file ${DEFAULT_LAYOUT_FILE}
292
341
 
293
342
  Options:
294
343
  --force overwrite existing files
295
344
  --agents-file target path for the generated AGENTS.md file
296
345
  --theme-file target path for the generated theme override file
346
+ --layout-file target path for the generated layout preset file
297
347
  --theme theme preset id (${Object.keys(THEME_PRESETS).join(', ')})
298
348
  --list-themes show the approved preset list
299
349
  --help, -h show this help
@@ -333,38 +383,100 @@ function renderTokenBlock(tokens) {
333
383
  .join('\n')
334
384
  }
335
385
 
336
- function createAgentsTemplate({ themeFile, themePreset }) {
386
+ function renderMarkdownList(items) {
387
+ return items.map((item) => `- ${item}`).join('\n')
388
+ }
389
+
390
+ function createAgentsTemplate({ themeFile, layoutFile, themePreset, layoutPreset }) {
337
391
  return `# Agent Rules
338
392
 
339
393
  This repo uses \`${PACKAGE_NAME}\` as the default UI library.
394
+ Use \`${PACKAGE_NAME}\` for React components and \`${PACKAGE_NAME}/core\` for framework-agnostic theme/runtime contracts.
340
395
  This repo is locked to the \`${themePreset.label}\` theme preset (\`${themePreset.id}\`).
396
+ This repo uses the \`${layoutPreset.label}\` shell preset (\`${layoutPreset.id}\`) as the shared layout baseline.
341
397
 
342
398
  Primary references:
343
399
  - \`node_modules/${PACKAGE_NAME}/README.md\`
344
400
  - \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`
345
- - \`uiScreenBlueprint\` and \`uiAiManifest\` from \`${PACKAGE_NAME}\`
401
+ - \`uiScreenBlueprint\`, \`uiAiManifest\`, and \`uiThemeLayerAssets\` from \`${PACKAGE_NAME}/core\`
346
402
  - \`${themeFile}\`
403
+ - \`${layoutFile}\`
347
404
 
348
405
  Theme preset summary:
349
406
  - ${themePreset.description}
350
407
  - Recommended for: ${themePreset.recommendedFor.join(', ')}
351
408
 
409
+ Layout preset summary:
410
+ ${renderMarkdownList(layoutPreset.shellRecipe)}
411
+
412
+ ## Workspace Base
413
+
414
+ For Vite + micro frontend repos, keep this structure stable:
415
+
416
+ - \`${PACKAGE_NAME}\` owns the React component surface
417
+ - \`${PACKAGE_NAME}/core\` owns theme contracts, bundled theme layers, color-mode runtime, and framework-agnostic contracts
418
+ - \`apps/shell\` owns the shared app shell, top-level routing, remote mounts, and theme imports
419
+ - \`apps/*-mfe\` owns page-level business screens and feature routes
420
+
421
+ If the repo still has a \`packages/shared\` folder, keep it for business utils or internal loaders, not for the primary theme runtime.
422
+
423
+ Recommended folders:
424
+
425
+ - shell: \`src/app\`, \`src/layouts\`, \`src/routes\`, \`src/remotes\`, \`src/styles/ui-theme.css\`
426
+ - remote: \`src/features\`, \`src/pages\`, \`src/routes\`, \`src/services\`, \`src/styles/index.css\`
427
+
428
+ Theme layers:
429
+
430
+ 1. Import \`${PACKAGE_NAME}/styles.css\` first.
431
+ 2. If the repo wants a bundled shell/theme layer, import one from \`${PACKAGE_NAME}/themes/*\` next.
432
+ 3. Import \`${themeFile}\` after the bundled theme layer.
433
+ 4. Keep app-specific overrides thin and token-based.
434
+
435
+ If the bundled theme layer is client-theme-scoped, set \`data-client-theme\` with \`applyDocumentClientTheme(...)\`.
436
+
352
437
  ## Required Flow
353
438
 
354
439
  When asked to build or edit a screen, follow these steps in order:
355
440
 
356
- 1. Read \`${themeFile}\`, \`node_modules/${PACKAGE_NAME}/README.md\`, \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`, and the exported \`uiScreenBlueprint\` contract before generating UI.
357
- 2. Fill the screen brief first. If route url, sidebar items, active sidebar item, title, actions, filters, fields, or columns are missing, ask for them or leave clear TODO placeholders instead of inventing them.
358
- 3. Verify the app entry imports \`${PACKAGE_NAME}/styles.css\` first and the project theme file right after it.
359
- 4. Identify the page kind (\`list | form | detail | dashboard\`), then map each block to canonical components from \`uiAiManifest\` before writing JSX.
360
- 5. Build the shell in this exact order: \`Sidebar\` -> \`Breadcrumb\` -> \`PageTitle\` -> top actions -> page body cards/grids.
361
- 6. For list pages, build filters first and then the \`DataTable\`. For form pages, build section cards and fields. For detail pages, build summary cards and related tables. For dashboard pages, build stat cards and then supporting cards/tables.
362
- 7. Keep all colors, radius, surface, and shadow decisions inside \`${themeFile}\`. If the preset is insufficient, update tokens there instead of styling one page ad hoc.
363
- 8. Before finishing, run the output checklist in this file.
441
+ 1. Read \`${themeFile}\`, \`${layoutFile}\`, \`node_modules/${PACKAGE_NAME}/README.md\`, \`node_modules/${PACKAGE_NAME}/AI_SETUP.md\`, and the exported \`uiScreenBlueprint\` contract before generating UI.
442
+ 2. If the task touches app bootstrap, shell setup, or micro frontend structure, scaffold the repo around the workspace base above before writing page JSX.
443
+ 3. Fill the shell brief and screen brief first. If a required field is missing, stop and ask for that exact value before writing JSX. Only leave TODO placeholders when the user explicitly asks for an incomplete scaffold.
444
+ 4. Verify the app entry imports \`${PACKAGE_NAME}/styles.css\` first, then any bundled theme layer from \`${PACKAGE_NAME}/themes/*\`, then \`${themeFile}\`.
445
+ 5. Treat \`${layoutFile}\` as the source of truth for the app shell. Keep the dark sidebar, gradient topbar, intro card, and card-based body structure aligned with that preset unless the user explicitly asks for a different shell.
446
+ 6. Keep the shell in the host app. Do not let a remote rebuild its own global shell unless the task explicitly asks for a standalone shell.
447
+ 7. Identify the page kind (\`list | form | detail | dashboard\`), then map each block to canonical components from \`uiAiManifest\` before writing JSX.
448
+ 8. Build the shell in this exact order: \`Sidebar\` -> workspace topbar -> intro card (\`Breadcrumb\` + \`PageTitle\`) -> optional segmented tabs -> toolbar card -> page body cards/grids.
449
+ 9. For list pages, build the toolbar card first and then the \`DataTable\`. For form pages, keep the same shell and swap the body into section cards and a bottom action row. For detail pages, keep the shell and render summary/detail cards plus related tables. For dashboard pages, keep the shell and render stat cards plus supporting cards/tables.
450
+ 10. If \`${layoutFile}\` says a slot is optional, omit it cleanly when the brief does not request it. Do not invent tabs, workspace labels, filters, or toolbar actions.
451
+ 11. Keep all colors, radius, surface, and shadow decisions inside \`${themeFile}\`. If the preset is insufficient, update tokens there instead of styling one page ad hoc.
452
+ 12. Before finishing, run the output checklist in this file.
453
+
454
+ ## Ask For Missing Input
455
+
456
+ If any of these are missing, ask the user directly before writing JSX:
457
+
458
+ ${renderMarkdownList(layoutPreset.askBeforeCoding)}
459
+
460
+ ## Shell Brief
461
+
462
+ Complete this shell brief before writing JSX:
463
+
464
+ \`\`\`yaml
465
+ layoutPreset: ${layoutPreset.id}
466
+ workspaceLabel:
467
+ timezoneLabel:
468
+ userBadgeLabel:
469
+ pageTabs:
470
+ - value:
471
+ label:
472
+ activePageTab:
473
+ searchPlaceholder:
474
+ toolbarNote:
475
+ \`\`\`
364
476
 
365
477
  ## Screen Brief
366
478
 
367
- Complete this brief before writing JSX:
479
+ Complete this screen brief before writing JSX:
368
480
 
369
481
  \`\`\`yaml
370
482
  pageKind: list | form | detail | dashboard
@@ -373,6 +485,7 @@ sidebarItems:
373
485
  - id:
374
486
  title:
375
487
  href:
488
+ icon:
376
489
  activeSidebarItemId:
377
490
  breadcrumbs:
378
491
  - label:
@@ -421,29 +534,44 @@ emptyState:
421
534
  permissions: []
422
535
  \`\`\`
423
536
 
537
+ ## Shell Lock
538
+
539
+ Keep the layout aligned with \`${layoutPreset.id}\`:
540
+
541
+ ${renderMarkdownList(layoutPreset.shellRecipe)}
542
+
424
543
  ## Page Frame Recipes
425
544
 
426
- - \`list\`: \`Sidebar\` -> \`Breadcrumb\` -> \`PageTitle\` -> header actions -> optional stats -> filter \`Card\` -> \`DataTable\` \`Card\`
427
- - \`form\`: \`Sidebar\` -> \`Breadcrumb\` -> \`PageTitle\` -> primary/cancel actions -> sectioned form \`Card\` blocks -> bottom action row
428
- - \`detail\`: \`Sidebar\` -> \`Breadcrumb\` -> \`PageTitle\` -> status/actions -> summary metadata \`Card\` -> detail \`Card\` blocks -> related \`DataTable\`
429
- - \`dashboard\`: \`Sidebar\` -> \`Breadcrumb\` -> \`PageTitle\` -> header actions -> \`Stat\` row -> filters -> insight \`Card\` blocks and \`DataTable\`
545
+ - \`list\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`DataTable\` \`Card\`
546
+ - \`form\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> top actions -> sectioned form \`Card\` blocks -> bottom action row
547
+ - \`detail\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> status/actions -> summary metadata \`Card\` -> detail \`Card\` blocks -> related \`DataTable\`
548
+ - \`dashboard\`: dark \`Sidebar\` -> workspace topbar -> intro card -> optional segmented tabs -> toolbar \`Card\` -> \`Stat\` row -> insight \`Card\` blocks and \`DataTable\`
430
549
 
431
550
  ## Hard Rules
432
551
 
433
552
  - import \`${PACKAGE_NAME}/styles.css\` once at the app entry
434
- - import the project theme override file after the package stylesheet
435
- - use root exports from \`${PACKAGE_NAME}\`
553
+ - import a bundled theme layer from \`${PACKAGE_NAME}/themes/*\` after the package stylesheet when the repo chooses one
554
+ - import the project theme override file after the bundled theme layer
555
+ - use \`applyDocumentClientTheme\` when the chosen bundled theme layer is client-theme-scoped
556
+ - use root exports from \`${PACKAGE_NAME}\` for React components
557
+ - use \`${PACKAGE_NAME}/core\` for theme/runtime utilities in non-React or mixed-framework setup
436
558
  - use \`${themeFile}\` as the only source of truth for colors, radius, surfaces, and shadows
559
+ - use \`${layoutFile}\` as the source of truth for the shell layout and shared page frame
437
560
  - keep layouts and component choices aligned with the shared preset-driven UI used across projects
561
+ - keep the host shell responsible for sidebar, topbar, remote mount, and theme mode
562
+ - keep remotes focused on feature routes and page business content
438
563
  - read \`uiAiManifest\` before choosing components
564
+ - read \`uiThemeLayerAssets\` before choosing a bundled theme layer
439
565
  - read \`uiThemeContract\` before changing colors, surfaces, borders, radius, or shadows
440
566
  - keep UI token-driven and theme-driven
441
567
 
442
568
  Do not:
443
569
  - import from \`MainFe\` unless the task explicitly targets a legacy screen
444
570
  - invent a second palette or one-off brand colors outside \`${themeFile}\`
571
+ - replace the shared dark-sidebar + gradient-topbar shell with a flat blank layout unless the user explicitly requests it
445
572
  - restyle individual pages if the preset tokens can solve it globally
446
573
  - create duplicate Button/Input/Select wrappers unless a project-specific behavior is required
574
+ - let each remote define a different shell or a different palette
447
575
 
448
576
  ## Component Choice
449
577
 
@@ -461,13 +589,17 @@ Do not:
461
589
 
462
590
  Before finishing, confirm all of these are true:
463
591
 
464
- - The screen brief is complete or unresolved values are clearly marked as TODO.
465
- - The shell contains \`Sidebar\`, \`Breadcrumb\`, and \`PageTitle\` in the correct order.
592
+ - The shell brief and screen brief are complete.
593
+ - Any missing required input was explicitly asked for before coding.
594
+ - The shell matches \`${layoutPreset.id}\` with a dark sidebar, gradient topbar, intro card, and card-based body structure.
466
595
  - The chosen components match the page kind and the brief.
467
596
  - No \`MainFe\` imports were used.
468
597
  - No hardcoded brand colors were added in page components.
469
598
  - Theme decisions live in \`${themeFile}\`, not in ad hoc JSX styling.
599
+ - The app entry import order is package stylesheet -> bundled theme layer if present -> project theme override.
600
+ - The shell still lives in the host app and remotes only own business screens.
470
601
  - Spacing, card structure, and actions are consistent with the shared preset.
602
+ - The layout shell stayed stable even if the page body changed.
471
603
  `
472
604
  }
473
605
 
@@ -487,6 +619,110 @@ ${renderTokenBlock(themePreset.tokens.dark)}
487
619
  `
488
620
  }
489
621
 
622
+ function createLayoutTemplate({ themeFile, layoutPreset }) {
623
+ return `/* Generated by scope-ui-init. */
624
+ /* Layout preset: ${layoutPreset.label} (${layoutPreset.id}) */
625
+ /* Use this file as the shared app-shell source of truth for AI/codegen. */
626
+
627
+ export const uiLayoutPreset = {
628
+ id: '${layoutPreset.id}',
629
+ label: '${layoutPreset.label}',
630
+ description:
631
+ '${layoutPreset.description}',
632
+ themeSource: '${themeFile}',
633
+ recommendedFor: [
634
+ ${layoutPreset.recommendedFor.map((item) => ` '${item}',`).join('\n')}
635
+ ],
636
+ shellRecipe: [
637
+ ${layoutPreset.shellRecipe.map((item) => ` '${item}',`).join('\n')}
638
+ ],
639
+ requiredFields: [
640
+ ${layoutPreset.requiredFields.map((item) => ` '${item}',`).join('\n')}
641
+ ],
642
+ askBeforeCoding: [
643
+ ${layoutPreset.askBeforeCoding.map((item) => ` '${item}',`).join('\n')}
644
+ ],
645
+ workspaceStructure: {
646
+ packageUi: ['components', 'theme contracts', 'bundled theme layers', 'color-mode runtime'],
647
+ shellApp: ['src/app', 'src/layouts', 'src/routes', 'src/remotes', 'src/styles/ui-theme.css'],
648
+ remoteApp: ['src/features', 'src/pages', 'src/routes', 'src/services', 'src/styles/index.css'],
649
+ },
650
+ themeLayers: [
651
+ '${PACKAGE_NAME}/styles.css',
652
+ '${PACKAGE_NAME}/themes/theme-ui-new-main-fe.css (optional bundled package layer)',
653
+ '${themeFile}',
654
+ ],
655
+ setupSteps: [
656
+ 'Import the package stylesheet once at the host app entry.',
657
+ 'If the app wants a bundled package theme layer, import it after the package stylesheet.',
658
+ 'Import the project themeSource after the bundled theme layer.',
659
+ 'If the chosen theme layer is client-theme-scoped, set data-client-theme at the document root.',
660
+ 'Initialize color mode at the host app entry and let the host own shell/theme concerns.',
661
+ 'Keep remotes focused on feature routes and business screens instead of rebuilding the global shell.',
662
+ ],
663
+ shell: {
664
+ sidebar: {
665
+ tone: 'dark',
666
+ width: '240px',
667
+ content: ['workspace badge', 'icon + label navigation', 'active state'],
668
+ },
669
+ topbar: {
670
+ background: 'theme gradient from --primary-grad-from to --primary-grad-to',
671
+ leftSlot: 'workspaceLabel',
672
+ rightSlots: ['timezoneLabel', 'userBadgeLabel'],
673
+ },
674
+ introCard: {
675
+ content: ['breadcrumbs', 'pageTitle', 'pageSubtitle'],
676
+ surface: 'soft elevated card',
677
+ },
678
+ pageTabs: {
679
+ optional: true,
680
+ style: 'segmented pills',
681
+ fields: ['pageTabs', 'activePageTab'],
682
+ },
683
+ toolbarCard: {
684
+ optional: true,
685
+ leftSlots: ['searchPlaceholder', 'filters'],
686
+ rightSlots: ['secondaryActions', 'primaryAction'],
687
+ },
688
+ },
689
+ pageBodies: {
690
+ list: ['toolbar card', 'DataTable card', 'rowActions', 'emptyState'],
691
+ form: ['sectioned form cards', 'fields', 'bottom action row'],
692
+ detail: ['summary metadata card', 'detailSections', 'related tables'],
693
+ dashboard: ['summaryStats', 'filters', 'insight cards', 'DataTable'],
694
+ },
695
+ hardRules: [
696
+ 'Keep the dark sidebar and gradient topbar shell stable across screens.',
697
+ 'Do not replace the intro card with a bare page title row.',
698
+ 'Use the shared theme tokens from the themeSource file for color, border, surface, and shadow decisions.',
699
+ 'Import theme layers in this order: package stylesheet, bundled package theme layer when present, then themeSource.',
700
+ 'Keep the host app responsible for the global shell and keep remotes page-scoped.',
701
+ 'Only omit tabs or toolbar sections when the brief explicitly leaves them out.',
702
+ 'Ask for missing required fields before generating JSX instead of guessing from the screenshot.',
703
+ ],
704
+ exampleBrief: {
705
+ layoutPreset: '${layoutPreset.id}',
706
+ workspaceLabel: 'Workspace',
707
+ timezoneLabel: 'UTC+07:00',
708
+ userBadgeLabel: 'L',
709
+ pageKind: 'list',
710
+ routeUrl: '/campaigns/new',
711
+ activeSidebarItemId: 'campaigns',
712
+ pageTabs: [
713
+ { value: 'overview', label: 'Overview' },
714
+ { value: 'coupons', label: 'Coupons' },
715
+ { value: 'redemption', label: 'Redemption' },
716
+ ],
717
+ activePageTab: 'coupons',
718
+ searchPlaceholder: 'Search by coupon code',
719
+ },
720
+ } as const
721
+
722
+ export type UiLayoutPreset = typeof uiLayoutPreset
723
+ `
724
+ }
725
+
490
726
  function writeFile(targetPath, content, force) {
491
727
  const absolutePath = resolve(process.cwd(), targetPath)
492
728
  const alreadyExists = existsSync(absolutePath)
@@ -511,7 +747,12 @@ const themePreset = resolveThemePreset(options.theme)
511
747
 
512
748
  const agentsResult = writeFile(
513
749
  options.agentsFile,
514
- createAgentsTemplate({ themeFile: options.themeFile, themePreset }),
750
+ createAgentsTemplate({
751
+ themeFile: options.themeFile,
752
+ layoutFile: options.layoutFile,
753
+ themePreset,
754
+ layoutPreset: LAYOUT_PRESET,
755
+ }),
515
756
  options.force,
516
757
  )
517
758
 
@@ -521,13 +762,23 @@ const themeResult = writeFile(
521
762
  options.force,
522
763
  )
523
764
 
765
+ const layoutResult = writeFile(
766
+ options.layoutFile,
767
+ createLayoutTemplate({ themeFile: options.themeFile, layoutPreset: LAYOUT_PRESET }),
768
+ options.force,
769
+ )
770
+
524
771
  console.log(`Initialized ${PACKAGE_NAME}`)
525
772
  console.log(`- theme preset: ${themePreset.label} (${themePreset.id})`)
773
+ console.log(`- layout preset: ${LAYOUT_PRESET.label} (${LAYOUT_PRESET.id})`)
526
774
  console.log(`- ${agentsResult.path}: ${agentsResult.status}`)
527
775
  console.log(`- ${themeResult.path}: ${themeResult.status}`)
776
+ console.log(`- ${layoutResult.path}: ${layoutResult.status}`)
528
777
  console.log('')
529
778
  console.log('Next steps:')
530
779
  console.log(`1. Import \`${PACKAGE_NAME}/styles.css\` once at your app entry.`)
531
- console.log(`2. Import \`${options.themeFile}\` right after the package stylesheet.`)
532
- console.log(`3. Let your agent read \`${options.agentsFile}\` before generating UI.`)
533
- console.log(`4. Re-run this command with \`--theme <preset> --force\` if you want another approved preset.`)
780
+ console.log(`2. If you want a bundled package theme layer, import one from \`${PACKAGE_NAME}/themes/*\` right after the package stylesheet.`)
781
+ console.log(`3. Import \`${options.themeFile}\` after the bundled theme layer.`)
782
+ console.log(`4. Let your agent read \`${options.agentsFile}\` and \`${options.layoutFile}\` before generating UI.`)
783
+ console.log('5. Keep the host app responsible for the global shell and keep remotes page-scoped.')
784
+ console.log(`6. Re-run this command with \`--theme <preset> --force\` if you want another approved preset.`)