ai-flow-dev 1.0.1
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/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +791 -0
- package/dist/cli.js.map +1 -0
- package/dist/fs-utils.d.ts +2 -0
- package/dist/fs-utils.d.ts.map +1 -0
- package/dist/fs-utils.js +46 -0
- package/dist/fs-utils.js.map +1 -0
- package/package.json +71 -0
- package/prompts/backend/flow-dev-feature.md +1318 -0
- package/prompts/backend/flow-dev-fix.md +903 -0
- package/prompts/backend/flow-dev-refactor.md +715 -0
- package/prompts/backend/flow-dev-review.md +401 -0
- package/prompts/backend/flow-dev-work.md +1129 -0
- package/prompts/backend/flow-docs-gen-phase-0.md +1840 -0
- package/prompts/backend/flow-docs-gen-phase-1.md +435 -0
- package/prompts/backend/flow-docs-gen-phase-2.md +460 -0
- package/prompts/backend/flow-docs-gen-phase-3.md +684 -0
- package/prompts/backend/flow-docs-gen-phase-4.md +516 -0
- package/prompts/backend/flow-docs-gen-phase-5.md +637 -0
- package/prompts/backend/flow-docs-gen-phase-6.md +465 -0
- package/prompts/backend/flow-docs-gen-phase-7.md +1207 -0
- package/prompts/backend/flow-docs-gen.md +820 -0
- package/prompts/backend/flow-docs-sync.md +526 -0
- package/prompts/backend/flow-project-init.md +248 -0
- package/prompts/backend/flow-project-roadmap.md +1159 -0
- package/prompts/frontend/flow-docs-gen-phase-0.md +494 -0
- package/prompts/frontend/flow-docs-gen-phase-1.md +449 -0
- package/prompts/frontend/flow-docs-gen-phase-2.md +983 -0
- package/prompts/frontend/flow-docs-gen-phase-3.md +685 -0
- package/prompts/frontend/flow-docs-gen-phase-4.md +480 -0
- package/prompts/frontend/flow-docs-gen-phase-5.md +483 -0
- package/prompts/frontend/flow-docs-gen-phase-6.md +570 -0
- package/prompts/frontend/flow-docs-gen-phase-7.md +582 -0
- package/prompts/frontend/flow-docs-gen.md +413 -0
- package/prompts/frontend/flow-docs-sync.md +561 -0
- package/prompts/mobile/flow-docs-gen-phase-0.md +387 -0
- package/prompts/mobile/flow-docs-gen-phase-1.md +530 -0
- package/prompts/mobile/flow-docs-gen-phase-2.md +584 -0
- package/prompts/mobile/flow-docs-gen-phase-3.md +659 -0
- package/prompts/mobile/flow-docs-gen-phase-4.md +363 -0
- package/prompts/mobile/flow-docs-gen-phase-5.md +369 -0
- package/prompts/mobile/flow-docs-gen-phase-6.md +490 -0
- package/prompts/mobile/flow-docs-gen-phase-7.md +407 -0
- package/prompts/mobile/flow-docs-gen.md +430 -0
- package/prompts/mobile/flow-docs-sync.md +634 -0
- package/templates/backend/.clauderules.template +111 -0
- package/templates/backend/.cursorrules.template +102 -0
- package/templates/backend/.env.example.template +122 -0
- package/templates/backend/README.template.md +200 -0
- package/templates/backend/ai-instructions.template.md +354 -0
- package/templates/backend/copilot-instructions.template.md +160 -0
- package/templates/backend/docs/api.template.md +251 -0
- package/templates/backend/docs/architecture.template.md +612 -0
- package/templates/backend/docs/business-flows.template.md +109 -0
- package/templates/backend/docs/code-standards.template.md +828 -0
- package/templates/backend/docs/contributing.template.md +163 -0
- package/templates/backend/docs/data-model.template.md +416 -0
- package/templates/backend/docs/operations.template.md +591 -0
- package/templates/backend/docs/testing.template.md +762 -0
- package/templates/backend/project-brief.template.md +176 -0
- package/templates/backend/specs/configuration.template.md +133 -0
- package/templates/backend/specs/security.template.md +422 -0
- package/templates/frontend/README.template.md +121 -0
- package/templates/frontend/ai-instructions.template.md +368 -0
- package/templates/frontend/docs/api-integration.template.md +390 -0
- package/templates/frontend/docs/components.template.md +567 -0
- package/templates/frontend/docs/error-handling.template.md +385 -0
- package/templates/frontend/docs/operations.template.md +123 -0
- package/templates/frontend/docs/performance.template.md +140 -0
- package/templates/frontend/docs/pwa.template.md +135 -0
- package/templates/frontend/docs/state-management.template.md +394 -0
- package/templates/frontend/docs/styling.template.md +779 -0
- package/templates/frontend/docs/testing.template.md +736 -0
- package/templates/frontend/project-brief.template.md +55 -0
- package/templates/frontend/specs/accessibility.template.md +111 -0
- package/templates/frontend/specs/configuration.template.md +520 -0
- package/templates/frontend/specs/security.template.md +197 -0
- package/templates/fullstack/README.template.md +282 -0
- package/templates/fullstack/ai-instructions.template.md +487 -0
- package/templates/fullstack/project-brief.template.md +197 -0
- package/templates/fullstack/specs/configuration.template.md +380 -0
- package/templates/mobile/AGENT.template.md +251 -0
- package/templates/mobile/README.template.md +195 -0
- package/templates/mobile/ai-instructions.template.md +221 -0
- package/templates/mobile/docs/app-store.template.md +163 -0
- package/templates/mobile/docs/architecture.template.md +100 -0
- package/templates/mobile/docs/native-features.template.md +137 -0
- package/templates/mobile/docs/navigation.template.md +81 -0
- package/templates/mobile/docs/offline-strategy.template.md +90 -0
- package/templates/mobile/docs/permissions.template.md +70 -0
- package/templates/mobile/docs/state-management.template.md +116 -0
- package/templates/mobile/docs/testing.template.md +146 -0
- package/templates/mobile/project-brief.template.md +97 -0
- package/templates/mobile/specs/build-configuration.template.md +116 -0
- package/templates/mobile/specs/deployment.template.md +114 -0
- package/templates/shared/AGENT.template.md +252 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Project Brief
|
|
2
|
+
|
|
3
|
+
> Business context and objectives for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ๐ Project Overview
|
|
8
|
+
|
|
9
|
+
**Name:** {{PROJECT_NAME}}
|
|
10
|
+
|
|
11
|
+
**Description:** {{PROJECT_DESCRIPTION}}
|
|
12
|
+
|
|
13
|
+
**Problem Statement:** {{PROBLEM_STATEMENT}}
|
|
14
|
+
|
|
15
|
+
**Target Users:** {{TARGET_USERS}}
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ๐ฏ Objectives
|
|
20
|
+
|
|
21
|
+
{{PROJECT_OBJECTIVES}}
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## ๐ Scope
|
|
26
|
+
|
|
27
|
+
{{PROJECT_SCOPE}}
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ๐ซ Out of Scope
|
|
32
|
+
|
|
33
|
+
{{OUT_OF_SCOPE}}
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## ๐ Success Metrics
|
|
38
|
+
|
|
39
|
+
{{SUCCESS_METRICS}}
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## โฑ๏ธ Timeline
|
|
44
|
+
|
|
45
|
+
{{PROJECT_TIMELINE}}
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## ๐ฅ Stakeholders
|
|
50
|
+
|
|
51
|
+
{{STAKEHOLDERS}}
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Accessibility Specification
|
|
2
|
+
|
|
3
|
+
> Accessibility requirements and WCAG compliance for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ๐ฏ Accessibility Target
|
|
8
|
+
|
|
9
|
+
**WCAG Level:** {{A11Y_COMPLIANCE}}
|
|
10
|
+
**Screen Reader Testing:** {{SCREEN_READER_TESTING}}
|
|
11
|
+
**Keyboard Navigation:** {{KEYBOARD_NAVIGATION}}
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## โฟ WCAG Compliance
|
|
16
|
+
|
|
17
|
+
### Level AA Requirements
|
|
18
|
+
|
|
19
|
+
- **Color Contrast:** 4.5:1 for normal text, 3:1 for large text
|
|
20
|
+
- **Keyboard Accessible:** All functionality available via keyboard
|
|
21
|
+
- **Focus Indicators:** Visible focus indicators
|
|
22
|
+
- **Alt Text:** Images have descriptive alt text
|
|
23
|
+
- **Semantic HTML:** Proper use of semantic elements
|
|
24
|
+
|
|
25
|
+
### Level AAA Requirements (if applicable)
|
|
26
|
+
|
|
27
|
+
- **Color Contrast:** 7:1 for normal text, 4.5:1 for large text
|
|
28
|
+
- **Sign Language:** Sign language interpretation for audio
|
|
29
|
+
- **Extended Audio Description:** Extended audio descriptions
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## โจ๏ธ Keyboard Navigation
|
|
34
|
+
|
|
35
|
+
### Focus Management
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Focus trap in modals
|
|
39
|
+
function trapFocus(element: HTMLElement) {
|
|
40
|
+
const focusableElements = element.querySelectorAll(
|
|
41
|
+
'a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])'
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const firstElement = focusableElements[0] as HTMLElement;
|
|
45
|
+
const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
|
|
46
|
+
|
|
47
|
+
element.addEventListener('keydown', (e) => {
|
|
48
|
+
if (e.key === 'Tab') {
|
|
49
|
+
if (e.shiftKey && document.activeElement === firstElement) {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
lastElement.focus();
|
|
52
|
+
} else if (!e.shiftKey && document.activeElement === lastElement) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
firstElement.focus();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Skip Links
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<a href="#main-content" class="skip-link">Skip to main content</a>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ๐ฃ๏ธ Screen Reader Support
|
|
70
|
+
|
|
71
|
+
### ARIA Labels
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// Descriptive labels
|
|
75
|
+
<button aria-label="Close dialog">ร</button>
|
|
76
|
+
|
|
77
|
+
// Live regions
|
|
78
|
+
<div aria-live="polite" aria-atomic="true">
|
|
79
|
+
{notification}
|
|
80
|
+
</div>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Semantic HTML
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<!-- โ
Good -->
|
|
87
|
+
<nav>
|
|
88
|
+
<ul>
|
|
89
|
+
<li><a href="/">Home</a></li>
|
|
90
|
+
</ul>
|
|
91
|
+
</nav>
|
|
92
|
+
|
|
93
|
+
<!-- โ Bad -->
|
|
94
|
+
<div>
|
|
95
|
+
<div><span>Home</span></div>
|
|
96
|
+
</div>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## ๐ Related Documents
|
|
102
|
+
|
|
103
|
+
- [Styling](../docs/styling.md) - Accessibility in styling
|
|
104
|
+
- [Components](../docs/components.md) - Accessible components
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
109
|
+
|
|
110
|
+
**WCAG Level:** {{A11Y_COMPLIANCE}}
|
|
111
|
+
|
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# Configuration Specification
|
|
2
|
+
|
|
3
|
+
> Environment variables, feature flags, and configuration management for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ๐ฏ Configuration Strategy
|
|
8
|
+
|
|
9
|
+
**Approach:** {{CONFIGURATION_APPROACH}}
|
|
10
|
+
|
|
11
|
+
**Key Principles:**
|
|
12
|
+
1. **Separation of Concerns** - Build-time vs runtime config
|
|
13
|
+
2. **Security First** - Never expose secrets to client
|
|
14
|
+
3. **Type Safety** - Validate and type all config
|
|
15
|
+
4. **Environment Parity** - Consistent config across environments
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ๐ Configuration Files
|
|
20
|
+
|
|
21
|
+
### File Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
{{PROJECT_NAME}}/
|
|
25
|
+
โโโ .env.local # Local overrides (gitignored)
|
|
26
|
+
โโโ .env.development # Development defaults
|
|
27
|
+
โโโ .env.production # Production defaults
|
|
28
|
+
โโโ .env.example # Template for new developers
|
|
29
|
+
โโโ src/
|
|
30
|
+
โโโ config/
|
|
31
|
+
โโโ index.ts # Configuration loader
|
|
32
|
+
โโโ schema.ts # Validation schema
|
|
33
|
+
โโโ constants.ts # Static constants
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Environment File Priority
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
.env.local # Highest priority (never commit)
|
|
40
|
+
.env.[mode] # Mode-specific (.env.development, .env.production)
|
|
41
|
+
.env # Base config
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Note:** {{BUILD_TOOL}} automatically loads these files in priority order.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## ๐ Environment Variables
|
|
49
|
+
|
|
50
|
+
### .env.example Template
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
#####################################
|
|
54
|
+
# {{PROJECT_NAME}} - Configuration
|
|
55
|
+
#####################################
|
|
56
|
+
|
|
57
|
+
#----------------------------------
|
|
58
|
+
# Application
|
|
59
|
+
#----------------------------------
|
|
60
|
+
VITE_APP_NAME={{PROJECT_NAME}}
|
|
61
|
+
VITE_APP_VERSION=1.0.0
|
|
62
|
+
VITE_APP_ENV=development
|
|
63
|
+
|
|
64
|
+
#----------------------------------
|
|
65
|
+
# API Configuration
|
|
66
|
+
#----------------------------------
|
|
67
|
+
VITE_API_BASE_URL=http://localhost:3000/api
|
|
68
|
+
VITE_API_TIMEOUT=30000
|
|
69
|
+
|
|
70
|
+
{{#IF_GRAPHQL}}
|
|
71
|
+
#----------------------------------
|
|
72
|
+
# GraphQL
|
|
73
|
+
#----------------------------------
|
|
74
|
+
VITE_GRAPHQL_URL=http://localhost:3000/graphql
|
|
75
|
+
VITE_GRAPHQL_WS_URL=ws://localhost:3000/graphql
|
|
76
|
+
{{/IF_GRAPHQL}}
|
|
77
|
+
|
|
78
|
+
{{#IF_AUTH}}
|
|
79
|
+
#----------------------------------
|
|
80
|
+
# Authentication
|
|
81
|
+
#----------------------------------
|
|
82
|
+
VITE_AUTH_DOMAIN={{AUTH_DOMAIN}}
|
|
83
|
+
VITE_AUTH_CLIENT_ID={{AUTH_CLIENT_ID}}
|
|
84
|
+
VITE_AUTH_REDIRECT_URI=http://localhost:5173/callback
|
|
85
|
+
{{/IF_AUTH}}
|
|
86
|
+
|
|
87
|
+
{{#IF_ANALYTICS}}
|
|
88
|
+
#----------------------------------
|
|
89
|
+
# Analytics & Monitoring
|
|
90
|
+
#----------------------------------
|
|
91
|
+
VITE_GOOGLE_ANALYTICS_ID=
|
|
92
|
+
VITE_SENTRY_DSN=
|
|
93
|
+
VITE_SENTRY_ENVIRONMENT=development
|
|
94
|
+
{{/IF_ANALYTICS}}
|
|
95
|
+
|
|
96
|
+
{{#IF_FEATURE_FLAGS}}
|
|
97
|
+
#----------------------------------
|
|
98
|
+
# Feature Flags
|
|
99
|
+
#----------------------------------
|
|
100
|
+
VITE_FEATURE_NEW_DASHBOARD=true
|
|
101
|
+
VITE_FEATURE_BETA_UI=false
|
|
102
|
+
{{/IF_FEATURE_FLAGS}}
|
|
103
|
+
|
|
104
|
+
#----------------------------------
|
|
105
|
+
# Build Configuration
|
|
106
|
+
#----------------------------------
|
|
107
|
+
VITE_PUBLIC_URL=/
|
|
108
|
+
VITE_SOURCE_MAPS=true
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Variable Naming Convention
|
|
112
|
+
|
|
113
|
+
**Format:** `VITE_[CATEGORY]_[NAME]`
|
|
114
|
+
|
|
115
|
+
**Categories:**
|
|
116
|
+
- `VITE_APP_*` - Application metadata
|
|
117
|
+
- `VITE_API_*` - API endpoints
|
|
118
|
+
- `VITE_AUTH_*` - Authentication config
|
|
119
|
+
- `VITE_FEATURE_*` - Feature flags
|
|
120
|
+
- `VITE_ANALYTICS_*` - Analytics services
|
|
121
|
+
|
|
122
|
+
**Important:** Only variables prefixed with `VITE_` (or your build tool's prefix) are exposed to the client.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## โ๏ธ Configuration Loader
|
|
127
|
+
|
|
128
|
+
### src/config/index.ts
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { z } from 'zod';
|
|
132
|
+
import { configSchema } from './schema';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Load and validate environment configuration
|
|
136
|
+
*/
|
|
137
|
+
function loadConfig() {
|
|
138
|
+
const rawConfig = {
|
|
139
|
+
// Application
|
|
140
|
+
app: {
|
|
141
|
+
name: import.meta.env.VITE_APP_NAME,
|
|
142
|
+
version: import.meta.env.VITE_APP_VERSION,
|
|
143
|
+
env: import.meta.env.VITE_APP_ENV || import.meta.env.MODE,
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
// API
|
|
147
|
+
api: {
|
|
148
|
+
baseUrl: import.meta.env.VITE_API_BASE_URL,
|
|
149
|
+
timeout: parseInt(import.meta.env.VITE_API_TIMEOUT || '30000', 10),
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
// Authentication
|
|
153
|
+
auth: {
|
|
154
|
+
domain: import.meta.env.VITE_AUTH_DOMAIN,
|
|
155
|
+
clientId: import.meta.env.VITE_AUTH_CLIENT_ID,
|
|
156
|
+
redirectUri: import.meta.env.VITE_AUTH_REDIRECT_URI,
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Feature Flags
|
|
160
|
+
features: {
|
|
161
|
+
newDashboard: import.meta.env.VITE_FEATURE_NEW_DASHBOARD === 'true',
|
|
162
|
+
betaUi: import.meta.env.VITE_FEATURE_BETA_UI === 'true',
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// Analytics
|
|
166
|
+
analytics: {
|
|
167
|
+
googleAnalyticsId: import.meta.env.VITE_GOOGLE_ANALYTICS_ID,
|
|
168
|
+
sentryDsn: import.meta.env.VITE_SENTRY_DSN,
|
|
169
|
+
sentryEnvironment: import.meta.env.VITE_SENTRY_ENVIRONMENT,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Validate configuration
|
|
174
|
+
try {
|
|
175
|
+
return configSchema.parse(rawConfig);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (error instanceof z.ZodError) {
|
|
178
|
+
console.error('โ Configuration validation failed:');
|
|
179
|
+
error.errors.forEach(err => {
|
|
180
|
+
console.error(` - ${err.path.join('.')}: ${err.message}`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
throw new Error('Invalid configuration. Please check your .env file.');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const config = loadConfig();
|
|
188
|
+
|
|
189
|
+
// Helper to check environment
|
|
190
|
+
export const isDevelopment = config.app.env === 'development';
|
|
191
|
+
export const isProduction = config.app.env === 'production';
|
|
192
|
+
export const isTest = config.app.env === 'test';
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### src/config/schema.ts
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { z } from 'zod';
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Configuration schema with validation
|
|
202
|
+
*/
|
|
203
|
+
export const configSchema = z.object({
|
|
204
|
+
app: z.object({
|
|
205
|
+
name: z.string().min(1, 'App name is required'),
|
|
206
|
+
version: z.string().regex(/^\d+\.\d+\.\d+$/, 'Invalid version format'),
|
|
207
|
+
env: z.enum(['development', 'production', 'test']),
|
|
208
|
+
}),
|
|
209
|
+
|
|
210
|
+
api: z.object({
|
|
211
|
+
baseUrl: z.string().url('Invalid API base URL'),
|
|
212
|
+
timeout: z.number().min(1000).max(60000),
|
|
213
|
+
}),
|
|
214
|
+
|
|
215
|
+
auth: z.object({
|
|
216
|
+
domain: z.string().min(1, 'Auth domain is required'),
|
|
217
|
+
clientId: z.string().min(1, 'Auth client ID is required'),
|
|
218
|
+
redirectUri: z.string().url('Invalid redirect URI'),
|
|
219
|
+
}).optional(),
|
|
220
|
+
|
|
221
|
+
features: z.object({
|
|
222
|
+
newDashboard: z.boolean(),
|
|
223
|
+
betaUi: z.boolean(),
|
|
224
|
+
}),
|
|
225
|
+
|
|
226
|
+
analytics: z.object({
|
|
227
|
+
googleAnalyticsId: z.string().optional(),
|
|
228
|
+
sentryDsn: z.string().url().optional(),
|
|
229
|
+
sentryEnvironment: z.string().optional(),
|
|
230
|
+
}),
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
export type Config = z.infer<typeof configSchema>;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## ๐๏ธ Build-Time vs Runtime Config
|
|
239
|
+
|
|
240
|
+
### Build-Time Configuration
|
|
241
|
+
|
|
242
|
+
**Replaced at build time** - Baked into bundle
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// โ
Build-time - Replaced with actual value
|
|
246
|
+
const apiUrl = import.meta.env.VITE_API_BASE_URL;
|
|
247
|
+
// Becomes: const apiUrl = "https://api.example.com";
|
|
248
|
+
|
|
249
|
+
// โ
Dead code elimination
|
|
250
|
+
if (import.meta.env.VITE_FEATURE_BETA === 'true') {
|
|
251
|
+
// This entire block removed if false
|
|
252
|
+
console.log('Beta features enabled');
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Use for:**
|
|
257
|
+
- Feature flags (code splitting)
|
|
258
|
+
- API endpoints
|
|
259
|
+
- Third-party keys (public)
|
|
260
|
+
- Build optimizations
|
|
261
|
+
|
|
262
|
+
### Runtime Configuration
|
|
263
|
+
|
|
264
|
+
**Fetched at runtime** - Not in bundle
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// public/config.json (generated at deploy time)
|
|
268
|
+
{
|
|
269
|
+
"apiUrl": "https://api.staging.example.com",
|
|
270
|
+
"features": {
|
|
271
|
+
"betaUi": true
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// src/config/runtime.ts
|
|
276
|
+
export async function loadRuntimeConfig() {
|
|
277
|
+
const response = await fetch('/config.json');
|
|
278
|
+
return response.json();
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Use for:**
|
|
283
|
+
- Multi-tenant deployments
|
|
284
|
+
- Dynamic feature flags
|
|
285
|
+
- A/B testing variants
|
|
286
|
+
- Per-customer configs
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## ๐ฉ Feature Flags
|
|
291
|
+
|
|
292
|
+
### Implementation Strategies
|
|
293
|
+
|
|
294
|
+
#### 1. Environment Variable Flags (Simple)
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// src/config/features.ts
|
|
298
|
+
export const features = {
|
|
299
|
+
newDashboard: import.meta.env.VITE_FEATURE_NEW_DASHBOARD === 'true',
|
|
300
|
+
betaUi: import.meta.env.VITE_FEATURE_BETA_UI === 'true',
|
|
301
|
+
analyticsV2: import.meta.env.VITE_FEATURE_ANALYTICS_V2 === 'true',
|
|
302
|
+
} as const;
|
|
303
|
+
|
|
304
|
+
// Usage
|
|
305
|
+
import { features } from './config/features';
|
|
306
|
+
|
|
307
|
+
function Dashboard() {
|
|
308
|
+
if (features.newDashboard) {
|
|
309
|
+
return <NewDashboard />;
|
|
310
|
+
}
|
|
311
|
+
return <LegacyDashboard />;
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### 2. LaunchDarkly / Similar Service (Advanced)
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// src/config/featureFlags.ts
|
|
319
|
+
import { LDProvider, useFlags } from 'launchdarkly-react-client-sdk';
|
|
320
|
+
|
|
321
|
+
export const FeatureFlagProvider = ({ children }) => (
|
|
322
|
+
<LDProvider
|
|
323
|
+
clientSideID={import.meta.env.VITE_LAUNCHDARKLY_CLIENT_ID}
|
|
324
|
+
user={{ key: 'user-id', anonymous: true }}
|
|
325
|
+
>
|
|
326
|
+
{children}
|
|
327
|
+
</LDProvider>
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
// Usage
|
|
331
|
+
function Dashboard() {
|
|
332
|
+
const { newDashboard } = useFlags();
|
|
333
|
+
|
|
334
|
+
if (newDashboard) {
|
|
335
|
+
return <NewDashboard />;
|
|
336
|
+
}
|
|
337
|
+
return <LegacyDashboard />;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### 3. Percentage Rollouts
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// src/utils/rollout.ts
|
|
345
|
+
export function isFeatureEnabled(
|
|
346
|
+
featureName: string,
|
|
347
|
+
userId: string,
|
|
348
|
+
rolloutPercentage: number
|
|
349
|
+
): boolean {
|
|
350
|
+
// Hash user ID to get deterministic random
|
|
351
|
+
const hash = simpleHash(`${featureName}-${userId}`);
|
|
352
|
+
const bucket = hash % 100;
|
|
353
|
+
|
|
354
|
+
return bucket < rolloutPercentage;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Usage
|
|
358
|
+
const showNewFeature = isFeatureEnabled('new-dashboard', user.id, 25); // 25% rollout
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## ๐ Security Best Practices
|
|
364
|
+
|
|
365
|
+
### 1. Never Expose Secrets
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
# โ WRONG - These should NOT be in frontend code
|
|
369
|
+
VITE_DATABASE_URL=postgres://... # Backend only!
|
|
370
|
+
VITE_API_SECRET_KEY=abc123... # Backend only!
|
|
371
|
+
VITE_STRIPE_SECRET_KEY=sk_live_... # Backend only!
|
|
372
|
+
|
|
373
|
+
# โ
CORRECT - Public keys only
|
|
374
|
+
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...
|
|
375
|
+
VITE_GOOGLE_MAPS_API_KEY=AIza...
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### 2. Sanitize Error Messages
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// โ Bad - Exposes config in production
|
|
382
|
+
if (!config.api.baseUrl) {
|
|
383
|
+
throw new Error(`Missing API URL: ${import.meta.env.VITE_API_BASE_URL}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// โ
Good - Generic message in production
|
|
387
|
+
if (!config.api.baseUrl) {
|
|
388
|
+
const message = isDevelopment
|
|
389
|
+
? `Missing API URL: ${import.meta.env.VITE_API_BASE_URL}`
|
|
390
|
+
: 'Configuration error. Please contact support.';
|
|
391
|
+
throw new Error(message);
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### 3. Validate All Inputs
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
// Always validate environment variables
|
|
399
|
+
const port = parseInt(import.meta.env.VITE_PORT || '3000', 10);
|
|
400
|
+
|
|
401
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
402
|
+
throw new Error('Invalid port number');
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## ๐ Environment-Specific Config
|
|
409
|
+
|
|
410
|
+
### Development (.env.development)
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
VITE_API_BASE_URL=http://localhost:3000/api
|
|
414
|
+
VITE_LOG_LEVEL=debug
|
|
415
|
+
VITE_SOURCE_MAPS=true
|
|
416
|
+
VITE_ENABLE_DEVTOOLS=true
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Staging (.env.staging)
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
VITE_API_BASE_URL=https://api.staging.example.com
|
|
423
|
+
VITE_LOG_LEVEL=info
|
|
424
|
+
VITE_SOURCE_MAPS=true
|
|
425
|
+
VITE_ENABLE_DEVTOOLS=true
|
|
426
|
+
VITE_SENTRY_ENVIRONMENT=staging
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Production (.env.production)
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
VITE_API_BASE_URL=https://api.example.com
|
|
433
|
+
VITE_LOG_LEVEL=error
|
|
434
|
+
VITE_SOURCE_MAPS=false
|
|
435
|
+
VITE_ENABLE_DEVTOOLS=false
|
|
436
|
+
VITE_SENTRY_ENVIRONMENT=production
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## ๐งช Testing Configuration
|
|
442
|
+
|
|
443
|
+
### Mocking Config in Tests
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// vitest.config.ts
|
|
447
|
+
export default defineConfig({
|
|
448
|
+
test: {
|
|
449
|
+
env: {
|
|
450
|
+
VITE_API_BASE_URL: 'http://localhost:3001/api',
|
|
451
|
+
VITE_APP_ENV: 'test',
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Or mock in individual tests
|
|
457
|
+
vi.stubEnv('VITE_FEATURE_BETA', 'true');
|
|
458
|
+
|
|
459
|
+
test('feature flag enabled', () => {
|
|
460
|
+
expect(features.betaUi).toBe(true);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
vi.unstubAllEnvs();
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## ๐ Configuration Monitoring
|
|
469
|
+
|
|
470
|
+
### Log Config on Startup (Development Only)
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// src/main.tsx
|
|
474
|
+
if (isDevelopment) {
|
|
475
|
+
console.group('๐ง Configuration');
|
|
476
|
+
console.table({
|
|
477
|
+
'App Name': config.app.name,
|
|
478
|
+
'Environment': config.app.env,
|
|
479
|
+
'API URL': config.api.baseUrl,
|
|
480
|
+
'Features': Object.entries(config.features)
|
|
481
|
+
.filter(([, enabled]) => enabled)
|
|
482
|
+
.map(([name]) => name)
|
|
483
|
+
.join(', '),
|
|
484
|
+
});
|
|
485
|
+
console.groupEnd();
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Sentry Context (Production)
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
import * as Sentry from '@sentry/react';
|
|
493
|
+
|
|
494
|
+
if (isProduction && config.analytics.sentryDsn) {
|
|
495
|
+
Sentry.init({
|
|
496
|
+
dsn: config.analytics.sentryDsn,
|
|
497
|
+
environment: config.app.env,
|
|
498
|
+
release: config.app.version,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
Sentry.setContext('config', {
|
|
502
|
+
apiUrl: config.api.baseUrl,
|
|
503
|
+
features: config.features,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## ๐ Related Documents
|
|
511
|
+
|
|
512
|
+
- [AI Instructions](../ai-instructions.md) - Configuration rules
|
|
513
|
+
- [Security Specification](security.md) - Security requirements
|
|
514
|
+
- [Deployment Guide](../docs/operations.md) - Environment setup
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
519
|
+
|
|
520
|
+
**Configuration Approach:** {{CONFIGURATION_APPROACH}}
|