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.
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add-infra.d.ts +6 -0
- package/dist/commands/add-infra.d.ts.map +1 -0
- package/dist/commands/add-infra.js +160 -0
- package/dist/commands/add-infra.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +63 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/db-sync.d.ts +13 -0
- package/dist/commands/db-sync.d.ts.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +61 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +214 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/.env.example +24 -0
- package/dist/templates/README.md +81 -0
- package/dist/templates/app/components/AcceptInviteClient.tsx +10 -0
- package/dist/templates/app/components/AdminDashboardClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamsClient.tsx +10 -0
- package/dist/templates/app/components/AdminUsersClient.tsx +10 -0
- package/dist/templates/app/components/ApiKeysClient.tsx +10 -0
- package/dist/templates/app/components/AutomationsClient.tsx +10 -0
- package/dist/templates/app/components/ChatClient.tsx +13 -0
- package/dist/templates/app/components/ClientOnly.tsx +6 -0
- package/dist/templates/app/components/DocumentsClient.tsx +10 -0
- package/dist/templates/app/components/OAuthConsentClient.tsx +10 -0
- package/dist/templates/app/components/PricingClient.tsx +10 -0
- package/dist/templates/app/components/TeamSettingsClient.tsx +10 -0
- package/dist/templates/app/components/VerifyEmailClient.tsx +10 -0
- package/dist/templates/app/entry.client.tsx +12 -0
- package/dist/templates/app/entry.server.tsx +67 -0
- package/dist/templates/app/root.tsx +91 -0
- package/dist/templates/app/routes/_index.tsx +82 -0
- package/dist/templates/app/routes/admin._index.tsx +57 -0
- package/dist/templates/app/routes/admin.teams.$teamId.tsx +57 -0
- package/dist/templates/app/routes/admin.teams._index.tsx +57 -0
- package/dist/templates/app/routes/admin.users.tsx +57 -0
- package/dist/templates/app/routes/api-keys.tsx +57 -0
- package/dist/templates/app/routes/automations.tsx +57 -0
- package/dist/templates/app/routes/chat._index.tsx +11 -0
- package/dist/templates/app/routes/chat.admin._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams.$teamId.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.users.tsx +10 -0
- package/dist/templates/app/routes/chat.api-keys.tsx +10 -0
- package/dist/templates/app/routes/chat.automations.tsx +10 -0
- package/dist/templates/app/routes/chat.documents.tsx +10 -0
- package/dist/templates/app/routes/chat.team.$teamId.settings.tsx +10 -0
- package/dist/templates/app/routes/chat.thread.$threadId.tsx +11 -0
- package/dist/templates/app/routes/chat.tsx +39 -0
- package/dist/templates/app/routes/documents.tsx +57 -0
- package/dist/templates/app/routes/invite.$token.tsx +10 -0
- package/dist/templates/app/routes/login.tsx +334 -0
- package/dist/templates/app/routes/oauth.consent.tsx +10 -0
- package/dist/templates/app/routes/pricing.tsx +10 -0
- package/dist/templates/app/routes/privacy.tsx +197 -0
- package/dist/templates/app/routes/register.tsx +398 -0
- package/dist/templates/app/routes/shared.$shareId.tsx +226 -0
- package/dist/templates/app/routes/team.$teamId.settings.tsx +57 -0
- package/dist/templates/app/routes/terms.tsx +173 -0
- package/dist/templates/app/routes/thread.$threadId.tsx +102 -0
- package/dist/templates/app/routes/verify-email.tsx +10 -0
- package/dist/templates/app/routes.ts +47 -0
- package/dist/templates/config/app.config.ts +216 -0
- package/dist/templates/docs/admin.md +257 -0
- package/dist/templates/docs/api-keys.md +403 -0
- package/dist/templates/docs/authentication.md +247 -0
- package/dist/templates/docs/configuration.md +1212 -0
- package/dist/templates/docs/custom-pages.md +466 -0
- package/dist/templates/docs/deployment.md +362 -0
- package/dist/templates/docs/development.md +411 -0
- package/dist/templates/docs/documents.md +293 -0
- package/dist/templates/docs/extensions.md +639 -0
- package/dist/templates/docs/index.md +139 -0
- package/dist/templates/docs/installation.md +286 -0
- package/dist/templates/docs/mcp.md +952 -0
- package/dist/templates/docs/native-tools.md +688 -0
- package/dist/templates/docs/queue.md +514 -0
- package/dist/templates/docs/scheduled-prompts.md +279 -0
- package/dist/templates/docs/settings.md +415 -0
- package/dist/templates/docs/slack.md +318 -0
- package/dist/templates/docs/styling.md +288 -0
- package/dist/templates/extensions/agents/.gitkeep +0 -0
- package/dist/templates/extensions/pages/.gitkeep +0 -0
- package/dist/templates/extensions/payment-plans/.gitkeep +0 -0
- package/dist/templates/index.html +16 -0
- package/dist/templates/infra-aws/.github/workflows/deploy.yml +95 -0
- package/dist/templates/infra-aws/README.md +207 -0
- package/dist/templates/infra-aws/bin/cdk.ts +18 -0
- package/dist/templates/infra-aws/cdk.json +43 -0
- package/dist/templates/infra-aws/config/deployment.ts +156 -0
- package/dist/templates/infra-aws/lib/chaaskit-stack.ts +419 -0
- package/dist/templates/infra-aws/package.json +27 -0
- package/dist/templates/infra-aws/scripts/build-app.sh +63 -0
- package/dist/templates/infra-aws/tsconfig.json +25 -0
- package/dist/templates/package.json +46 -0
- package/dist/templates/prisma/schema/base.prisma +584 -0
- package/dist/templates/prisma/schema/custom.prisma +24 -0
- package/dist/templates/prisma/schema.prisma +271 -0
- package/dist/templates/public/favicon.svg +4 -0
- package/dist/templates/public/logo.svg +4 -0
- package/dist/templates/react-router.config.ts +11 -0
- package/dist/templates/server.js +52 -0
- package/dist/templates/src/main.tsx +8 -0
- package/dist/templates/tsconfig.json +26 -0
- package/dist/templates/vite.config.ts +26 -0
- package/package.json +46 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Route } from './+types/documents';
|
|
2
|
+
import { lazy, Suspense } from 'react';
|
|
3
|
+
import { ClientOnly } from '../components/ClientOnly';
|
|
4
|
+
|
|
5
|
+
const DocumentsClient = lazy(() => import('../components/DocumentsClient'));
|
|
6
|
+
|
|
7
|
+
export function meta({}: Route.MetaArgs) {
|
|
8
|
+
return [{ title: 'Documents' }];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function links() {
|
|
12
|
+
return [{ rel: 'stylesheet', href: '/node_modules/@chaaskit/client/dist/lib/styles.css' }];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default function Documents() {
|
|
16
|
+
return (
|
|
17
|
+
<ClientOnly fallback={<LoadingSkeleton />}>
|
|
18
|
+
{() => (
|
|
19
|
+
<Suspense fallback={<LoadingSkeleton />}>
|
|
20
|
+
<DocumentsClient />
|
|
21
|
+
</Suspense>
|
|
22
|
+
)}
|
|
23
|
+
</ClientOnly>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function LoadingSkeleton() {
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
style={{
|
|
31
|
+
display: 'flex',
|
|
32
|
+
height: '100vh',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
width: '2rem',
|
|
41
|
+
height: '2rem',
|
|
42
|
+
border: '2px solid rgb(var(--color-primary))',
|
|
43
|
+
borderTopColor: 'transparent',
|
|
44
|
+
borderRadius: '50%',
|
|
45
|
+
animation: 'spin 1s linear infinite',
|
|
46
|
+
}}
|
|
47
|
+
/>
|
|
48
|
+
<style>
|
|
49
|
+
{`
|
|
50
|
+
@keyframes spin {
|
|
51
|
+
to { transform: rotate(360deg); }
|
|
52
|
+
}
|
|
53
|
+
`}
|
|
54
|
+
</style>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRoute } from '@chaaskit/client/ssr-utils';
|
|
2
|
+
|
|
3
|
+
const route = createRoute({
|
|
4
|
+
title: 'Accept Invitation',
|
|
5
|
+
load: () => import('@chaaskit/client/routes/AcceptInviteRoute'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const meta = route.meta;
|
|
9
|
+
export const links = route.links;
|
|
10
|
+
export default route.default;
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { Form, redirect, useNavigation } from 'react-router';
|
|
2
|
+
import type { Route } from './+types/login';
|
|
3
|
+
import { config } from '../../config/app.config';
|
|
4
|
+
|
|
5
|
+
export async function loader({}: Route.LoaderArgs) {
|
|
6
|
+
return { config };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function action({ request }: Route.ActionArgs) {
|
|
10
|
+
const formData = await request.formData();
|
|
11
|
+
const email = formData.get('email') as string;
|
|
12
|
+
const password = formData.get('password') as string;
|
|
13
|
+
|
|
14
|
+
const apiUrl = process.env.API_URL || 'http://localhost:3000';
|
|
15
|
+
const res = await fetch(`${apiUrl}/api/auth/login`, {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: { 'Content-Type': 'application/json' },
|
|
18
|
+
body: JSON.stringify({ email, password }),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
// Try to parse JSON, fallback to text for rate limit errors etc.
|
|
23
|
+
let errorMessage = 'Login failed';
|
|
24
|
+
const contentType = res.headers.get('content-type');
|
|
25
|
+
if (contentType?.includes('application/json')) {
|
|
26
|
+
try {
|
|
27
|
+
const data = await res.json();
|
|
28
|
+
// Handle both {error: "string"} and {error: {message: "string"}} formats
|
|
29
|
+
errorMessage = typeof data.error === 'string'
|
|
30
|
+
? data.error
|
|
31
|
+
: data.error?.message || data.message || 'Login failed';
|
|
32
|
+
} catch {
|
|
33
|
+
errorMessage = await res.text() || 'Login failed';
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
errorMessage = await res.text() || 'Login failed';
|
|
37
|
+
}
|
|
38
|
+
return { error: errorMessage };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get redirect URL from query params or default to /chat
|
|
42
|
+
const url = new URL(request.url);
|
|
43
|
+
const redirectTo = url.searchParams.get('redirect') || '/chat';
|
|
44
|
+
|
|
45
|
+
// Forward the session cookie from the API response
|
|
46
|
+
const setCookie = res.headers.get('set-cookie');
|
|
47
|
+
|
|
48
|
+
return redirect(redirectTo, {
|
|
49
|
+
headers: setCookie ? { 'Set-Cookie': setCookie } : {},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function meta({}: Route.MetaArgs) {
|
|
54
|
+
return [{ title: `Sign In - ${config.app.name}` }];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default function Login({
|
|
58
|
+
loaderData,
|
|
59
|
+
actionData,
|
|
60
|
+
}: Route.ComponentProps) {
|
|
61
|
+
const { config } = loaderData;
|
|
62
|
+
const navigation = useNavigation();
|
|
63
|
+
const isSubmitting = navigation.state === 'submitting';
|
|
64
|
+
|
|
65
|
+
const hasGoogle = config.auth?.methods?.includes('google') ?? false;
|
|
66
|
+
const hasGitHub = config.auth?.methods?.includes('github') ?? false;
|
|
67
|
+
const hasEmailPassword = config.auth?.methods?.includes('email-password') ?? true;
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div
|
|
71
|
+
style={{
|
|
72
|
+
display: 'flex',
|
|
73
|
+
minHeight: '100vh',
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
justifyContent: 'center',
|
|
76
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
77
|
+
padding: '1rem',
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<div style={{ width: '100%', maxWidth: '28rem' }}>
|
|
81
|
+
<div style={{ marginBottom: '2rem', textAlign: 'center' }}>
|
|
82
|
+
{config.ui?.logo && (
|
|
83
|
+
<img
|
|
84
|
+
src={
|
|
85
|
+
typeof config.ui.logo === 'string'
|
|
86
|
+
? config.ui.logo
|
|
87
|
+
: config.ui.logo.light
|
|
88
|
+
}
|
|
89
|
+
alt={config.app.name}
|
|
90
|
+
style={{
|
|
91
|
+
height: '4rem',
|
|
92
|
+
width: '4rem',
|
|
93
|
+
marginLeft: 'auto',
|
|
94
|
+
marginRight: 'auto',
|
|
95
|
+
marginBottom: '1rem',
|
|
96
|
+
borderRadius: '0.5rem',
|
|
97
|
+
objectFit: 'contain',
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
)}
|
|
101
|
+
<h1
|
|
102
|
+
style={{
|
|
103
|
+
fontSize: '1.875rem',
|
|
104
|
+
fontWeight: 'bold',
|
|
105
|
+
color: 'rgb(var(--color-text-primary))',
|
|
106
|
+
margin: 0,
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
Welcome back
|
|
110
|
+
</h1>
|
|
111
|
+
<p
|
|
112
|
+
style={{
|
|
113
|
+
marginTop: '0.5rem',
|
|
114
|
+
color: 'rgb(var(--color-text-secondary))',
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
Sign in to {config.app.name}
|
|
118
|
+
</p>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{/* OAuth buttons */}
|
|
122
|
+
{(hasGoogle || hasGitHub) && (
|
|
123
|
+
<div
|
|
124
|
+
style={{
|
|
125
|
+
marginBottom: '1.5rem',
|
|
126
|
+
display: 'flex',
|
|
127
|
+
flexDirection: 'column',
|
|
128
|
+
gap: '0.75rem',
|
|
129
|
+
}}
|
|
130
|
+
>
|
|
131
|
+
{hasGoogle && (
|
|
132
|
+
<a
|
|
133
|
+
href="/api/auth/oauth/google"
|
|
134
|
+
style={{
|
|
135
|
+
display: 'flex',
|
|
136
|
+
width: '100%',
|
|
137
|
+
alignItems: 'center',
|
|
138
|
+
justifyContent: 'center',
|
|
139
|
+
gap: '0.5rem',
|
|
140
|
+
borderRadius: '0.5rem',
|
|
141
|
+
border: '1px solid rgb(var(--color-border))',
|
|
142
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
143
|
+
padding: '0.5rem 1rem',
|
|
144
|
+
color: 'rgb(var(--color-text-primary))',
|
|
145
|
+
textDecoration: 'none',
|
|
146
|
+
}}
|
|
147
|
+
>
|
|
148
|
+
Continue with Google
|
|
149
|
+
</a>
|
|
150
|
+
)}
|
|
151
|
+
{hasGitHub && (
|
|
152
|
+
<a
|
|
153
|
+
href="/api/auth/oauth/github"
|
|
154
|
+
style={{
|
|
155
|
+
display: 'flex',
|
|
156
|
+
width: '100%',
|
|
157
|
+
alignItems: 'center',
|
|
158
|
+
justifyContent: 'center',
|
|
159
|
+
gap: '0.5rem',
|
|
160
|
+
borderRadius: '0.5rem',
|
|
161
|
+
border: '1px solid rgb(var(--color-border))',
|
|
162
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
163
|
+
padding: '0.5rem 1rem',
|
|
164
|
+
color: 'rgb(var(--color-text-primary))',
|
|
165
|
+
textDecoration: 'none',
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
Continue with GitHub
|
|
169
|
+
</a>
|
|
170
|
+
)}
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
173
|
+
|
|
174
|
+
{(hasGoogle || hasGitHub) && hasEmailPassword && (
|
|
175
|
+
<div style={{ position: 'relative', marginBottom: '1.5rem' }}>
|
|
176
|
+
<div
|
|
177
|
+
style={{
|
|
178
|
+
position: 'absolute',
|
|
179
|
+
inset: 0,
|
|
180
|
+
display: 'flex',
|
|
181
|
+
alignItems: 'center',
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
<div
|
|
185
|
+
style={{
|
|
186
|
+
width: '100%',
|
|
187
|
+
borderTop: '1px solid rgb(var(--color-border))',
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
</div>
|
|
191
|
+
<div
|
|
192
|
+
style={{
|
|
193
|
+
position: 'relative',
|
|
194
|
+
display: 'flex',
|
|
195
|
+
justifyContent: 'center',
|
|
196
|
+
fontSize: '0.875rem',
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
<span
|
|
200
|
+
style={{
|
|
201
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
202
|
+
padding: '0 0.5rem',
|
|
203
|
+
color: 'rgb(var(--color-text-muted))',
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
Or continue with email
|
|
207
|
+
</span>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
)}
|
|
211
|
+
|
|
212
|
+
{hasEmailPassword && (
|
|
213
|
+
<Form
|
|
214
|
+
method="post"
|
|
215
|
+
style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}
|
|
216
|
+
>
|
|
217
|
+
<div>
|
|
218
|
+
<label
|
|
219
|
+
htmlFor="email"
|
|
220
|
+
style={{
|
|
221
|
+
display: 'block',
|
|
222
|
+
fontSize: '0.875rem',
|
|
223
|
+
fontWeight: 500,
|
|
224
|
+
color: 'rgb(var(--color-text-primary))',
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
Email
|
|
228
|
+
</label>
|
|
229
|
+
<input
|
|
230
|
+
type="email"
|
|
231
|
+
id="email"
|
|
232
|
+
name="email"
|
|
233
|
+
required
|
|
234
|
+
style={{
|
|
235
|
+
marginTop: '0.25rem',
|
|
236
|
+
width: '100%',
|
|
237
|
+
borderRadius: '0.5rem',
|
|
238
|
+
border: '1px solid rgb(var(--color-input-border))',
|
|
239
|
+
backgroundColor: 'rgb(var(--color-input-background))',
|
|
240
|
+
padding: '0.5rem 1rem',
|
|
241
|
+
color: 'rgb(var(--color-text-primary))',
|
|
242
|
+
boxSizing: 'border-box',
|
|
243
|
+
}}
|
|
244
|
+
/>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<div>
|
|
248
|
+
<label
|
|
249
|
+
htmlFor="password"
|
|
250
|
+
style={{
|
|
251
|
+
display: 'block',
|
|
252
|
+
fontSize: '0.875rem',
|
|
253
|
+
fontWeight: 500,
|
|
254
|
+
color: 'rgb(var(--color-text-primary))',
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
Password
|
|
258
|
+
</label>
|
|
259
|
+
<input
|
|
260
|
+
type="password"
|
|
261
|
+
id="password"
|
|
262
|
+
name="password"
|
|
263
|
+
required
|
|
264
|
+
style={{
|
|
265
|
+
marginTop: '0.25rem',
|
|
266
|
+
width: '100%',
|
|
267
|
+
borderRadius: '0.5rem',
|
|
268
|
+
border: '1px solid rgb(var(--color-input-border))',
|
|
269
|
+
backgroundColor: 'rgb(var(--color-input-background))',
|
|
270
|
+
padding: '0.5rem 1rem',
|
|
271
|
+
color: 'rgb(var(--color-text-primary))',
|
|
272
|
+
boxSizing: 'border-box',
|
|
273
|
+
}}
|
|
274
|
+
/>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
{actionData?.error && (
|
|
278
|
+
<div
|
|
279
|
+
style={{
|
|
280
|
+
padding: '0.75rem',
|
|
281
|
+
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
|
282
|
+
borderRadius: '0.5rem',
|
|
283
|
+
color: 'rgb(239, 68, 68)',
|
|
284
|
+
fontSize: '0.875rem',
|
|
285
|
+
textAlign: 'center',
|
|
286
|
+
}}
|
|
287
|
+
>
|
|
288
|
+
{actionData.error}
|
|
289
|
+
</div>
|
|
290
|
+
)}
|
|
291
|
+
|
|
292
|
+
<button
|
|
293
|
+
type="submit"
|
|
294
|
+
disabled={isSubmitting}
|
|
295
|
+
style={{
|
|
296
|
+
width: '100%',
|
|
297
|
+
borderRadius: '0.5rem',
|
|
298
|
+
backgroundColor: 'rgb(var(--color-primary))',
|
|
299
|
+
padding: '0.5rem 1rem',
|
|
300
|
+
fontWeight: 500,
|
|
301
|
+
color: 'white',
|
|
302
|
+
border: 'none',
|
|
303
|
+
cursor: isSubmitting ? 'not-allowed' : 'pointer',
|
|
304
|
+
opacity: isSubmitting ? 0.7 : 1,
|
|
305
|
+
}}
|
|
306
|
+
>
|
|
307
|
+
{isSubmitting ? 'Signing in...' : 'Sign in'}
|
|
308
|
+
</button>
|
|
309
|
+
</Form>
|
|
310
|
+
)}
|
|
311
|
+
|
|
312
|
+
<p
|
|
313
|
+
style={{
|
|
314
|
+
marginTop: '1.5rem',
|
|
315
|
+
textAlign: 'center',
|
|
316
|
+
fontSize: '0.875rem',
|
|
317
|
+
color: 'rgb(var(--color-text-secondary))',
|
|
318
|
+
}}
|
|
319
|
+
>
|
|
320
|
+
Don't have an account?{' '}
|
|
321
|
+
<a
|
|
322
|
+
href="/register"
|
|
323
|
+
style={{
|
|
324
|
+
color: 'rgb(var(--color-primary))',
|
|
325
|
+
textDecoration: 'none',
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
328
|
+
Sign up
|
|
329
|
+
</a>
|
|
330
|
+
</p>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRoute } from '@chaaskit/client/ssr-utils';
|
|
2
|
+
|
|
3
|
+
const route = createRoute({
|
|
4
|
+
title: 'OAuth Consent',
|
|
5
|
+
load: () => import('@chaaskit/client/routes/OAuthConsentRoute'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const meta = route.meta;
|
|
9
|
+
export const links = route.links;
|
|
10
|
+
export default route.default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRoute } from '@chaaskit/client/ssr-utils';
|
|
2
|
+
|
|
3
|
+
const route = createRoute({
|
|
4
|
+
title: 'Pricing',
|
|
5
|
+
load: () => import('@chaaskit/client/routes/PricingRoute'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const meta = route.meta;
|
|
9
|
+
export const links = route.links;
|
|
10
|
+
export default route.default;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { Route } from './+types/privacy';
|
|
2
|
+
import { config } from '../../config/app.config';
|
|
3
|
+
|
|
4
|
+
export function meta({}: Route.MetaArgs) {
|
|
5
|
+
return [
|
|
6
|
+
{ title: `Privacy Policy - ${config.app.name}` },
|
|
7
|
+
{ name: 'description', content: `Privacy Policy for ${config.app.name}` },
|
|
8
|
+
];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function Privacy() {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
style={{
|
|
15
|
+
minHeight: '100vh',
|
|
16
|
+
backgroundColor: 'rgb(var(--color-background))',
|
|
17
|
+
padding: '2rem 1rem',
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
<div style={{ maxWidth: '48rem', marginLeft: 'auto', marginRight: 'auto' }}>
|
|
21
|
+
<div style={{ marginBottom: '2rem' }}>
|
|
22
|
+
<a
|
|
23
|
+
href="/"
|
|
24
|
+
style={{
|
|
25
|
+
fontSize: '0.875rem',
|
|
26
|
+
color: 'rgb(var(--color-primary))',
|
|
27
|
+
textDecoration: 'none',
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
← Back to {config.app.name}
|
|
31
|
+
</a>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<article>
|
|
35
|
+
<h1
|
|
36
|
+
style={{
|
|
37
|
+
fontSize: '2rem',
|
|
38
|
+
fontWeight: 'bold',
|
|
39
|
+
color: 'rgb(var(--color-text-primary))',
|
|
40
|
+
marginBottom: '1.5rem',
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
Privacy Policy
|
|
44
|
+
</h1>
|
|
45
|
+
|
|
46
|
+
<p
|
|
47
|
+
style={{
|
|
48
|
+
color: 'rgb(var(--color-text-muted))',
|
|
49
|
+
marginBottom: '2rem',
|
|
50
|
+
fontSize: '0.875rem',
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
Last updated:{' '}
|
|
54
|
+
{new Date().toLocaleDateString('en-US', {
|
|
55
|
+
year: 'numeric',
|
|
56
|
+
month: 'long',
|
|
57
|
+
day: 'numeric',
|
|
58
|
+
})}
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
<div
|
|
62
|
+
style={{
|
|
63
|
+
color: 'rgb(var(--color-text-secondary))',
|
|
64
|
+
lineHeight: 1.7,
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<Section title="Information We Collect">
|
|
68
|
+
<p>
|
|
69
|
+
We collect information you provide directly to us, such as when
|
|
70
|
+
you create an account, use our services, or contact us for
|
|
71
|
+
support.
|
|
72
|
+
</p>
|
|
73
|
+
<ul style={{ marginTop: '1rem', paddingLeft: '1.5rem' }}>
|
|
74
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
75
|
+
Account information (name, email address)
|
|
76
|
+
</li>
|
|
77
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
78
|
+
Chat conversations and messages
|
|
79
|
+
</li>
|
|
80
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
81
|
+
Usage data and preferences
|
|
82
|
+
</li>
|
|
83
|
+
</ul>
|
|
84
|
+
</Section>
|
|
85
|
+
|
|
86
|
+
<Section title="How We Use Your Information">
|
|
87
|
+
<p>We use the information we collect to:</p>
|
|
88
|
+
<ul style={{ marginTop: '1rem', paddingLeft: '1.5rem' }}>
|
|
89
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
90
|
+
Provide, maintain, and improve our services
|
|
91
|
+
</li>
|
|
92
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
93
|
+
Process your requests and respond to your inquiries
|
|
94
|
+
</li>
|
|
95
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
96
|
+
Send you technical notices and support messages
|
|
97
|
+
</li>
|
|
98
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
99
|
+
Detect, prevent, and address technical issues
|
|
100
|
+
</li>
|
|
101
|
+
</ul>
|
|
102
|
+
</Section>
|
|
103
|
+
|
|
104
|
+
<Section title="Data Security">
|
|
105
|
+
<p>
|
|
106
|
+
We implement appropriate security measures to protect your
|
|
107
|
+
personal information. However, no method of transmission over the
|
|
108
|
+
Internet or electronic storage is 100% secure.
|
|
109
|
+
</p>
|
|
110
|
+
</Section>
|
|
111
|
+
|
|
112
|
+
<Section title="AI Processing">
|
|
113
|
+
<p>
|
|
114
|
+
Your conversations may be processed by AI models to provide
|
|
115
|
+
responses. We do not use your conversations to train AI models
|
|
116
|
+
without your explicit consent.
|
|
117
|
+
</p>
|
|
118
|
+
</Section>
|
|
119
|
+
|
|
120
|
+
<Section title="Data Retention">
|
|
121
|
+
<p>
|
|
122
|
+
We retain your information for as long as your account is active
|
|
123
|
+
or as needed to provide you services. You can request deletion of
|
|
124
|
+
your data at any time.
|
|
125
|
+
</p>
|
|
126
|
+
</Section>
|
|
127
|
+
|
|
128
|
+
<Section title="Third-Party Services">
|
|
129
|
+
<p>
|
|
130
|
+
We may use third-party services that collect, monitor, and
|
|
131
|
+
analyze data. These services have their own privacy policies
|
|
132
|
+
addressing how they use such information.
|
|
133
|
+
</p>
|
|
134
|
+
</Section>
|
|
135
|
+
|
|
136
|
+
<Section title="Your Rights">
|
|
137
|
+
<p>You have the right to:</p>
|
|
138
|
+
<ul style={{ marginTop: '1rem', paddingLeft: '1.5rem' }}>
|
|
139
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
140
|
+
Access your personal data
|
|
141
|
+
</li>
|
|
142
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
143
|
+
Correct inaccurate data
|
|
144
|
+
</li>
|
|
145
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
146
|
+
Request deletion of your data
|
|
147
|
+
</li>
|
|
148
|
+
<li style={{ marginBottom: '0.5rem' }}>
|
|
149
|
+
Export your data
|
|
150
|
+
</li>
|
|
151
|
+
</ul>
|
|
152
|
+
</Section>
|
|
153
|
+
|
|
154
|
+
<Section title="Changes to This Policy">
|
|
155
|
+
<p>
|
|
156
|
+
We may update this privacy policy from time to time. We will
|
|
157
|
+
notify you of any changes by posting the new policy on this page.
|
|
158
|
+
</p>
|
|
159
|
+
</Section>
|
|
160
|
+
|
|
161
|
+
<Section title="Contact Us">
|
|
162
|
+
<p>
|
|
163
|
+
If you have any questions about this Privacy Policy, please
|
|
164
|
+
contact us.
|
|
165
|
+
</p>
|
|
166
|
+
</Section>
|
|
167
|
+
</div>
|
|
168
|
+
</article>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function Section({
|
|
175
|
+
title,
|
|
176
|
+
children,
|
|
177
|
+
}: {
|
|
178
|
+
title: string;
|
|
179
|
+
children: React.ReactNode;
|
|
180
|
+
}) {
|
|
181
|
+
return (
|
|
182
|
+
<>
|
|
183
|
+
<h2
|
|
184
|
+
style={{
|
|
185
|
+
fontSize: '1.25rem',
|
|
186
|
+
fontWeight: 600,
|
|
187
|
+
marginTop: '2rem',
|
|
188
|
+
marginBottom: '1rem',
|
|
189
|
+
color: 'rgb(var(--color-text-primary))',
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
{title}
|
|
193
|
+
</h2>
|
|
194
|
+
{children}
|
|
195
|
+
</>
|
|
196
|
+
);
|
|
197
|
+
}
|