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.
Files changed (40) hide show
  1. package/dist/cli.js +20 -10
  2. package/package.json +1 -1
  3. package/templates/agent/app/admin/agent/page.tsx.hbs +127 -0
  4. package/templates/agent/app/page.tsx.hbs +85 -108
  5. package/templates/classroom/app/(auth)/sign-in/page.tsx.hbs +9 -0
  6. package/templates/classroom/app/(auth)/sign-up/page.tsx.hbs +9 -0
  7. package/templates/classroom/app/globals.css.hbs +87 -0
  8. package/templates/classroom/app/layout.tsx.hbs +41 -0
  9. package/templates/classroom/app/page.tsx.hbs +103 -0
  10. package/templates/classroom/app/projects/[id]/feedback/page.tsx.hbs +159 -0
  11. package/templates/classroom/app/projects/[id]/present/page.tsx.hbs +113 -0
  12. package/templates/classroom/next.config.ts.hbs +7 -0
  13. package/templates/classroom/postcss.config.mjs.hbs +14 -0
  14. package/templates/classroom/proxy.ts.hbs +10 -0
  15. package/templates/classroom/tsconfig.json.hbs +21 -0
  16. package/templates/content/app/newsletter/page.tsx.hbs +90 -0
  17. package/templates/content/app/page.tsx.hbs +93 -111
  18. package/templates/content/app/posts/[slug]/page.tsx.hbs +119 -0
  19. package/templates/dashboard/app/admin/data/[entity]/page.tsx.hbs +68 -0
  20. package/templates/dashboard/app/admin/page.tsx.hbs +59 -0
  21. package/templates/dashboard/app/page.tsx.hbs +42 -108
  22. package/templates/dashboard/src/lib/db.ts.hbs +39 -0
  23. package/templates/portfolio/app/(auth)/sign-in/page.tsx.hbs +9 -0
  24. package/templates/portfolio/app/(auth)/sign-up/page.tsx.hbs +9 -0
  25. package/templates/portfolio/app/globals.css.hbs +87 -0
  26. package/templates/portfolio/app/layout.tsx.hbs +41 -0
  27. package/templates/portfolio/app/page.tsx.hbs +86 -0
  28. package/templates/portfolio/next.config.ts.hbs +7 -0
  29. package/templates/portfolio/postcss.config.mjs.hbs +14 -0
  30. package/templates/portfolio/proxy.ts.hbs +10 -0
  31. package/templates/portfolio/tsconfig.json.hbs +21 -0
  32. package/templates/saas/app/admin/billing/page.tsx.hbs +145 -0
  33. package/templates/saas/app/admin/page.tsx.hbs +106 -0
  34. package/templates/saas/app/admin/team/page.tsx.hbs +134 -0
  35. package/templates/saas/app/page.tsx.hbs +95 -110
  36. package/templates/saas/app/pricing/page.tsx.hbs +131 -0
  37. package/templates/agent/TODO.md +0 -9
  38. package/templates/content/TODO.md +0 -9
  39. package/templates/dashboard/TODO.md +0 -9
  40. 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.15";
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 browsing, Sebastn Connect." },
336
- { value: "agent", label: "AI Agent", hint: "Web4 wallet-bound agent + MCP server. Public verification." },
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-githat-app",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "GitHat CLI — scaffold apps and manage the skills marketplace",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 { SignInButton, SignUpButton, UserButton, useAuth } from '@githat/nextjs';
3
+ import Link from 'next/link';
4
+ import { useAuth } from '@githat/nextjs';
4
5
 
5
6
  /**
6
- * Plain GitHat homepage.
7
+ * AI Agent template — Web4 identity, MCP, public verification.
7
8
  *
8
- * No dashboard, no orgs, no agents just one page that flips between
9
- * "signed out" and "signed in." The smallest possible example of "I
10
- * have GitHat wired up." Replace this file with whatever your app
11
- * actually does auth keeps working.
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, isLoading, user } = useAuth();
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
- display: 'flex',
36
- minHeight: 'calc(100vh - 64px)',
37
- alignItems: 'center',
38
- justifyContent: 'center',
39
- padding: 'var(--space-8) var(--space-4)',
40
- background: 'var(--bg)',
41
- }}
42
- >
43
- <main
44
- style=\{{
45
- width: '100%',
46
- maxWidth: '32rem',
47
- textAlign: 'center',
48
- color: 'var(--fg)',
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
- <h1
54
- style=\{{
55
- fontFamily: 'var(--font-wordmark)',
56
- fontSize: '2.5rem',
57
- lineHeight: 1.1,
58
- marginBottom: 'var(--space-3)',
59
- }}
60
- >
61
- Welcome to {{businessName}}
62
- </h1>
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
- <div
89
- style=\{{
90
- display: 'flex',
91
- alignItems: 'center',
92
- justifyContent: 'center',
93
- gap: 'var(--space-4)',
94
- marginBottom: 'var(--space-6)',
95
- }}
96
- >
97
- <UserButton />
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
- </main>
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
+ }