@jmruthers/pace-core 0.6.6 → 0.6.7

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 (246) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +255 -0
  4. package/audit-tool/audits/03-architecture.cjs +196 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +291 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +241 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-7PMH7XN7.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
  28. package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
  29. package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
  30. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  31. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  32. package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
  33. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  34. package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
  35. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  36. package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
  37. package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
  38. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  39. package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
  40. package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
  41. package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
  42. package/dist/components.d.ts +5 -4
  43. package/dist/components.js +27 -32
  44. package/dist/eslint-rules/index.cjs +22 -9
  45. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  46. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  47. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  48. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
  49. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  50. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  51. package/dist/hooks.d.ts +5 -5
  52. package/dist/hooks.js +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +18 -17
  55. package/dist/rbac/index.js +6 -6
  56. package/dist/theming/runtime.d.ts +14 -1
  57. package/dist/theming/runtime.js +1 -1
  58. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  59. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  60. package/dist/utils.d.ts +2 -2
  61. package/dist/utils.js +8 -8
  62. package/docs/README.md +1 -1
  63. package/docs/api/modules.md +47 -31
  64. package/docs/api-reference/components.md +18 -20
  65. package/docs/api-reference/hooks.md +80 -80
  66. package/docs/api-reference/types.md +1 -1
  67. package/docs/api-reference/utilities.md +1 -1
  68. package/docs/architecture/README.md +1 -1
  69. package/docs/core-concepts/events.md +3 -3
  70. package/docs/core-concepts/organisations.md +6 -6
  71. package/docs/core-concepts/permissions.md +6 -6
  72. package/docs/documentation-index.md +12 -18
  73. package/docs/getting-started/documentation-index.md +1 -1
  74. package/docs/getting-started/examples/README.md +4 -4
  75. package/docs/getting-started/examples/full-featured-app.md +1 -1
  76. package/docs/getting-started/faq.md +2 -2
  77. package/docs/getting-started/quick-reference.md +4 -4
  78. package/docs/implementation-guides/authentication.md +15 -15
  79. package/docs/implementation-guides/component-styling.md +1 -1
  80. package/docs/implementation-guides/data-tables.md +126 -33
  81. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  82. package/docs/implementation-guides/dynamic-colors.md +3 -3
  83. package/docs/implementation-guides/file-upload-storage.md +2 -2
  84. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  85. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  86. package/docs/implementation-guides/large-datasets.md +3 -2
  87. package/docs/implementation-guides/organisation-security.md +2 -2
  88. package/docs/implementation-guides/performance.md +2 -2
  89. package/docs/implementation-guides/permission-enforcement.md +1 -1
  90. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  91. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  92. package/docs/rbac/README.md +5 -5
  93. package/docs/rbac/advanced-patterns.md +6 -6
  94. package/docs/rbac/api-reference.md +20 -20
  95. package/docs/rbac/event-based-apps.md +3 -3
  96. package/docs/rbac/examples.md +41 -41
  97. package/docs/rbac/getting-started.md +37 -37
  98. package/docs/rbac/performance.md +1 -1
  99. package/docs/rbac/quick-start.md +52 -52
  100. package/docs/rbac/secure-client-protection.md +1 -1
  101. package/docs/rbac/troubleshooting.md +1 -1
  102. package/docs/security/README.md +5 -5
  103. package/docs/standards/0-standards-overview.md +220 -0
  104. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
  105. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  106. package/docs/standards/3-architecture-standards.md +606 -0
  107. package/docs/standards/4-code-quality-standards.md +728 -0
  108. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  109. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  110. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  111. package/docs/standards/8-testing-documentation-standards.md +401 -0
  112. package/docs/standards/9-operations-standards.md +1102 -0
  113. package/docs/standards/README.md +203 -104
  114. package/docs/troubleshooting/README.md +4 -4
  115. package/docs/troubleshooting/common-issues.md +2 -2
  116. package/docs/troubleshooting/debugging.md +9 -9
  117. package/docs/troubleshooting/migration.md +4 -4
  118. package/eslint-config-pace-core.cjs +21 -10
  119. package/package.json +6 -5
  120. package/scripts/install-cursor-rules.cjs +11 -243
  121. package/scripts/install-eslint-config.cjs +284 -0
  122. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  123. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  124. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
  125. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  126. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  127. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  128. package/src/__tests__/templates/component.test.template.tsx +18 -15
  129. package/src/components/Calendar/Calendar.tsx +201 -47
  130. package/src/components/ContextSelector/ContextSelector.tsx +137 -153
  131. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  132. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  133. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  134. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  135. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  136. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  137. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  138. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  139. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  140. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  141. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  142. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  143. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  144. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  145. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  146. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  147. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  148. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  149. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  150. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  151. package/src/components/DataTable/components/index.ts +2 -1
  152. package/src/components/DataTable/types.ts +0 -18
  153. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  154. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  155. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  156. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  157. package/src/components/Dialog/Dialog.test.tsx +1 -0
  158. package/src/components/Dialog/Dialog.tsx +25 -8
  159. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  160. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  161. package/src/components/FileUpload/FileUpload.tsx +112 -130
  162. package/src/components/Progress/Progress.tsx +2 -4
  163. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  164. package/src/components/Select/Select.tsx +86 -77
  165. package/src/components/Select/types.ts +3 -0
  166. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  167. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  168. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  169. package/src/hooks/public/usePublicEvent.ts +5 -5
  170. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  171. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  172. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  173. package/src/hooks/useAppConfig.ts +2 -2
  174. package/src/hooks/useEventTheme.test.ts +7 -7
  175. package/src/hooks/useEventTheme.ts +1 -4
  176. package/src/hooks/useFileDisplay.ts +2 -2
  177. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  178. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  179. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  180. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  181. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  182. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  183. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  184. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  185. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  186. package/src/styles/core.css +7 -0
  187. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  188. package/src/theming/parseEventColours.ts +22 -10
  189. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  190. package/src/utils/storage/README.md +1 -1
  191. package/cursor-rules/01-standards-compliance.mdc +0 -285
  192. package/cursor-rules/04-testing-standards.mdc +0 -270
  193. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  194. package/cursor-rules/06-code-quality.mdc +0 -311
  195. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  196. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  197. package/cursor-rules/11-performance-optimization.mdc +0 -169
  198. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  199. package/dist/DataTable-LRJL4IRV.js +0 -15
  200. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  201. package/dist/eslint-rules/rules/components.cjs +0 -113
  202. package/dist/eslint-rules/rules/imports.cjs +0 -102
  203. package/docs/best-practices/README.md +0 -472
  204. package/docs/best-practices/accessibility.md +0 -604
  205. package/docs/best-practices/common-patterns.md +0 -516
  206. package/docs/best-practices/deployment.md +0 -1103
  207. package/docs/best-practices/performance.md +0 -1328
  208. package/docs/best-practices/security.md +0 -940
  209. package/docs/best-practices/testing.md +0 -1034
  210. package/docs/rbac/compliance/compliance-guide.md +0 -544
  211. package/docs/standards/01-standards-compliance.md +0 -188
  212. package/docs/standards/03-solid-principles.md +0 -39
  213. package/docs/standards/04-testing-standards.md +0 -36
  214. package/docs/standards/05-bug-reports-and-features.md +0 -27
  215. package/docs/standards/06-code-quality.md +0 -34
  216. package/docs/standards/07-tech-stack-compliance.md +0 -30
  217. package/docs/standards/10-error-handling-patterns.md +0 -401
  218. package/docs/standards/11-performance-optimization.md +0 -348
  219. package/docs/standards/12-ci-cd-integration.md +0 -370
  220. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  221. package/scripts/audit/audit-compliance.cjs +0 -1295
  222. package/scripts/audit/audit-components.cjs +0 -260
  223. package/scripts/audit/audit-rbac.cjs +0 -954
  224. package/scripts/audit/audit-standards.cjs +0 -1268
  225. package/scripts/audit/index.cjs +0 -1927
  226. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  227. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  228. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  229. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  230. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  231. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  232. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  233. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  234. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  235. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  236. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  237. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  238. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  239. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  240. package/src/components/DataTable/utils/debugTools.ts +0 -514
  241. package/src/eslint-rules/index.cjs +0 -22
  242. package/src/eslint-rules/rules/components.cjs +0 -113
  243. package/src/eslint-rules/rules/imports.cjs +0 -102
  244. package/src/eslint-rules/rules/rbac.cjs +0 -790
  245. package/src/eslint-rules/utils/helpers.cjs +0 -42
  246. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -1,1103 +0,0 @@
1
- ---
2
- lastUpdated: 2025-11-18T17:00:00+11:00
3
- version: 0.5.181
4
- reviewedBy: documentation-standards-audit
5
- ---
6
-
7
- # Deployment Best Practices
8
-
9
- Proper deployment is crucial for production success. This guide provides comprehensive deployment strategies and best practices for `@jmruthers/pace-core` applications.
10
-
11
- ## Overview
12
-
13
- Deployment in `@jmruthers/pace-core` covers multiple environments:
14
-
15
- - **Development**: Local development and testing
16
- - **Staging**: Pre-production testing and validation
17
- - **Production**: Live application with high availability
18
- - **CI/CD**: Automated build and deployment pipelines
19
-
20
- ## Environment Configuration
21
-
22
- ### 1. Environment Variables
23
-
24
- ```typescript
25
- // .env.local (development)
26
- VITE_SUPABASE_URL=http://localhost:54321
27
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
28
- VITE_SUPABASE_PUBLISHABLE_KEY=your-local-publishable-key
29
- VITE_APP_ENV=development
30
- VITE_DEBUG=true
31
-
32
- // .env.staging
33
- VITE_SUPABASE_URL=https://your-project.supabase.co
34
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
35
- VITE_SUPABASE_PUBLISHABLE_KEY=your-staging-publishable-key
36
- VITE_APP_ENV=staging
37
- VITE_DEBUG=false
38
-
39
- // .env.production
40
- VITE_SUPABASE_URL=https://your-project.supabase.co
41
- // Accepts both legacy anon keys and modern publishable keys (sb_publishable_...)
42
- VITE_SUPABASE_PUBLISHABLE_KEY=your-production-publishable-key
43
- VITE_APP_ENV=production
44
- VITE_DEBUG=false
45
- ```
46
-
47
- ### 2. Environment-Specific Configuration
48
-
49
- ```typescript
50
- // config/environment.ts
51
- export const getEnvironmentConfig = () => {
52
- const env = import.meta.env.VITE_APP_ENV || 'development';
53
-
54
- const configs = {
55
- development: {
56
- apiUrl: 'http://localhost:54321',
57
- debug: true,
58
- logLevel: 'debug',
59
- features: {
60
- analytics: false,
61
- monitoring: false,
62
- },
63
- },
64
- staging: {
65
- apiUrl: 'https://your-staging-project.supabase.co',
66
- debug: false,
67
- logLevel: 'info',
68
- features: {
69
- analytics: true,
70
- monitoring: true,
71
- },
72
- },
73
- production: {
74
- apiUrl: 'https://your-production-project.supabase.co',
75
- debug: false,
76
- logLevel: 'warn',
77
- features: {
78
- analytics: true,
79
- monitoring: true,
80
- },
81
- },
82
- };
83
-
84
- return configs[env] || configs.development;
85
- };
86
- ```
87
-
88
- ### 3. Feature Flags
89
-
90
- ```typescript
91
- // utils/featureFlags.ts
92
- export const FEATURE_FLAGS = {
93
- NEW_UI: process.env.VITE_FEATURE_NEW_UI === 'true',
94
- BETA_FEATURES: process.env.VITE_FEATURE_BETA === 'true',
95
- ANALYTICS: process.env.VITE_FEATURE_ANALYTICS === 'true',
96
- DEBUG_MODE: process.env.VITE_DEBUG === 'true',
97
- };
98
-
99
- export const isFeatureEnabled = (feature: keyof typeof FEATURE_FLAGS) => {
100
- return FEATURE_FLAGS[feature];
101
- };
102
-
103
- // Usage in components
104
- function MyComponent() {
105
- if (isFeatureEnabled('NEW_UI')) {
106
- return <NewUIComponent />;
107
- }
108
- return <LegacyComponent />;
109
- }
110
- ```
111
-
112
- ## Build Optimization
113
-
114
- ### 1. Production Build Configuration
115
-
116
- ```typescript
117
- // vite.config.ts
118
- import { defineConfig } from 'vite';
119
- import react from '@vitejs/plugin-react';
120
- import { resolve } from 'path';
121
-
122
- export default defineConfig({
123
- plugins: [react()],
124
- build: {
125
- target: 'es2015',
126
- outDir: 'dist',
127
- sourcemap: false, // Disable in production
128
- minify: 'terser',
129
- rollupOptions: {
130
- output: {
131
- manualChunks: {
132
- vendor: ['react', 'react-dom'],
133
- paceCore: ['@jmruthers/pace-core'],
134
- supabase: ['@supabase/supabase-js'],
135
- },
136
- },
137
- },
138
- terserOptions: {
139
- compress: {
140
- drop_console: true, // Remove console.log in production
141
- drop_debugger: true,
142
- },
143
- },
144
- },
145
- define: {
146
- __DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
147
- },
148
- });
149
- ```
150
-
151
- ### 2. Bundle Analysis
152
-
153
- ```typescript
154
- // scripts/analyze-bundle.js
155
- import { build } from 'vite';
156
- import { visualizer } from 'rollup-plugin-visualizer';
157
-
158
- export default defineConfig({
159
- plugins: [
160
- visualizer({
161
- filename: 'dist/stats.html',
162
- open: true,
163
- gzipSize: true,
164
- brotliSize: true,
165
- }),
166
- ],
167
- build: {
168
- rollupOptions: {
169
- output: {
170
- manualChunks: {
171
- vendor: ['react', 'react-dom'],
172
- paceCore: ['@jmruthers/pace-core'],
173
- supabase: ['@supabase/supabase-js'],
174
- utils: ['lodash', 'date-fns'],
175
- },
176
- },
177
- },
178
- },
179
- });
180
- ```
181
-
182
- ### 3. Code Splitting
183
-
184
- ```typescript
185
- // Lazy load components based on routes
186
- import { lazy, Suspense } from 'react';
187
-
188
- const AdminDashboard = lazy(() => import('./AdminDashboard'));
189
- const UserDashboard = lazy(() => import('./UserDashboard'));
190
- const Analytics = lazy(() => import('./Analytics'));
191
-
192
- import { useCan } from '@jmruthers/pace-core/rbac';
193
-
194
- function App() {
195
- const { user, selectedOrganisationId } = useUnifiedAuth();
196
- const { can: canViewAdmin } = useCan(
197
- user?.id || '',
198
- { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
199
- 'read:page.admin'
200
- );
201
-
202
- return (
203
- <Suspense fallback={<LoadingSpinner />}>
204
- {canViewAdmin ? (
205
- <AdminDashboard />
206
- ) : (
207
- <UserDashboard />
208
- )}
209
- {canViewAdmin && (
210
- <Suspense fallback={<div>Loading analytics...</div>}>
211
- <Analytics />
212
- </Suspense>
213
- )}
214
- </Suspense>
215
- );
216
- }
217
- ```
218
-
219
- ## CI/CD Pipeline
220
-
221
- ### 1. GitHub Actions Workflow
222
-
223
- ```yaml
224
- # .github/workflows/deploy.yml
225
- name: Deploy
226
-
227
- on:
228
- push:
229
- branches: [main, develop]
230
- pull_request:
231
- branches: [main]
232
-
233
- jobs:
234
- test:
235
- runs-on: ubuntu-latest
236
- steps:
237
- - uses: actions/checkout@v3
238
-
239
- - name: Setup Node.js
240
- uses: actions/setup-node@v3
241
- with:
242
- node-version: '18'
243
- cache: 'npm'
244
-
245
- - name: Install dependencies
246
- run: npm ci
247
-
248
- - name: Run tests
249
- run: npm test
250
-
251
- - name: Run type check
252
- run: npm run type-check
253
-
254
- - name: Run linting
255
- run: npm run lint
256
-
257
- build:
258
- needs: test
259
- runs-on: ubuntu-latest
260
- if: github.ref == 'refs/heads/main'
261
- steps:
262
- - uses: actions/checkout@v3
263
-
264
- - name: Setup Node.js
265
- uses: actions/setup-node@v3
266
- with:
267
- node-version: '18'
268
- cache: 'npm'
269
-
270
- - name: Install dependencies
271
- run: npm ci
272
-
273
- - name: Build application
274
- run: npm run build
275
- env:
276
- VITE_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
277
- VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.SUPABASE_PUBLISHABLE_KEY }}
278
- VITE_APP_ENV: production
279
-
280
- - name: Upload build artifacts
281
- uses: actions/upload-artifact@v3
282
- with:
283
- name: build-files
284
- path: dist/
285
-
286
- deploy-staging:
287
- needs: build
288
- runs-on: ubuntu-latest
289
- if: github.ref == 'refs/heads/develop'
290
- steps:
291
- - uses: actions/checkout@v3
292
-
293
- - name: Download build artifacts
294
- uses: actions/download-artifact@v3
295
- with:
296
- name: build-files
297
- path: dist/
298
-
299
- - name: Deploy to staging
300
- run: |
301
- # Deploy to staging environment
302
- # This could be Vercel, Netlify, AWS, etc.
303
- echo "Deploying to staging..."
304
-
305
- deploy-production:
306
- needs: build
307
- runs-on: ubuntu-latest
308
- if: github.ref == 'refs/heads/main'
309
- environment: production
310
- steps:
311
- - uses: actions/checkout@v3
312
-
313
- - name: Download build artifacts
314
- uses: actions/download-artifact@v3
315
- with:
316
- name: build-files
317
- path: dist/
318
-
319
- - name: Deploy to production
320
- run: |
321
- # Deploy to production environment
322
- echo "Deploying to production..."
323
- ```
324
-
325
- ### 2. Environment-Specific Deployments
326
-
327
- ```yaml
328
- # .github/workflows/deploy-staging.yml
329
- name: Deploy to Staging
330
-
331
- on:
332
- push:
333
- branches: [develop]
334
-
335
- jobs:
336
- deploy:
337
- runs-on: ubuntu-latest
338
- steps:
339
- - uses: actions/checkout@v3
340
-
341
- - name: Setup Node.js
342
- uses: actions/setup-node@v3
343
- with:
344
- node-version: '18'
345
- cache: 'npm'
346
-
347
- - name: Install dependencies
348
- run: npm ci
349
-
350
- - name: Run tests
351
- run: npm test
352
-
353
- - name: Build for staging
354
- run: npm run build:staging
355
- env:
356
- VITE_SUPABASE_URL: ${{ secrets.STAGING_SUPABASE_URL }}
357
- VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.STAGING_SUPABASE_PUBLISHABLE_KEY }}
358
- VITE_APP_ENV: staging
359
-
360
- - name: Deploy to Vercel (Staging)
361
- uses: amondnet/vercel-action@v25
362
- with:
363
- vercel-token: ${{ secrets.VERCEL_TOKEN }}
364
- vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
365
- vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
366
- vercel-args: '--prod'
367
- ```
368
-
369
- ### 3. Automated Testing in CI
370
-
371
- ```yaml
372
- # .github/workflows/test.yml
373
- name: Test
374
-
375
- on:
376
- push:
377
- branches: [main, develop]
378
- pull_request:
379
- branches: [main]
380
-
381
- jobs:
382
- test:
383
- runs-on: ubuntu-latest
384
- strategy:
385
- matrix:
386
- node-version: [16, 18, 20]
387
-
388
- steps:
389
- - uses: actions/checkout@v3
390
-
391
- - name: Setup Node.js ${{ matrix.node-version }}
392
- uses: actions/setup-node@v3
393
- with:
394
- node-version: ${{ matrix.node-version }}
395
- cache: 'npm'
396
-
397
- - name: Install dependencies
398
- run: npm ci
399
-
400
- - name: Run unit tests
401
- run: npm run test:unit
402
-
403
- - name: Run integration tests
404
- run: npm run test:integration
405
-
406
- - name: Run E2E tests
407
- run: npm run test:e2e
408
-
409
- - name: Upload coverage
410
- uses: codecov/codecov-action@v3
411
- with:
412
- file: ./coverage/lcov.info
413
- ```
414
-
415
- ## Deployment Platforms
416
-
417
- ### 1. Vercel Deployment
418
-
419
- ```json
420
- // vercel.json
421
- {
422
- "version": 2,
423
- "builds": [
424
- {
425
- "src": "package.json",
426
- "use": "@vercel/static-build",
427
- "config": {
428
- "distDir": "dist"
429
- }
430
- }
431
- ],
432
- "routes": [
433
- {
434
- "src": "/api/(.*)",
435
- "dest": "/api/$1"
436
- },
437
- {
438
- "src": "/(.*)",
439
- "dest": "/index.html"
440
- }
441
- ],
442
- "env": {
443
- "VITE_SUPABASE_URL": "@supabase-url",
444
- "VITE_SUPABASE_PUBLISHABLE_KEY": "@supabase-publishable-key"
445
- }
446
- }
447
- ```
448
-
449
- ### 2. Netlify Deployment
450
-
451
- ```toml
452
- # netlify.toml
453
- [build]
454
- command = "npm run build"
455
- publish = "dist"
456
-
457
- [build.environment]
458
- VITE_SUPABASE_URL = "https://your-project.supabase.co"
459
- VITE_APP_ENV = "production"
460
-
461
- [[redirects]]
462
- from = "/*"
463
- to = "/index.html"
464
- status = 200
465
-
466
- [[headers]]
467
- for = "/*"
468
- [headers.values]
469
- X-Frame-Options = "DENY"
470
- X-XSS-Protection = "1; mode=block"
471
- X-Content-Type-Options = "nosniff"
472
- Referrer-Policy = "strict-origin-when-cross-origin"
473
- ```
474
-
475
- ### 3. AWS S3 + CloudFront
476
-
477
- ```typescript
478
- // scripts/deploy-aws.js
479
- import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
480
- import { CloudFrontClient, CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
481
- import { readdir, readFile } from 'fs/promises';
482
- import { join } from 'path';
483
-
484
- const s3Client = new S3Client({ region: 'us-east-1' });
485
- const cloudFrontClient = new CloudFrontClient({ region: 'us-east-1' });
486
-
487
- async function deployToS3() {
488
- const bucketName = process.env.AWS_S3_BUCKET;
489
- const distributionId = process.env.AWS_CLOUDFRONT_DISTRIBUTION_ID;
490
-
491
- // Upload build files to S3
492
- const buildDir = join(process.cwd(), 'dist');
493
- const files = await readdir(buildDir, { recursive: true });
494
-
495
- for (const file of files) {
496
- const filePath = join(buildDir, file);
497
- const fileContent = await readFile(filePath);
498
-
499
- await s3Client.send(new PutObjectCommand({
500
- Bucket: bucketName,
501
- Key: file,
502
- Body: fileContent,
503
- ContentType: getContentType(file),
504
- CacheControl: getCacheControl(file),
505
- }));
506
- }
507
-
508
- // Invalidate CloudFront cache
509
- await cloudFrontClient.send(new CreateInvalidationCommand({
510
- DistributionId: distributionId,
511
- InvalidationBatch: {
512
- Paths: {
513
- Quantity: 1,
514
- Items: ['/*'],
515
- },
516
- CallerReference: Date.now().toString(),
517
- },
518
- }));
519
- }
520
-
521
- function getContentType(filename) {
522
- if (filename.endsWith('.html')) return 'text/html';
523
- if (filename.endsWith('.css')) return 'text/css';
524
- if (filename.endsWith('.js')) return 'application/javascript';
525
- if (filename.endsWith('.json')) return 'application/json';
526
- return 'application/octet-stream';
527
- }
528
-
529
- function getCacheControl(filename) {
530
- if (filename.endsWith('.html')) return 'no-cache';
531
- if (filename.endsWith('.css') || filename.endsWith('.js')) return 'public, max-age=31536000';
532
- return 'public, max-age=86400';
533
- }
534
-
535
- deployToS3().catch(console.error);
536
- ```
537
-
538
- ## Security Deployment
539
-
540
- ### 1. Security Headers
541
-
542
- ```typescript
543
- // server/security-headers.js
544
- export const securityHeaders = {
545
- 'Content-Security-Policy': [
546
- "default-src 'self'",
547
- "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
548
- "style-src 'self' 'unsafe-inline'",
549
- "img-src 'self' data: https:",
550
- "font-src 'self'",
551
- "connect-src 'self' https://*.supabase.co",
552
- "frame-ancestors 'none'",
553
- ].join('; '),
554
-
555
- 'X-Frame-Options': 'DENY',
556
- 'X-Content-Type-Options': 'nosniff',
557
- 'X-XSS-Protection': '1; mode=block',
558
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
559
- 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
560
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
561
- };
562
- ```
563
-
564
- ### 2. Environment Variable Security
565
-
566
- ```bash
567
- # .env.example (template for required variables)
568
- VITE_SUPABASE_URL=
569
- VITE_SUPABASE_PUBLISHABLE_KEY=
570
- VITE_APP_ENV=development
571
- VITE_DEBUG=false
572
-
573
- # .env.production (actual production values - never commit)
574
- VITE_SUPABASE_URL=https://your-project.supabase.co
575
- VITE_SUPABASE_PUBLISHABLE_KEY=your-production-publishable-key
576
- VITE_APP_ENV=production
577
- VITE_DEBUG=false
578
- ```
579
-
580
- ### 3. SSL/TLS Configuration
581
-
582
- ```nginx
583
- # nginx.conf
584
- server {
585
- listen 443 ssl http2;
586
- server_name your-domain.com;
587
-
588
- ssl_certificate /path/to/certificate.crt;
589
- ssl_certificate_key /path/to/private.key;
590
-
591
- ssl_protocols TLSv1.2 TLSv1.3;
592
- ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
593
- ssl_prefer_server_ciphers off;
594
-
595
- ssl_session_cache shared:SSL:10m;
596
- ssl_session_timeout 10m;
597
-
598
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
599
- add_header X-Frame-Options DENY always;
600
- add_header X-Content-Type-Options nosniff always;
601
- add_header X-XSS-Protection "1; mode=block" always;
602
-
603
- location / {
604
- root /var/www/html;
605
- try_files $uri $uri/ /index.html;
606
- }
607
- }
608
- ```
609
-
610
- ## Monitoring and Logging
611
-
612
- ### 1. Application Monitoring
613
-
614
- ```typescript
615
- // utils/monitoring.ts
616
- export class ApplicationMonitor {
617
- private static instance: ApplicationMonitor;
618
- private metrics: Map<string, number> = new Map();
619
- private errors: Error[] = [];
620
-
621
- static getInstance(): ApplicationMonitor {
622
- if (!ApplicationMonitor.instance) {
623
- ApplicationMonitor.instance = new ApplicationMonitor();
624
- }
625
- return ApplicationMonitor.instance;
626
- }
627
-
628
- trackEvent(eventName: string, properties?: Record<string, any>) {
629
- // Send to analytics service
630
- if (typeof gtag !== 'undefined') {
631
- gtag('event', eventName, properties);
632
- }
633
-
634
- // Track custom metrics
635
- this.metrics.set(eventName, (this.metrics.get(eventName) || 0) + 1);
636
- }
637
-
638
- trackError(error: Error, context?: Record<string, any>) {
639
- this.errors.push(error);
640
-
641
- // Send to error tracking service
642
- if (typeof Sentry !== 'undefined') {
643
- Sentry.captureException(error, {
644
- extra: context,
645
- });
646
- }
647
- }
648
-
649
- trackPerformance(metric: string, value: number) {
650
- // Send to performance monitoring service
651
- if (typeof gtag !== 'undefined') {
652
- gtag('event', 'timing_complete', {
653
- name: metric,
654
- value: value,
655
- });
656
- }
657
- }
658
-
659
- getMetrics() {
660
- return Object.fromEntries(this.metrics);
661
- }
662
-
663
- getErrors() {
664
- return this.errors;
665
- }
666
- }
667
-
668
- // Usage
669
- const monitor = ApplicationMonitor.getInstance();
670
- monitor.trackEvent('user_login');
671
- monitor.trackError(new Error('API call failed'), { endpoint: '/api/events' });
672
- monitor.trackPerformance('page_load', 1200);
673
- ```
674
-
675
- ### 2. Health Checks
676
-
677
- ```typescript
678
- // api/health.ts
679
- export const healthCheck = async (req: Request, res: Response) => {
680
- try {
681
- // Check database connection
682
- const { data, error } = await supabase
683
- .from('health_check')
684
- .select('*')
685
- .limit(1);
686
-
687
- if (error) {
688
- return res.status(503).json({
689
- status: 'unhealthy',
690
- database: 'down',
691
- timestamp: new Date().toISOString(),
692
- });
693
- }
694
-
695
- // Check external services
696
- const externalServices = await Promise.allSettled([
697
- fetch('https://api.supabase.co/health'),
698
- fetch('https://your-analytics-service.com/health'),
699
- ]);
700
-
701
- const healthy = externalServices.every(result =>
702
- result.status === 'fulfilled' && result.value.ok
703
- );
704
-
705
- return res.status(healthy ? 200 : 503).json({
706
- status: healthy ? 'healthy' : 'degraded',
707
- database: 'up',
708
- external_services: externalServices.map(result =>
709
- result.status === 'fulfilled' && result.value.ok ? 'up' : 'down'
710
- ),
711
- timestamp: new Date().toISOString(),
712
- });
713
- } catch (error) {
714
- return res.status(503).json({
715
- status: 'unhealthy',
716
- error: error.message,
717
- timestamp: new Date().toISOString(),
718
- });
719
- }
720
- };
721
- ```
722
-
723
- ### 3. Logging Configuration
724
-
725
- ```typescript
726
- // utils/logger.ts
727
- export enum LogLevel {
728
- DEBUG = 0,
729
- INFO = 1,
730
- WARN = 2,
731
- ERROR = 3,
732
- }
733
-
734
- export class Logger {
735
- private level: LogLevel;
736
- private context: string;
737
-
738
- constructor(context: string, level: LogLevel = LogLevel.INFO) {
739
- this.context = context;
740
- this.level = level;
741
- }
742
-
743
- debug(message: string, data?: any) {
744
- if (this.level <= LogLevel.DEBUG) {
745
- console.debug(`[DEBUG] ${this.context}: ${message}`, data);
746
- }
747
- }
748
-
749
- info(message: string, data?: any) {
750
- if (this.level <= LogLevel.INFO) {
751
- console.info(`[INFO] ${this.context}: ${message}`, data);
752
- }
753
- }
754
-
755
- warn(message: string, data?: any) {
756
- if (this.level <= LogLevel.WARN) {
757
- console.warn(`[WARN] ${this.context}: ${message}`, data);
758
- }
759
- }
760
-
761
- error(message: string, error?: Error, data?: any) {
762
- if (this.level <= LogLevel.ERROR) {
763
- console.error(`[ERROR] ${this.context}: ${message}`, error, data);
764
- }
765
- }
766
- }
767
-
768
- // Usage
769
- const logger = new Logger('AuthService', LogLevel.DEBUG);
770
- logger.info('User logged in', { userId: '123' });
771
- logger.error('Authentication failed', new Error('Invalid credentials'));
772
- ```
773
-
774
- ## Rollback Strategy
775
-
776
- ### 1. Blue-Green Deployment
777
-
778
- ```yaml
779
- # .github/workflows/blue-green-deploy.yml
780
- name: Blue-Green Deployment
781
-
782
- on:
783
- push:
784
- branches: [main]
785
-
786
- jobs:
787
- deploy-blue:
788
- runs-on: ubuntu-latest
789
- steps:
790
- - name: Deploy to Blue Environment
791
- run: |
792
- # Deploy to blue environment
793
- echo "Deploying to blue environment..."
794
-
795
- - name: Run Health Checks
796
- run: |
797
- # Run health checks on blue environment
798
- curl -f https://blue.your-domain.com/health
799
-
800
- - name: Switch Traffic to Blue
801
- run: |
802
- # Switch traffic from green to blue
803
- echo "Switching traffic to blue environment..."
804
-
805
- rollback:
806
- runs-on: ubuntu-latest
807
- if: failure()
808
- steps:
809
- - name: Rollback to Green
810
- run: |
811
- # Rollback to green environment
812
- echo "Rolling back to green environment..."
813
- ```
814
-
815
- ### 2. Canary Deployment
816
-
817
- ```typescript
818
- // utils/canary-deployment.ts
819
- export class CanaryDeployment {
820
- private static instance: CanaryDeployment;
821
- private currentVersion: string;
822
- private canaryPercentage: number = 0;
823
-
824
- static getInstance(): CanaryDeployment {
825
- if (!CanaryDeployment.instance) {
826
- CanaryDeployment.instance = new CanaryDeployment();
827
- }
828
- return CanaryDeployment.instance;
829
- }
830
-
831
- setCanaryPercentage(percentage: number) {
832
- this.canaryPercentage = Math.max(0, Math.min(100, percentage));
833
- }
834
-
835
- shouldServeCanary(userId: string): boolean {
836
- // Deterministic canary selection based on user ID
837
- const hash = this.hashString(userId);
838
- return (hash % 100) < this.canaryPercentage;
839
- }
840
-
841
- private hashString(str: string): number {
842
- let hash = 0;
843
- for (let i = 0; i < str.length; i++) {
844
- const char = str.charCodeAt(i);
845
- hash = ((hash << 5) - hash) + char;
846
- hash = hash & hash; // Convert to 32-bit integer
847
- }
848
- return Math.abs(hash);
849
- }
850
-
851
- trackCanaryMetrics(userId: string, version: string, success: boolean) {
852
- // Track canary metrics
853
- const monitor = ApplicationMonitor.getInstance();
854
- monitor.trackEvent('canary_request', {
855
- userId,
856
- version,
857
- success,
858
- percentage: this.canaryPercentage,
859
- });
860
- }
861
- }
862
-
863
- // Usage
864
- const canary = CanaryDeployment.getInstance();
865
- canary.setCanaryPercentage(10); // 10% of users get canary
866
-
867
- if (canary.shouldServeCanary(user.id)) {
868
- // Serve canary version
869
- canary.trackCanaryMetrics(user.id, 'v2.0.0', true);
870
- }
871
- ```
872
-
873
- ## Performance Monitoring
874
-
875
- ### 1. Core Web Vitals
876
-
877
- ```typescript
878
- // utils/web-vitals.ts
879
- import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
880
-
881
- export const trackWebVitals = () => {
882
- getCLS(console.log);
883
- getFID(console.log);
884
- getFCP(console.log);
885
- getLCP(console.log);
886
- getTTFB(console.log);
887
- };
888
-
889
- export const trackCustomMetrics = () => {
890
- // Track custom performance metrics
891
- const observer = new PerformanceObserver((list) => {
892
- for (const entry of list.getEntries()) {
893
- const monitor = ApplicationMonitor.getInstance();
894
- monitor.trackPerformance(entry.name, entry.startTime);
895
- }
896
- });
897
-
898
- observer.observe({ entryTypes: ['measure', 'navigation'] });
899
- };
900
-
901
- // Track component render times
902
- export const trackComponentPerformance = (componentName: string) => {
903
- const startTime = performance.now();
904
-
905
- return () => {
906
- const endTime = performance.now();
907
- const renderTime = endTime - startTime;
908
-
909
- const monitor = ApplicationMonitor.getInstance();
910
- monitor.trackPerformance(`${componentName}_render`, renderTime);
911
- };
912
- };
913
- ```
914
-
915
- ### 2. Error Tracking
916
-
917
- ```typescript
918
- // utils/error-tracking.ts
919
- import * as Sentry from '@sentry/react';
920
-
921
- export const initializeErrorTracking = () => {
922
- if (process.env.VITE_APP_ENV === 'production') {
923
- Sentry.init({
924
- dsn: process.env.VITE_SENTRY_DSN,
925
- environment: process.env.VITE_APP_ENV,
926
- integrations: [
927
- new Sentry.BrowserTracing(),
928
- new Sentry.Replay(),
929
- ],
930
- tracesSampleRate: 0.1,
931
- replaysSessionSampleRate: 0.1,
932
- replaysOnErrorSampleRate: 1.0,
933
- });
934
- }
935
- };
936
-
937
- export const captureError = (error: Error, context?: Record<string, any>) => {
938
- if (process.env.VITE_APP_ENV === 'production') {
939
- Sentry.captureException(error, {
940
- extra: context,
941
- });
942
- } else {
943
- console.error('Error captured:', error, context);
944
- }
945
- };
946
- ```
947
-
948
- ## Deployment Checklist
949
-
950
- ### Pre-Deployment Checklist
951
-
952
- - [ ] All tests passing
953
- - [ ] Code review completed
954
- - [ ] Security scan passed
955
- - [ ] Performance benchmarks met
956
- - [ ] Environment variables configured
957
- - [ ] Database migrations applied
958
- - [ ] SSL certificates valid
959
- - [ ] Monitoring configured
960
- - [ ] Rollback plan ready
961
- - [ ] Team notified
962
-
963
- ### Deployment Checklist
964
-
965
- - [ ] Deploy to staging environment
966
- - [ ] Run smoke tests
967
- - [ ] Verify all features work
968
- - [ ] Check performance metrics
969
- - [ ] Validate security headers
970
- - [ ] Test error handling
971
- - [ ] Verify monitoring alerts
972
- - [ ] Deploy to production
973
- - [ ] Monitor application health
974
- - [ ] Verify user experience
975
-
976
- ### Post-Deployment Checklist
977
-
978
- - [ ] Monitor error rates
979
- - [ ] Check performance metrics
980
- - [ ] Verify user feedback
981
- - [ ] Monitor resource usage
982
- - [ ] Check security alerts
983
- - [ ] Validate analytics data
984
- - [ ] Update documentation
985
- - [ ] Archive old deployment
986
- - [ ] Clean up temporary files
987
- - [ ] Schedule next deployment
988
-
989
- ## Troubleshooting Deployment Issues
990
-
991
- ### 1. Common Deployment Problems
992
-
993
- ```typescript
994
- // utils/deployment-troubleshooting.ts
995
- export const commonDeploymentIssues = {
996
- buildFailures: {
997
- symptoms: ['Build timeout', 'Memory errors', 'Dependency conflicts'],
998
- solutions: [
999
- 'Increase build memory allocation',
1000
- 'Update dependencies',
1001
- 'Clear build cache',
1002
- 'Check for circular dependencies',
1003
- ],
1004
- },
1005
-
1006
- environmentIssues: {
1007
- symptoms: ['Missing environment variables', 'Wrong API endpoints'],
1008
- solutions: [
1009
- 'Verify all required env vars are set',
1010
- 'Check environment-specific configs',
1011
- 'Validate API credentials',
1012
- 'Test API connectivity',
1013
- ],
1014
- },
1015
-
1016
- performanceIssues: {
1017
- symptoms: ['Slow page loads', 'High memory usage'],
1018
- solutions: [
1019
- 'Optimize bundle size',
1020
- 'Implement code splitting',
1021
- 'Add caching strategies',
1022
- 'Monitor resource usage',
1023
- ],
1024
- },
1025
- };
1026
- ```
1027
-
1028
- ### 2. Emergency Rollback
1029
-
1030
- ```bash
1031
- #!/bin/bash
1032
- # emergency-rollback.sh
1033
-
1034
- echo "Starting emergency rollback..."
1035
-
1036
- # Stop current deployment
1037
- echo "Stopping current deployment..."
1038
- # Add your deployment stop commands here
1039
-
1040
- # Rollback to previous version
1041
- echo "Rolling back to previous version..."
1042
- # Add your rollback commands here
1043
-
1044
- # Verify rollback
1045
- echo "Verifying rollback..."
1046
- curl -f https://your-domain.com/health
1047
-
1048
- if [ $? -eq 0 ]; then
1049
- echo "Rollback successful"
1050
- exit 0
1051
- else
1052
- echo "Rollback failed"
1053
- exit 1
1054
- fi
1055
-
1056
- ## ♿ Accessibility
1057
-
1058
- Deployment should maintain accessibility:
1059
-
1060
- - **Production builds maintain accessibility** - Verify accessibility features work in production
1061
- - **Environment variables don't break accessibility** - Ensure accessibility settings are correct
1062
- - **CDN caching doesn't affect accessibility** - Verify cached assets maintain accessibility
1063
- - **Error pages are accessible** - Ensure error pages meet accessibility standards
1064
- - **Monitoring includes accessibility metrics** - Track accessibility in production
1065
-
1066
- ### Accessibility Best Practices
1067
-
1068
- 1. **Test production builds with screen readers** - Verify accessibility works in production
1069
- 2. **Monitor accessibility in production** - Track accessibility metrics
1070
- 3. **Ensure error pages are accessible** - Error pages should meet WCAG standards
1071
- 4. **Test with assistive technologies** - Verify production deployment works with screen readers
1072
- 5. **Document accessibility requirements** - Include accessibility in deployment checklists
1073
-
1074
- ## ⚠️ Edge Cases
1075
-
1076
- ### Deployment Failures
1077
-
1078
- When deployment fails:
1079
- - Have rollback plan ready
1080
- - Test deployment procedures in staging
1081
- - Monitor deployment logs
1082
- - Verify all dependencies are available
1083
- - Test with minimal configuration
1084
-
1085
- ### Environment-Specific Issues
1086
-
1087
- When issues occur in specific environments:
1088
- - Verify environment variables are correct
1089
- - Check build configuration matches environment
1090
- - Ensure all services are available
1091
- - Test with environment-specific data
1092
- - Review environment differences
1093
-
1094
- ### Rollback Scenarios
1095
-
1096
- When rollback is needed:
1097
- - Have automated rollback procedures
1098
- - Test rollback in staging environment
1099
- - Verify data integrity after rollback
1100
- - Document rollback steps clearly
1101
- - Monitor system after rollback
1102
-
1103
- For more information about deploying your application, see the [Security Guide](./security.md) and [Performance Guide](./performance.md).