@playcademy/sdk 0.0.1-beta.3 → 0.0.1-beta.30

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.
package/README.md CHANGED
@@ -1,169 +1,548 @@
1
- # Playcademy SDK
1
+ # @playcademy/sdk
2
2
 
3
- A TypeScript SDK for interacting with the Playcademy platform API.
3
+ **Official TypeScript SDK for the Playcademy platform**
4
+
5
+ The Playcademy SDK provides a comprehensive, type-safe interface for building games on the Playcademy platform. It handles authentication, game sessions, user data, inventory management, and all platform APIs through a unified client interface.
4
6
 
5
7
  ## Overview
6
8
 
7
- This SDK provides a unified client for various interactions with Playcademy.
9
+ The SDK serves as the primary interface between your game and the Playcademy platform, providing:
10
+
11
+ - **Automatic Environment Detection**: Seamlessly works in development and production
12
+ - **Type-Safe API Access**: Full TypeScript support with comprehensive type definitions
13
+ - **Session Management**: Automatic game session handling and state persistence
14
+ - **Event System**: Real-time notifications for inventory changes, level ups, and more
15
+ - **Developer Tools**: Built-in support for game development and testing workflows
16
+
17
+ ### Key Benefits
18
+
19
+ - **Zero Configuration**: Automatic initialization with environment detection
20
+ - **Production Ready**: Battle-tested API patterns with robust error handling
21
+ - **Real-Time Events**: Subscribe to platform events like inventory changes and level ups
22
+ - **Comprehensive Coverage**: Access to all Playcademy platform features
23
+ - **Development Experience**: Integrated with sandbox environment for local development
24
+
25
+ ### Use Cases
8
26
 
9
- ## Install
27
+ - **Game Development**: Primary SDK for building games on Playcademy
28
+ - **Web Applications**: Frontend applications interacting with the platform
29
+ - **Developer Tools**: Scripts and utilities for game management
30
+ - **Server Integration**: Backend services integrating with Playcademy APIs
31
+ - **Testing & Automation**: Automated testing of platform integrations
32
+
33
+ ## Installation
34
+
35
+ Install the SDK using your preferred package manager:
10
36
 
11
37
  ```bash
38
+ # Using Bun (recommended)
12
39
  bun add @playcademy/sdk
13
- # or
40
+
41
+ # Using npm
14
42
  npm install @playcademy/sdk
15
- # or
43
+
44
+ # Using yarn
16
45
  yarn add @playcademy/sdk
17
- # or
46
+
47
+ # Using pnpm
18
48
  pnpm add @playcademy/sdk
19
49
  ```
20
50
 
21
- ## Initialization
51
+ ## Quick Start
22
52
 
23
- ### Browser / Mini-Games (Runtime Environment)
53
+ ### Automatic Initialization (Recommended)
24
54
 
25
- For code running within the Playcademy game loader environment (e.g., mini-games):
55
+ For most game development scenarios, use automatic initialization:
26
56
 
27
- ```ts
28
- import { initFromWindow } from '@playcademy/sdk'
57
+ ```typescript
58
+ import { PlaycademyClient } from '@playcademy/sdk'
29
59
 
30
- // Reads configuration from window.PLAYCADEMY injected by the loader
31
- const client = await initFromWindow() // initFromWindow is async
60
+ async function initializeGame() {
61
+ try {
62
+ // Automatic initialization - detects environment and configures appropriately
63
+ const client = await PlaycademyClient.init()
64
+
65
+ // Get current user
66
+ const user = await client.users.me()
67
+ console.log('Welcome,', user.name)
68
+
69
+ // The client is ready for all platform operations
70
+ return client
71
+ } catch (error) {
72
+ console.error('Failed to initialize Playcademy SDK:', error)
73
+ throw error
74
+ }
75
+ }
32
76
  ```
33
77
 
34
- ### General Use (Node.js, Backend, UI Tooling)
78
+ ### Environment Detection
35
79
 
36
- For server-side code, UI applications, or other environments where you manage configuration manually:
80
+ The SDK automatically detects and configures for different environments:
37
81
 
38
- ```ts
39
- import { PlaycademyClient, type LoginResponse } from '@playcademy/sdk'
82
+ - **Development**: Connects to local sandbox (started by `@playcademy/vite-plugin`)
83
+ - **Production**: Receives configuration from Playcademy platform loader
84
+ - **Testing**: Falls back to mock configuration for automated testing
40
85
 
41
- async function initializeAndUseClient() {
42
- const baseUrl = 'https://api.playcademy.com' // Or your local /api endpoint
43
- let loginResponse: LoginResponse
86
+ ## Core Features
44
87
 
45
- try {
46
- // 1. Authenticate to get a token
47
- loginResponse = await PlaycademyClient.login(
48
- baseUrl,
49
- 'user@example.com',
50
- 'password',
51
- )
52
- } catch (error) {
53
- console.error('Login failed:', error)
54
- return
55
- }
88
+ ### Game Session Management
56
89
 
57
- // 2. Instantiate the client with the token
58
- // Optionally provide a gameId to enable automatic session management for that game.
59
- const client = new PlaycademyClient({
60
- baseUrl: baseUrl,
61
- token: loginResponse.token,
62
- // gameId: 'your-game-id' // Optional: if provided, client attempts to auto-start/end session
63
- })
90
+ ```typescript
91
+ // Automatic session management when gameId is available
92
+ const client = await PlaycademyClient.init()
64
93
 
65
- // If the token has appropriate permissions, you can access all namespaces:
66
- // client.dev.games.upsert(...)
67
- // client.admin.rewards.createReward(...)
68
- // Calling a method without sufficient token permissions will result in a server error.
94
+ // Save transient game state (position, health, temporary data)
95
+ await client.games.saveState({
96
+ currentLevel: 'forest_glade',
97
+ playerPosition: { x: 100, y: 200 },
98
+ health: 85,
99
+ activePowerUps: ['speed_boost'],
100
+ })
69
101
 
70
- // Example: Listen for auth changes (e.g., if token is refreshed or cleared by logout)
71
- client.onAuthChange(token => {
72
- console.log('Authentication token changed:', token)
73
- // You might want to update stored token here
74
- })
102
+ // Load previously saved state
103
+ const gameState = await client.games.loadState()
104
+ console.log('Loaded state:', gameState)
105
+
106
+ // Exit game (automatically ends session if managed)
107
+ await client.runtime.exit()
108
+ ```
109
+
110
+ ### User & Inventory Management
111
+
112
+ ```typescript
113
+ // Get user information
114
+ const user = await client.users.me()
115
+
116
+ // Inventory operations (accepts UUIDs or slugs)
117
+ const inventory = await client.users.inventory.get()
118
+ await client.users.inventory.add('magic-sword', 1)
119
+ await client.users.inventory.remove('health-potion', 1)
120
+
121
+ // Check item quantities and ownership
122
+ const goldCount = await client.users.inventory.quantity('gold-coin')
123
+ const hasKey = await client.users.inventory.has('dungeon-key')
124
+ const hasEnoughGold = await client.users.inventory.has('gold-coin', 100)
125
+ ```
75
126
 
76
- // Example: Logout
77
- // await client.auth.logout();
127
+ ### Credits & Currency
128
+
129
+ ```typescript
130
+ // Platform currency management
131
+ const balance = await client.credits.balance()
132
+ await client.credits.add(100)
133
+ await client.credits.spend(50)
134
+
135
+ // Check affordability
136
+ if ((await client.credits.balance()) >= 100) {
137
+ await client.credits.spend(100)
138
+ console.log('Purchase successful!')
78
139
  }
140
+ ```
141
+
142
+ ### Experience & Levels
143
+
144
+ ```typescript
145
+ // Level management
146
+ const userLevel = await client.levels.get()
147
+ const progress = await client.levels.progress()
148
+ console.log(`Level ${userLevel.currentLevel}, ${progress.xpToNextLevel} XP to next level`)
79
149
 
80
- initializeAndUseClient()
150
+ // Add experience points
151
+ const result = await client.levels.addXP(100)
152
+ if (result.leveledUp) {
153
+ console.log(`Level up! ${result.oldLevel} → ${result.newLevel}`)
154
+ console.log('Credits awarded:', result.creditsAwarded)
155
+ }
81
156
  ```
82
157
 
83
- ## Quickstart: Mini-Game Example
158
+ ## API Reference
84
159
 
85
- ```ts
86
- import { initFromWindow } from '@playcademy/sdk'
160
+ ### Core Modules
87
161
 
88
- async function runGame() {
89
- const client = await initFromWindow()
162
+ #### **Authentication** (`client.auth`)
90
163
 
91
- try {
92
- // 1) Start a game session (gameId is optional, defaults to client.gameId)
93
- const { sessionId } = await client.games.startSession()
94
- console.log('Session started:', sessionId)
95
-
96
- // 2) Fetch player's inventory/rewards
97
- const rewards = await client.users.inventory.get()
98
- console.log('Player inventory:', rewards)
99
-
100
- // 3) Save game state (uses client.gameId implicitly)
101
- await client.games.saveState({
102
- currentLevel: 'level_2', // This is separate from progress, often more transient
103
- health: 95,
104
- })
105
- console.log('Game state saved')
164
+ - `logout()`: Logs out user and clears authentication token
106
165
 
107
- // 4) Load game state (uses client.gameId implicitly)
108
- const loadedState = await client.games.loadState()
109
- console.log('Game state loaded:', loadedState)
166
+ #### **Users** (`client.users`)
110
167
 
111
- // 5) End the session when finished (gameId is optional)
112
- await client.games.endSession(sessionId)
113
- console.log('Session ended')
168
+ - `me()`: Get current user information
169
+ - **Inventory** (`client.users.inventory`):
170
+ - `get()`: Get user's inventory
171
+ - `add(identifier, quantity)`: Add items to inventory
172
+ - `remove(identifier, quantity)`: Remove items from inventory
173
+ - `quantity(identifier)`: Get item quantity
174
+ - `has(identifier, minQuantity?)`: Check item ownership
114
175
 
115
- // 6) Exit the game view (if embedded)
116
- client.runtime.exit()
117
- } catch (error) {
118
- console.error('An error occurred:', error)
176
+ #### **Games** (`client.games`)
177
+
178
+ - `list()`: Get all available games
179
+ - `fetch(gameIdOrSlug)`: Get specific game details
180
+ - `saveState(state)`: Save transient game state
181
+ - `loadState()`: Load saved game state
182
+ - `startSession(gameId?)`: Start game session
183
+ - `endSession(sessionId, gameId?)`: End game session
184
+
185
+ #### **Credits** (`client.credits`)
186
+
187
+ - `balance()`: Get current credits balance
188
+ - `add(amount)`: Add credits to user
189
+ - `spend(amount)`: Spend user credits
190
+
191
+ #### **Levels** (`client.levels`)
192
+
193
+ - `get()`: Get current user level information
194
+ - `progress()`: Get level progress and XP to next level
195
+ - `addXP(amount)`: Add experience points
196
+ - **Config** (`client.levels.config`):
197
+ - `list()`: Get all level configurations
198
+ - `get(level)`: Get specific level configuration
199
+
200
+ #### **Maps** (`client.maps`)
201
+
202
+ - `elements(mapId)`: Get map elements and points of interest
203
+
204
+ #### **Runtime** (`client.runtime`)
205
+
206
+ - `getGameToken(gameId, options?)`: Get game-specific authentication token
207
+ - `exit()`: Signal platform to exit game view
208
+
209
+ #### **Leaderboard** (`client.leaderboard`) - Game-specific
210
+
211
+ - `fetch(options?)`: Get leaderboard for a specific game
212
+ - `options.timeframe`: Filter by time period (`'all_time'`, `'monthly'`, `'weekly'`, `'daily'`)
213
+ - `options.gameId`: Game ID to fetch leaderboard for (required)
214
+ - `options.limit`: Number of entries to return (default: 10)
215
+ - `options.offset`: Pagination offset (default: 0)
216
+
217
+ #### **Scores** (`client.scores`) - Platform-wide
218
+
219
+ - `submit(gameId, score, metadata?)`: Submit a score for any game
220
+ - `getUserScores(userId, options?)`: Get all scores for a user
221
+ - `options.gameId`: Filter by specific game (optional)
222
+ - `options.limit`: Number of scores to return (default: 50)
223
+
224
+ ### Developer Tools
225
+
226
+ #### **Developer Authentication** (`client.dev.auth`)
227
+
228
+ - `applyForDeveloper()`: Apply for developer status
229
+ - `getDeveloperStatus()`: Check current developer status
230
+
231
+ #### **Game Management** (`client.dev.games`)
232
+
233
+ - `upsert(slug, metadata, gameFile)`: Create or update game
234
+ - `update(gameId, updates)`: Update game properties
235
+ - `delete(gameId)`: Delete game
236
+
237
+ #### **API Keys** (`client.dev.keys`)
238
+
239
+ - `createKey(gameId, name)`: Create API key for server authentication
240
+ - `listKeys()`: List all API keys
241
+ - `revokeKey(keyId)`: Revoke API key
242
+
243
+ #### **Item Management** (`client.dev.items`)
244
+
245
+ - `list(gameId)`: List all items for a game
246
+ - `get(gameId, slug)`: Get specific item
247
+ - `create(gameId, slug, data)`: Create new game item
248
+ - `update(gameId, itemId, updates)`: Update existing item
249
+ - `delete(gameId, itemId)`: Delete item
250
+
251
+ ## Event System
252
+
253
+ The SDK provides real-time event notifications for important platform changes:
254
+
255
+ ### Available Events
256
+
257
+ ```typescript
258
+ // Authentication changes
259
+ client.on('authChange', payload => {
260
+ console.log('Authentication changed:', payload.token)
261
+ })
262
+
263
+ // Inventory changes
264
+ client.on('inventoryChange', payload => {
265
+ console.log(`Item ${payload.itemId}: ${payload.delta} (total: ${payload.newTotal})`)
266
+ })
267
+
268
+ // Experience gained
269
+ client.on('xpGained', payload => {
270
+ console.log(`Gained ${payload.amount} XP (total: ${payload.totalXP})`)
271
+ })
272
+
273
+ // Level up notifications
274
+ client.on('levelUp', payload => {
275
+ console.log(`Level up! ${payload.oldLevel} → ${payload.newLevel}`)
276
+ console.log('Credits awarded:', payload.creditsAwarded)
277
+ })
278
+ ```
279
+
280
+ ### Event-Driven UI Updates
281
+
282
+ ```typescript
283
+ // Update UI in response to platform events
284
+ client.on('inventoryChange', payload => {
285
+ updateInventoryDisplay(payload.itemId, payload.newTotal)
286
+ })
287
+
288
+ client.on('levelUp', payload => {
289
+ showLevelUpAnimation(payload.newLevel)
290
+ showCreditsAwarded(payload.creditsAwarded)
291
+ })
292
+
293
+ client.on('xpGained', payload => {
294
+ updateXPBar(payload.totalXP, payload.leveledUp)
295
+ })
296
+ ```
297
+
298
+ ## Advanced Usage
299
+
300
+ ### Manual Initialization
301
+
302
+ For server-side applications or custom environments:
303
+
304
+ ```typescript
305
+ import { PlaycademyClient } from '@playcademy/sdk'
306
+
307
+ import type { LoginResponse } from '@playcademy/sdk'
308
+
309
+ // Step 1: Authenticate
310
+ const loginData: LoginResponse = await PlaycademyClient.login(
311
+ 'https://api.playcademy.com',
312
+ 'user@example.com',
313
+ 'password',
314
+ )
315
+
316
+ // Step 2: Initialize client
317
+ const client = new PlaycademyClient({
318
+ baseUrl: 'https://api.playcademy.com',
319
+ token: loginData.token,
320
+ gameId: 'your-game-id', // Optional: enables automatic session management
321
+ })
322
+ ```
323
+
324
+ ### Custom Configuration
325
+
326
+ ```typescript
327
+ const client = new PlaycademyClient({
328
+ baseUrl: 'https://api.playcademy.com',
329
+ token: 'your-auth-token',
330
+ gameId: 'your-game-id',
331
+ // Additional options
332
+ timeout: 10000, // Request timeout in milliseconds
333
+ retries: 3, // Number of retry attempts
334
+ })
335
+ ```
336
+
337
+ ### Error Handling
338
+
339
+ ```typescript
340
+ import { PlaycademyError } from '@playcademy/sdk'
341
+
342
+ try {
343
+ const user = await client.users.me()
344
+ // Handle success
345
+ } catch (error) {
346
+ if (error instanceof PlaycademyError) {
347
+ console.error('Playcademy API Error:', error.message)
348
+ console.error('Status Code:', error.statusCode)
349
+ console.error('Error Code:', error.code)
350
+ } else {
351
+ console.error('Unexpected error:', error)
119
352
  }
120
353
  }
354
+ ```
355
+
356
+ ## Development Environment
357
+
358
+ ### Integration with Playcademy Vite Plugin
359
+
360
+ When using the official Playcademy Vite templates, the development environment is automatically configured:
361
+
362
+ ```typescript
363
+ // In your game's main file
364
+ import { PlaycademyClient } from '@playcademy/sdk'
365
+
366
+ // The vite plugin automatically starts the sandbox
367
+ const client = await PlaycademyClient.init()
368
+ // SDK automatically connects to local sandbox at http://localhost:4321
369
+ ```
370
+
371
+ ### Manual Sandbox Setup
372
+
373
+ If not using the Vite plugin, start the sandbox manually:
121
374
 
122
- runGame()
123
- ```
124
-
125
- ## API Modules
126
-
127
- The `PlaycademyClient` instance provides access to all API modules.
128
- The server will determine if the provided token has sufficient permissions for each operation.
129
- Internal event handling uses a `BusEvents` enum for type safety.
130
- All methods returning data are strongly typed.
131
-
132
- - **`auth`**: User logout. For login, use the static `PlaycademyClient.login()` method.
133
- - `logout()`: Logs out the current user and clears the token from the client instance.
134
- - **`onAuthChange(callback)`**: A top-level client method to subscribe to authentication token changes (login, logout, explicit `setToken`).
135
- - **`users`**:
136
- - `me()`: Fetch current user details.
137
- - **`inventory`**:
138
- - `get()`: Get player inventory.
139
- - `add(rewardId, qty)`: Add item to player inventory.
140
- - `spend(rewardId, qty)`: Spend item from player inventory.
141
- - **`progress`**: Manages persistent progress data for a game (e.g., levels completed, scores, collectibles).
142
- - `get(gameId?)`: Get the entire progress state for a game. `gameId` is optional and defaults to the client's current game context.
143
- - `update(data, gameId?)`: Update the progress state for a game. `gameId` is optional. The `data` object can be structured to hold progress for various internal nodes or aspects of the game.
144
- - **`games`**: Manages game sessions and transient game state.
145
- - `fetch(gameIdOrSlug)`: Fetch game details with manifest.
146
- - `list()`: List all games.
147
- - `saveState(state)`: Save transient game state (e.g., current position, temporary buffs) for the current game context.
148
- - `loadState()`: Load transient game state for the current game context.
149
- - `startSession(gameId?)`: Start a game session. `gameId` is optional and defaults to `client.gameId` if set. If the client is managing an automatic session, this can be used to start additional, distinct sessions.
150
- - `endSession(sessionId, gameId?)`: End a game session. `gameId` is optional. If this ends an automatically managed session, the client will no longer attempt to auto-end it.
151
- - **`runtime`**:
152
- - `getGameToken(gameId, options?: { apply?: boolean })`: Fetches a game-specific token. If `options.apply` is true, it sets this token as the active token on the client instance (default is false).
153
- - `exit()`: Signals the hosting environment to close the game view. If the client is managing an automatic session (because `gameId` was provided at construction), this method will attempt to end that session before signaling exit.
154
- - **`maps`**:
155
- - `elements(mapId)`: Fetch elements (like nodes, points of interest) for a specific map.
156
- - **`dev.auth`**: Apply for developer status, get status.
157
- - **`dev.games`**: Upsert, update, delete games.
158
- - **`dev.keys`**: Create, list, revoke API keys for games.
159
- - **`admin.games`**: Pause/resume games.
160
- - **`admin.rewards`**: CRUD operations for rewards.
161
- - **`telemetry`**: Push metrics.
375
+ ```bash
376
+ # Start sandbox server
377
+ bunx @playcademy/sandbox --port 4321 --verbose
378
+
379
+ # In your application
380
+ const client = new PlaycademyClient({
381
+ baseUrl: 'http://localhost:4321/api',
382
+ token: 'dev-token' // Sandbox provides mock authentication
383
+ })
384
+ ```
385
+
386
+ ## Best Practices
387
+
388
+ ### Initialization & Setup
389
+
390
+ - **Always use automatic initialization** for game development with `PlaycademyClient.init()`
391
+ - **Handle initialization errors gracefully** with proper try-catch blocks
392
+ - **Store the client instance** for reuse throughout your application lifecycle
393
+
394
+ ### State Management
395
+
396
+ - **Use `games.saveState()`** for transient data (current level, position, temporary status)
397
+ - **Use `users.inventory`** for persistent items and resources that carry between sessions
398
+ - **Save state periodically**, not on every frame or minor change
399
+ - **Load state once** at game start, then manage locally
400
+
401
+ ### Performance Optimization
402
+
403
+ - **Cache frequently accessed data** like user information and inventory
404
+ - **Batch inventory operations** when possible instead of individual API calls
405
+ - **Use event listeners** to update UI reactively rather than polling
406
+ - **Implement proper loading states** for better user experience
407
+
408
+ ### Error Handling
409
+
410
+ - **Wrap all SDK calls** in appropriate try-catch blocks
411
+ - **Provide fallback behavior** for network errors and API failures
412
+ - **Show meaningful error messages** to users when operations fail
413
+ - **Implement retry logic** for non-critical operations
414
+
415
+ ### Development Workflow
416
+
417
+ - **Use the sandbox environment** for all local development
418
+ - **Test both online and offline scenarios** to ensure robust error handling
419
+ - **Enable verbose logging** during development for debugging
420
+ - **Validate API responses** and handle edge cases appropriately
421
+
422
+ ## Testing
423
+
424
+ ### Unit Testing
425
+
426
+ ```typescript
427
+ // Mock the SDK for unit tests
428
+ import { jest } from '@jest/globals'
429
+
430
+ // Mock the entire SDK module
431
+ jest.mock('@playcademy/sdk', () => ({
432
+ PlaycademyClient: {
433
+ init: jest.fn().mockResolvedValue({
434
+ users: {
435
+ me: jest.fn().mockResolvedValue({ id: 'test-user', name: 'Test User' }),
436
+ inventory: {
437
+ get: jest.fn().mockResolvedValue([]),
438
+ add: jest.fn().mockResolvedValue(undefined),
439
+ },
440
+ },
441
+ }),
442
+ },
443
+ }))
444
+ ```
445
+
446
+ ### Integration Testing
447
+
448
+ ```typescript
449
+ // Test with real sandbox
450
+ import { PlaycademyClient } from '@playcademy/sdk'
451
+
452
+ describe('Playcademy Integration', () => {
453
+ let client: PlaycademyClient
454
+
455
+ beforeAll(async () => {
456
+ // Initialize with sandbox
457
+ client = new PlaycademyClient({
458
+ baseUrl: 'http://localhost:4321/api',
459
+ token: 'test-token',
460
+ })
461
+ })
462
+
463
+ test('should fetch user data', async () => {
464
+ const user = await client.users.me()
465
+ expect(user).toBeDefined()
466
+ expect(user.name).toEqual(expect.any(String))
467
+ })
468
+ })
469
+ ```
470
+
471
+ ## Troubleshooting
472
+
473
+ ### Common Issues
474
+
475
+ **SDK Initialization Timeout**
476
+
477
+ ```
478
+ Error: PLAYCADEMY_INIT not received within 5000ms
479
+ ```
480
+
481
+ - Ensure you're running in the correct environment (development with sandbox, or production with platform)
482
+ - Check that the Vite plugin is properly configured
483
+ - Verify the sandbox is running on the expected port
484
+
485
+ **Authentication Errors**
486
+
487
+ ```
488
+ Error: Unauthorized (401)
489
+ ```
490
+
491
+ - Check that your authentication token is valid
492
+ - Ensure you have the necessary permissions for the operation
493
+ - Try re-authenticating with `PlaycademyClient.login()`
494
+
495
+ **Network Connection Issues**
496
+
497
+ ```
498
+ Error: Failed to fetch
499
+ ```
500
+
501
+ - Verify the API endpoint is accessible
502
+ - Check network connectivity
503
+ - Ensure CORS is properly configured for cross-origin requests
504
+
505
+ ### Debugging
506
+
507
+ Use these debugging techniques for troubleshooting SDK issues:
508
+
509
+ ```typescript
510
+ // Check initialization process
511
+ try {
512
+ const client = await PlaycademyClient.init()
513
+ console.log('SDK initialized successfully')
514
+ } catch (error) {
515
+ console.error('SDK initialization failed:', error)
516
+ }
517
+
518
+ // Monitor network requests in browser dev tools (Network tab)
519
+ // Check console for SDK error messages
520
+ // Verify API responses and error details
521
+ ```
522
+
523
+ ### Getting Help
524
+
525
+ - Check the [platform documentation](../../apps/docs/) for detailed guides
526
+ - Review the [Vite plugin configuration](../vite-plugin/) for development setup
527
+ - Examine the [game templates](../../templates/) for working examples
528
+ - Use browser dev tools to inspect network requests and responses
162
529
 
163
530
  ## Contributing
164
531
 
165
- PRs welcome. Fork, build, test, send a PR.
532
+ The SDK is a critical component of the Playcademy platform ecosystem. When contributing:
533
+
534
+ 1. **Maintain Type Safety**: Ensure all new APIs are fully typed
535
+ 2. **Update Documentation**: Keep this README and JSDoc comments current
536
+ 3. **Add Tests**: Include both unit and integration tests for new features
537
+ 4. **Follow Patterns**: Use consistent patterns with existing SDK methods
538
+ 5. **Handle Errors**: Implement proper error handling and user feedback
539
+
540
+ For general contribution guidelines, see the [monorepo CONTRIBUTING.md](../../CONTRIBUTING.md).
166
541
 
167
- ## License
542
+ ## Related Packages
168
543
 
169
- MIT
544
+ - [`@playcademy/api-core`](../api-core/): API handlers used by the SDK
545
+ - [`@playcademy/data`](../data/): Database schema and type definitions
546
+ - [`@playcademy/vite-plugin`](../vite-plugin/): Development environment integration
547
+ - [`@playcademy/sandbox`](../sandbox/): Local development server
548
+ - **Game Templates**: See `/templates` for example integrations