@mr.dj2u/knowledge 0.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 (83) hide show
  1. package/dist/content/checklists/ship-test-loop.md +16 -0
  2. package/dist/content/checklists/unified-agent-bundle-validation.md +8 -0
  3. package/dist/content/examples/ship-test-loop.md +13 -0
  4. package/dist/content/examples/unified-agent-bundle-bootstrap.md +8 -0
  5. package/dist/content/guides/animation-performance.md +30 -0
  6. package/dist/content/guides/post-create-onboarding.md +113 -0
  7. package/dist/content/patterns/api/api-routes.md +314 -0
  8. package/dist/content/patterns/api/error-handling.md +311 -0
  9. package/dist/content/patterns/database/drizzle-schema.md +280 -0
  10. package/dist/content/patterns/database/migrations.md +365 -0
  11. package/dist/content/patterns/database/query-organization.md +537 -0
  12. package/dist/content/patterns/database/relations.md +450 -0
  13. package/dist/content/patterns/deployment/build-configuration.md +452 -0
  14. package/dist/content/patterns/deployment/ci-cd-patterns.md +448 -0
  15. package/dist/content/patterns/deployment/environment-config.md +380 -0
  16. package/dist/content/patterns/deployment/hosting-setup.md +425 -0
  17. package/dist/content/patterns/project/configuration-patterns.md +459 -0
  18. package/dist/content/patterns/project/documentation-org.md +506 -0
  19. package/dist/content/patterns/project/folder-structure.md +398 -0
  20. package/dist/content/patterns/project/library-exports.md +465 -0
  21. package/dist/content/patterns/project/monorepo-structure.md +500 -0
  22. package/dist/content/patterns/routing/dynamic-routes.md +221 -0
  23. package/dist/content/patterns/routing/file-based-routing.md +186 -0
  24. package/dist/content/patterns/routing/route-groups.md +429 -0
  25. package/dist/content/patterns/state/persistence-middleware.md +521 -0
  26. package/dist/content/patterns/state/selector-hooks.md +538 -0
  27. package/dist/content/patterns/state/store-organization.md +539 -0
  28. package/dist/content/patterns/state/zustand-patterns.md +348 -0
  29. package/dist/content/patterns/styling/component-styling.md +468 -0
  30. package/dist/content/patterns/styling/responsive-patterns.md +398 -0
  31. package/dist/content/patterns/styling/theme-configuration.md +426 -0
  32. package/dist/content/patterns/styling/uniwind-setup.md +412 -0
  33. package/dist/content/prompts/continue-development.md +27 -0
  34. package/dist/content/prompts/create-expo-super-stack.md +29 -0
  35. package/dist/content/prompts/fix-seo.md +29 -0
  36. package/dist/content/prompts/onboard-new-expo-app.md +11 -0
  37. package/dist/content/prompts/prepare-deploy.md +29 -0
  38. package/dist/content/prompts/project-research-plan.md +29 -0
  39. package/dist/content/prompts/review-expo-project.md +29 -0
  40. package/dist/content/prompts/run-doctor.md +30 -0
  41. package/dist/content/prompts/ship-test-loop.md +24 -0
  42. package/dist/content/reference/create-expo-stack-uniwind.md +29 -0
  43. package/dist/content/reference/doctor-dogfood.md +42 -0
  44. package/dist/content/reference/mcp-sdk-transport.md +30 -0
  45. package/dist/content/reference/package-ci-patterns.md +24 -0
  46. package/dist/content/reference/reference-repo-evacuation.md +31 -0
  47. package/dist/content/resource-index.json +67 -0
  48. package/dist/content/rules/app-folder-architecture.md +13 -0
  49. package/dist/content/rules/env-hygiene.md +9 -0
  50. package/dist/content/rules/seo-metadata.md +7 -0
  51. package/dist/content/rules/ssr-safety.md +9 -0
  52. package/dist/content/skills/api-routes.md +33 -0
  53. package/dist/content/skills/continue-development.md +31 -0
  54. package/dist/content/skills/debugging.md +31 -0
  55. package/dist/content/skills/deployment.md +32 -0
  56. package/dist/content/skills/dev-server-management.md +31 -0
  57. package/dist/content/skills/env-vars.md +32 -0
  58. package/dist/content/skills/expo-router-architecture.md +33 -0
  59. package/dist/content/skills/expo-ssr-safety.md +32 -0
  60. package/dist/content/skills/plugin-creation.md +41 -0
  61. package/dist/content/skills/production-server-patterns.md +31 -0
  62. package/dist/content/skills/project-onboarding.md +31 -0
  63. package/dist/content/skills/research-plan-intake.md +31 -0
  64. package/dist/content/skills/seo-metadata.md +31 -0
  65. package/dist/content/skills/super-stack-startup.md +31 -0
  66. package/dist/content/skills/uniwind-theming.md +32 -0
  67. package/dist/index.d.ts +46 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +369 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/patterns/index.d.ts +78 -0
  72. package/dist/patterns/index.d.ts.map +1 -0
  73. package/dist/patterns/index.js +264 -0
  74. package/dist/patterns/index.js.map +1 -0
  75. package/dist/prompts/index.d.ts +35 -0
  76. package/dist/prompts/index.d.ts.map +1 -0
  77. package/dist/prompts/index.js +270 -0
  78. package/dist/prompts/index.js.map +1 -0
  79. package/dist/skills/index.d.ts +3 -0
  80. package/dist/skills/index.d.ts.map +1 -0
  81. package/dist/skills/index.js +2 -0
  82. package/dist/skills/index.js.map +1 -0
  83. package/package.json +50 -0
@@ -0,0 +1,539 @@
1
+ # Store Organization Pattern
2
+
3
+ ## Description
4
+
5
+ Store organization structures Zustand stores into logically separated, focused stores rather than monolithic state objects. Each store manages a specific domain (auth, UI, features) with clear separation of concerns, improving maintainability, performance, and reusability.
6
+
7
+ ## When to Use
8
+
9
+ **Use store organization** for:
10
+ - ✅ Separating auth/user state from app state
11
+ - ✅ Feature-specific stores (dex tracker, favorites, settings)
12
+ - ✅ UI state isolation (modals, navigation stacks)
13
+ - ✅ Preventing unnecessary re-renders across unrelated state changes
14
+ - ✅ Reusable store composition across projects
15
+
16
+ ## Core Principles
17
+
18
+ **One store per domain:**
19
+ - `useAuthStore` - User authentication, profile, session
20
+ - `useUIStore` - Modals, toasts, navigation state
21
+ - `useFeatureStore` - Feature-specific data (favorites, tracking)
22
+ - `useSettingsStore` - User preferences, app configuration
23
+
24
+ **Tight cohesion, loose coupling:**
25
+ - Each store manages its own domain exclusively
26
+ - Stores don't depend on each other
27
+ - Actions within a store are self-contained
28
+ - Cross-store operations handled at component/hook level
29
+
30
+ ## Code Example
31
+
32
+ ### Basic Store Structure
33
+
34
+ ```typescript
35
+ // File: src/store/authStore.ts
36
+ import { create } from 'zustand';
37
+ import { persist, createJSONStorage } from 'zustand/middleware';
38
+ import AsyncStorage from '@react-native-async-storage/async-storage';
39
+
40
+ interface User {
41
+ id: string;
42
+ email: string;
43
+ username: string;
44
+ }
45
+
46
+ interface Profile {
47
+ id: string;
48
+ displayName: string;
49
+ avatar?: string;
50
+ bio?: string;
51
+ ageVerified: boolean;
52
+ }
53
+
54
+ interface Session {
55
+ accessToken: string;
56
+ refreshToken: string;
57
+ expiresAt: number;
58
+ }
59
+
60
+ interface AuthState {
61
+ // State
62
+ user: User | null;
63
+ profile: Profile | null;
64
+ session: Session | null;
65
+ isLoggedIn: boolean;
66
+ loading: boolean;
67
+ error: string | null;
68
+
69
+ // Computed properties
70
+ isAdult: boolean;
71
+ canUseSocialFeatures: boolean;
72
+
73
+ // Actions
74
+ setUser: (user: User | null) => void;
75
+ setProfile: (profile: Profile | null) => void;
76
+ setSession: (session: Session | null) => void;
77
+ setLoading: (loading: boolean) => void;
78
+ setError: (error: string | null) => void;
79
+ signOut: () => Promise<void>;
80
+ initializeAuth: () => Promise<void>;
81
+ reset: () => void;
82
+ }
83
+
84
+ export const useAuthStore = create<AuthState>()(
85
+ persist(
86
+ (set, get) => ({
87
+ // Initial state
88
+ user: null,
89
+ profile: null,
90
+ session: null,
91
+ isLoggedIn: false,
92
+ loading: true,
93
+ error: null,
94
+
95
+ // Computed properties (getters)
96
+ get isAdult(): boolean {
97
+ const profile = get().profile;
98
+ if (!profile?.ageVerified) return false;
99
+ return true;
100
+ },
101
+
102
+ get canUseSocialFeatures(): boolean {
103
+ return get().isLoggedIn && get().isAdult;
104
+ },
105
+
106
+ // Actions
107
+ setUser: (user) => {
108
+ set({ user, isLoggedIn: !!user, error: null });
109
+ },
110
+
111
+ setProfile: (profile) => {
112
+ set({ profile, error: null });
113
+ },
114
+
115
+ setSession: (session) => {
116
+ set({ session, error: null });
117
+ },
118
+
119
+ setLoading: (loading) => {
120
+ set({ loading });
121
+ },
122
+
123
+ setError: (error) => {
124
+ set({ error });
125
+ },
126
+
127
+ signOut: async () => {
128
+ try {
129
+ set({ loading: true });
130
+ // Call logout API
131
+ await supabase.auth.signOut();
132
+
133
+ set({
134
+ user: null,
135
+ profile: null,
136
+ session: null,
137
+ isLoggedIn: false,
138
+ loading: false,
139
+ error: null,
140
+ });
141
+ } catch (error) {
142
+ set({
143
+ error: error instanceof Error ? error.message : 'Logout failed',
144
+ loading: false,
145
+ });
146
+ }
147
+ },
148
+
149
+ initializeAuth: async () => {
150
+ try {
151
+ set({ loading: true });
152
+ // Check session, load user and profile
153
+ const { data } = await supabase.auth.getSession();
154
+
155
+ if (data.session) {
156
+ set({
157
+ session: {
158
+ accessToken: data.session.access_token,
159
+ refreshToken: data.session.refresh_token || '',
160
+ expiresAt: data.session.expires_at || 0,
161
+ },
162
+ isLoggedIn: true,
163
+ loading: false,
164
+ });
165
+ // Load user and profile...
166
+ } else {
167
+ set({ isLoggedIn: false, loading: false });
168
+ }
169
+ } catch (error) {
170
+ set({
171
+ error: error instanceof Error ? error.message : 'Initialization failed',
172
+ loading: false,
173
+ });
174
+ }
175
+ },
176
+
177
+ reset: () => {
178
+ set({
179
+ user: null,
180
+ profile: null,
181
+ session: null,
182
+ isLoggedIn: false,
183
+ loading: true,
184
+ error: null,
185
+ });
186
+ },
187
+ }),
188
+ {
189
+ name: 'auth-storage',
190
+ storage: createJSONStorage(() => AsyncStorage),
191
+ // Partial persistence - don't persist loading or error states
192
+ partialize: (state) => ({
193
+ user: state.user,
194
+ profile: state.profile,
195
+ session: state.session,
196
+ }),
197
+ }
198
+ )
199
+ );
200
+ ```
201
+
202
+ ### UI State Store
203
+
204
+ ```typescript
205
+ // File: src/store/uiStore.ts
206
+ import { create } from 'zustand';
207
+
208
+ interface Toast {
209
+ id: string;
210
+ message: string;
211
+ type: 'success' | 'error' | 'info';
212
+ duration?: number;
213
+ }
214
+
215
+ interface UIState {
216
+ // Modals
217
+ modals: Record<string, boolean>;
218
+ openModal: (id: string) => void;
219
+ closeModal: (id: string) => void;
220
+
221
+ // Toasts
222
+ toasts: Toast[];
223
+ showToast: (message: string, type: Toast['type'], duration?: number) => void;
224
+ dismissToast: (id: string) => void;
225
+
226
+ // Loading states
227
+ globalLoading: boolean;
228
+ setGlobalLoading: (loading: boolean) => void;
229
+
230
+ // Theme
231
+ darkMode: boolean;
232
+ toggleDarkMode: () => void;
233
+ }
234
+
235
+ export const useUIStore = create<UIState>((set, get) => ({
236
+ // Modals
237
+ modals: {},
238
+ openModal: (id) => {
239
+ set((state) => ({
240
+ modals: { ...state.modals, [id]: true },
241
+ }));
242
+ },
243
+ closeModal: (id) => {
244
+ set((state) => ({
245
+ modals: { ...state.modals, [id]: false },
246
+ }));
247
+ },
248
+
249
+ // Toasts
250
+ toasts: [],
251
+ showToast: (message, type, duration = 3000) => {
252
+ const id = `${Date.now()}`;
253
+ set((state) => ({
254
+ toasts: [...state.toasts, { id, message, type, duration }],
255
+ }));
256
+
257
+ // Auto-dismiss
258
+ setTimeout(() => {
259
+ get().dismissToast(id);
260
+ }, duration);
261
+ },
262
+ dismissToast: (id) => {
263
+ set((state) => ({
264
+ toasts: state.toasts.filter((t) => t.id !== id),
265
+ }));
266
+ },
267
+
268
+ // Loading
269
+ globalLoading: false,
270
+ setGlobalLoading: (loading) => set({ globalLoading: loading }),
271
+
272
+ // Theme
273
+ darkMode: false,
274
+ toggleDarkMode: () => {
275
+ set((state) => ({ darkMode: !state.darkMode }));
276
+ },
277
+ }));
278
+ ```
279
+
280
+ ### Feature-Specific Store
281
+
282
+ ```typescript
283
+ // File: src/store/dexTrackerStore.ts
284
+ import { create } from 'zustand';
285
+ import { persist, createJSONStorage } from 'zustand/middleware';
286
+ import AsyncStorage from '@react-native-async-storage/async-storage';
287
+
288
+ interface DexTrackerState {
289
+ // State
290
+ trackedPokemon: Record<number, boolean>;
291
+ shinyPokemon: Record<number, boolean>;
292
+ favoritesList: number[];
293
+
294
+ // Computed
295
+ totalCaught: () => number;
296
+ totalShiny: () => number;
297
+ completionPercentage: () => number;
298
+ isCaught: (dexNumber: number) => boolean;
299
+ isShiny: (dexNumber: number) => boolean;
300
+ isFavorite: (dexNumber: number) => boolean;
301
+
302
+ // Actions
303
+ addPokemon: (dexNumber: number) => void;
304
+ removePokemon: (dexNumber: number) => void;
305
+ toggleShiny: (dexNumber: number) => void;
306
+ addFavorite: (dexNumber: number) => void;
307
+ removeFavorite: (dexNumber: number) => void;
308
+ resetTracker: () => void;
309
+ }
310
+
311
+ export const useDexTrackerStore = create<DexTrackerState>()(
312
+ persist(
313
+ (set, get) => ({
314
+ trackedPokemon: {},
315
+ shinyPokemon: {},
316
+ favoritesList: [],
317
+
318
+ // Computed (getters)
319
+ totalCaught: () => Object.keys(get().trackedPokemon).length,
320
+ totalShiny: () => Object.keys(get().shinyPokemon).length,
321
+ completionPercentage: () => (get().totalCaught() / 1025) * 100,
322
+ isCaught: (dexNumber) => !!get().trackedPokemon[dexNumber],
323
+ isShiny: (dexNumber) => !!get().shinyPokemon[dexNumber],
324
+ isFavorite: (dexNumber) => get().favoritesList.includes(dexNumber),
325
+
326
+ // Actions
327
+ addPokemon: (dexNumber) => {
328
+ set((state) => ({
329
+ trackedPokemon: {
330
+ ...state.trackedPokemon,
331
+ [dexNumber]: true,
332
+ },
333
+ }));
334
+ },
335
+
336
+ removePokemon: (dexNumber) => {
337
+ set((state) => {
338
+ const { [dexNumber]: _, ...rest } = state.trackedPokemon;
339
+ return { trackedPokemon: rest };
340
+ });
341
+ },
342
+
343
+ toggleShiny: (dexNumber) => {
344
+ set((state) => ({
345
+ shinyPokemon: {
346
+ ...state.shinyPokemon,
347
+ [dexNumber]: !state.shinyPokemon[dexNumber],
348
+ },
349
+ }));
350
+ },
351
+
352
+ addFavorite: (dexNumber) => {
353
+ set((state) => {
354
+ if (state.favoritesList.includes(dexNumber)) {
355
+ return state;
356
+ }
357
+ return {
358
+ favoritesList: [...state.favoritesList, dexNumber],
359
+ };
360
+ });
361
+ },
362
+
363
+ removeFavorite: (dexNumber) => {
364
+ set((state) => ({
365
+ favoritesList: state.favoritesList.filter((id) => id !== dexNumber),
366
+ }));
367
+ },
368
+
369
+ resetTracker: () => {
370
+ set({
371
+ trackedPokemon: {},
372
+ shinyPokemon: {},
373
+ favoritesList: [],
374
+ });
375
+ },
376
+ }),
377
+ {
378
+ name: 'dex-tracker-storage',
379
+ storage: createJSONStorage(() => AsyncStorage),
380
+ }
381
+ )
382
+ );
383
+ ```
384
+
385
+ ### Multi-Store Architecture
386
+
387
+ ```typescript
388
+ // File: src/store/index.ts
389
+ // Central export point for all stores
390
+
391
+ export { useAuthStore } from './authStore';
392
+ export { useUIStore } from './uiStore';
393
+ export { useDexTrackerStore } from './dexTrackerStore';
394
+ export { useSettingsStore } from './settingsStore';
395
+ export { useFavoritesStore } from './favoritesStore';
396
+
397
+ // Usage in components
398
+ import { useAuthStore, useUIStore, useDexTrackerStore } from '@/store';
399
+ ```
400
+
401
+ ## Store Usage Patterns
402
+
403
+ ### Using Stores in Components
404
+
405
+ ```typescript
406
+ // File: src/components/UserProfile.tsx
407
+ import { useAuthStore } from '@/store/authStore';
408
+
409
+ export function UserProfile() {
410
+ // Using selector hook for performance (only re-render on email change)
411
+ const userEmail = useAuthStore((state) => state.user?.email);
412
+
413
+ return <Text>{userEmail}</Text>;
414
+ }
415
+ ```
416
+
417
+ ### Cross-Store Operations
418
+
419
+ ```typescript
420
+ // File: src/hooks/useLogout.ts
421
+ import { useAuthStore } from '@/store/authStore';
422
+ import { useUIStore } from '@/store/uiStore';
423
+ import { useDexTrackerStore } from '@/store/dexTrackerStore';
424
+
425
+ export function useLogout() {
426
+ const signOut = useAuthStore((state) => state.signOut);
427
+ const resetTracker = useDexTrackerStore((state) => state.resetTracker);
428
+ const showToast = useUIStore((state) => state.showToast);
429
+
430
+ return async () => {
431
+ try {
432
+ await signOut();
433
+ resetTracker();
434
+ showToast('Logged out successfully', 'success');
435
+ } catch (error) {
436
+ showToast('Logout failed', 'error');
437
+ }
438
+ };
439
+ }
440
+ ```
441
+
442
+ ### Store Composition
443
+
444
+ ```typescript
445
+ // File: src/hooks/useAppState.ts
446
+ // Custom hook that combines multiple stores
447
+
448
+ export function useAppState() {
449
+ const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
450
+ const user = useAuthStore((state) => state.user);
451
+ const profile = useAuthStore((state) => state.profile);
452
+ const darkMode = useUIStore((state) => state.darkMode);
453
+ const totalCaught = useDexTrackerStore((state) => state.totalCaught());
454
+
455
+ return {
456
+ isLoggedIn,
457
+ user,
458
+ profile,
459
+ darkMode,
460
+ totalCaught,
461
+ };
462
+ }
463
+ ```
464
+
465
+ ## Store Organization Best Practices
466
+
467
+ ### ✅ DO
468
+
469
+ 1. **Keep stores focused on single domain**
470
+ ```typescript
471
+ // ✅ GOOD
472
+ useAuthStore // Auth only
473
+ useUIStore // UI state only
474
+ useDexStore // Feature only
475
+ ```
476
+
477
+ 2. **Use partial persistence**
478
+ ```typescript
479
+ partialize: (state) => ({
480
+ user: state.user, // Persist
481
+ profile: state.profile, // Persist
482
+ loading: state.loading, // DON'T persist (transient)
483
+ error: state.error, // DON'T persist (transient)
484
+ })
485
+ ```
486
+
487
+ 3. **Provide computed properties as getters**
488
+ ```typescript
489
+ get isAdult(): boolean {
490
+ return this.profile?.ageVerified " false;
491
+ }
492
+ ```
493
+
494
+ ### ❌ DON'T
495
+
496
+ 1. **Don't create monolithic stores**
497
+ ```typescript
498
+ // ❌ WRONG
499
+ useAppStore // Auth + UI + Features + Settings - too much!
500
+
501
+ // ✅ RIGHT
502
+ useAuthStore
503
+ useUIStore
504
+ useFeaturesStore
505
+ useSettingsStore
506
+ ```
507
+
508
+ 2. **Don't duplicate state across stores**
509
+ ```typescript
510
+ // ❌ WRONG
511
+ // useAuthStore has user
512
+ // useUIStore also has user (duplicated)
513
+
514
+ // ✅ RIGHT
515
+ // Only useAuthStore has user
516
+ // useUIStore can import it via selectors
517
+ ```
518
+
519
+ 3. **Don't make stores depend on each other**
520
+ ```typescript
521
+ // ❌ WRONG
522
+ export const useFeatureStore = create((set, get) => ({
523
+ signOut: useAuthStore.getState().signOut, // Circular dependency
524
+ }))
525
+
526
+ // ✅ RIGHT
527
+ // Composed in hooks/components, not in stores
528
+ ```
529
+
530
+ ## Related Patterns
531
+
532
+ - [Zustand Patterns](./zustand-patterns.md) — Zustand fundamentals
533
+ - [Persistence Middleware](./persistence-middleware.md) — Persistence setup
534
+ - [Selector Hooks](./selector-hooks.md) — Performance optimization
535
+
536
+ ---
537
+
538
+ *Pattern extracted from production repositories: core-monorepo, PokePages, DJsPortfolio*
539
+ *Files: src/store/ directory structures*