create-chaaskit 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 (122) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +25 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/add-infra.d.ts +6 -0
  6. package/dist/commands/add-infra.d.ts.map +1 -0
  7. package/dist/commands/add-infra.js +160 -0
  8. package/dist/commands/add-infra.js.map +1 -0
  9. package/dist/commands/build.d.ts +2 -0
  10. package/dist/commands/build.d.ts.map +1 -0
  11. package/dist/commands/build.js +63 -0
  12. package/dist/commands/build.js.map +1 -0
  13. package/dist/commands/db-sync.d.ts +13 -0
  14. package/dist/commands/db-sync.d.ts.map +1 -0
  15. package/dist/commands/db-sync.js +108 -0
  16. package/dist/commands/db-sync.js.map +1 -0
  17. package/dist/commands/dev.d.ts +7 -0
  18. package/dist/commands/dev.d.ts.map +1 -0
  19. package/dist/commands/dev.js +61 -0
  20. package/dist/commands/dev.js.map +1 -0
  21. package/dist/commands/init.d.ts +9 -0
  22. package/dist/commands/init.d.ts.map +1 -0
  23. package/dist/commands/init.js +214 -0
  24. package/dist/commands/init.js.map +1 -0
  25. package/dist/index.d.ts +3 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +57 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/templates/.env.example +24 -0
  30. package/dist/templates/README.md +81 -0
  31. package/dist/templates/app/components/AcceptInviteClient.tsx +10 -0
  32. package/dist/templates/app/components/AdminDashboardClient.tsx +10 -0
  33. package/dist/templates/app/components/AdminTeamClient.tsx +10 -0
  34. package/dist/templates/app/components/AdminTeamsClient.tsx +10 -0
  35. package/dist/templates/app/components/AdminUsersClient.tsx +10 -0
  36. package/dist/templates/app/components/ApiKeysClient.tsx +10 -0
  37. package/dist/templates/app/components/AutomationsClient.tsx +10 -0
  38. package/dist/templates/app/components/ChatClient.tsx +13 -0
  39. package/dist/templates/app/components/ClientOnly.tsx +6 -0
  40. package/dist/templates/app/components/DocumentsClient.tsx +10 -0
  41. package/dist/templates/app/components/OAuthConsentClient.tsx +10 -0
  42. package/dist/templates/app/components/PricingClient.tsx +10 -0
  43. package/dist/templates/app/components/TeamSettingsClient.tsx +10 -0
  44. package/dist/templates/app/components/VerifyEmailClient.tsx +10 -0
  45. package/dist/templates/app/entry.client.tsx +12 -0
  46. package/dist/templates/app/entry.server.tsx +67 -0
  47. package/dist/templates/app/root.tsx +91 -0
  48. package/dist/templates/app/routes/_index.tsx +82 -0
  49. package/dist/templates/app/routes/admin._index.tsx +57 -0
  50. package/dist/templates/app/routes/admin.teams.$teamId.tsx +57 -0
  51. package/dist/templates/app/routes/admin.teams._index.tsx +57 -0
  52. package/dist/templates/app/routes/admin.users.tsx +57 -0
  53. package/dist/templates/app/routes/api-keys.tsx +57 -0
  54. package/dist/templates/app/routes/automations.tsx +57 -0
  55. package/dist/templates/app/routes/chat._index.tsx +11 -0
  56. package/dist/templates/app/routes/chat.admin._index.tsx +10 -0
  57. package/dist/templates/app/routes/chat.admin.teams.$teamId.tsx +10 -0
  58. package/dist/templates/app/routes/chat.admin.teams._index.tsx +10 -0
  59. package/dist/templates/app/routes/chat.admin.users.tsx +10 -0
  60. package/dist/templates/app/routes/chat.api-keys.tsx +10 -0
  61. package/dist/templates/app/routes/chat.automations.tsx +10 -0
  62. package/dist/templates/app/routes/chat.documents.tsx +10 -0
  63. package/dist/templates/app/routes/chat.team.$teamId.settings.tsx +10 -0
  64. package/dist/templates/app/routes/chat.thread.$threadId.tsx +11 -0
  65. package/dist/templates/app/routes/chat.tsx +39 -0
  66. package/dist/templates/app/routes/documents.tsx +57 -0
  67. package/dist/templates/app/routes/invite.$token.tsx +10 -0
  68. package/dist/templates/app/routes/login.tsx +334 -0
  69. package/dist/templates/app/routes/oauth.consent.tsx +10 -0
  70. package/dist/templates/app/routes/pricing.tsx +10 -0
  71. package/dist/templates/app/routes/privacy.tsx +197 -0
  72. package/dist/templates/app/routes/register.tsx +398 -0
  73. package/dist/templates/app/routes/shared.$shareId.tsx +226 -0
  74. package/dist/templates/app/routes/team.$teamId.settings.tsx +57 -0
  75. package/dist/templates/app/routes/terms.tsx +173 -0
  76. package/dist/templates/app/routes/thread.$threadId.tsx +102 -0
  77. package/dist/templates/app/routes/verify-email.tsx +10 -0
  78. package/dist/templates/app/routes.ts +47 -0
  79. package/dist/templates/config/app.config.ts +216 -0
  80. package/dist/templates/docs/admin.md +257 -0
  81. package/dist/templates/docs/api-keys.md +403 -0
  82. package/dist/templates/docs/authentication.md +247 -0
  83. package/dist/templates/docs/configuration.md +1212 -0
  84. package/dist/templates/docs/custom-pages.md +466 -0
  85. package/dist/templates/docs/deployment.md +362 -0
  86. package/dist/templates/docs/development.md +411 -0
  87. package/dist/templates/docs/documents.md +293 -0
  88. package/dist/templates/docs/extensions.md +639 -0
  89. package/dist/templates/docs/index.md +139 -0
  90. package/dist/templates/docs/installation.md +286 -0
  91. package/dist/templates/docs/mcp.md +952 -0
  92. package/dist/templates/docs/native-tools.md +688 -0
  93. package/dist/templates/docs/queue.md +514 -0
  94. package/dist/templates/docs/scheduled-prompts.md +279 -0
  95. package/dist/templates/docs/settings.md +415 -0
  96. package/dist/templates/docs/slack.md +318 -0
  97. package/dist/templates/docs/styling.md +288 -0
  98. package/dist/templates/extensions/agents/.gitkeep +0 -0
  99. package/dist/templates/extensions/pages/.gitkeep +0 -0
  100. package/dist/templates/extensions/payment-plans/.gitkeep +0 -0
  101. package/dist/templates/index.html +16 -0
  102. package/dist/templates/infra-aws/.github/workflows/deploy.yml +95 -0
  103. package/dist/templates/infra-aws/README.md +207 -0
  104. package/dist/templates/infra-aws/bin/cdk.ts +18 -0
  105. package/dist/templates/infra-aws/cdk.json +43 -0
  106. package/dist/templates/infra-aws/config/deployment.ts +156 -0
  107. package/dist/templates/infra-aws/lib/chaaskit-stack.ts +419 -0
  108. package/dist/templates/infra-aws/package.json +27 -0
  109. package/dist/templates/infra-aws/scripts/build-app.sh +63 -0
  110. package/dist/templates/infra-aws/tsconfig.json +25 -0
  111. package/dist/templates/package.json +46 -0
  112. package/dist/templates/prisma/schema/base.prisma +584 -0
  113. package/dist/templates/prisma/schema/custom.prisma +24 -0
  114. package/dist/templates/prisma/schema.prisma +271 -0
  115. package/dist/templates/public/favicon.svg +4 -0
  116. package/dist/templates/public/logo.svg +4 -0
  117. package/dist/templates/react-router.config.ts +11 -0
  118. package/dist/templates/server.js +52 -0
  119. package/dist/templates/src/main.tsx +8 -0
  120. package/dist/templates/tsconfig.json +26 -0
  121. package/dist/templates/vite.config.ts +26 -0
  122. package/package.json +46 -0
@@ -0,0 +1,1212 @@
1
+ # Configuration
2
+
3
+ All application configuration is centralized in `config/app.config.ts`. This file controls the UI, theming, authentication, AI agent, payments, MCP, and more.
4
+
5
+ ## Configuration File
6
+
7
+ ```typescript
8
+ // config/app.config.ts
9
+ import type { AppConfig } from '@chaaskit/shared';
10
+
11
+ const config: AppConfig = {
12
+ app: { ... },
13
+ ui: { ... },
14
+ theming: { ... },
15
+ auth: { ... },
16
+ agent: { ... },
17
+ payments: { ... },
18
+ legal: { ... },
19
+ userSettings: { ... },
20
+ mcp: { ... },
21
+ sharing: { ... },
22
+ promptTemplates: { ... },
23
+ teams: { ... },
24
+ projects: { ... },
25
+ admin: { ... },
26
+ api: { ... },
27
+ documents: { ... },
28
+ slack: { ... },
29
+ queue: { ... },
30
+ email: { ... },
31
+ scheduledPrompts: { ... },
32
+ };
33
+
34
+ export default config;
35
+ ```
36
+
37
+ ## Environment Variables
38
+
39
+ Required variables in `.env`:
40
+
41
+ | Variable | Description | Example |
42
+ |----------|-------------|---------|
43
+ | `DATABASE_URL` | PostgreSQL connection string | `postgresql://...` |
44
+ | `SESSION_SECRET` | Session encryption key (32+ chars) | `your-secret-key` |
45
+ | `JWT_SECRET` | JWT signing key (32+ chars) | `your-jwt-key` |
46
+ | `APP_URL` | Frontend URL | `http://localhost:5173` |
47
+ | `API_URL` | Backend URL | `http://localhost:3000` |
48
+
49
+ AI Provider (at least one required):
50
+
51
+ | Variable | Description |
52
+ |----------|-------------|
53
+ | `ANTHROPIC_API_KEY` | Anthropic API key |
54
+ | `OPENAI_API_KEY` | OpenAI API key |
55
+
56
+ MCP (optional):
57
+
58
+ | Variable | Description |
59
+ |----------|-------------|
60
+ | `MCP_CREDENTIAL_KEY` | Encryption key for user credentials (32+ chars, falls back to SESSION_SECRET) |
61
+
62
+ Payments (optional):
63
+
64
+ | Variable | Description |
65
+ |----------|-------------|
66
+ | `STRIPE_SECRET_KEY` | Stripe secret key |
67
+ | `STRIPE_WEBHOOK_SECRET` | Stripe webhook secret |
68
+
69
+ OAuth (optional):
70
+
71
+ | Variable | Description |
72
+ |----------|-------------|
73
+ | `GOOGLE_CLIENT_ID` | Google OAuth client ID |
74
+ | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
75
+ | `GITHUB_CLIENT_ID` | GitHub OAuth client ID |
76
+ | `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret |
77
+
78
+ Slack (optional):
79
+
80
+ | Variable | Description |
81
+ |----------|-------------|
82
+ | `SLACK_CLIENT_ID` | Slack OAuth client ID |
83
+ | `SLACK_CLIENT_SECRET` | Slack OAuth client secret |
84
+ | `SLACK_SIGNING_SECRET` | Slack request signing secret |
85
+ | `SLACK_INTERNAL_SECRET` | Random secret for internal endpoints |
86
+
87
+ Queue (optional, for SQS provider):
88
+
89
+ | Variable | Description |
90
+ |----------|-------------|
91
+ | `AWS_ACCESS_KEY_ID` | AWS access key (or use IAM role) |
92
+ | `AWS_SECRET_ACCESS_KEY` | AWS secret key (or use IAM role) |
93
+ | `SQS_QUEUE_URL` | SQS queue URL |
94
+ | `SQS_DLQ_URL` | SQS dead letter queue URL (optional) |
95
+
96
+ ## Configuration Sections
97
+
98
+ ### App Info
99
+
100
+ ```typescript
101
+ app: {
102
+ name: 'AI Chat',
103
+ description: 'Your AI assistant',
104
+ url: process.env.APP_URL || 'http://localhost:5173',
105
+ basePath: '/app', // Optional: run chat app under a path
106
+ }
107
+ ```
108
+
109
+ ### Base Path (Marketing Site Integration)
110
+
111
+ The `basePath` option allows you to run the authenticated chat application under a sub-path (e.g., `/chat`), freeing up the root URL for a marketing site or other public pages.
112
+
113
+ **Default behavior** (no basePath or `basePath: '/'`):
114
+ - Chat app routes: `/`, `/login`, `/thread/:id`, etc.
115
+
116
+ **With basePath: '/chat'**:
117
+ - Chat app routes: `/chat`, `/chat/thread/:id`, `/chat/documents`, etc.
118
+ - Auth routes: `/login`, `/register` (remain at root for better UX)
119
+ - Root path `/` is free for your landing page
120
+
121
+ **Example configuration:**
122
+
123
+ ```typescript
124
+ // config/app.config.ts
125
+ app: {
126
+ name: 'My App',
127
+ basePath: '/chat', // Chat app lives under /chat/*
128
+ }
129
+ ```
130
+
131
+ **Adding custom pages:**
132
+
133
+ With React Router v7, add pages by creating files in `app/routes/`:
134
+
135
+ ```tsx
136
+ // app/routes/_index.tsx - Landing page at /
137
+ // app/routes/pricing.tsx - Pricing page at /pricing
138
+ // app/routes/about.tsx - About page at /about
139
+ // app/routes/chat._index.tsx - Main chat at /chat
140
+ ```
141
+
142
+ See [Custom Pages](./custom-pages.md) for detailed examples.
143
+
144
+ **Notes:**
145
+ - The API routes (`/api/*`) are unaffected - they always live at the root
146
+ - Use `useAppPath()` hook to build paths that respect the basePath
147
+ - Shared thread links use the appropriate path (e.g., `/shared/:id`)
148
+
149
+ ### UI Settings
150
+
151
+ ```typescript
152
+ ui: {
153
+ welcomeTitle: 'Welcome to AI Chat',
154
+ welcomeSubtitle: 'How can I help you today?',
155
+ inputPlaceholder: 'Type your message...',
156
+ logo: '/logo.svg', // or { light: '/logo-light.svg', dark: '/logo-dark.svg' }
157
+ samplePrompts: [
158
+ { label: 'Explain a concept', prompt: 'Explain quantum computing...' },
159
+ { label: 'Write code', prompt: 'Write a function to sort...' },
160
+ ],
161
+ }
162
+ ```
163
+
164
+ ### Theming
165
+
166
+ ```typescript
167
+ theming: {
168
+ defaultTheme: 'light', // 'light' | 'dark'
169
+ allowUserThemeSwitch: true,
170
+ themes: {
171
+ light: {
172
+ name: 'Light',
173
+ colors: {
174
+ primary: '#6366f1',
175
+ primaryHover: '#4f46e5',
176
+ background: '#ffffff',
177
+ // ... see full color list in types
178
+ },
179
+ },
180
+ dark: {
181
+ name: 'Dark',
182
+ colors: { ... },
183
+ },
184
+ },
185
+ fonts: {
186
+ sans: 'Inter, system-ui, sans-serif',
187
+ mono: 'JetBrains Mono, monospace',
188
+ },
189
+ }
190
+ ```
191
+
192
+ See [Styling Guide](./styling.md) for CSS variables and component styling conventions.
193
+
194
+ ### AI Agent
195
+
196
+ The platform supports both single-agent and multi-agent configurations.
197
+
198
+ #### Multi-Agent Configuration (Recommended)
199
+
200
+ Configure multiple AI agents with different providers, models, and capabilities:
201
+
202
+ ```typescript
203
+ agent: {
204
+ agents: [
205
+ // General purpose assistant - available to all users
206
+ {
207
+ id: 'general',
208
+ name: 'General Assistant',
209
+ provider: 'openai',
210
+ model: 'gpt-4o-mini',
211
+ systemPrompt: 'You are a helpful AI assistant.',
212
+ maxTokens: 4096,
213
+ isDefault: true,
214
+ // No allowedTools = all tools available
215
+ // No plans = available to all users
216
+ },
217
+ // Code expert - available to pro users only
218
+ {
219
+ id: 'code-expert',
220
+ name: 'Code Expert',
221
+ provider: 'anthropic',
222
+ model: 'claude-sonnet-4-20250514',
223
+ systemPrompt: 'You are an expert programmer.',
224
+ maxTokens: 8192,
225
+ allowedTools: ['github:*', 'filesystem:read_file'],
226
+ plans: ['pro', 'enterprise'],
227
+ },
228
+ // External agent - custom endpoint
229
+ {
230
+ id: 'custom-agent',
231
+ name: 'Custom Agent',
232
+ type: 'external',
233
+ endpoint: 'https://my-agent.example.com/chat',
234
+ headers: { 'Authorization': 'Bearer ${CUSTOM_AGENT_KEY}' },
235
+ plans: ['enterprise'],
236
+ },
237
+ ],
238
+ }
239
+ ```
240
+
241
+ **Agent Properties:**
242
+
243
+ | Property | Type | Description |
244
+ |----------|------|-------------|
245
+ | `id` | string | Unique identifier for the agent |
246
+ | `name` | string | Display name shown in the selector |
247
+ | `provider` | `'anthropic'` \| `'openai'` | AI provider (for built-in agents) |
248
+ | `model` | string | Model identifier (e.g., `gpt-4o-mini`, `claude-sonnet-4-20250514`) |
249
+ | `systemPrompt` | string | System prompt for the agent |
250
+ | `maxTokens` | number | Maximum tokens per response |
251
+ | `isDefault` | boolean | If true, this agent is used for new threads by default |
252
+ | `allowedTools` | string[] | Tool patterns to restrict access (optional) |
253
+ | `plans` | string[] | Plan IDs that can access this agent (optional, omit for all plans) |
254
+
255
+ **Tool Pattern Syntax:**
256
+
257
+ - `server:*` - All tools from an MCP server (e.g., `github:*`)
258
+ - `server:tool-name` - Specific MCP tool (e.g., `filesystem:read_file`)
259
+ - `native:*` - All native tools (built into the application)
260
+ - `native:tool-name` - Specific native tool (e.g., `native:web-scrape`)
261
+ - Omit `allowedTools` to allow all MCP tools (native tools are opt-in)
262
+
263
+ **Native Tools:**
264
+
265
+ Native tools are built into the application and don't require external MCP servers. They are opt-in and must be explicitly listed in `allowedTools` to be available to an agent.
266
+
267
+ | Tool | Description |
268
+ |------|-------------|
269
+ | `native:web-scrape` | Fetches a URL and returns the content as plain text. Useful for reading web pages, documentation, or articles. |
270
+
271
+ Example enabling native tools:
272
+
273
+ ```typescript
274
+ {
275
+ id: 'research-assistant',
276
+ name: 'Research Assistant',
277
+ provider: 'anthropic',
278
+ model: 'claude-sonnet-4-20250514',
279
+ systemPrompt: 'You are a research assistant.',
280
+ maxTokens: 8192,
281
+ allowedTools: ['native:web-scrape', 'search:*'], // Native web-scrape + all search server tools
282
+ }
283
+ ```
284
+
285
+ See [Native Tools](./native-tools.md) for the full list of available native tools and how to create custom ones.
286
+
287
+ **Agent Selection:**
288
+
289
+ - When multiple agents are configured, a selector appears on the welcome screen
290
+ - Each thread is locked to the agent it was created with
291
+ - If only one agent is configured or available to the user, the selector is hidden
292
+
293
+ #### Legacy Single-Agent Configuration
294
+
295
+ For simpler setups, you can still use the legacy single-agent configuration:
296
+
297
+ Built-in provider:
298
+
299
+ ```typescript
300
+ agent: {
301
+ type: 'built-in',
302
+ provider: 'anthropic', // or 'openai'
303
+ model: 'claude-sonnet-4-20250514',
304
+ systemPrompt: 'You are a helpful AI assistant.',
305
+ maxTokens: 4096,
306
+ }
307
+ ```
308
+
309
+ External provider:
310
+
311
+ ```typescript
312
+ agent: {
313
+ type: 'external',
314
+ endpoint: 'https://your-api.com/chat',
315
+ headers: {
316
+ 'Authorization': '${API_KEY}', // Env var substitution
317
+ },
318
+ }
319
+ ```
320
+
321
+ ### Authentication
322
+
323
+ ```typescript
324
+ auth: {
325
+ methods: ['email-password', 'google', 'github', 'magic-link'],
326
+ allowUnauthenticated: false, // Allow anonymous chats
327
+ magicLink: {
328
+ enabled: true,
329
+ expiresInMinutes: 15,
330
+ },
331
+ emailVerification: {
332
+ enabled: true, // Require email verification for new users
333
+ codeLength: 6, // Length of verification code (default: 6)
334
+ expiresInMinutes: 15, // Code expiration time (default: 15)
335
+ allowResendAfterSeconds: 60, // Cooldown before resend (default: 60)
336
+ },
337
+ }
338
+ ```
339
+
340
+ #### Email Verification
341
+
342
+ When email verification is enabled, new users registering with email/password will need to verify their email address before accessing protected features.
343
+
344
+ **How it works:**
345
+ 1. User registers with email/password
346
+ 2. A 6-digit numeric code is sent to their email
347
+ 3. User is redirected to the verification page
348
+ 4. User enters the code to verify their email
349
+ 5. After verification, user can access all features
350
+
351
+ **Graceful degradation:** If email verification is enabled but the email provider isn't configured, users are auto-verified on registration. This allows you to enable the feature in config before setting up email.
352
+
353
+ **OAuth and Magic Link users:** Users who sign in via OAuth (Google, GitHub) or magic link are automatically verified since they've already proven email ownership through those flows.
354
+
355
+ **Existing users:** When you enable email verification on an existing app, previously unverified users will be prompted to verify their email on their next protected action.
356
+
357
+ See [Authentication](./authentication.md) for full documentation on auth methods, OAuth setup, and customization.
358
+
359
+ ### MCP Integration
360
+
361
+ ```typescript
362
+ mcp: {
363
+ servers: [
364
+ // Stdio server (local process, no auth)
365
+ {
366
+ id: 'filesystem',
367
+ name: 'File System',
368
+ transport: 'stdio',
369
+ command: 'npx',
370
+ args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
371
+ enabled: true,
372
+ },
373
+ // Streamable HTTP with admin API key
374
+ {
375
+ id: 'company-tools',
376
+ name: 'Company Tools',
377
+ transport: 'streamable-http',
378
+ url: 'https://tools.company.com/mcp',
379
+ enabled: true,
380
+ authMode: 'admin',
381
+ adminApiKeyEnvVar: 'COMPANY_TOOLS_API_KEY',
382
+ },
383
+ // Streamable HTTP with user API key
384
+ {
385
+ id: 'openai-tools',
386
+ name: 'OpenAI Tools',
387
+ transport: 'streamable-http',
388
+ url: 'https://mcp.openai.com',
389
+ enabled: true,
390
+ authMode: 'user-apikey',
391
+ userInstructions: 'Enter your OpenAI API key',
392
+ },
393
+ // Streamable HTTP with user OAuth
394
+ {
395
+ id: 'github-tools',
396
+ name: 'GitHub Tools',
397
+ transport: 'streamable-http',
398
+ url: 'https://github-mcp.example.com',
399
+ enabled: true,
400
+ authMode: 'user-oauth',
401
+ oauth: {
402
+ authorizationEndpoint: 'https://github.com/login/oauth/authorize',
403
+ tokenEndpoint: 'https://github.com/login/oauth/access_token',
404
+ clientId: '${GITHUB_MCP_CLIENT_ID}',
405
+ clientSecretEnvVar: 'GITHUB_MCP_CLIENT_SECRET',
406
+ scopes: ['repo', 'read:user'],
407
+ },
408
+ userInstructions: 'Connect your GitHub account',
409
+ },
410
+ ],
411
+ allowUserServers: true,
412
+ requireToolConfirmation: true,
413
+ toolTimeout: 30000,
414
+ showToolCalls: true, // Set to false to hide tool execution cards
415
+ }
416
+ ```
417
+
418
+ See [MCP Integration](./mcp.md) for full documentation.
419
+
420
+ ### Payments
421
+
422
+ ```typescript
423
+ payments: {
424
+ enabled: true,
425
+ provider: 'stripe',
426
+ plans: [
427
+ {
428
+ id: 'free',
429
+ name: 'Free',
430
+ type: 'free',
431
+ params: { monthlyMessageLimit: 20 },
432
+ },
433
+ {
434
+ id: 'pro',
435
+ name: 'Pro',
436
+ type: 'subscription',
437
+ params: {
438
+ stripePriceId: 'price_...',
439
+ monthlyMessageLimit: 1000,
440
+ },
441
+ },
442
+ ],
443
+ }
444
+ ```
445
+
446
+ ### Legal
447
+
448
+ Configure required legal document links:
449
+
450
+ ```typescript
451
+ legal: {
452
+ privacyPolicyUrl: 'https://example.com/privacy',
453
+ termsOfServiceUrl: 'https://example.com/terms',
454
+ }
455
+ ```
456
+
457
+ These URLs are displayed in the registration form and footer.
458
+
459
+ ### User Settings
460
+
461
+ Define custom settings fields that users can configure in their profile. These settings provide context to the AI:
462
+
463
+ ```typescript
464
+ userSettings: {
465
+ fields: [
466
+ {
467
+ key: 'name',
468
+ label: 'Your Name',
469
+ type: 'text',
470
+ placeholder: 'Enter your name',
471
+ },
472
+ {
473
+ key: 'role',
474
+ label: 'Your Role',
475
+ type: 'select',
476
+ options: ['Developer', 'Designer', 'Manager', 'Other'],
477
+ },
478
+ {
479
+ key: 'context',
480
+ label: 'Additional Context',
481
+ type: 'textarea',
482
+ placeholder: 'Any context the AI should know about you...',
483
+ },
484
+ ],
485
+ }
486
+ ```
487
+
488
+ **Field Types:**
489
+
490
+ | Type | Description |
491
+ |------|-------------|
492
+ | `text` | Single-line text input |
493
+ | `select` | Dropdown selection from predefined options |
494
+ | `textarea` | Multi-line text input |
495
+
496
+ See [User Settings](./settings.md) for full documentation on settings integration and MCP credentials.
497
+
498
+ ### Prompt Templates
499
+
500
+ Enable reusable prompt templates with variable substitution:
501
+
502
+ ```typescript
503
+ promptTemplates: {
504
+ enabled: true,
505
+ allowUserTemplates: true, // Allow users to create their own templates
506
+ builtIn: [
507
+ {
508
+ id: 'code-review',
509
+ name: 'Code Review',
510
+ prompt: 'Review this {{language}} code for best practices:\n\n{{code}}',
511
+ variables: ['language', 'code'],
512
+ },
513
+ {
514
+ id: 'explain-concept',
515
+ name: 'Explain Concept',
516
+ prompt: 'Explain {{concept}} in simple terms for a {{audience}}.',
517
+ variables: ['concept', 'audience'],
518
+ },
519
+ ],
520
+ }
521
+ ```
522
+
523
+ Templates use `{{variable}}` syntax for substitution. Users fill in the variables when using a template.
524
+
525
+ ### Admin Dashboard
526
+
527
+ Configure admin access for site-wide management:
528
+
529
+ ```typescript
530
+ admin: {
531
+ emails: [
532
+ 'admin@example.com',
533
+ 'another-admin@example.com',
534
+ ],
535
+ }
536
+ ```
537
+
538
+ Users whose email addresses are in this list have access to the admin dashboard with user management, team management, and usage analytics.
539
+
540
+ See [Admin Dashboard](./admin.md) for full documentation.
541
+
542
+ ### API Keys
543
+
544
+ Enable programmatic API access via API keys:
545
+
546
+ ```typescript
547
+ api: {
548
+ enabled: true,
549
+ keyPrefix: 'myapp-', // Optional, default: "sk-"
550
+ allowedPlans: ['pro', 'enterprise'], // Optional: restrict to specific plans
551
+ allowedEndpoints: [ // Required: whitelist endpoints
552
+ '/api/chat',
553
+ '/api/threads',
554
+ '/api/threads/*',
555
+ '/api/threads/**',
556
+ '/api/search',
557
+ '/api/export/*',
558
+ ],
559
+ }
560
+ ```
561
+
562
+ **Endpoint Patterns:**
563
+ - `/api/threads` - Exact match only
564
+ - `/api/threads/*` - Single path segment (e.g., `/api/threads/123`)
565
+ - `/api/threads/**` - Any depth (e.g., `/api/threads/123/messages`)
566
+
567
+ See [API Keys](./api-keys.md) for full documentation.
568
+
569
+ ### Sharing
570
+
571
+ ```typescript
572
+ sharing: {
573
+ enabled: true, // Enable thread sharing feature
574
+ scope: 'public', // 'public' = anyone with link, 'team' = team members only
575
+ expirationOptions: ['1h', '24h', '7d', '30d', 'never'],
576
+ }
577
+ ```
578
+
579
+ See [Thread Sharing](#thread-sharing) below for more details.
580
+
581
+ ## Config API Endpoint
582
+
583
+ The frontend loads configuration from the server via `/api/config`:
584
+
585
+ ```http
586
+ GET /api/config
587
+ ```
588
+
589
+ Response includes client-safe configuration (excludes sensitive server-side settings like API keys).
590
+
591
+ This allows the frontend to stay in sync with `config/app.config.ts` without hardcoding values.
592
+
593
+ ## Hot Reloading
594
+
595
+ The backend watches the config directory and auto-restarts on changes:
596
+
597
+ ```bash
598
+ # In package.json (server)
599
+ "dev": "tsx watch --watch=../../config src/index.ts"
600
+ ```
601
+
602
+ ## Type Safety
603
+
604
+ The configuration is fully typed. Import types from `@chaaskit/shared`:
605
+
606
+ ```typescript
607
+ import type { AppConfig, ThemeConfig, AgentConfig, MCPConfig } from '@chaaskit/shared';
608
+ ```
609
+
610
+ ## Thread Sharing
611
+
612
+ Thread sharing allows users to create read-only links to share conversations with others.
613
+
614
+ ### Configuration
615
+
616
+ ```typescript
617
+ sharing: {
618
+ enabled: false, // Set to true to enable sharing
619
+ scope: 'public', // Who can view shared links
620
+ expirationOptions: ['1h', '24h', '7d', '30d', 'never'],
621
+ }
622
+ ```
623
+
624
+ ### Scope Options
625
+
626
+ | Scope | Description |
627
+ |-------|-------------|
628
+ | `public` | Anyone with the link can view the conversation |
629
+ | `team` | Only authenticated users who share a team with the thread owner can view |
630
+
631
+ ### How It Works
632
+
633
+ 1. **Creating a share**: Users click "Share" in the sidebar when viewing a conversation
634
+ 2. **Choose expiration**: Select how long the link should remain active
635
+ 3. **Copy link**: The shareable URL is automatically copied to clipboard
636
+ 4. **Managing shares**: Users can view active shares and revoke them at any time
637
+
638
+ ### API Endpoints
639
+
640
+ | Method | Endpoint | Description |
641
+ |--------|----------|-------------|
642
+ | `POST` | `/api/share/:threadId` | Create a shareable link |
643
+ | `GET` | `/api/share/thread/:threadId` | List active shares for a thread |
644
+ | `GET` | `/api/share/view/:shareId` | View a shared thread (public or team-scoped) |
645
+ | `DELETE` | `/api/share/:shareId` | Revoke a share link |
646
+
647
+ ### Shared Thread Page
648
+
649
+ Shared threads are viewable at `/shared/:shareId`. The page displays:
650
+ - Thread title and messages (read-only)
651
+ - App branding with link to sign up
652
+ - Appropriate error messages for expired or inaccessible links
653
+
654
+ ### Team Scope Behavior
655
+
656
+ When `scope: 'team'`:
657
+ - Viewers must be authenticated
658
+ - Viewers must share at least one team with the thread owner
659
+ - Unauthenticated users see "Please sign in to view this shared conversation"
660
+ - Users without team access see "You don't have access to this conversation"
661
+
662
+ ## Team Workspaces
663
+
664
+ Team workspaces allow users to collaborate on conversations within shared team contexts.
665
+
666
+ ### Configuration
667
+
668
+ ```typescript
669
+ teams: {
670
+ enabled: true, // Set to false to disable team workspaces (personal only)
671
+ }
672
+ ```
673
+
674
+ ### Enabling/Disabling Teams
675
+
676
+ | Setting | Behavior |
677
+ |---------|----------|
678
+ | `enabled: true` | Team selector shown in sidebar, team settings accessible, team threads supported |
679
+ | `enabled: false` | Team features completely hidden, API endpoints blocked, personal workspaces only |
680
+
681
+ When teams are disabled:
682
+ - Team selector is hidden from the sidebar
683
+ - Team settings page redirects to home
684
+ - All `/api/teams/*` endpoints return 403 Forbidden
685
+ - `teamId` parameter is ignored in chat requests
686
+ - Team context is not sent to the AI agent
687
+ - Existing team data is preserved (can re-enable later)
688
+
689
+ ### Team Features
690
+
691
+ **Team Selector**: Users can switch between personal workspace and team workspaces in the sidebar.
692
+
693
+ **Team Roles**:
694
+
695
+ | Role | Permissions |
696
+ |------|-------------|
697
+ | `owner` | Full control, can archive team, manage all members |
698
+ | `admin` | Can invite/remove members, edit team settings, create threads |
699
+ | `member` | Can create and participate in team threads |
700
+ | `viewer` | Can view team threads (read-only) |
701
+
702
+ **Team Context**: Admins and owners can set team-wide context that is automatically included in all team conversations. This is useful for:
703
+ - Project guidelines and coding standards
704
+ - Company policies or preferences
705
+ - Domain-specific knowledge
706
+ - Team conventions
707
+
708
+ The team context is combined with user context when sent to the AI:
709
+
710
+ ```
711
+ Team context:
712
+ <team context here>
713
+
714
+ User context:
715
+ <user context here>
716
+ ```
717
+
718
+ ### URL-Based Team Selection
719
+
720
+ Team selection is persisted via URL query parameter (`?team=<teamId>`), enabling:
721
+ - Bookmarkable team-specific URLs
722
+ - Shareable links that open in the correct team context
723
+ - Persistence across page reloads
724
+
725
+ Priority: URL parameter > localStorage
726
+
727
+ ### Team Settings Page
728
+
729
+ Accessible at `/team/:teamId/settings` for team members. Features include:
730
+ - **Team Name**: Editable by admins and owners
731
+ - **Team Context**: AI context editable by admins and owners
732
+ - **Invite Members**: Send email invitations (admins and owners)
733
+ - **Manage Members**: Update roles, remove members (admins and owners)
734
+ - **Danger Zone**: Archive team (owner) or leave team (members)
735
+
736
+ ### API Endpoints
737
+
738
+ | Method | Endpoint | Description | Required Role |
739
+ |--------|----------|-------------|---------------|
740
+ | `GET` | `/api/teams` | List user's teams | Authenticated |
741
+ | `POST` | `/api/teams` | Create a new team | Authenticated |
742
+ | `GET` | `/api/teams/:teamId` | Get team details | Team member |
743
+ | `PATCH` | `/api/teams/:teamId` | Update team name/context | Admin |
744
+ | `POST` | `/api/teams/:teamId/archive` | Archive team | Owner |
745
+ | `POST` | `/api/teams/:teamId/invite` | Invite a member | Admin |
746
+ | `DELETE` | `/api/teams/:teamId/invite/:inviteId` | Cancel invite | Admin |
747
+ | `POST` | `/api/teams/:teamId/leave` | Leave team | Member (not owner) |
748
+ | `DELETE` | `/api/teams/:teamId/members/:userId` | Remove member | Admin |
749
+ | `PATCH` | `/api/teams/:teamId/members/:userId` | Update member role | Owner |
750
+ | `POST` | `/api/teams/accept-invite/:token` | Accept invitation | Authenticated |
751
+
752
+ ### Database Schema
753
+
754
+ Teams are stored with the following structure:
755
+
756
+ ```prisma
757
+ model Team {
758
+ id String @id @default(cuid())
759
+ name String
760
+ context String? // AI context for team conversations
761
+ archivedAt DateTime? // null = active, set = archived
762
+ members TeamMember[]
763
+ threads Thread[]
764
+ invites TeamInvite[]
765
+ createdAt DateTime @default(now())
766
+ updatedAt DateTime @updatedAt
767
+ }
768
+
769
+ model TeamMember {
770
+ id String @id @default(cuid())
771
+ teamId String
772
+ userId String
773
+ role String // 'owner' | 'admin' | 'member' | 'viewer'
774
+ team Team @relation(...)
775
+ user User @relation(...)
776
+ createdAt DateTime @default(now())
777
+ }
778
+ ```
779
+
780
+ ## Projects
781
+
782
+ Projects allow users to organize conversations into folders with shared AI context. Projects can be personal or team-based, with configurable sharing settings.
783
+
784
+ ### Configuration
785
+
786
+ ```typescript
787
+ projects: {
788
+ enabled: true, // Set to false to disable projects feature
789
+ colors: [ // Preset colors for project folders
790
+ '#ef4444', // red
791
+ '#f97316', // orange
792
+ '#eab308', // yellow
793
+ '#22c55e', // green
794
+ '#14b8a6', // teal
795
+ '#3b82f6', // blue
796
+ '#8b5cf6', // purple
797
+ '#ec4899', // pink
798
+ ],
799
+ }
800
+ ```
801
+
802
+ ### Enabling/Disabling Projects
803
+
804
+ | Setting | Behavior |
805
+ |---------|----------|
806
+ | `enabled: true` | Project folders shown in sidebar, create/edit project buttons visible |
807
+ | `enabled: false` | Project features completely hidden, API endpoints blocked, threads have no project association |
808
+
809
+ When projects are disabled:
810
+ - Project folders are hidden from the sidebar
811
+ - "New Project" button is hidden
812
+ - All `/api/projects/*` endpoints return 403 Forbidden
813
+ - `projectId` parameter is ignored in thread creation
814
+ - Project context is not sent to the AI agent
815
+ - Existing project data is preserved (can re-enable later)
816
+
817
+ ### Project Features
818
+
819
+ **Project Folders**: Display in the sidebar with collapsible thread lists. Each project shows a colored folder icon and thread count.
820
+
821
+ **Project Context**: Each project can have AI context that is automatically included in all conversations within the project. This is combined with team and user context in the following order:
822
+
823
+ ```
824
+ Team context:
825
+ <team context here>
826
+
827
+ Project context:
828
+ <project context here>
829
+
830
+ User context:
831
+ <user context here>
832
+ ```
833
+
834
+ **Project Colors**: Projects are assigned a color from the configured preset list, displayed as a colored folder icon.
835
+
836
+ ### Project Sharing
837
+
838
+ Projects can be personal (private) or team-based with configurable sharing:
839
+
840
+ | Sharing | Description |
841
+ |---------|-------------|
842
+ | `private` | Only the project creator can see the project and its threads |
843
+ | `team` | All team members can see and contribute to the project |
844
+
845
+ Personal projects (no team association) are always private to the creator.
846
+
847
+ ### Project Hierarchy
848
+
849
+ - **Personal Projects**: Created without a team, visible only to the creator
850
+ - **Team Projects**: Created within a team context, can be private or team-shared
851
+ - **Thread Assignment**: Threads belong to exactly one project (or no project). Threads cannot be moved between projects after creation.
852
+
853
+ ### Project Archiving
854
+
855
+ When a project is archived:
856
+ - The project is hidden from the sidebar
857
+ - All threads within the project are also archived
858
+ - Archived data is preserved (can be restored if needed via database)
859
+
860
+ ### Permissions
861
+
862
+ | Action | Personal Project | Team Project (Private) | Team Project (Team-shared) |
863
+ |--------|-----------------|----------------------|---------------------------|
864
+ | View | Creator only | Creator only | All team members |
865
+ | Create threads | Creator | Creator | Team members (except viewers) |
866
+ | Edit project | Creator | Creator | Owner/Admin |
867
+ | Archive project | Creator | Creator | Owner/Admin |
868
+
869
+ ### API Endpoints
870
+
871
+ | Method | Endpoint | Description |
872
+ |--------|----------|-------------|
873
+ | `GET` | `/api/projects` | List user's accessible projects |
874
+ | `GET` | `/api/projects?teamId=<id>` | List projects for a specific team |
875
+ | `POST` | `/api/projects` | Create a new project |
876
+ | `GET` | `/api/projects/:projectId` | Get project details |
877
+ | `PATCH` | `/api/projects/:projectId` | Update project name/context/sharing |
878
+ | `POST` | `/api/projects/:projectId/archive` | Archive project and its threads |
879
+
880
+ ### Database Schema
881
+
882
+ Projects are stored with the following structure:
883
+
884
+ ```prisma
885
+ model Project {
886
+ id String @id @default(cuid())
887
+ name String
888
+ context String? // AI context for project threads
889
+ color String // Hex color from preset list
890
+ sharing String @default("private") // 'private' | 'team'
891
+ userId String // Creator
892
+ teamId String? // Optional team association
893
+ threads Thread[]
894
+ archivedAt DateTime? // null = active, set = archived
895
+ createdAt DateTime @default(now())
896
+ updatedAt DateTime @updatedAt
897
+ }
898
+
899
+ model Thread {
900
+ id String @id @default(cuid())
901
+ title String
902
+ projectId String? // Optional project association
903
+ project Project? @relation(...)
904
+ archivedAt DateTime? // null = active, set = archived
905
+ // ... other fields
906
+ }
907
+ ```
908
+
909
+ ### User Interface
910
+
911
+ **Sidebar Behavior**:
912
+ - Project folders are collapsible - click to expand/collapse
913
+ - Threads within projects are displayed nested under the folder
914
+ - The currently viewed thread is highlighted with a subtle background
915
+ - Threads without a project appear in an "Other Threads" section
916
+
917
+ **Project Context Bar**:
918
+ When creating a new chat within a project or viewing a thread that belongs to a project, a context bar appears at the top of the chat pane showing:
919
+ - The project's colored folder icon
920
+ - The project name
921
+ - For new chats: "New chat will be added to this project"
922
+
923
+ **Thread-Driven Selection**:
924
+ - Viewing a thread automatically updates the project context to match the thread's project
925
+ - Clicking the main "New Chat" button clears any project selection
926
+ - Clicking the "+" button on a project folder creates a new chat within that project
927
+
928
+ ---
929
+
930
+ ## Documents
931
+
932
+ Mentionable documents allow users to upload and reference content in chat using @-mentions.
933
+
934
+ ### Configuration
935
+
936
+ ```typescript
937
+ documents: {
938
+ enabled: true,
939
+ storage: {
940
+ provider: 'database', // 'database' | 'filesystem' | 's3'
941
+ // filesystem: { basePath: './uploads/documents' },
942
+ // s3: { bucket: 'my-bucket', region: 'us-east-1' },
943
+ },
944
+ maxFileSizeMB: 10,
945
+ hybridThreshold: 1000, // Documents under this char count are injected into context
946
+ acceptedTypes: [
947
+ 'text/plain',
948
+ 'text/markdown',
949
+ 'text/x-markdown',
950
+ 'text/csv',
951
+ 'application/json',
952
+ ],
953
+ }
954
+ ```
955
+
956
+ ### Key Features
957
+
958
+ - **Scoped documents**: Personal (`@my/`), team (`@team/slug/`), project (`@project/slug/`)
959
+ - **Hybrid access**: Small docs injected into context, large docs accessed via AI tools
960
+ - **File attachments**: Chat attachments automatically upload as documents with @-mentions
961
+ - **AI tools**: `list_documents`, `read_document`, `search_in_document`, `save_document`
962
+
963
+ See [Mentionable Documents](./documents.md) for full documentation.
964
+
965
+ ---
966
+
967
+ ## Slack Integration
968
+
969
+ Connect your team's Slack workspace to chat with the AI assistant via @mentions.
970
+
971
+ ### Configuration
972
+
973
+ ```typescript
974
+ slack: {
975
+ enabled: true,
976
+ clientIdEnvVar: 'SLACK_CLIENT_ID',
977
+ clientSecretEnvVar: 'SLACK_CLIENT_SECRET',
978
+ signingSecretEnvVar: 'SLACK_SIGNING_SECRET',
979
+ internalSecretEnvVar: 'SLACK_INTERNAL_SECRET',
980
+
981
+ // Optional: Restrict to specific plans
982
+ allowedPlans: ['pro', 'enterprise'],
983
+
984
+ aiChat: {
985
+ enabled: true,
986
+ threadContinuity: true, // Maintain context across Slack thread replies
987
+ },
988
+
989
+ notifications: {
990
+ events: [
991
+ { event: 'thread_shared', enabled: true },
992
+ { event: 'message_liked', enabled: true },
993
+ { event: 'team_member_joined', enabled: true },
994
+ ],
995
+ },
996
+ }
997
+ ```
998
+
999
+ ### Environment Variables
1000
+
1001
+ | Variable | Description |
1002
+ |----------|-------------|
1003
+ | `SLACK_CLIENT_ID` | OAuth Client ID from your Slack app |
1004
+ | `SLACK_CLIENT_SECRET` | OAuth Client Secret from your Slack app |
1005
+ | `SLACK_SIGNING_SECRET` | Signing secret for request verification |
1006
+ | `SLACK_INTERNAL_SECRET` | Random secret for internal endpoint auth |
1007
+
1008
+ ### Key Features
1009
+
1010
+ - **AI Chat via @mentions**: Team members mention the bot in Slack to get AI responses
1011
+ - **Thread Continuity**: Follow-up messages in a Slack thread maintain conversation context
1012
+ - **Team Notifications**: Get notified when threads are shared, messages are liked, or members join
1013
+ - **Per-Team Connection**: Each team connects their own Slack workspace
1014
+
1015
+ See [Slack Integration](./slack.md) for setup instructions and full documentation.
1016
+
1017
+ ---
1018
+
1019
+ ## Email
1020
+
1021
+ Transactional email support for email verification, team invitations, and notifications.
1022
+
1023
+ ### Configuration
1024
+
1025
+ ```typescript
1026
+ email: {
1027
+ enabled: true,
1028
+ providerConfig: {
1029
+ type: 'ses',
1030
+ region: 'us-east-1',
1031
+ },
1032
+ fromAddress: 'noreply@example.com',
1033
+ fromName: 'My App',
1034
+ }
1035
+ ```
1036
+
1037
+ ### AWS Credentials
1038
+
1039
+ The SES provider uses the AWS SDK's default credential chain, which automatically checks (in order):
1040
+
1041
+ 1. **Environment variables** - `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
1042
+ 2. **Shared credentials file** - `~/.aws/credentials`
1043
+ 3. **ECS container credentials** - Task IAM role
1044
+ 4. **EC2 instance metadata** - Instance IAM role
1045
+ 5. **Web identity token** - For EKS pods
1046
+
1047
+ **For local development**, set environment variables in `.env`:
1048
+ ```
1049
+ AWS_ACCESS_KEY_ID=your-access-key
1050
+ AWS_SECRET_ACCESS_KEY=your-secret-key
1051
+ ```
1052
+
1053
+ **For production on AWS**, use IAM roles (recommended):
1054
+ - EC2: Attach an IAM role with SES permissions to your instance
1055
+ - ECS: Configure a task IAM role with SES permissions
1056
+ - Lambda: The execution role needs SES permissions
1057
+
1058
+ No explicit credentials are needed when using IAM roles - the SDK discovers them automatically.
1059
+
1060
+ ### Supported Providers
1061
+
1062
+ Currently supported:
1063
+ - **SES** (Amazon Simple Email Service)
1064
+
1065
+ Future providers (not yet implemented):
1066
+ - Resend
1067
+ - SendGrid
1068
+ - Postmark
1069
+
1070
+ ### Email Features
1071
+
1072
+ When email is configured, the following features are available:
1073
+
1074
+ | Feature | Description |
1075
+ |---------|-------------|
1076
+ | **Email Verification** | 6-digit codes sent to verify new user emails |
1077
+ | **Team Invitations** | Invitation emails when users are invited to teams |
1078
+ | **Magic Links** | Login links sent via email (existing feature) |
1079
+
1080
+ ### Graceful Degradation
1081
+
1082
+ Email features gracefully handle the case where email is not configured:
1083
+ - **Email Verification**: Users are auto-verified on registration
1084
+ - **Team Invitations**: Invite URL is returned but no email sent
1085
+ - **Magic Links**: Link is logged to console in development
1086
+
1087
+ This allows you to develop locally without email setup and add it when deploying.
1088
+
1089
+ ### Testing Email
1090
+
1091
+ In development, when email is not configured, verification codes and invitation URLs are logged to the console:
1092
+
1093
+ ```
1094
+ [Auth] Email disabled - verification code for user@example.com: 123456
1095
+ [Teams] Email disabled - invitation URL for user@example.com: http://localhost:5173/invite/abc123
1096
+ ```
1097
+
1098
+ ### API Endpoints
1099
+
1100
+ | Method | Endpoint | Description |
1101
+ |--------|----------|-------------|
1102
+ | `POST` | `/api/auth/verify-email` | Verify email with 6-digit code |
1103
+ | `POST` | `/api/auth/resend-verification` | Resend verification email |
1104
+
1105
+ ### Database Schema
1106
+
1107
+ ```prisma
1108
+ model EmailVerification {
1109
+ id String @id @default(cuid())
1110
+ code String // Hashed 6-digit code
1111
+ userId String
1112
+ user User @relation(...)
1113
+ expiresAt DateTime
1114
+ usedAt DateTime?
1115
+ attempts Int @default(0) // Brute force protection
1116
+ createdAt DateTime @default(now())
1117
+ }
1118
+ ```
1119
+
1120
+ ---
1121
+
1122
+ ## Job Queue
1123
+
1124
+ Background job processing for async tasks, scheduled jobs, and recurring workflows.
1125
+
1126
+ ### Configuration
1127
+
1128
+ ```typescript
1129
+ queue: {
1130
+ enabled: true,
1131
+
1132
+ // Provider: 'memory' for dev, 'sqs' for production
1133
+ providerConfig: {
1134
+ type: 'memory',
1135
+ maxHistorySize: 1000,
1136
+ },
1137
+ // Or for production:
1138
+ // providerConfig: {
1139
+ // type: 'sqs',
1140
+ // region: 'us-east-1',
1141
+ // queueUrl: process.env.SQS_QUEUE_URL!,
1142
+ // deadLetterQueueUrl: process.env.SQS_DLQ_URL,
1143
+ // visibilityTimeout: 60,
1144
+ // },
1145
+
1146
+ worker: {
1147
+ mode: 'in-process', // 'in-process' | 'standalone'
1148
+ concurrency: 5,
1149
+ pollInterval: 1000,
1150
+ shutdownTimeout: 30000,
1151
+ },
1152
+
1153
+ scheduler: {
1154
+ enabled: true,
1155
+ pollInterval: 60000,
1156
+ },
1157
+ }
1158
+ ```
1159
+
1160
+ ### Configuration Options
1161
+
1162
+ | Option | Type | Default | Description |
1163
+ |--------|------|---------|-------------|
1164
+ | `enabled` | boolean | `false` | Enable the queue system |
1165
+ | `providerConfig.type` | `'memory'` \| `'sqs'` | - | Queue backend |
1166
+ | `worker.mode` | `'in-process'` \| `'standalone'` | `'in-process'` | Run workers in server process or separately |
1167
+ | `worker.concurrency` | number | `5` | Concurrent jobs per worker |
1168
+ | `scheduler.enabled` | boolean | `false` | Enable database-backed job scheduling |
1169
+
1170
+ See [Job Queue](./queue.md) for full documentation on handlers, scheduling, and production deployment.
1171
+
1172
+ ---
1173
+
1174
+ ## Scheduled Prompts (Automations)
1175
+
1176
+ Run AI prompts automatically on a schedule with notifications.
1177
+
1178
+ ### Configuration
1179
+
1180
+ ```typescript
1181
+ scheduledPrompts: {
1182
+ enabled: true,
1183
+ featureName: 'Automations', // Display name in UI
1184
+ allowUserPrompts: true, // Personal automations
1185
+ allowTeamPrompts: true, // Team automations
1186
+ defaultTimezone: 'UTC',
1187
+
1188
+ // Plan-based limits
1189
+ planLimits: [
1190
+ { plan: 'free', maxUserPrompts: 1, maxTeamPrompts: 0 },
1191
+ { plan: 'pro', maxUserPrompts: 5, maxTeamPrompts: 10 },
1192
+ { plan: 'enterprise', maxUserPrompts: 20, maxTeamPrompts: 50 },
1193
+ ],
1194
+ defaultMaxUserPrompts: 0, // Fallback for unlisted plans
1195
+ defaultMaxTeamPrompts: 0,
1196
+ }
1197
+ ```
1198
+
1199
+ ### Configuration Options
1200
+
1201
+ | Option | Type | Default | Description |
1202
+ |--------|------|---------|-------------|
1203
+ | `enabled` | boolean | `false` | Enable scheduled prompts |
1204
+ | `featureName` | string | `"Scheduled Prompts"` | Display name in sidebar |
1205
+ | `allowUserPrompts` | boolean | `true` | Allow personal automations |
1206
+ | `allowTeamPrompts` | boolean | `true` | Allow team automations |
1207
+ | `defaultTimezone` | string | `"UTC"` | Default timezone for new prompts |
1208
+ | `planLimits` | array | `[]` | Limits per subscription plan |
1209
+
1210
+ **Note:** Scheduled prompts require the [Job Queue](#job-queue) to be enabled.
1211
+
1212
+ See [Scheduled Prompts](./scheduled-prompts.md) for full documentation on creating automations and notifications.