@powerhousedao/academy 5.1.0-staging.0 → 5.1.0

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 (76) hide show
  1. package/CHANGELOG.md +46 -1148
  2. package/blog/BeyondCommunication-ABlueprintForDevelopment.md +1 -2
  3. package/blog/TheChallengeOfChange.md +0 -1
  4. package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
  5. package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +27 -24
  6. package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +10 -155
  7. package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +35 -122
  8. package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +155 -178
  9. package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
  10. package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +22 -62
  11. package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -0
  12. package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
  13. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
  14. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +44 -75
  15. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +22 -28
  16. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +31 -28
  17. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +206 -211
  18. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +62 -176
  19. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +0 -21
  20. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +319 -309
  21. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +0 -4
  22. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +0 -4
  23. package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
  24. package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +35 -111
  25. package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +79 -195
  26. package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +241 -435
  27. package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +27 -388
  28. package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +7 -95
  29. package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
  30. package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +2 -6
  31. package/docs/academy/04-APIReferences/01-ReactHooks.md +501 -291
  32. package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +39 -7
  33. package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
  34. package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
  35. package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +24 -72
  36. package/docs/academy/08-Glossary.md +0 -7
  37. package/docusaurus.config.ts +3 -28
  38. package/package.json +1 -1
  39. package/sidebars.ts +13 -49
  40. package/src/css/custom.css +18 -26
  41. package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -425
  42. package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -557
  43. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/Modules.png +0 -0
  44. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/VetraStudioDrive.png +0 -0
  45. package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +0 -384
  46. package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +0 -24
  47. package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +0 -211
  48. package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  49. package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +0 -462
  50. package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +0 -45
  51. package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  52. package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +0 -61
  53. package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +0 -384
  54. package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +0 -8
  55. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +0 -7
  56. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +0 -9
  57. package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +0 -160
  58. package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +0 -316
  59. package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +0 -672
  60. package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +0 -957
  61. package/docs/academy/04-APIReferences/renown-sdk/_category_.json +0 -8
  62. package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  63. package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +0 -462
  64. package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  65. package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +0 -370
  66. package/static/img/Vetra-logo-dark.svg +0 -11
  67. package/static/img/vetra-logo-light.svg +0 -11
  68. /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline/360/237/232/247" → 02-RevisionHistoryTimeline} +0 -0
  69. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /01-WhatIsADocumentModel" → 01-WhatIsADocumentModel} +0 -0
  70. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-DAOandDocumentsModelsQ+A" → 02-DAOandDocumentsModelsQ+A} +0 -0
  71. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-domain-modeling" → 02-domain-modeling} +0 -0
  72. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /03-BenefitsOfDocumentModels" → 03-BenefitsOfDocumentModels} +0 -0
  73. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /04-UtilitiesAndTips" → 04-UtilitiesAndTips} +0 -0
  74. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /05-best-practices" → 05-best-practices} +0 -0
  75. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /_category_.json" → _category_.json} +0 -0
  76. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /three-data-layers.png" → three-data-layers.png} +0 -0
@@ -1,672 +0,0 @@
1
- # Authentication Guide
2
-
3
- Comprehensive guide to implementing authentication with the Renown SDK.
4
-
5
- ## Table of Contents
6
-
7
- - [Overview](#overview)
8
- - [Authentication Flow](#authentication-flow)
9
- - [Setup](#setup)
10
- - [Implementation](#implementation)
11
- - [Advanced Patterns](#advanced-patterns)
12
- - [Security Considerations](#security-considerations)
13
-
14
- ## Overview
15
-
16
- The Renown SDK provides a complete authentication system that:
17
-
18
- 1. **Auto-initializes** the Renown SDK and ConnectCrypto (zero configuration!)
19
- 2. **Manages** user sessions across page reloads
20
- 3. **Handles** authentication redirects from Renown portal
21
- 4. **Fetches** user profile data automatically
22
- 5. **Provides** React hooks, components, and context for easy integration
23
-
24
- ## Authentication Flow
25
-
26
- ### 1. Initial Load
27
-
28
- ```
29
- User visits app
30
-
31
- RenownUserProvider initializes
32
-
33
- Check sessionStorage for existing session
34
-
35
- ├─ Session found → Restore user → Authorized
36
- └─ No session → Check URL params → Initialize SDK → Not Authorized
37
- ```
38
-
39
- ### 2. Login Flow
40
-
41
- ```
42
- User clicks "Login"
43
-
44
- openRenown() called
45
-
46
- Redirect to Renown Portal
47
-
48
- User authenticates
49
-
50
- Redirect back to app with DID
51
-
52
- handleRenownReturn() processes
53
-
54
- login() called
55
-
56
- Fetch user profile
57
-
58
- Store in sessionStorage
59
-
60
- Update auth state → Authorized
61
- ```
62
-
63
- ### 3. Session Restoration
64
-
65
- ```
66
- User refreshes page
67
-
68
- RenownUserProvider checks sessionStorage
69
-
70
- Valid session found
71
-
72
- Fetch latest profile data
73
-
74
- Restore auth state → Authorized
75
- ```
76
-
77
- ## Setup
78
-
79
- ### Step 1: Wrap Your App with RenownUserProvider
80
-
81
- The RenownUserProvider automatically initializes the Renown SDK - no manual setup required!
82
-
83
- ```typescript
84
- // app/layout.tsx (Next.js App Router)
85
- import { RenownUserProvider } from '@renown/sdk'
86
-
87
- export default function RootLayout({
88
- children,
89
- }: {
90
- children: React.ReactNode
91
- }) {
92
- return (
93
- <html lang="en">
94
- <body>
95
- <RenownUserProvider>
96
- {children}
97
- </RenownUserProvider>
98
- </body>
99
- </html>
100
- )
101
- }
102
- ```
103
-
104
- That's it! The SDK is now initialized and ready to use.
105
-
106
- ### Optional: Customize Configuration
107
-
108
- You can customize the Renown URL, network, and chain:
109
-
110
- ```typescript
111
- <RenownUserProvider
112
- renownUrl={process.env.NEXT_PUBLIC_RENOWN_URL || 'https://www.renown.id'}
113
- networkId="eip155"
114
- chainId="1"
115
- >
116
- {children}
117
- </RenownUserProvider>
118
- ```
119
-
120
- ### Optional: Add Loading/Error Screens
121
-
122
- Provide custom UI for initialization states:
123
-
124
- ```typescript
125
- <RenownUserProvider
126
- loadingComponent={
127
- <div className="loading-screen">
128
- <Spinner />
129
- <p>Initializing authentication...</p>
130
- </div>
131
- }
132
- errorComponent={(error, retry) => (
133
- <div className="error-screen">
134
- <h2>Authentication Failed</h2>
135
- <p>{error.message}</p>
136
- <button onClick={retry}>Try Again</button>
137
- </div>
138
- )}
139
- >
140
- {children}
141
- </RenownUserProvider>
142
- ```
143
-
144
- ## Implementation
145
-
146
- ### Using the RenownAuthButton Component
147
-
148
- The simplest way to add authentication is to use the built-in `RenownAuthButton` component:
149
-
150
- ```typescript
151
- 'use client'
152
-
153
- import { RenownAuthButton } from '@renown/sdk'
154
-
155
- export function Header() {
156
- return (
157
- <header>
158
- <h1>My App</h1>
159
- <RenownAuthButton showLogoutButton showUsername />
160
- </header>
161
- )
162
- }
163
- ```
164
-
165
- ### Custom Login Component with useUser Hook
166
-
167
- For full control, build your own component using the `useUser` hook:
168
-
169
- ```typescript
170
- 'use client'
171
-
172
- import { useUser } from '@renown/sdk'
173
-
174
- export function CustomRenownAuthButton() {
175
- const { user, loginStatus, isLoading, openRenown, logout } = useUser()
176
-
177
- if (isLoading) {
178
- return (
179
- <button disabled>
180
- <Spinner />
181
- Loading...
182
- </button>
183
- )
184
- }
185
-
186
- if (loginStatus === 'authorized' && user) {
187
- return (
188
- <div className="flex items-center gap-2">
189
- {user.avatar && (
190
- <img
191
- src={user.avatar}
192
- alt={user.name || 'User'}
193
- className="w-8 h-8 rounded-full"
194
- />
195
- )}
196
- <span>{user.name || user.did.slice(0, 15)}...</span>
197
- <button onClick={logout}>Logout</button>
198
- </div>
199
- )
200
- }
201
-
202
- return (
203
- <button onClick={openRenown}>
204
- Login with Renown
205
- </button>
206
- )
207
- }
208
- ```
209
-
210
- ### Protected Route Component
211
-
212
- ```typescript
213
- 'use client'
214
-
215
- import { useUser } from '@renown/sdk'
216
- import { useRouter } from 'next/navigation'
217
- import { useEffect } from 'react'
218
-
219
- export function ProtectedRoute({ children }: { children: React.ReactNode }) {
220
- const { user, loginStatus, isLoading, openRenown } = useUser()
221
- const router = useRouter()
222
-
223
- useEffect(() => {
224
- if (!isLoading && loginStatus !== 'authorized') {
225
- // Redirect to login or show login prompt
226
- router.push('/login')
227
- }
228
- }, [isLoading, loginStatus, router])
229
-
230
- if (isLoading) {
231
- return <div>Loading...</div>
232
- }
233
-
234
- if (loginStatus !== 'authorized' || !user) {
235
- return (
236
- <div className="flex flex-col items-center justify-center min-h-screen">
237
- <h1>Authentication Required</h1>
238
- <p>Please log in to access this page</p>
239
- <button onClick={openRenown}>Login</button>
240
- </div>
241
- )
242
- }
243
-
244
- return <>{children}</>
245
- }
246
- ```
247
-
248
- ### User Profile Display
249
-
250
- ```typescript
251
- 'use client'
252
-
253
- import { useUser } from '@renown/sdk'
254
-
255
- export function UserProfile() {
256
- const { user, logout } = useUser()
257
-
258
- if (!user) return null
259
-
260
- return (
261
- <div className="profile-card">
262
- <header>
263
- {user.avatar && (
264
- <img
265
- src={user.avatar}
266
- alt={user.name || 'User avatar'}
267
- className="avatar"
268
- />
269
- )}
270
- <h2>{user.name || 'Anonymous User'}</h2>
271
- </header>
272
-
273
- <dl className="profile-details">
274
- <dt>DID</dt>
275
- <dd>{user.did}</dd>
276
-
277
- {user.ethAddress && (
278
- <>
279
- <dt>Ethereum Address</dt>
280
- <dd>{user.ethAddress}</dd>
281
- </>
282
- )}
283
-
284
- {user.email && (
285
- <>
286
- <dt>Email</dt>
287
- <dd>{user.email}</dd>
288
- </>
289
- )}
290
- </dl>
291
-
292
- <button onClick={logout}>Logout</button>
293
- </div>
294
- )
295
- }
296
- ```
297
-
298
- ## Advanced Patterns
299
-
300
- ### Conditional Navigation Based on Auth
301
-
302
- ```typescript
303
- 'use client'
304
-
305
- import { useUser } from '@renown/sdk'
306
- import Link from 'next/link'
307
-
308
- export function Navigation() {
309
- const { user, loginStatus } = useUser()
310
-
311
- const isAuthorized = loginStatus === 'authorized'
312
-
313
- return (
314
- <nav>
315
- <Link href="/">Home</Link>
316
-
317
- {isAuthorized ? (
318
- <>
319
- <Link href="/dashboard">Dashboard</Link>
320
- <Link href="/profile">Profile</Link>
321
- <Link href="/settings">Settings</Link>
322
- </>
323
- ) : (
324
- <>
325
- <Link href="/about">About</Link>
326
- <Link href="/pricing">Pricing</Link>
327
- </>
328
- )}
329
- </nav>
330
- )
331
- }
332
- ```
333
-
334
- ### Auth State Listener
335
-
336
- ```typescript
337
- 'use client'
338
-
339
- import { useUser } from '@renown/sdk'
340
- import { useEffect } from 'react'
341
- import { useRouter } from 'next/navigation'
342
- import { toast } from 'react-hot-toast'
343
-
344
- export function AuthStateListener() {
345
- const { user, loginStatus } = useUser()
346
- const router = useRouter()
347
-
348
- useEffect(() => {
349
- if (loginStatus === 'authorized' && user) {
350
- // User just logged in
351
- toast.success(`Welcome back, ${user.name || 'User'}!`)
352
-
353
- // Track analytics
354
- analytics.identify(user.did, {
355
- name: user.name,
356
- ethAddress: user.ethAddress,
357
- })
358
-
359
- // Redirect to dashboard
360
- router.push('/dashboard')
361
- }
362
- }, [loginStatus, user, router])
363
-
364
- useEffect(() => {
365
- if (loginStatus === 'not-authorized') {
366
- // User logged out
367
- toast.info('You have been logged out')
368
-
369
- // Clear analytics
370
- analytics.reset()
371
-
372
- // Redirect to home
373
- router.push('/')
374
- }
375
- }, [loginStatus, router])
376
-
377
- return null // This is a listener component
378
- }
379
- ```
380
-
381
- ### Custom Auth Hook with Additional Logic
382
-
383
- ```typescript
384
- 'use client'
385
-
386
- import { useUser as useRenownAuth } from '@renown/sdk'
387
- import { useEffect, useState } from 'react'
388
-
389
- interface ExtendedAuthState {
390
- user: User | null
391
- isAuthenticated: boolean
392
- isLoading: boolean
393
- hasCompletedProfile: boolean
394
- login: () => void
395
- logout: () => Promise<void>
396
- }
397
-
398
- export function useUser(): ExtendedAuthState {
399
- const auth = useRenownAuth()
400
- const [hasCompletedProfile, setHasCompletedProfile] = useState(false)
401
-
402
- useEffect(() => {
403
- if (auth.user) {
404
- // Check if user has completed their profile
405
- const isComplete = !!(
406
- auth.user.name &&
407
- auth.user.avatar &&
408
- auth.user.email
409
- )
410
- setHasCompletedProfile(isComplete)
411
- } else {
412
- setHasCompletedProfile(false)
413
- }
414
- }, [auth.user])
415
-
416
- return {
417
- user: auth.user,
418
- isAuthenticated: auth.loginStatus === 'authorized',
419
- isLoading: auth.isLoading,
420
- hasCompletedProfile,
421
- login: auth.openRenown,
422
- logout: auth.logout,
423
- }
424
- }
425
- ```
426
-
427
- ### Role-Based Access Control
428
-
429
- ```typescript
430
- 'use client'
431
-
432
- import { useUser } from '@renown/sdk'
433
- import { ReactNode } from 'react'
434
-
435
- interface RBACProps {
436
- children: ReactNode
437
- allowedRoles?: string[]
438
- fallback?: ReactNode
439
- }
440
-
441
- export function RoleBasedAccess({
442
- children,
443
- allowedRoles = [],
444
- fallback = <div>Access Denied</div>
445
- }: RBACProps) {
446
- const { user, loginStatus } = useUser()
447
-
448
- if (loginStatus !== 'authorized' || !user) {
449
- return fallback
450
- }
451
-
452
- // Check user roles (you'd fetch this from your backend)
453
- const userRoles = getUserRoles(user.did) // Implement this
454
-
455
- const hasAccess = allowedRoles.length === 0 ||
456
- allowedRoles.some(role => userRoles.includes(role))
457
-
458
- return hasAccess ? <>{children}</> : fallback
459
- }
460
-
461
- // Usage
462
- function AdminPanel() {
463
- return (
464
- <RoleBasedAccess allowedRoles={['admin', 'moderator']}>
465
- <h1>Admin Panel</h1>
466
- {/* Admin content */}
467
- </RoleBasedAccess>
468
- )
469
- }
470
- ```
471
-
472
- ## Security Considerations
473
-
474
- ### 1. Token Storage
475
-
476
- The SDK stores session data in `sessionStorage` (not `localStorage`) for security:
477
-
478
- - ✅ Session data clears when tab closes
479
- - ✅ Not accessible across tabs
480
- - ✅ Not persisted across browser sessions
481
- - ✅ Protected from XSS via httpOnly (for API tokens)
482
-
483
- ### 2. DID Validation
484
-
485
- Always validate DIDs before processing:
486
-
487
- ```typescript
488
- function isValidDID(did: string): boolean {
489
- // Must start with did:pkh:
490
- if (!did.startsWith('did:pkh:')) return false
491
-
492
- // Must have correct number of parts
493
- const parts = did.split(':')
494
- if (parts.length !== 5) return false
495
-
496
- // Validate ethereum address format
497
- const address = parts[4]
498
- if (!address.match(/^0x[a-fA-F0-9]{40}$/)) return false
499
-
500
- return true
501
- }
502
- ```
503
-
504
- ### 3. Secure Communication
505
-
506
- Always use HTTPS for Renown URLs:
507
-
508
- ```typescript
509
- const RENOWN_URL = process.env.NEXT_PUBLIC_RENOWN_URL
510
-
511
- if (RENOWN_URL && !RENOWN_URL.startsWith('https://')) {
512
- console.warn('WARNING: Renown URL should use HTTPS')
513
- }
514
- ```
515
-
516
- ### 4. Session Timeout
517
-
518
- Implement session timeout for security:
519
-
520
- ```typescript
521
- const SESSION_TIMEOUT = 24 * 60 * 60 * 1000 // 24 hours
522
-
523
- function isSessionValid(timestamp: number): boolean {
524
- const now = Date.now()
525
- const age = now - timestamp
526
- return age < SESSION_TIMEOUT
527
- }
528
- ```
529
-
530
- ### 5. Server-Side Verification
531
-
532
- **Never trust client-side auth alone**. Always verify on the server:
533
-
534
- ```typescript
535
- // Server-side API route
536
- export async function GET(request: Request) {
537
- const authHeader = request.headers.get('authorization')
538
-
539
- if (!authHeader) {
540
- return new Response('Unauthorized', { status: 401 })
541
- }
542
-
543
- // Verify the JWT/credential with Renown
544
- const isValid = await verifyRenownCredential(authHeader)
545
-
546
- if (!isValid) {
547
- return new Response('Invalid credentials', { status: 403 })
548
- }
549
-
550
- // Proceed with authorized request
551
- return Response.json({ data: 'Protected data' })
552
- }
553
- ```
554
-
555
- ## Best Practices
556
-
557
- ### 1. Handle Loading States
558
-
559
- Always handle loading states to provide good UX:
560
-
561
- ```typescript
562
- function MyComponent() {
563
- const { user, isLoading, loginStatus } = useUser()
564
-
565
- if (isLoading) {
566
- return <Skeleton /> // Show skeleton/spinner
567
- }
568
-
569
- // Now safe to use user/loginStatus
570
- }
571
- ```
572
-
573
- ### 2. Graceful Degradation
574
-
575
- Provide fallbacks for unauthenticated users:
576
-
577
- ```typescript
578
- function FeatureSection() {
579
- const { user } = useUser()
580
-
581
- return (
582
- <section>
583
- {user ? (
584
- <PersonalizedContent user={user} />
585
- ) : (
586
- <GenericContent />
587
- )}
588
- </section>
589
- )
590
- }
591
- ```
592
-
593
- ### 3. Cleanup on Unmount
594
-
595
- Clean up subscriptions and listeners:
596
-
597
- ```typescript
598
- useEffect(() => {
599
- const handleAuthChange = () => {
600
- // Handle auth changes
601
- }
602
-
603
- // Subscribe to auth events
604
- const unsubscribe = subscribeToAuthEvents(handleAuthChange)
605
-
606
- return () => {
607
- unsubscribe() // Cleanup
608
- }
609
- }, [])
610
- ```
611
-
612
- ### 4. Error Boundaries
613
-
614
- Wrap auth components in error boundaries:
615
-
616
- ```typescript
617
- <ErrorBoundary fallback={<AuthError />}>
618
- <RenownUserProvider>
619
- <App />
620
- </RenownUserProvider>
621
- </ErrorBoundary>
622
- ```
623
-
624
- ## Troubleshooting
625
-
626
- ### Issue: Auth state not updating
627
-
628
- **Cause:** Component not re-rendering when auth changes
629
-
630
- **Solution:** Ensure you're using `useUser()` hook, not accessing `window.renown` directly
631
-
632
- ```typescript
633
- // ❌ Wrong
634
- const user = window.renown?.user
635
-
636
- // ✅ Correct
637
- const { user } = useUser()
638
- ```
639
-
640
- ### Issue: Session not persisting
641
-
642
- **Cause:** SessionStorage might be disabled or cleared
643
-
644
- **Solution:** Check browser settings and handle gracefully
645
-
646
- ```typescript
647
- try {
648
- SessionStorageManager.setUserData(data)
649
- } catch (error) {
650
- console.warn('SessionStorage not available:', error)
651
- // Fallback to in-memory storage
652
- }
653
- ```
654
-
655
- ### Issue: Multiple login popups
656
-
657
- **Cause:** `openRenown()` called multiple times
658
-
659
- **Solution:** Debounce the login button
660
-
661
- ```typescript
662
- const handleLogin = useCallback(
663
- debounce(() => {
664
- openRenown()
665
- }, 1000),
666
- [openRenown]
667
- )
668
- ```
669
-
670
- ## Next Steps
671
-
672
- - Read the [API Reference](./02-APIReference.md) for detailed documentation