create-githat-app 1.7.0 → 1.8.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.js +3 -3
- package/package.json +6 -2
- package/templates/agent/app/(auth)/forgot-password/page.tsx.hbs +11 -0
- package/templates/agent/app/(auth)/reset-password/page.tsx.hbs +39 -0
- package/templates/agent/app/(auth)/verify-email/page.tsx.hbs +41 -0
- package/templates/agent/app/admin/agent/page.tsx.hbs +159 -62
- package/templates/agent/app/admin/layout.tsx.hbs +82 -0
- package/templates/agent/app/admin/mcp/page.tsx.hbs +156 -0
- package/templates/agent/app/dashboard/agents/page.tsx.hbs +9 -0
- package/templates/agent/app/dashboard/layout.tsx.hbs +9 -0
- package/templates/agent/app/dashboard/mcp/page.tsx.hbs +9 -0
- package/templates/agent/app/dashboard/page.tsx.hbs +128 -0
- package/templates/agent/app/globals.css.hbs +14 -9
- package/templates/agent/app/layout.tsx.hbs +7 -2
- package/templates/agent/app/page.tsx.hbs +127 -70
- package/templates/agent/app/verify/agent/page.tsx.hbs +124 -0
- package/templates/agent/next.config.ts.hbs +4 -5
- package/templates/agent/public/HERO_IMAGE.md +23 -0
- package/templates/base/githat/api/agents.ts.hbs +6 -6
- package/templates/base/githat/config.ts.hbs +7 -9
- package/templates/base/githat/dashboard/overview.tsx.hbs +106 -16
- package/templates/classroom/app/layout.tsx.hbs +6 -1
- package/templates/classroom/next.config.ts.hbs +4 -5
- package/templates/content/app/layout.tsx.hbs +6 -1
- package/templates/content/next.config.ts.hbs +4 -5
- package/templates/dashboard/app/admin/data/[entity]/page.tsx.hbs +2 -2
- package/templates/dashboard/app/layout.tsx.hbs +6 -1
- package/templates/dashboard/next.config.ts.hbs +4 -5
- package/templates/fullstack/apps-web-nextjs/app/layout.tsx.hbs +6 -1
- package/templates/fullstack/apps-web-nextjs/next.config.ts.hbs +5 -5
- package/templates/marketplace/app/layout.tsx.hbs +6 -1
- package/templates/marketplace/next.config.ts.hbs +4 -5
- package/templates/nextjs/app/(auth)/forgot-password/page.tsx.hbs +2 -54
- package/templates/nextjs/app/(auth)/reset-password/page.tsx.hbs +8 -75
- package/templates/nextjs/app/layout.tsx.hbs +6 -1
- package/templates/nextjs/next.config.ts.hbs +4 -5
- package/templates/plain/app/layout.tsx.hbs +6 -1
- package/templates/plain/next.config.ts.hbs +4 -5
- package/templates/portfolio/app/layout.tsx.hbs +6 -1
- package/templates/portfolio/next.config.ts.hbs +4 -5
- package/templates/saas/app/layout.tsx.hbs +6 -1
- package/templates/saas/next.config.ts.hbs +4 -5
- package/templates/agent/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/agent/proxy.ts.hbs +0 -10
- package/templates/classroom/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/classroom/proxy.ts.hbs +0 -10
- package/templates/content/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/content/proxy.ts.hbs +0 -10
- package/templates/dashboard/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/dashboard/proxy.ts.hbs +0 -10
- package/templates/fullstack/apps-web-nextjs/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/marketplace/app/(shop)/[slug]/p/[productId]/page.tsx.hbs +0 -99
- package/templates/marketplace/app/(shop)/[slug]/page.tsx.hbs +0 -90
- package/templates/marketplace/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/marketplace/proxy.ts.hbs +0 -10
- package/templates/nextjs/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/nextjs/proxy.ts.hbs +0 -10
- package/templates/plain/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/plain/proxy.ts.hbs +0 -10
- package/templates/portfolio/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/portfolio/proxy.ts.hbs +0 -10
- package/templates/saas/app/api/githat/[...path]/route.ts.hbs +0 -21
- package/templates/saas/proxy.ts.hbs +0 -10
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{{#unless includeDashboard}}{{else}}
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
+
import Link from 'next/link';
|
|
4
5
|
import { useAuth } from '@githat/nextjs';
|
|
5
6
|
|
|
6
7
|
export function DashboardOverview() {
|
|
@@ -8,29 +9,118 @@ export function DashboardOverview() {
|
|
|
8
9
|
|
|
9
10
|
return (
|
|
10
11
|
<div>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
<div style=\{{ marginBottom: '2rem' }}>
|
|
13
|
+
<h1 style=\{{ fontSize: '1.5rem', fontWeight: 700, color: '#fafafa', marginBottom: '0.375rem' }}>
|
|
14
|
+
Welcome back{user?.name ? `, ${user.name}` : ''}
|
|
15
|
+
</h1>
|
|
16
|
+
{org && (
|
|
17
|
+
<p style=\{{ color: '#71717a', fontSize: '0.875rem' }}>
|
|
18
|
+
{org.name} · <span style=\{{ color: '#a1a1aa' }}>{org.role}</span>
|
|
19
|
+
</p>
|
|
20
|
+
)}
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
{/* Stats row */}
|
|
24
|
+
<div style=\{{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(14rem, 1fr))', gap: '1rem', marginBottom: '2.5rem' }}>
|
|
25
|
+
<StatCard label="Status" value="Active" sub="Account health" />
|
|
26
|
+
<StatCard label="Plan" value={org?.tier ?? 'Free'} sub="Current tier" />
|
|
27
|
+
<StatCard label="Identity" value="GitHat" sub="Auth provider" />
|
|
28
|
+
{{#if includeOrgManagement}}
|
|
29
|
+
<StatCard label="Members" value={String(org?.memberCount ?? 1)} sub="Team size" />
|
|
30
|
+
{{/if}}
|
|
31
|
+
</div>
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<
|
|
33
|
+
{/* Quick actions */}
|
|
34
|
+
<div style=\{{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(20rem, 1fr))', gap: '1rem' }}>
|
|
35
|
+
{{#if includeOrgManagement}}
|
|
36
|
+
<ActionCard
|
|
37
|
+
title="Invite team members"
|
|
38
|
+
desc="Add your business partner, accountant, or employee to your org."
|
|
39
|
+
cta="Invite"
|
|
40
|
+
href="/dashboard/members"
|
|
41
|
+
accent="#6366f1"
|
|
42
|
+
/>
|
|
43
|
+
<ActionCard
|
|
44
|
+
title="Organization settings"
|
|
45
|
+
desc="Update your org name, billing plan, and member permissions."
|
|
46
|
+
cta="Settings"
|
|
47
|
+
href="/dashboard/settings"
|
|
48
|
+
accent="#8b5cf6"
|
|
49
|
+
/>
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if includeMcpModule}}
|
|
52
|
+
<ActionCard
|
|
53
|
+
title="Connect an MCP server"
|
|
54
|
+
desc="Hook your data into any AI assistant via the Model Context Protocol."
|
|
55
|
+
cta="Connect"
|
|
56
|
+
href="/dashboard/mcp"
|
|
57
|
+
accent="#0ea5e9"
|
|
58
|
+
/>
|
|
59
|
+
{{/if}}
|
|
60
|
+
{{#if includeAgentModule}}
|
|
61
|
+
<ActionCard
|
|
62
|
+
title="Deploy an AI agent"
|
|
63
|
+
desc="Register a wallet-bound autonomous agent with capability scoping and a kill switch."
|
|
64
|
+
cta="Deploy"
|
|
65
|
+
href="/dashboard/agents"
|
|
66
|
+
accent="#10b981"
|
|
67
|
+
/>
|
|
68
|
+
{{/if}}
|
|
69
|
+
<ActionCard
|
|
70
|
+
title="Manage apps"
|
|
71
|
+
desc="View and rotate your publishable keys, configure allowed origins."
|
|
72
|
+
cta="View apps"
|
|
73
|
+
href="/dashboard/apps"
|
|
74
|
+
accent="#f59e0b"
|
|
75
|
+
/>
|
|
24
76
|
</div>
|
|
25
77
|
</div>
|
|
26
78
|
);
|
|
27
79
|
}
|
|
28
80
|
|
|
29
|
-
function StatCard({
|
|
81
|
+
function StatCard({ label, value, sub }{{#if typescript}}: { label: string; value: string; sub: string }{{/if}}) {
|
|
82
|
+
return (
|
|
83
|
+
<div style=\{{
|
|
84
|
+
background: '#111113',
|
|
85
|
+
border: '1px solid #1e1e2e',
|
|
86
|
+
borderRadius: '0.75rem',
|
|
87
|
+
padding: '1.5rem',
|
|
88
|
+
}}>
|
|
89
|
+
<p style=\{{ fontSize: '0.8125rem', color: '#71717a', marginBottom: '0.375rem' }}>{label}</p>
|
|
90
|
+
<p style=\{{ fontSize: '1.5rem', fontWeight: 700, color: '#fafafa', marginBottom: '0.25rem' }}>{value}</p>
|
|
91
|
+
<p style=\{{ fontSize: '0.75rem', color: '#52525b' }}>{sub}</p>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function ActionCard({ title, desc, cta, href, accent }{{#if typescript}}: {
|
|
97
|
+
title: string; desc: string; cta: string; href: string; accent: string;
|
|
98
|
+
}{{/if}}) {
|
|
30
99
|
return (
|
|
31
|
-
<div style=\{{
|
|
32
|
-
|
|
33
|
-
|
|
100
|
+
<div style=\{{
|
|
101
|
+
background: '#111113',
|
|
102
|
+
border: '1px solid #1e1e2e',
|
|
103
|
+
borderRadius: '0.75rem',
|
|
104
|
+
padding: '1.5rem',
|
|
105
|
+
display: 'flex',
|
|
106
|
+
flexDirection: 'column',
|
|
107
|
+
gap: '0.75rem',
|
|
108
|
+
}}>
|
|
109
|
+
<h3 style=\{{ fontSize: '0.9375rem', fontWeight: 600, color: '#fafafa' }}>{title}</h3>
|
|
110
|
+
<p style=\{{ fontSize: '0.875rem', color: '#71717a', lineHeight: 1.6, flex: 1 }}>{desc}</p>
|
|
111
|
+
<Link href={href} style=\{{
|
|
112
|
+
display: 'inline-block',
|
|
113
|
+
background: accent,
|
|
114
|
+
color: '#fff',
|
|
115
|
+
textDecoration: 'none',
|
|
116
|
+
padding: '0.5rem 1rem',
|
|
117
|
+
borderRadius: '0.375rem',
|
|
118
|
+
fontSize: '0.875rem',
|
|
119
|
+
fontWeight: 600,
|
|
120
|
+
alignSelf: 'flex-start',
|
|
121
|
+
}}>
|
|
122
|
+
{cta} →
|
|
123
|
+
</Link>
|
|
34
124
|
</div>
|
|
35
125
|
);
|
|
36
126
|
}
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -6,8 +6,8 @@ import { listEntities } from '../../../../src/lib/db';
|
|
|
6
6
|
*
|
|
7
7
|
* Server component — runs `listEntities(entityName)` (which you
|
|
8
8
|
* implement in src/lib/db.ts) and renders rows as a basic table.
|
|
9
|
-
* Auth-gating
|
|
10
|
-
* need entity-level RBAC, check `verifyToken` claims here.
|
|
9
|
+
* Auth-gating happens client-side via `useAuth` in the static export;
|
|
10
|
+
* if you need entity-level RBAC, check `verifyToken` claims here.
|
|
11
11
|
*/
|
|
12
12
|
export default async function EntityPage({
|
|
13
13
|
params,
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -14,7 +14,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
14
14
|
<body>
|
|
15
15
|
<GitHatProvider config=\{{
|
|
16
16
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
17
|
-
apiUrl: '
|
|
17
|
+
apiUrl: 'https://api.githat.io',
|
|
18
|
+
{{#if typescript}}
|
|
19
|
+
tokenStorage: 'localStorage' as const,
|
|
20
|
+
{{else}}
|
|
21
|
+
tokenStorage: 'localStorage',
|
|
22
|
+
{{/if}}
|
|
18
23
|
signInUrl: '/sign-in',
|
|
19
24
|
signUpUrl: '/sign-up',
|
|
20
25
|
afterSignInUrl: '/dashboard',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
6
|
+
// Proxy API calls to the backend in development
|
|
7
7
|
async rewrites() {
|
|
8
8
|
return [
|
|
9
9
|
{
|
|
@@ -25,7 +25,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
25
25
|
<body>
|
|
26
26
|
<GitHatProvider config=\{{
|
|
27
27
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
28
|
-
apiUrl: '
|
|
28
|
+
apiUrl: 'https://api.githat.io',
|
|
29
|
+
{{#if typescript}}
|
|
30
|
+
tokenStorage: 'localStorage' as const,
|
|
31
|
+
{{else}}
|
|
32
|
+
tokenStorage: 'localStorage',
|
|
33
|
+
{{/if}}
|
|
29
34
|
signInUrl: '/sign-in',
|
|
30
35
|
signUpUrl: '/sign-up',
|
|
31
36
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -1,62 +1,10 @@
|
|
|
1
1
|
{{#if includeForgotPassword}}
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { useState } from 'react';
|
|
5
|
-
{{#if includeGithatFolder}}
|
|
6
|
-
import { authApi } from '../../../githat/api/auth{{#unless typescript}}.js{{/unless}}';
|
|
7
|
-
{{/if}}
|
|
2
|
+
import { ForgotPasswordForm } from '@githat/nextjs';
|
|
8
3
|
|
|
9
4
|
export default function ForgotPasswordPage() {
|
|
10
|
-
const [email, setEmail] = useState('');
|
|
11
|
-
const [sent, setSent] = useState(false);
|
|
12
|
-
const [error, setError] = useState('');
|
|
13
|
-
|
|
14
|
-
const handleSubmit = async (e{{#if typescript}}: React.FormEvent{{/if}}) => {
|
|
15
|
-
e.preventDefault();
|
|
16
|
-
setError('');
|
|
17
|
-
try {
|
|
18
|
-
{{#if includeGithatFolder}}
|
|
19
|
-
await authApi.forgotPassword(email);
|
|
20
|
-
{{else}}
|
|
21
|
-
await fetch('{{apiUrl}}/auth/forgot-password', {
|
|
22
|
-
method: 'POST',
|
|
23
|
-
headers: { 'Content-Type': 'application/json' },
|
|
24
|
-
body: JSON.stringify({ email }),
|
|
25
|
-
});
|
|
26
|
-
{{/if}}
|
|
27
|
-
setSent(true);
|
|
28
|
-
} catch (err) {
|
|
29
|
-
setError('Something went wrong. Please try again.');
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
5
|
return (
|
|
34
6
|
<main {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b]"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b' }}{{/if}}>
|
|
35
|
-
<
|
|
36
|
-
<h1 style=\{{ fontSize: '1.5rem', fontWeight: 600, color: '#fafafa', marginBottom: '0.5rem' }}>Reset password</h1>
|
|
37
|
-
{sent ? (
|
|
38
|
-
<p style=\{{ color: '#a1a1aa' }}>Check your email for a reset link.</p>
|
|
39
|
-
) : (
|
|
40
|
-
<form onSubmit={handleSubmit}>
|
|
41
|
-
<p style=\{{ color: '#a1a1aa', marginBottom: '1.5rem' }}>Enter your email to receive a reset link.</p>
|
|
42
|
-
{error && <p style=\{{ color: '#ef4444', marginBottom: '1rem', fontSize: '0.875rem' }}>{error}</p>}
|
|
43
|
-
<input
|
|
44
|
-
type="email"
|
|
45
|
-
value={email}
|
|
46
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
47
|
-
placeholder="you@example.com"
|
|
48
|
-
required
|
|
49
|
-
style=\{{ width: '100%', padding: '0.625rem 0.75rem', background: '#111113', border: '1px solid #1e1e2e', borderRadius: '0.375rem', color: '#fafafa', marginBottom: '1rem', outline: 'none' }}
|
|
50
|
-
/>
|
|
51
|
-
<button
|
|
52
|
-
type="submit"
|
|
53
|
-
style=\{{ width: '100%', padding: '0.625rem', background: '#7c3aed', color: '#fff', border: 'none', borderRadius: '0.375rem', fontWeight: 600, cursor: 'pointer' }}
|
|
54
|
-
>
|
|
55
|
-
Send reset link
|
|
56
|
-
</button>
|
|
57
|
-
</form>
|
|
58
|
-
)}
|
|
59
|
-
</div>
|
|
7
|
+
<ForgotPasswordForm signInUrl="/sign-in" />
|
|
60
8
|
</main>
|
|
61
9
|
);
|
|
62
10
|
}
|
|
@@ -1,56 +1,21 @@
|
|
|
1
1
|
{{#if includeForgotPassword}}
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
-
import { Suspense
|
|
5
|
-
import { useSearchParams
|
|
6
|
-
{
|
|
7
|
-
import { authApi } from '../../../githat/api/auth{{#unless typescript}}.js{{/unless}}';
|
|
8
|
-
{{/if}}
|
|
4
|
+
import { Suspense } from 'react';
|
|
5
|
+
import { useSearchParams } from 'next/navigation';
|
|
6
|
+
import { ResetPasswordForm } from '@githat/nextjs';
|
|
9
7
|
|
|
10
8
|
function ResetPasswordContent() {
|
|
11
9
|
const searchParams = useSearchParams();
|
|
12
|
-
const router = useRouter();
|
|
13
10
|
const token = searchParams.get('token');
|
|
14
11
|
|
|
15
|
-
const [password, setPassword] = useState('');
|
|
16
|
-
const [confirm, setConfirm] = useState('');
|
|
17
|
-
const [error, setError] = useState('');
|
|
18
|
-
const [loading, setLoading] = useState(false);
|
|
19
|
-
|
|
20
|
-
const handleSubmit = async (e{{#if typescript}}: React.FormEvent{{/if}}) => {
|
|
21
|
-
e.preventDefault();
|
|
22
|
-
if (password !== confirm) {
|
|
23
|
-
setError('Passwords do not match');
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
setError('');
|
|
27
|
-
setLoading(true);
|
|
28
|
-
try {
|
|
29
|
-
{{#if includeGithatFolder}}
|
|
30
|
-
await authApi.resetPassword(token!, password);
|
|
31
|
-
{{else}}
|
|
32
|
-
const res = await fetch('{{apiUrl}}/auth/reset-password', {
|
|
33
|
-
method: 'POST',
|
|
34
|
-
headers: { 'Content-Type': 'application/json' },
|
|
35
|
-
body: JSON.stringify({ token, password }),
|
|
36
|
-
});
|
|
37
|
-
if (!res.ok) throw new Error('Reset failed');
|
|
38
|
-
{{/if}}
|
|
39
|
-
router.push('/sign-in?reset=success');
|
|
40
|
-
} catch (err) {
|
|
41
|
-
setError('Failed to reset password. The link may have expired.');
|
|
42
|
-
} finally {
|
|
43
|
-
setLoading(false);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
12
|
if (!token) {
|
|
48
13
|
return (
|
|
49
14
|
<main {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b]"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b' }}{{/if}}>
|
|
50
|
-
<div style=\{{ textAlign: 'center' }}>
|
|
51
|
-
<h1 style=\{{ fontSize: '1.
|
|
52
|
-
<p style=\{{ color: '#a1a1aa' }}>
|
|
53
|
-
<a href="/forgot-password" style=\{{ color: '#7c3aed' }}>Request a new one</a>
|
|
15
|
+
<div {{#if useTailwind}}className="text-center"{{else}}style=\{{ textAlign: 'center' }}{{/if}}>
|
|
16
|
+
<h1 {{#if useTailwind}}className="text-xl font-semibold text-white mb-2"{{else}}style=\{{ fontSize: '1.25rem', fontWeight: 600, color: '#fafafa', marginBottom: '0.5rem' }}{{/if}}>Invalid reset link</h1>
|
|
17
|
+
<p {{#if useTailwind}}className="text-zinc-400"{{else}}style=\{{ color: '#a1a1aa' }}{{/if}}>
|
|
18
|
+
<a href="/forgot-password" {{#if useTailwind}}className="text-violet-500 hover:underline"{{else}}style=\{{ color: '#7c3aed' }}{{/if}}>Request a new one</a>
|
|
54
19
|
</p>
|
|
55
20
|
</div>
|
|
56
21
|
</main>
|
|
@@ -59,39 +24,7 @@ function ResetPasswordContent() {
|
|
|
59
24
|
|
|
60
25
|
return (
|
|
61
26
|
<main {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b]"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b' }}{{/if}}>
|
|
62
|
-
<
|
|
63
|
-
<h1 style=\{{ fontSize: '1.5rem', fontWeight: 600, color: '#fafafa', marginBottom: '0.5rem' }}>Reset password</h1>
|
|
64
|
-
<p style=\{{ color: '#a1a1aa', marginBottom: '1.5rem' }}>Enter your new password below.</p>
|
|
65
|
-
{error && <p style=\{{ color: '#ef4444', marginBottom: '1rem', fontSize: '0.875rem' }}>{error}</p>}
|
|
66
|
-
<form onSubmit={handleSubmit}>
|
|
67
|
-
<input
|
|
68
|
-
type="password"
|
|
69
|
-
value={password}
|
|
70
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
71
|
-
placeholder="New password"
|
|
72
|
-
required
|
|
73
|
-
minLength={8}
|
|
74
|
-
disabled={loading}
|
|
75
|
-
style=\{{ width: '100%', padding: '0.625rem 0.75rem', background: '#111113', border: '1px solid #1e1e2e', borderRadius: '0.375rem', color: '#fafafa', marginBottom: '1rem', outline: 'none' }}
|
|
76
|
-
/>
|
|
77
|
-
<input
|
|
78
|
-
type="password"
|
|
79
|
-
value={confirm}
|
|
80
|
-
onChange={(e) => setConfirm(e.target.value)}
|
|
81
|
-
placeholder="Confirm password"
|
|
82
|
-
required
|
|
83
|
-
disabled={loading}
|
|
84
|
-
style=\{{ width: '100%', padding: '0.625rem 0.75rem', background: '#111113', border: '1px solid #1e1e2e', borderRadius: '0.375rem', color: '#fafafa', marginBottom: '1rem', outline: 'none' }}
|
|
85
|
-
/>
|
|
86
|
-
<button
|
|
87
|
-
type="submit"
|
|
88
|
-
disabled={loading}
|
|
89
|
-
style=\{{ width: '100%', padding: '0.625rem', background: '#7c3aed', color: '#fff', border: 'none', borderRadius: '0.375rem', fontWeight: 600, cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1 }}
|
|
90
|
-
>
|
|
91
|
-
{loading ? 'Resetting...' : 'Reset password'}
|
|
92
|
-
</button>
|
|
93
|
-
</form>
|
|
94
|
-
</div>
|
|
27
|
+
<ResetPasswordForm token={token} signInUrl="/sign-in" />
|
|
95
28
|
</main>
|
|
96
29
|
);
|
|
97
30
|
}
|
|
@@ -20,7 +20,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
20
20
|
...githatConfig,
|
|
21
21
|
{{else}}
|
|
22
22
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
23
|
-
apiUrl: '
|
|
23
|
+
apiUrl: 'https://api.githat.io',
|
|
24
|
+
{{#if typescript}}
|
|
25
|
+
tokenStorage: 'localStorage' as const,
|
|
26
|
+
{{else}}
|
|
27
|
+
tokenStorage: 'localStorage',
|
|
28
|
+
{{/if}}
|
|
24
29
|
signInUrl: '/sign-in',
|
|
25
30
|
signUpUrl: '/sign-up',
|
|
26
31
|
afterSignInUrl: '/dashboard',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -19,7 +19,12 @@ export default function RootLayout({ children }{{#if typescript}}: { children: R
|
|
|
19
19
|
*/}
|
|
20
20
|
<GitHatProvider config=\{{
|
|
21
21
|
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
-
apiUrl: '
|
|
22
|
+
apiUrl: 'https://api.githat.io',
|
|
23
|
+
{{#if typescript}}
|
|
24
|
+
tokenStorage: 'localStorage' as const,
|
|
25
|
+
{{else}}
|
|
26
|
+
tokenStorage: 'localStorage',
|
|
27
|
+
{{/if}}
|
|
23
28
|
signInUrl: '/sign-in',
|
|
24
29
|
signUpUrl: '/sign-up',
|
|
25
30
|
afterSignInUrl: '/',
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
{{/if}}import { withGitHat } from '@githat/nextjs/server';
|
|
1
|
+
import { withGitHat } from '@githat/nextjs/server';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const nextConfig = {
|
|
4
|
+
output: 'export',
|
|
5
|
+
images: { unoptimized: true },
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
export default withGitHat(nextConfig);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Same-origin GitHat API proxy.
|
|
3
|
-
*
|
|
4
|
-
* Forwards every request to api.githat.io and re-emits upstream Set-Cookie
|
|
5
|
-
* headers on this app's domain. Without this bridge, the auth cookie set
|
|
6
|
-
* by api.githat.io is invisible to the consumer's proxy.ts and getAuth(),
|
|
7
|
-
* which produces a sign-in → app-page → "session expired" loop.
|
|
8
|
-
*
|
|
9
|
-
* The SDK is wired to this URL via `apiUrl: "/api/githat"` on
|
|
10
|
-
* GitHatProvider, so every fetch becomes same-origin and cookies land
|
|
11
|
-
* on this app's domain.
|
|
12
|
-
*
|
|
13
|
-
* Implementation lives in @githat/nextjs/server.githatApiProxy().
|
|
14
|
-
*/
|
|
15
|
-
import { githatApiProxy } from "@githat/nextjs/server";
|
|
16
|
-
|
|
17
|
-
export const { GET, POST, PUT, PATCH, DELETE, OPTIONS } = githatApiProxy();
|
|
18
|
-
|
|
19
|
-
// Auth flows are stateful — never cache the proxied responses.
|
|
20
|
-
export const dynamic = "force-dynamic";
|
|
21
|
-
export const revalidate = 0;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { authProxy } from '@githat/nextjs/proxy';
|
|
2
|
-
|
|
3
|
-
export const proxy = authProxy({
|
|
4
|
-
publicRoutes: ['/', '/sign-in', '/sign-up'{{#if includeForgotPassword}}, '/forgot-password', '/reset-password'{{/if}}{{#if includeEmailVerification}}, '/verify-email'{{/if}}],
|
|
5
|
-
signInUrl: '/sign-in',
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export const config = {
|
|
9
|
-
matcher: ['/((?!_next|api|.*\\..*).*)'],
|
|
10
|
-
};
|