@bluealba/platform-cli 1.0.1 → 1.0.2

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 (42) hide show
  1. package/dist/index.js +277 -9
  2. package/docs/404.mdx +5 -0
  3. package/docs/architecture/api-explorer.mdx +478 -0
  4. package/docs/architecture/architecture-diagrams.mdx +12 -0
  5. package/docs/architecture/authentication-system.mdx +903 -0
  6. package/docs/architecture/authorization-system.mdx +886 -0
  7. package/docs/architecture/bootstrap.mdx +1442 -0
  8. package/docs/architecture/gateway-architecture.mdx +845 -0
  9. package/docs/architecture/multi-tenancy.mdx +1150 -0
  10. package/docs/architecture/overview.mdx +776 -0
  11. package/docs/architecture/scheduler.mdx +818 -0
  12. package/docs/architecture/shell.mdx +885 -0
  13. package/docs/architecture/ui-extension-points.mdx +781 -0
  14. package/docs/architecture/user-states.mdx +794 -0
  15. package/docs/development/overview.mdx +21 -0
  16. package/docs/development/workflow.mdx +914 -0
  17. package/docs/getting-started/core-concepts.mdx +892 -0
  18. package/docs/getting-started/installation.mdx +780 -0
  19. package/docs/getting-started/overview.mdx +83 -0
  20. package/docs/getting-started/quick-start.mdx +940 -0
  21. package/docs/guides/adding-documentation-sites.mdx +1367 -0
  22. package/docs/guides/creating-services.mdx +1736 -0
  23. package/docs/guides/creating-ui-modules.mdx +1860 -0
  24. package/docs/guides/identity-providers.mdx +1007 -0
  25. package/docs/guides/mermaid-diagrams.mdx +212 -0
  26. package/docs/guides/using-feature-flags.mdx +1059 -0
  27. package/docs/guides/working-with-rooms.mdx +566 -0
  28. package/docs/index.mdx +57 -0
  29. package/docs/platform-cli/commands.mdx +604 -0
  30. package/docs/platform-cli/overview.mdx +195 -0
  31. package/package.json +5 -2
  32. package/skills/ba-platform/platform-cli.skill.md +26 -0
  33. package/skills/ba-platform/platform.skill.md +35 -0
  34. package/templates/application-monorepo-template/gitignore +95 -0
  35. package/templates/bootstrap-service-template/gitignore +57 -0
  36. package/templates/bootstrap-service-template/src/main.ts +6 -16
  37. package/templates/customization-ui-module-template/gitignore +73 -0
  38. package/templates/nestjs-service-module-template/gitignore +56 -0
  39. package/templates/platform-init-template/{{platformName}}-core/gitignore +97 -0
  40. package/templates/react-ui-module-template/Dockerfile +1 -1
  41. package/templates/react-ui-module-template/caddy/Caddyfile +1 -1
  42. package/templates/react-ui-module-template/gitignore +72 -0
@@ -0,0 +1,781 @@
1
+ ---
2
+ title: UI Extension Points
3
+ description: The extension point mechanism for customizing and extending micro-frontend components in the Blue Alba Platform
4
+ ---
5
+
6
+ import { Card, CardGrid, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
7
+
8
+ **UI Extension Points** provide a powerful mechanism for micro-frontends to declare customizable extension points that can be replaced or extended by other micro-frontends. This enables deep customization of the platform UI without modifying core code.
9
+
10
+ ## Overview
11
+
12
+ Extension points solve a key challenge in micro-frontend architectures: **how to allow one micro-frontend to customize or extend components defined in another micro-frontend**.
13
+
14
+ <CardGrid stagger>
15
+ <Card title="Declarative Extension" icon="puzzle">
16
+ Modules declare extension points where others can plug in custom components
17
+ </Card>
18
+
19
+ <Card title="React Component Replacement" icon="seti:react">
20
+ Replace entire React components with your own implementations
21
+ </Card>
22
+
23
+ <Card title="Dynamic Extension" icon="random">
24
+ Extensions are registered/unregistered following React component lifecycle
25
+ </Card>
26
+
27
+ <Card title="Scoped by Module" icon="seti:folder">
28
+ Extension points are namespaced by module to avoid collisions
29
+ </Card>
30
+
31
+ <Card title="Fallback Support" icon="approve-check">
32
+ Default components render when no extension is provided
33
+ </Card>
34
+
35
+ <Card title="Type-Safe" icon="seti:typescript">
36
+ Full TypeScript support with typed props
37
+ </Card>
38
+ </CardGrid>
39
+
40
+ ---
41
+
42
+ ## Core Concepts
43
+
44
+ ### Extension Point
45
+
46
+ An **extension point** is a placeholder in a micro-frontend where other modules can inject custom components.
47
+
48
+ **Example**: The Shell declares an `ApplicationSelector` extension point allowing products to customize how applications are displayed in the navbar.
49
+
50
+ ### Extension
51
+
52
+ An **extension** is a React component that replaces or enhances an extension point.
53
+
54
+ **Example**: A product creates a custom `ApplicationSelector` component with a different layout and extends the Shell's extension point.
55
+
56
+ ---
57
+
58
+ ## Declaring Extension Points
59
+
60
+ Modules can declare extension points in two ways:
61
+
62
+ ### 1. Inline Extension Point Component
63
+
64
+ Use the `<ExtensionPoint>` component to create a placeholder within JSX:
65
+
66
+ ```typescript
67
+ import { ExtensionPoint } from '@bluealba-public/pae-ui-react-core';
68
+
69
+ const MyComponent = () => {
70
+ return (
71
+ <div>
72
+ <h1>Welcome</h1>
73
+ <ExtensionPoint name="Greeting" />
74
+ </div>
75
+ );
76
+ };
77
+ ```
78
+
79
+ **With Default Content**:
80
+
81
+ ```typescript
82
+ const MyComponent = () => {
83
+ return (
84
+ <div>
85
+ <h1>Welcome</h1>
86
+ <ExtensionPoint name="Greeting">
87
+ <span>Hello, World!</span>
88
+ </ExtensionPoint>
89
+ </div>
90
+ );
91
+ };
92
+ ```
93
+
94
+ **Scoping**:
95
+
96
+ The extension point is automatically scoped to the current module:
97
+ - Module: `@mycompany/my-ui`
98
+ - Extension point name: `Greeting`
99
+ - **Full name**: `@mycompany/my-ui::Greeting`
100
+
101
+ ### 2. Component as Extension Point (HOC)
102
+
103
+ Use the `extensionPoint()` higher-order component to make an entire component replaceable:
104
+
105
+ ```typescript
106
+ import { extensionPoint } from '@bluealba-public/pae-ui-react-core';
107
+
108
+ const MenuApplicationSelector: React.FC = () => {
109
+ return (
110
+ <div className="app-selector">
111
+ {/* Application selector implementation */}
112
+ </div>
113
+ );
114
+ };
115
+
116
+ // Make this component an extension point
117
+ MenuApplicationSelector.displayName = 'ApplicationSelector';
118
+ export default extensionPoint(MenuApplicationSelector);
119
+ ```
120
+
121
+ **Behavior**:
122
+ - If no extension is provided, `MenuApplicationSelector` renders normally
123
+ - If an extension is registered, `MenuApplicationSelector` is completely replaced
124
+ - The `displayName` becomes the extension point name
125
+
126
+ ---
127
+
128
+ ## Extending Extension Points
129
+
130
+ Other modules can extend these points in two ways:
131
+
132
+ ### 1. Using ExtendExtensionPoint Component
133
+
134
+ The simplest way to extend an extension point:
135
+
136
+ ```typescript
137
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
138
+ import MyCustomSelector from './MyCustomSelector';
139
+
140
+ function MyCustomizationUI() {
141
+ return (
142
+ <ExtendExtensionPoint
143
+ module="@bluealba/pae-shell-ui"
144
+ point="ApplicationSelector"
145
+ >
146
+ <MyCustomSelector />
147
+ </ExtendExtensionPoint>
148
+ );
149
+ }
150
+ ```
151
+
152
+ **Inline Content**:
153
+
154
+ ```typescript
155
+ <ExtendExtensionPoint
156
+ module="@bluealba/pae-shell-ui"
157
+ point="ApplicationSelector"
158
+ >
159
+ <div className="custom-selector">
160
+ <h3>My Custom App Selector</h3>
161
+ {/* Custom implementation */}
162
+ </div>
163
+ </ExtendExtensionPoint>
164
+ ```
165
+
166
+ ### 2. Using useExtendExtensionPoint Hook
167
+
168
+ For more programmatic control:
169
+
170
+ ```typescript
171
+ import { useExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
172
+ import MyCustomSelector from './MyCustomSelector';
173
+
174
+ const MyCustomizationUI = () => {
175
+ // Register the extension
176
+ useExtendExtensionPoint(
177
+ '@bluealba/pae-shell-ui',
178
+ 'ApplicationSelector',
179
+ MyCustomSelector
180
+ );
181
+
182
+ return (
183
+ <div>
184
+ {/* Rest of your component */}
185
+ </div>
186
+ );
187
+ };
188
+ ```
189
+
190
+ **Conditional Extension**:
191
+
192
+ ```typescript
193
+ const MyCustomizationUI = () => {
194
+ const [enableCustomSelector, setEnableCustomSelector] = useState(true);
195
+
196
+ // Only extend when condition is true
197
+ useExtendExtensionPoint(
198
+ '@bluealba/pae-shell-ui',
199
+ 'ApplicationSelector',
200
+ enableCustomSelector ? MyCustomSelector : null
201
+ );
202
+
203
+ return (
204
+ <div>
205
+ <button onClick={() => setEnableCustomSelector(!enableCustomSelector)}>
206
+ Toggle Custom Selector
207
+ </button>
208
+ </div>
209
+ );
210
+ };
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Extension Lifecycle
216
+
217
+ Extensions follow the React component lifecycle:
218
+
219
+ ```
220
+ ┌─────────────────────────────────────────────────────────┐
221
+ │ 1. Extension Component Mounts │
222
+ │ <ExtendExtensionPoint> component renders │
223
+ └────────────────────┬────────────────────────────────────┘
224
+
225
+
226
+ ┌─────────────────────────────────────────────────────────┐
227
+ │ 2. Extension Registers │
228
+ │ Extension point registry updated │
229
+ │ Original component replaced (if using HOC) │
230
+ └────────────────────┬────────────────────────────────────┘
231
+
232
+
233
+ ┌─────────────────────────────────────────────────────────┐
234
+ │ 3. Extension Renders │
235
+ │ Custom component displays in place of original │
236
+ └────────────────────┬────────────────────────────────────┘
237
+
238
+
239
+ ┌─────────────────────────────────────────────────────────┐
240
+ │ 4. Extension Component Unmounts │
241
+ │ <ExtendExtensionPoint> unmounts (route change, etc.) │
242
+ └────────────────────┬────────────────────────────────────┘
243
+
244
+
245
+ ┌─────────────────────────────────────────────────────────┐
246
+ │ 5. Extension Unregisters │
247
+ │ Extension point registry updated │
248
+ │ Original component restored (if using HOC) │
249
+ └─────────────────────────────────────────────────────────┘
250
+ ```
251
+
252
+ **Key Point**: Extensions are **dynamic**. When the extending component unmounts, the extension is automatically removed and the original component restored.
253
+
254
+ ---
255
+
256
+ ## Common Use Cases
257
+
258
+ ### Customize Platform Shell
259
+
260
+ Replace Shell components with branded alternatives:
261
+
262
+ <Tabs>
263
+ <TabItem label="Custom Logo">
264
+ ```typescript
265
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
266
+ import CompanyLogo from './CompanyLogo';
267
+
268
+ <ExtendExtensionPoint
269
+ module="@bluealba/pae-shell-ui"
270
+ point="NavbarPortalLogo"
271
+ >
272
+ <CompanyLogo />
273
+ </ExtendExtensionPoint>
274
+ ```
275
+ </TabItem>
276
+
277
+ <TabItem label="Custom Splash Screen">
278
+ ```typescript
279
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
280
+ import CustomSplash from './CustomSplash';
281
+
282
+ <ExtendExtensionPoint
283
+ module="@bluealba/pae-shell-ui"
284
+ point="SplashScreen"
285
+ >
286
+ <CustomSplash />
287
+ </ExtendExtensionPoint>
288
+ ```
289
+ </TabItem>
290
+
291
+ <TabItem label="Custom Application Selector">
292
+ ```typescript
293
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
294
+ import GridAppSelector from './GridAppSelector';
295
+
296
+ <ExtendExtensionPoint
297
+ module="@bluealba/pae-shell-ui"
298
+ point="ApplicationSelector"
299
+ >
300
+ <GridAppSelector />
301
+ </ExtendExtensionPoint>
302
+ ```
303
+ </TabItem>
304
+ </Tabs>
305
+
306
+ ### Add Navbar Tools
307
+
308
+ Inject custom tools into the Shell navbar:
309
+
310
+ ```typescript
311
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
312
+ import ThemeToggleButton from './ThemeToggleButton';
313
+
314
+ function MyFeatureUI() {
315
+ return (
316
+ <ExtendExtensionPoint
317
+ module="@bluealba/pae-shell-ui"
318
+ point="NavbarTools"
319
+ >
320
+ <ThemeToggleButton />
321
+ </ExtendExtensionPoint>
322
+ );
323
+ }
324
+ ```
325
+
326
+ ### Extend Application Components
327
+
328
+ Applications can also define extension points:
329
+
330
+ ```typescript
331
+ // In @mycompany/crm-ui
332
+ import { ExtensionPoint } from '@bluealba-public/pae-ui-react-core';
333
+
334
+ export const CustomerDetailView = () => {
335
+ return (
336
+ <div>
337
+ <h2>Customer Details</h2>
338
+ {/* Standard fields */}
339
+
340
+ <ExtensionPoint name="CustomerDetailActions">
341
+ <button>Email Customer</button>
342
+ </ExtensionPoint>
343
+ </div>
344
+ );
345
+ };
346
+ ```
347
+
348
+ Then another module extends it:
349
+
350
+ ```typescript
351
+ // In @mycompany/crm-advanced-features-ui
352
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
353
+
354
+ <ExtendExtensionPoint
355
+ module="@mycompany/crm-ui"
356
+ point="CustomerDetailActions"
357
+ >
358
+ <div>
359
+ <button>Email Customer</button>
360
+ <button>Schedule Call</button>
361
+ <button>Create Task</button>
362
+ </div>
363
+ </ExtendExtensionPoint>
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Passing Props to Extensions
369
+
370
+ Extension points can pass props to extending components:
371
+
372
+ ### Declaring with Props
373
+
374
+ ```typescript
375
+ import { ExtensionPoint } from '@bluealba-public/pae-ui-react-core';
376
+
377
+ interface GreetingProps {
378
+ userName: string;
379
+ isAdmin: boolean;
380
+ }
381
+
382
+ const MyComponent = ({ userName, isAdmin }: { userName: string; isAdmin: boolean }) => {
383
+ return (
384
+ <div>
385
+ <ExtensionPoint<GreetingProps>
386
+ name="Greeting"
387
+ userName={userName}
388
+ isAdmin={isAdmin}
389
+ >
390
+ <span>Hello, {userName}!</span>
391
+ </ExtensionPoint>
392
+ </div>
393
+ );
394
+ };
395
+ ```
396
+
397
+ ### Receiving Props in Extension
398
+
399
+ ```typescript
400
+ interface GreetingProps {
401
+ userName: string;
402
+ isAdmin: boolean;
403
+ }
404
+
405
+ const CustomGreeting: React.FC<GreetingProps> = ({ userName, isAdmin }) => {
406
+ return (
407
+ <div className="custom-greeting">
408
+ <h2>Welcome, {userName}!</h2>
409
+ {isAdmin && <span className="badge">Admin</span>}
410
+ </div>
411
+ );
412
+ };
413
+
414
+ // Extend with typed component
415
+ <ExtendExtensionPoint
416
+ module="@mycompany/my-ui"
417
+ point="Greeting"
418
+ >
419
+ <CustomGreeting userName="" isAdmin={false} />
420
+ </ExtendExtensionPoint>
421
+ ```
422
+
423
+ ---
424
+
425
+ ## Multiple Extensions
426
+
427
+ Only **one extension** can be active per extension point at a time:
428
+
429
+ **Last Registered Wins**:
430
+
431
+ ```typescript
432
+ // Module A extends the point
433
+ <ExtendExtensionPoint module="shell" point="Logo">
434
+ <LogoA />
435
+ </ExtendExtensionPoint>
436
+
437
+ // Module B also extends the same point (loaded after A)
438
+ <ExtendExtensionPoint module="shell" point="Logo">
439
+ <LogoB /> {/* This one will be used */}
440
+ </ExtendExtensionPoint>
441
+ ```
442
+
443
+ **Control with Module Load Order**:
444
+
445
+ Ensure the module with the desired extension loads last by using `dependsOn`:
446
+
447
+ ```json
448
+ {
449
+ "name": "@bluealba/pae-shell-ui",
450
+ "dependsOn": [
451
+ "@mycompany/platform-customization-ui"
452
+ ]
453
+ }
454
+ ```
455
+
456
+ This ensures `platform-customization-ui` loads first and its extensions can be overridden by Shell if needed.
457
+
458
+ ---
459
+
460
+ ## Best Practices
461
+
462
+ <CardGrid>
463
+ <Card title="Use Descriptive Names" icon="pencil">
464
+ Choose clear, descriptive names for extension points that indicate their purpose
465
+ </Card>
466
+
467
+ <Card title="Provide Fallback Content" icon="approve-check">
468
+ Always include default content for extension points
469
+ </Card>
470
+
471
+ <Card title="Document Extension Points" icon="document">
472
+ Document available extension points, their props, and usage examples
473
+ </Card>
474
+
475
+ <Card title="Type Your Props" icon="seti:typescript">
476
+ Use TypeScript interfaces for extension point props
477
+ </Card>
478
+
479
+ <Card title="Respect Lifecycles" icon="seti:clock">
480
+ Understand that extensions are dynamic and can mount/unmount
481
+ </Card>
482
+
483
+ <Card title="Avoid Deep Nesting" icon="warning">
484
+ Don't create chains of extensions extending extensions
485
+ </Card>
486
+ </CardGrid>
487
+
488
+ ---
489
+
490
+ ## Platform Shell Extension Points
491
+
492
+ The Shell provides these commonly-used extension points:
493
+
494
+ <Tabs>
495
+ <TabItem label="Branding">
496
+ ```typescript
497
+ // Platform logo in navbar
498
+ NAVBAR_PORTAL_LOGO: "NavbarPortalLogo"
499
+ EXPANDED_NAVBAR_PORTAL_LOGO: "ExpandedNavbarPortalLogo"
500
+
501
+ // Splash screen
502
+ SPLASH_SCREEN: "SplashScreen"
503
+ SPLASH_LOGO: "SplashLogo"
504
+
505
+ // Versions dialog
506
+ VERSIONS_LOGO: "VersionsLogo"
507
+ ```
508
+ </TabItem>
509
+
510
+ <TabItem label="Navigation">
511
+ ```typescript
512
+ // Application selector
513
+ APPLICATIONS_SELECTOR: "ApplicationSelector"
514
+
515
+ // Application menu
516
+ CURRENT_APPLICATION_MENU: "CurrentApplicationMenu"
517
+ CURRENT_APPLICATION_MENU_CONTENT: "CurrentApplicationMenuContent"
518
+
519
+ // Menu buttons
520
+ OPEN_MENU_BUTTON: "OpenMenuButton"
521
+ CLOSE_MENU_BUTTON: "CloseMenuButton"
522
+ ```
523
+ </TabItem>
524
+
525
+ <TabItem label="Navbar">
526
+ ```typescript
527
+ // Navbar sections
528
+ NAVBAR_CONTENT: "NavbarContent"
529
+ NAVBAR_TOOLS: "NavbarTools"
530
+
531
+ // Navbar controls
532
+ NAVBAR_TOGGLE_STATE_BUTTON: "NavbarToggleStateButton"
533
+
534
+ // Admin
535
+ ADMIN_APPLICATION_ICON: "AdminApplication"
536
+ ```
537
+ </TabItem>
538
+
539
+ <TabItem label="User">
540
+ ```typescript
541
+ // User section
542
+ LOGGED_IN_USER_SECTION: "LoggedInUserSection"
543
+ LOGGED_IN_USER_AVATAR: "LoggedInUser"
544
+ ```
545
+ </TabItem>
546
+
547
+ <TabItem label="Top-Level">
548
+ ```typescript
549
+ // Top-level placeholder for global styles, etc.
550
+ SHELL_TOP_ELEMENTS: "ShellTopElements"
551
+ ```
552
+ </TabItem>
553
+ </Tabs>
554
+
555
+ See the [Shell Architecture](/architecture/shell/) documentation for detailed information on each extension point.
556
+
557
+ ---
558
+
559
+ ## Example: Theme Toggle Extension
560
+
561
+ Complete example of adding a theme toggle to the navbar:
562
+
563
+ ### 1. Create the Component
564
+
565
+ ```typescript
566
+ // ThemeToggleButton.tsx
567
+ import React, { useState } from 'react';
568
+
569
+ const ThemeToggleButton: React.FC = () => {
570
+ const [isDark, setIsDark] = useState(false);
571
+
572
+ const toggleTheme = () => {
573
+ setIsDark(!isDark);
574
+ document.documentElement.setAttribute('data-theme', isDark ? 'light' : 'dark');
575
+ };
576
+
577
+ return (
578
+ <button
579
+ onClick={toggleTheme}
580
+ className="theme-toggle"
581
+ title={isDark ? 'Switch to Light Mode' : 'Switch to Dark Mode'}
582
+ >
583
+ {isDark ? '☀️' : '🌙'}
584
+ </button>
585
+ );
586
+ };
587
+
588
+ export default ThemeToggleButton;
589
+ ```
590
+
591
+ ### 2. Register the Extension
592
+
593
+ ```typescript
594
+ // In your customization UI module's root component
595
+ import { ExtendExtensionPoint } from '@bluealba-public/pae-ui-react-core';
596
+ import ThemeToggleButton from './ThemeToggleButton';
597
+
598
+ function PlatformCustomizationUI() {
599
+ return (
600
+ <ExtendExtensionPoint
601
+ module="@bluealba/pae-shell-ui"
602
+ point="NavbarTools"
603
+ >
604
+ <ThemeToggleButton />
605
+ </ExtendExtensionPoint>
606
+ );
607
+ }
608
+
609
+ export default PlatformCustomizationUI;
610
+ ```
611
+
612
+ ### 3. Configure Bootstrap
613
+
614
+ Ensure your customization module loads:
615
+
616
+ ```json
617
+ {
618
+ "name": "@mycompany/platform-customization-ui",
619
+ "type": "app",
620
+ "baseUrl": "/platform-customization-ui",
621
+ "service": {
622
+ "host": "platform-customization-ui",
623
+ "port": 80
624
+ },
625
+ "ui": {
626
+ "route": "/",
627
+ "mountAtSelector": "body",
628
+ "bundleFile": "platform-customization-ui.js",
629
+ "isPlatformCustomization": true
630
+ },
631
+ "dependsOn": []
632
+ }
633
+ ```
634
+
635
+ **Key**: Set `isPlatformCustomization: true` to ensure early loading.
636
+
637
+ ---
638
+
639
+ ## Troubleshooting
640
+
641
+ ### Extension Not Applying
642
+
643
+ **Check**:
644
+ 1. Module declaring extension point is loaded
645
+ 2. Module providing extension is loaded
646
+ 3. Extension module loads after the module it's extending
647
+ 4. Extension point name matches exactly (case-sensitive)
648
+ 5. Module name matches exactly
649
+
650
+ **Debug**:
651
+ ```typescript
652
+ // Add logging to verify registration
653
+ useExtendExtensionPoint(
654
+ '@bluealba/pae-shell-ui',
655
+ 'NavbarTools',
656
+ () => {
657
+ console.log('NavbarTools extension registered');
658
+ return <ThemeToggleButton />;
659
+ }
660
+ );
661
+ ```
662
+
663
+ ### Extension Disappears
664
+
665
+ **Cause**: The component registering the extension unmounted.
666
+
667
+ **Solution**: Ensure the component registering the extension remains mounted. For persistent extensions, register them in a root-level component that doesn't unmount.
668
+
669
+ ### Multiple Extensions Conflict
670
+
671
+ **Cause**: Multiple modules extending the same point.
672
+
673
+ **Solution**:
674
+ - Use module load order to control priority
675
+ - Consolidate extensions into a single module
676
+ - Create separate extension points for different features
677
+
678
+ ### TypeScript Type Errors
679
+
680
+ **Cause**: Props mismatch between extension point and extension component.
681
+
682
+ **Solution**:
683
+ - Export prop types from the module declaring the extension point
684
+ - Import and use these types in your extension component
685
+
686
+ ```typescript
687
+ // In module declaring extension point
688
+ export interface NavbarToolsProps {
689
+ isCollapsed: boolean;
690
+ }
691
+
692
+ // In extending module
693
+ import { NavbarToolsProps } from '@bluealba/pae-shell-ui';
694
+
695
+ const MyTool: React.FC<NavbarToolsProps> = ({ isCollapsed }) => {
696
+ // Implementation
697
+ };
698
+ ```
699
+
700
+ ---
701
+
702
+ ## Advanced Patterns
703
+
704
+ ### Conditional Extension
705
+
706
+ Only extend under certain conditions:
707
+
708
+ ```typescript
709
+ const ConditionalExtension = () => {
710
+ const { user } = useAuth();
711
+ const { features } = useTenantConfig();
712
+
713
+ if (user.isAdmin && features.customTheme) {
714
+ return (
715
+ <ExtendExtensionPoint
716
+ module="@bluealba/pae-shell-ui"
717
+ point="NavbarTools"
718
+ >
719
+ <ThemeToggleButton />
720
+ </ExtendExtensionPoint>
721
+ );
722
+ }
723
+
724
+ return null;
725
+ };
726
+ ```
727
+
728
+ ### Composing Extensions
729
+
730
+ Create a component that extends multiple points:
731
+
732
+ ```typescript
733
+ const PlatformCustomizations = () => {
734
+ return (
735
+ <>
736
+ <ExtendExtensionPoint module="shell" point="NavbarPortalLogo">
737
+ <CompanyLogo />
738
+ </ExtendExtensionPoint>
739
+
740
+ <ExtendExtensionPoint module="shell" point="SplashScreen">
741
+ <CompanySplash />
742
+ </ExtendExtensionPoint>
743
+
744
+ <ExtendExtensionPoint module="shell" point="NavbarTools">
745
+ <ThemeToggle />
746
+ </ExtendExtensionPoint>
747
+ </>
748
+ );
749
+ };
750
+ ```
751
+
752
+ ### Wrapping Original Component
753
+
754
+ Extend while preserving original behavior:
755
+
756
+ ```typescript
757
+ import { useExtensionPoint } from '@bluealba-public/pae-ui-react-core';
758
+
759
+ const EnhancedApplicationSelector = () => {
760
+ // Get the original component
761
+ const OriginalSelector = useExtensionPoint(
762
+ '@bluealba/pae-shell-ui',
763
+ 'ApplicationSelector'
764
+ );
765
+
766
+ return (
767
+ <div className="enhanced-selector">
768
+ <div className="banner">Featured Apps</div>
769
+ <OriginalSelector />
770
+ </div>
771
+ );
772
+ };
773
+ ```
774
+
775
+ ---
776
+
777
+ ## Next Steps
778
+
779
+ - **[Shell Architecture](/_/docs/architecture/shell/)** - Available Shell extension points
780
+ - **[Bootstrap](/_/docs/architecture/bootstrap/)** - Configuring module load order
781
+ - **[Getting Started with UI Development](/_/docs/development/ui-development/)** - Creating micro-frontends