create-githat-app 1.0.15 → 1.0.16
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 +20 -10
- package/package.json +1 -1
- package/templates/agent/app/admin/agent/page.tsx.hbs +127 -0
- package/templates/agent/app/page.tsx.hbs +85 -108
- package/templates/classroom/app/(auth)/sign-in/page.tsx.hbs +9 -0
- package/templates/classroom/app/(auth)/sign-up/page.tsx.hbs +9 -0
- package/templates/classroom/app/globals.css.hbs +87 -0
- package/templates/classroom/app/layout.tsx.hbs +41 -0
- package/templates/classroom/app/page.tsx.hbs +103 -0
- package/templates/classroom/app/projects/[id]/feedback/page.tsx.hbs +159 -0
- package/templates/classroom/app/projects/[id]/present/page.tsx.hbs +113 -0
- package/templates/classroom/next.config.ts.hbs +7 -0
- package/templates/classroom/postcss.config.mjs.hbs +14 -0
- package/templates/classroom/proxy.ts.hbs +10 -0
- package/templates/classroom/tsconfig.json.hbs +21 -0
- package/templates/content/app/newsletter/page.tsx.hbs +90 -0
- package/templates/content/app/page.tsx.hbs +93 -111
- package/templates/content/app/posts/[slug]/page.tsx.hbs +119 -0
- package/templates/dashboard/app/admin/data/[entity]/page.tsx.hbs +68 -0
- package/templates/dashboard/app/admin/page.tsx.hbs +59 -0
- package/templates/dashboard/app/page.tsx.hbs +42 -108
- package/templates/dashboard/src/lib/db.ts.hbs +39 -0
- package/templates/portfolio/app/(auth)/sign-in/page.tsx.hbs +9 -0
- package/templates/portfolio/app/(auth)/sign-up/page.tsx.hbs +9 -0
- package/templates/portfolio/app/globals.css.hbs +87 -0
- package/templates/portfolio/app/layout.tsx.hbs +41 -0
- package/templates/portfolio/app/page.tsx.hbs +86 -0
- package/templates/portfolio/next.config.ts.hbs +7 -0
- package/templates/portfolio/postcss.config.mjs.hbs +14 -0
- package/templates/portfolio/proxy.ts.hbs +10 -0
- package/templates/portfolio/tsconfig.json.hbs +21 -0
- package/templates/saas/app/admin/billing/page.tsx.hbs +145 -0
- package/templates/saas/app/admin/page.tsx.hbs +106 -0
- package/templates/saas/app/admin/team/page.tsx.hbs +134 -0
- package/templates/saas/app/page.tsx.hbs +95 -110
- package/templates/saas/app/pricing/page.tsx.hbs +131 -0
- package/templates/agent/TODO.md +0 -9
- package/templates/content/TODO.md +0 -9
- package/templates/dashboard/TODO.md +0 -9
- package/templates/saas/TODO.md +0 -9
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import gradient from "gradient-string";
|
|
|
11
11
|
import chalk from "chalk";
|
|
12
12
|
|
|
13
13
|
// src/constants.ts
|
|
14
|
-
var VERSION = "1.0.
|
|
14
|
+
var VERSION = "1.0.16";
|
|
15
15
|
var DEFAULT_API_URL = "https://api.githat.io";
|
|
16
16
|
var DASHBOARD_URL = "https://githat.io/dashboard/apps";
|
|
17
17
|
var BRAND_COLORS = ["#7c3aed", "#6366f1", "#8b5cf6"];
|
|
@@ -332,10 +332,12 @@ async function promptFramework(typescriptOverride, isFullstack) {
|
|
|
332
332
|
const frameworkOptions = isFullstack ? [{ value: "nextjs", label: "Next.js 16", hint: "App Router \xB7 SSR \xB7 middleware auth" }] : [
|
|
333
333
|
{ value: "plain", label: "Plain", hint: "Auth + a homepage. Smallest possible GitHat app." },
|
|
334
334
|
{ value: "saas", label: "SaaS", hint: "Orgs, teams, RBAC, subscription billing. Replaces Clerk + Stripe." },
|
|
335
|
-
{ value: "marketplace", label: "Marketplace", hint: "Multi-vendor commerce. Anonymous-first
|
|
336
|
-
{ value: "
|
|
337
|
-
{ value: "content", label: "Content", hint: "Paywalled posts, newsletter, one-time purchases. Replaces Substack." },
|
|
335
|
+
{ value: "marketplace", label: "Marketplace", hint: "Multi-vendor commerce. Anonymous-first, Sebastn Connect." },
|
|
336
|
+
{ value: "content", label: "Content", hint: "Paywalled posts, newsletter. Replaces Substack." },
|
|
338
337
|
{ value: "dashboard", label: "Dashboard", hint: "Auth-gated admin UI over your existing database." },
|
|
338
|
+
{ value: "portfolio", label: "Portfolio", hint: "Personal site: public projects, auth-gated editor." },
|
|
339
|
+
{ value: "classroom", label: "Classroom", hint: "Live student presentations + real-time audience feedback." },
|
|
340
|
+
{ value: "agent", label: "AI Agent", hint: "Web4 wallet-bound agent + MCP server. Public verification." },
|
|
339
341
|
{ value: "nextjs", label: "Next.js (full kit)", hint: "Legacy: dashboard + orgs + agents + MCP scaffolding." },
|
|
340
342
|
{ value: "react-vite", label: "React + Vite", hint: "SPA \xB7 client-side routing." }
|
|
341
343
|
];
|
|
@@ -693,7 +695,9 @@ var NEXT_LIKE = /* @__PURE__ */ new Set([
|
|
|
693
695
|
"marketplace",
|
|
694
696
|
"agent",
|
|
695
697
|
"content",
|
|
696
|
-
"dashboard"
|
|
698
|
+
"dashboard",
|
|
699
|
+
"portfolio",
|
|
700
|
+
"classroom"
|
|
697
701
|
]);
|
|
698
702
|
Handlebars.registerHelper("ifNext", function(framework, options) {
|
|
699
703
|
return NEXT_LIKE.has(framework) ? options.fn(this) : options.inverse(this);
|
|
@@ -751,7 +755,9 @@ var NEXT_LIKE2 = /* @__PURE__ */ new Set([
|
|
|
751
755
|
"marketplace",
|
|
752
756
|
"agent",
|
|
753
757
|
"content",
|
|
754
|
-
"dashboard"
|
|
758
|
+
"dashboard",
|
|
759
|
+
"portfolio",
|
|
760
|
+
"classroom"
|
|
755
761
|
]);
|
|
756
762
|
var MINIMAL = /* @__PURE__ */ new Set([
|
|
757
763
|
"plain",
|
|
@@ -759,7 +765,9 @@ var MINIMAL = /* @__PURE__ */ new Set([
|
|
|
759
765
|
"marketplace",
|
|
760
766
|
"agent",
|
|
761
767
|
"content",
|
|
762
|
-
"dashboard"
|
|
768
|
+
"dashboard",
|
|
769
|
+
"portfolio",
|
|
770
|
+
"classroom"
|
|
763
771
|
]);
|
|
764
772
|
function buildPackageJson(ctx) {
|
|
765
773
|
const isNext = NEXT_LIKE2.has(ctx.framework);
|
|
@@ -973,7 +981,9 @@ async function scaffold(context, options) {
|
|
|
973
981
|
"marketplace",
|
|
974
982
|
"agent",
|
|
975
983
|
"content",
|
|
976
|
-
"dashboard"
|
|
984
|
+
"dashboard",
|
|
985
|
+
"portfolio",
|
|
986
|
+
"classroom"
|
|
977
987
|
]);
|
|
978
988
|
if (!isFullstack && NEXT_LIKE3.has(context.framework)) {
|
|
979
989
|
await registerApp(context.projectName, root);
|
|
@@ -1630,7 +1640,7 @@ skillsCommand.action(() => {
|
|
|
1630
1640
|
// src/cli.ts
|
|
1631
1641
|
var program = new Command7();
|
|
1632
1642
|
program.name("githat").description("GitHat CLI - Scaffold apps and manage skills").version(VERSION);
|
|
1633
|
-
program.command("create [project-name]", { isDefault: true }).description("Scaffold a new GitHat app").option("--key <key>", "GitHat publishable key (pk_live_...)").option("--ts", "Use TypeScript (default)").option("--js", "Use JavaScript").option("--plain", "Smallest scaffold: auth + a homepage. No dashboard.").option("--saas", "B2B starter: orgs, teams, RBAC, subscription billing.").option("--marketplace", "Multi-vendor commerce: anonymous-first browsing, Sebastn Connect.").option("--agent", "Web4 wallet-bound autonomous agent + MCP server registration.").option("--content", "Paywalled posts, newsletter, one-time purchases via Sebastn.").option("--dashboard", "Admin UI over your existing database, auth-gated.").option("--fullstack", "Create fullstack project (Turborepo)").option("--backend <framework>", "Backend framework (hono, express, fastify)").option("-y, --yes", "Skip prompts and use defaults").action(async (projectName, opts) => {
|
|
1643
|
+
program.command("create [project-name]", { isDefault: true }).description("Scaffold a new GitHat app").option("--key <key>", "GitHat publishable key (pk_live_...)").option("--ts", "Use TypeScript (default)").option("--js", "Use JavaScript").option("--plain", "Smallest scaffold: auth + a homepage. No dashboard.").option("--saas", "B2B starter: orgs, teams, RBAC, subscription billing.").option("--marketplace", "Multi-vendor commerce: anonymous-first browsing, Sebastn Connect.").option("--agent", "Web4 wallet-bound autonomous agent + MCP server registration.").option("--content", "Paywalled posts, newsletter, one-time purchases via Sebastn.").option("--dashboard", "Admin UI over your existing database, auth-gated.").option("--portfolio", "Personal portfolio: public projects, auth-gated editor.").option("--classroom", "Live student presentations with real-time audience feedback.").option("--fullstack", "Create fullstack project (Turborepo)").option("--backend <framework>", "Backend framework (hono, express, fastify)").option("-y, --yes", "Skip prompts and use defaults").action(async (projectName, opts) => {
|
|
1634
1644
|
try {
|
|
1635
1645
|
displayBanner();
|
|
1636
1646
|
if (!opts.yes && !opts.key) {
|
|
@@ -1656,7 +1666,7 @@ program.command("create [project-name]", { isDefault: true }).description("Scaff
|
|
|
1656
1666
|
p12.cancel(chalk10.red("Project name is required when using --yes flag"));
|
|
1657
1667
|
process.exit(1);
|
|
1658
1668
|
}
|
|
1659
|
-
const template = opts.marketplace ? "marketplace" : opts.agent ? "agent" : opts.saas ? "saas" : opts.content ? "content" : opts.dashboard ? "dashboard" : opts.plain ? "plain" : void 0;
|
|
1669
|
+
const template = opts.marketplace ? "marketplace" : opts.classroom ? "classroom" : opts.portfolio ? "portfolio" : opts.agent ? "agent" : opts.saas ? "saas" : opts.content ? "content" : opts.dashboard ? "dashboard" : opts.plain ? "plain" : void 0;
|
|
1660
1670
|
const answers = await runPrompts({
|
|
1661
1671
|
initialName: projectName,
|
|
1662
1672
|
publishableKey: opts.key,
|
package/package.json
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { useAuth } from '@githat/nextjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Agent operator dashboard — control the agent you registered.
|
|
8
|
+
*
|
|
9
|
+
* Three core actions an operator does:
|
|
10
|
+
* 1. See live status (active / paused / revoked)
|
|
11
|
+
* 2. Adjust capabilities (which tools the agent can call)
|
|
12
|
+
* 3. Hit the kill switch
|
|
13
|
+
*
|
|
14
|
+
* Real apps fetch the agent record from GitHat's
|
|
15
|
+
* GET /agent/{walletAddress}. Stub below shows the data shape.
|
|
16
|
+
*/
|
|
17
|
+
export default function AgentAdminPage() {
|
|
18
|
+
const { isSignedIn, isLoading } = useAuth();
|
|
19
|
+
|
|
20
|
+
if (isLoading) return <div style=\{{ padding: 'var(--space-8)', color: 'var(--fg-muted)' }}>Loading…</div>;
|
|
21
|
+
if (!isSignedIn) {
|
|
22
|
+
return (
|
|
23
|
+
<div style=\{{ padding: 'var(--space-8)', textAlign: 'center' }}>
|
|
24
|
+
<Link href="/sign-in" style=\{{ color: 'var(--primary)' }}>Sign in →</Link>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const agent = {
|
|
30
|
+
name: 'My research agent',
|
|
31
|
+
wallet: '0xAB12…CDEf',
|
|
32
|
+
status: 'active' as 'active' | 'paused' | 'revoked',
|
|
33
|
+
capabilities: ['web.search', 'web.fetch', 'arxiv.read'],
|
|
34
|
+
actionsLast24h: 47,
|
|
35
|
+
verifyUrl: 'https://githat.io/verify/agent/0xAB12...CDEf',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div style=\{{ padding: 'var(--space-8) var(--space-4)', maxWidth: '48rem', margin: '0 auto' }}>
|
|
40
|
+
<h1 style=\{{ fontFamily: 'var(--font-wordmark)', fontSize: '2rem', marginBottom: 'var(--space-2)' }}>
|
|
41
|
+
{agent.name}
|
|
42
|
+
</h1>
|
|
43
|
+
<p style=\{{ color: 'var(--fg-muted)', fontSize: '0.875rem', marginBottom: 'var(--space-6)' }}>
|
|
44
|
+
Wallet: <code>{agent.wallet}</code>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<section style=\{{
|
|
48
|
+
padding: 'var(--space-5)',
|
|
49
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
50
|
+
border: '1px solid var(--border)',
|
|
51
|
+
background: 'var(--surface)',
|
|
52
|
+
marginBottom: 'var(--space-6)',
|
|
53
|
+
}}>
|
|
54
|
+
<div style=\{{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 'var(--space-3)' }}>
|
|
55
|
+
<span style=\{{ fontSize: '0.875rem', color: 'var(--fg-muted)' }}>Status</span>
|
|
56
|
+
<span style=\{{
|
|
57
|
+
padding: 'var(--space-1) var(--space-3)',
|
|
58
|
+
borderRadius: 'var(--radius-full, 9999px)',
|
|
59
|
+
background: agent.status === 'active' ? 'var(--success)' : agent.status === 'paused' ? 'var(--warn)' : 'var(--danger)',
|
|
60
|
+
color: 'var(--bg)',
|
|
61
|
+
fontSize: '0.75rem',
|
|
62
|
+
fontWeight: 700,
|
|
63
|
+
}}>
|
|
64
|
+
{agent.status.toUpperCase()}
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
<div style=\{{ fontSize: '2rem', fontWeight: 600, marginBottom: 'var(--space-1)' }}>
|
|
68
|
+
{agent.actionsLast24h}
|
|
69
|
+
</div>
|
|
70
|
+
<div style=\{{ fontSize: '0.75rem', color: 'var(--fg-subtle)' }}>actions in the last 24 hours</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
<section style=\{{ marginBottom: 'var(--space-6)' }}>
|
|
74
|
+
<h2 style=\{{ fontSize: '1.125rem', marginBottom: 'var(--space-3)' }}>Capabilities</h2>
|
|
75
|
+
<ul style=\{{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexWrap: 'wrap', gap: 'var(--space-2)' }}>
|
|
76
|
+
{agent.capabilities.map((cap) => (
|
|
77
|
+
<li key={cap} style=\{{
|
|
78
|
+
padding: 'var(--space-2) var(--space-3)',
|
|
79
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
80
|
+
border: '1px solid var(--border)',
|
|
81
|
+
background: 'var(--surface)',
|
|
82
|
+
fontSize: '0.875rem',
|
|
83
|
+
fontFamily: 'var(--font-mono, monospace)',
|
|
84
|
+
}}>
|
|
85
|
+
{cap}
|
|
86
|
+
</li>
|
|
87
|
+
))}
|
|
88
|
+
</ul>
|
|
89
|
+
</section>
|
|
90
|
+
|
|
91
|
+
<section style=\{{ display: 'flex', gap: 'var(--space-3)', flexWrap: 'wrap' }}>
|
|
92
|
+
<a href={agent.verifyUrl} target="_blank" rel="noopener noreferrer" style=\{{
|
|
93
|
+
padding: 'var(--space-3) var(--space-4)',
|
|
94
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
95
|
+
border: '1px solid var(--border)',
|
|
96
|
+
color: 'var(--fg)',
|
|
97
|
+
textDecoration: 'none',
|
|
98
|
+
}}>
|
|
99
|
+
Public verify URL ↗
|
|
100
|
+
</a>
|
|
101
|
+
<Link href="/admin/mcp" style=\{{
|
|
102
|
+
padding: 'var(--space-3) var(--space-4)',
|
|
103
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
104
|
+
border: '1px solid var(--border)',
|
|
105
|
+
color: 'var(--fg)',
|
|
106
|
+
textDecoration: 'none',
|
|
107
|
+
}}>
|
|
108
|
+
MCP servers
|
|
109
|
+
</Link>
|
|
110
|
+
<button
|
|
111
|
+
onClick={() => { /* TODO: POST /api/agent/kill */ }}
|
|
112
|
+
style=\{{
|
|
113
|
+
padding: 'var(--space-3) var(--space-4)',
|
|
114
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
115
|
+
border: '1px solid var(--danger)',
|
|
116
|
+
background: 'transparent',
|
|
117
|
+
color: 'var(--danger)',
|
|
118
|
+
fontWeight: 600,
|
|
119
|
+
cursor: 'pointer',
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
Kill switch
|
|
123
|
+
</button>
|
|
124
|
+
</section>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
@@ -1,123 +1,100 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { useAuth } from '@githat/nextjs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* AI Agent template — Web4 identity, MCP, public verification.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The pitch: every other auth platform stops at humans. GitHat
|
|
10
|
+
* extends identity to autonomous agents — wallet-bound (Ethereum
|
|
11
|
+
* sigs), capability-scoped, kill-switchable, audit-logged. Anyone
|
|
12
|
+
* can verify an agent at /verify/agent/<wallet>.
|
|
13
|
+
*
|
|
14
|
+
* This template is the agent operator's dashboard, plus the public
|
|
15
|
+
* /verify endpoint anyone can hit to check an agent's status.
|
|
12
16
|
*/
|
|
13
17
|
export default function Home() {
|
|
14
|
-
const { isSignedIn
|
|
15
|
-
|
|
16
|
-
if (isLoading) {
|
|
17
|
-
return (
|
|
18
|
-
<div
|
|
19
|
-
style=\{{
|
|
20
|
-
display: 'flex',
|
|
21
|
-
minHeight: 'calc(100vh - 64px)',
|
|
22
|
-
alignItems: 'center',
|
|
23
|
-
justifyContent: 'center',
|
|
24
|
-
color: 'var(--fg-muted)',
|
|
25
|
-
}}
|
|
26
|
-
>
|
|
27
|
-
Loading…
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
18
|
+
const { isSignedIn } = useAuth();
|
|
31
19
|
|
|
32
20
|
return (
|
|
33
|
-
<div
|
|
34
|
-
style=\{{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
21
|
+
<div style=\{{ background: 'var(--bg)', color: 'var(--fg)', minHeight: 'calc(100vh - 64px)' }}>
|
|
22
|
+
<section style=\{{
|
|
23
|
+
padding: 'var(--space-12) var(--space-4)',
|
|
24
|
+
textAlign: 'center',
|
|
25
|
+
maxWidth: '40rem',
|
|
26
|
+
margin: '0 auto',
|
|
27
|
+
}}>
|
|
28
|
+
<h1 style=\{{
|
|
29
|
+
fontFamily: 'var(--font-wordmark, Georgia, serif)',
|
|
30
|
+
fontSize: 'clamp(2rem, 5vw, 3rem)',
|
|
31
|
+
lineHeight: 1.1,
|
|
32
|
+
marginBottom: 'var(--space-3)',
|
|
33
|
+
}}>
|
|
34
|
+
{{businessName}}
|
|
35
|
+
</h1>
|
|
36
|
+
<p style=\{{ color: 'var(--fg-muted)', fontSize: '1.125rem', marginBottom: 'var(--space-6)' }}>
|
|
37
|
+
Wallet-bound identity for autonomous AI agents. Capability
|
|
38
|
+
scoping, kill switch, audit trail — and a public /verify
|
|
39
|
+
endpoint anyone can hit.
|
|
40
|
+
</p>
|
|
51
41
|
{!isSignedIn ? (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<p
|
|
64
|
-
style=\{{
|
|
65
|
-
color: 'var(--fg-muted)',
|
|
66
|
-
marginBottom: 'var(--space-6)',
|
|
67
|
-
lineHeight: 1.6,
|
|
68
|
-
}}
|
|
69
|
-
>
|
|
70
|
-
Sign in to continue, or create an account in 30 seconds.
|
|
71
|
-
We use GitHat for identity — your password never touches
|
|
72
|
-
this app.
|
|
73
|
-
</p>
|
|
74
|
-
<div
|
|
75
|
-
style=\{{
|
|
76
|
-
display: 'flex',
|
|
77
|
-
gap: 'var(--space-3)',
|
|
78
|
-
justifyContent: 'center',
|
|
79
|
-
flexWrap: 'wrap',
|
|
80
|
-
}}
|
|
81
|
-
>
|
|
82
|
-
<SignInButton />
|
|
83
|
-
<SignUpButton />
|
|
84
|
-
</div>
|
|
85
|
-
</>
|
|
42
|
+
<Link href="/sign-up" style=\{{
|
|
43
|
+
display: 'inline-block',
|
|
44
|
+
padding: 'var(--space-3) var(--space-6)',
|
|
45
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
46
|
+
background: 'var(--primary)',
|
|
47
|
+
color: 'var(--bg)',
|
|
48
|
+
fontWeight: 600,
|
|
49
|
+
textDecoration: 'none',
|
|
50
|
+
}}>
|
|
51
|
+
Register an agent →
|
|
52
|
+
</Link>
|
|
86
53
|
) : (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<h1
|
|
99
|
-
style=\{{
|
|
100
|
-
fontFamily: 'var(--font-wordmark)',
|
|
101
|
-
fontSize: '2rem',
|
|
102
|
-
margin: 0,
|
|
103
|
-
}}
|
|
104
|
-
>
|
|
105
|
-
Hello{user?.name ? `, ${user.name}` : ''}.
|
|
106
|
-
</h1>
|
|
107
|
-
</div>
|
|
108
|
-
<p
|
|
109
|
-
style=\{{
|
|
110
|
-
color: 'var(--fg-muted)',
|
|
111
|
-
lineHeight: 1.6,
|
|
112
|
-
}}
|
|
113
|
-
>
|
|
114
|
-
That's it. The plain template doesn't ship a dashboard or
|
|
115
|
-
any other route — replace this page with whatever your
|
|
116
|
-
app actually does. Authentication will keep working.
|
|
117
|
-
</p>
|
|
118
|
-
</>
|
|
54
|
+
<Link href="/admin/agent" style=\{{
|
|
55
|
+
display: 'inline-block',
|
|
56
|
+
padding: 'var(--space-3) var(--space-6)',
|
|
57
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
58
|
+
background: 'var(--primary)',
|
|
59
|
+
color: 'var(--bg)',
|
|
60
|
+
fontWeight: 600,
|
|
61
|
+
textDecoration: 'none',
|
|
62
|
+
}}>
|
|
63
|
+
Open agent dashboard →
|
|
64
|
+
</Link>
|
|
119
65
|
)}
|
|
120
|
-
</
|
|
66
|
+
</section>
|
|
67
|
+
|
|
68
|
+
<section style=\{{ padding: 'var(--space-8) var(--space-4)', background: 'var(--surface-sub)' }}>
|
|
69
|
+
<div style=\{{ maxWidth: '48rem', margin: '0 auto' }}>
|
|
70
|
+
<h2 style=\{{ fontSize: '1.5rem', marginBottom: 'var(--space-4)' }}>What you get</h2>
|
|
71
|
+
<ul style=\{{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 'var(--space-3)' }}>
|
|
72
|
+
<Item emoji="🪪" title="Wallet-bound identity" body="Ethereum-style key pair. The agent signs requests; clients verify the signature. No shared secrets to leak." />
|
|
73
|
+
<Item emoji="🎚" title="Capability scopes" body="Each agent can only call the tools you explicitly granted. Add or revoke at any time." />
|
|
74
|
+
<Item emoji="🛑" title="Kill switch" body="One click and the agent is revoked everywhere. Existing tokens stop working immediately." />
|
|
75
|
+
<Item emoji="📜" title="Audit log" body="Every action is logged with timestamp, capability used, and signature. Prove what happened." />
|
|
76
|
+
<Item emoji="🔍" title="Public verification" body="Anyone can hit githat.io/verify/agent/<wallet> and see the agent's status, capabilities, and recent actions." />
|
|
77
|
+
</ul>
|
|
78
|
+
</div>
|
|
79
|
+
</section>
|
|
121
80
|
</div>
|
|
122
81
|
);
|
|
123
82
|
}
|
|
83
|
+
|
|
84
|
+
function Item({ emoji, title, body }: { emoji: string; title: string; body: string }) {
|
|
85
|
+
return (
|
|
86
|
+
<li style=\{{
|
|
87
|
+
display: 'flex',
|
|
88
|
+
gap: 'var(--space-4)',
|
|
89
|
+
padding: 'var(--space-4)',
|
|
90
|
+
borderRadius: 'var(--radius-md, 0.5rem)',
|
|
91
|
+
background: 'var(--surface)',
|
|
92
|
+
}}>
|
|
93
|
+
<span style=\{{ fontSize: '1.5rem' }} aria-hidden>{emoji}</span>
|
|
94
|
+
<div>
|
|
95
|
+
<div style=\{{ fontWeight: 600, marginBottom: 'var(--space-1)' }}>{title}</div>
|
|
96
|
+
<div style=\{{ fontSize: '0.875rem', color: 'var(--fg-muted)' }}>{body}</div>
|
|
97
|
+
</div>
|
|
98
|
+
</li>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SignInForm } from '@githat/nextjs';
|
|
2
|
+
|
|
3
|
+
export default function SignInPage() {
|
|
4
|
+
return (
|
|
5
|
+
<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}}>
|
|
6
|
+
<SignInForm signUpUrl="/sign-up" {{#if includeForgotPassword}}forgotPasswordUrl="/forgot-password"{{/if}} />
|
|
7
|
+
</main>
|
|
8
|
+
);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SignUpForm } from '@githat/nextjs';
|
|
2
|
+
|
|
3
|
+
export default function SignUpPage() {
|
|
4
|
+
return (
|
|
5
|
+
<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}}>
|
|
6
|
+
<SignUpForm signInUrl="/sign-in" />
|
|
7
|
+
</main>
|
|
8
|
+
);
|
|
9
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tailwind v4 — required because @githat/nextjs/styles is processed
|
|
3
|
+
* through @tailwindcss/postcss. Plain doesn't ship utility classes,
|
|
4
|
+
* but the import is needed for the auth pages to render styled.
|
|
5
|
+
*/
|
|
6
|
+
@import "tailwindcss";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Plain template — self-contained globals.
|
|
10
|
+
*
|
|
11
|
+
* Defines the minimum CSS variables a GitHat app uses for layout and
|
|
12
|
+
* the auth-page styling that ships with @githat/nextjs/styles.
|
|
13
|
+
* Override these in your own files when you want a real theme.
|
|
14
|
+
*
|
|
15
|
+
* Light theme by default; flip --bg/--fg for dark.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
:root {
|
|
19
|
+
/* Surface */
|
|
20
|
+
--bg: #ffffff;
|
|
21
|
+
--surface: #fafafa;
|
|
22
|
+
--surface-sub: #f4f4f5;
|
|
23
|
+
|
|
24
|
+
/* Borders */
|
|
25
|
+
--border: #e5e7eb;
|
|
26
|
+
|
|
27
|
+
/* Foreground */
|
|
28
|
+
--fg: #0a0a0a;
|
|
29
|
+
--fg-muted: #525252;
|
|
30
|
+
--fg-subtle: #737373;
|
|
31
|
+
|
|
32
|
+
/* Brand — change these two to re-skin the whole auth flow */
|
|
33
|
+
--primary: #6366f1;
|
|
34
|
+
--accent: #f59e0b;
|
|
35
|
+
|
|
36
|
+
/* Semantic */
|
|
37
|
+
--success: #16a34a;
|
|
38
|
+
--warn: #d97706;
|
|
39
|
+
--danger: #dc2626;
|
|
40
|
+
|
|
41
|
+
/* Spacing — used by @githat/nextjs/styles */
|
|
42
|
+
--space-1: 0.25rem;
|
|
43
|
+
--space-2: 0.5rem;
|
|
44
|
+
--space-3: 0.75rem;
|
|
45
|
+
--space-4: 1rem;
|
|
46
|
+
--space-6: 1.5rem;
|
|
47
|
+
--space-8: 2rem;
|
|
48
|
+
|
|
49
|
+
/* Radius */
|
|
50
|
+
--radius: 0.5rem;
|
|
51
|
+
--radius-md: 0.5rem;
|
|
52
|
+
--radius-lg: 0.75rem;
|
|
53
|
+
|
|
54
|
+
/* Fonts */
|
|
55
|
+
--font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
56
|
+
--font-wordmark: 'Instrument Serif', Georgia, serif;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (prefers-color-scheme: dark) {
|
|
60
|
+
:root {
|
|
61
|
+
--bg: #0a0a0a;
|
|
62
|
+
--surface: #18181b;
|
|
63
|
+
--surface-sub: #27272a;
|
|
64
|
+
--border: #3f3f46;
|
|
65
|
+
--fg: #fafafa;
|
|
66
|
+
--fg-muted: #a1a1aa;
|
|
67
|
+
--fg-subtle: #71717a;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
* {
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
margin: 0;
|
|
74
|
+
padding: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
body {
|
|
78
|
+
font-family: var(--font-sans);
|
|
79
|
+
background: var(--bg);
|
|
80
|
+
color: var(--fg);
|
|
81
|
+
line-height: 1.5;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
a {
|
|
85
|
+
color: inherit;
|
|
86
|
+
text-decoration: none;
|
|
87
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GitHatProvider } from '@githat/nextjs';
|
|
2
|
+
import '@githat/nextjs/styles';
|
|
3
|
+
import './globals.css';
|
|
4
|
+
|
|
5
|
+
export const metadata = {
|
|
6
|
+
title: '{{businessName}}',
|
|
7
|
+
description: '{{description}}',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({ children }{{#if typescript}}: { children: React.ReactNode }{{/if}}) {
|
|
11
|
+
return (
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<body>
|
|
14
|
+
{/*
|
|
15
|
+
Plain template: no @githat/ui dep, no Wordmark. The
|
|
16
|
+
full-kit (`nextjs`) template uses @githat/ui for the
|
|
17
|
+
shared design system; the plain scaffold is the smallest
|
|
18
|
+
working app, so we avoid extra deps.
|
|
19
|
+
*/}
|
|
20
|
+
<GitHatProvider config=\{{
|
|
21
|
+
publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
|
|
22
|
+
signInUrl: '/sign-in',
|
|
23
|
+
signUpUrl: '/sign-up',
|
|
24
|
+
afterSignInUrl: '/',
|
|
25
|
+
afterSignOutUrl: '/',
|
|
26
|
+
}}>
|
|
27
|
+
<header style=\{{
|
|
28
|
+
padding: '1rem 1.5rem',
|
|
29
|
+
borderBottom: '1px solid var(--border, #e5e7eb)',
|
|
30
|
+
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
31
|
+
}}>
|
|
32
|
+
<a href="/" style=\{{ textDecoration: 'none', color: 'inherit', fontWeight: 600 }}>
|
|
33
|
+
{{businessName}}
|
|
34
|
+
</a>
|
|
35
|
+
</header>
|
|
36
|
+
<main>{children}</main>
|
|
37
|
+
</GitHatProvider>
|
|
38
|
+
</body>
|
|
39
|
+
</html>
|
|
40
|
+
);
|
|
41
|
+
}
|