create-githat-app 1.0.2 → 1.0.4

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 (43) hide show
  1. package/dist/cli.js +316 -99
  2. package/package.json +1 -1
  3. package/templates/fullstack/apps-api-express/.env.example.hbs +6 -0
  4. package/templates/fullstack/apps-api-express/.env.local.hbs +6 -0
  5. package/templates/fullstack/apps-api-express/package.json.hbs +24 -0
  6. package/templates/fullstack/apps-api-express/src/index.ts.hbs +41 -0
  7. package/templates/fullstack/apps-api-express/src/routes/health.ts.hbs +11 -0
  8. package/templates/fullstack/apps-api-express/src/routes/users.ts.hbs +43 -0
  9. package/templates/fullstack/apps-api-express/tsconfig.json.hbs +16 -0
  10. package/templates/fullstack/apps-api-fastify/.env.example.hbs +6 -0
  11. package/templates/fullstack/apps-api-fastify/.env.local.hbs +6 -0
  12. package/templates/fullstack/apps-api-fastify/package.json.hbs +22 -0
  13. package/templates/fullstack/apps-api-fastify/src/index.ts.hbs +28 -0
  14. package/templates/fullstack/apps-api-fastify/src/routes/health.ts.hbs +11 -0
  15. package/templates/fullstack/apps-api-fastify/src/routes/users.ts.hbs +43 -0
  16. package/templates/fullstack/apps-api-fastify/tsconfig.json.hbs +16 -0
  17. package/templates/fullstack/apps-api-hono/.env.example.hbs +6 -0
  18. package/templates/fullstack/apps-api-hono/.env.local.hbs +6 -0
  19. package/templates/fullstack/apps-api-hono/package.json.hbs +22 -0
  20. package/templates/fullstack/apps-api-hono/src/index.ts.hbs +35 -0
  21. package/templates/fullstack/apps-api-hono/src/routes/health.ts.hbs +11 -0
  22. package/templates/fullstack/apps-api-hono/src/routes/users.ts.hbs +43 -0
  23. package/templates/fullstack/apps-api-hono/tsconfig.json.hbs +16 -0
  24. package/templates/fullstack/apps-web-nextjs/.env.example.hbs +5 -0
  25. package/templates/fullstack/apps-web-nextjs/.env.local.hbs +5 -0
  26. package/templates/fullstack/apps-web-nextjs/app/(auth)/forgot-password/page.tsx.hbs +11 -0
  27. package/templates/fullstack/apps-web-nextjs/app/(auth)/reset-password/page.tsx.hbs +11 -0
  28. package/templates/fullstack/apps-web-nextjs/app/(auth)/sign-in/page.tsx.hbs +9 -0
  29. package/templates/fullstack/apps-web-nextjs/app/(auth)/sign-up/page.tsx.hbs +9 -0
  30. package/templates/fullstack/apps-web-nextjs/app/(auth)/verify-email/page.tsx.hbs +11 -0
  31. package/templates/fullstack/apps-web-nextjs/app/dashboard/layout.tsx.hbs +9 -0
  32. package/templates/fullstack/apps-web-nextjs/app/dashboard/page.tsx.hbs +27 -0
  33. package/templates/fullstack/apps-web-nextjs/app/globals.css.hbs +20 -0
  34. package/templates/fullstack/apps-web-nextjs/app/layout.tsx.hbs +26 -0
  35. package/templates/fullstack/apps-web-nextjs/app/page.tsx.hbs +18 -0
  36. package/templates/fullstack/apps-web-nextjs/next.config.ts.hbs +15 -0
  37. package/templates/fullstack/apps-web-nextjs/package.json.hbs +33 -0
  38. package/templates/fullstack/apps-web-nextjs/postcss.config.mjs.hbs +9 -0
  39. package/templates/fullstack/apps-web-nextjs/tsconfig.json.hbs +21 -0
  40. package/templates/fullstack/root/.gitignore.hbs +42 -0
  41. package/templates/fullstack/root/githat.yaml.hbs +17 -0
  42. package/templates/fullstack/root/package.json.hbs +15 -0
  43. package/templates/fullstack/root/turbo.json.hbs +20 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-githat-app",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "GitHat CLI — scaffold apps and manage the skills marketplace",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY=pk_live_your_key_here
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY={{#if publishableKey}}{{publishableKey}}{{else}}pk_live_your_key_here{{/if}}
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@{{projectName}}/api",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@githat/nextjs": "^0.2.2",
14
+ "cors": "^2.8.5",
15
+ "express": "^5.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/cors": "^2.8.17",
19
+ "@types/express": "^5.0.0",
20
+ "@types/node": "^22.0.0",
21
+ "tsx": "^4.19.0",
22
+ "typescript": "^5.9.0"
23
+ }
24
+ }
@@ -0,0 +1,41 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { healthRoutes } from './routes/health.js';
4
+ import { userRoutes } from './routes/users.js';
5
+
6
+ const app = express();
7
+
8
+ // Middleware
9
+ app.use(express.json());
10
+ app.use(cors({
11
+ origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
12
+ credentials: true,
13
+ }));
14
+
15
+ // Request logging
16
+ app.use((req, res, next) => {
17
+ console.log(`${req.method} ${req.path}`);
18
+ next();
19
+ });
20
+
21
+ // Routes
22
+ app.use('/health', healthRoutes);
23
+ app.use('/users', userRoutes);
24
+
25
+ // 404 handler
26
+ app.use((req, res) => {
27
+ res.status(404).json({ error: 'Not found' });
28
+ });
29
+
30
+ // Error handler
31
+ app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
32
+ console.error(err);
33
+ res.status(500).json({ error: 'Internal server error' });
34
+ });
35
+
36
+ const port = Number(process.env.PORT) || 3001;
37
+ app.listen(port, () => {
38
+ console.log(`🚀 API server running at http://localhost:${port}`);
39
+ });
40
+
41
+ export default app;
@@ -0,0 +1,11 @@
1
+ import { Router } from 'express';
2
+
3
+ export const healthRoutes = Router();
4
+
5
+ healthRoutes.get('/', (req, res) => {
6
+ res.json({
7
+ status: 'ok',
8
+ timestamp: new Date().toISOString(),
9
+ service: '{{projectName}}-api',
10
+ });
11
+ });
@@ -0,0 +1,43 @@
1
+ import { Router } from 'express';
2
+
3
+ export const userRoutes = Router();
4
+
5
+ // Example protected route - verify GitHat tokens here
6
+ userRoutes.get('/me', async (req, res) => {
7
+ // Get the Authorization header
8
+ const authHeader = req.headers.authorization;
9
+ if (!authHeader?.startsWith('Bearer ')) {
10
+ return res.status(401).json({ error: 'Unauthorized' });
11
+ }
12
+
13
+ const token = authHeader.slice(7);
14
+
15
+ // Verify the token with GitHat API
16
+ try {
17
+ const response = await fetch('{{apiUrl}}/auth/verify', {
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ 'X-Publishable-Key': process.env.GITHAT_PUBLISHABLE_KEY || '',
22
+ },
23
+ body: JSON.stringify({ token }),
24
+ });
25
+
26
+ if (!response.ok) {
27
+ return res.status(401).json({ error: 'Invalid token' });
28
+ }
29
+
30
+ const { user, org } = await response.json();
31
+ return res.json({ user, org });
32
+ } catch (error) {
33
+ console.error('Token verification failed:', error);
34
+ return res.status(500).json({ error: 'Authentication failed' });
35
+ }
36
+ });
37
+
38
+ // Example: Get user profile
39
+ userRoutes.get('/:id', async (req, res) => {
40
+ const { id } = req.params;
41
+ // TODO: Implement user lookup
42
+ res.json({ id, message: 'User lookup not implemented' });
43
+ });
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "resolveJsonModule": true
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY=pk_live_your_key_here
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY={{#if publishableKey}}{{publishableKey}}{{else}}pk_live_your_key_here{{/if}}
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@{{projectName}}/api",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@fastify/cors": "^10.0.0",
14
+ "@githat/nextjs": "^0.2.2",
15
+ "fastify": "^5.2.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^22.0.0",
19
+ "tsx": "^4.19.0",
20
+ "typescript": "^5.9.0"
21
+ }
22
+ }
@@ -0,0 +1,28 @@
1
+ import Fastify from 'fastify';
2
+ import cors from '@fastify/cors';
3
+ import { healthRoutes } from './routes/health.js';
4
+ import { userRoutes } from './routes/users.js';
5
+
6
+ const app = Fastify({ logger: true });
7
+
8
+ // Middleware
9
+ await app.register(cors, {
10
+ origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
11
+ credentials: true,
12
+ });
13
+
14
+ // Routes
15
+ await app.register(healthRoutes, { prefix: '/health' });
16
+ await app.register(userRoutes, { prefix: '/users' });
17
+
18
+ // Start server
19
+ const port = Number(process.env.PORT) || 3001;
20
+ try {
21
+ await app.listen({ port, host: '0.0.0.0' });
22
+ console.log(`🚀 API server running at http://localhost:${port}`);
23
+ } catch (err) {
24
+ app.log.error(err);
25
+ process.exit(1);
26
+ }
27
+
28
+ export default app;
@@ -0,0 +1,11 @@
1
+ import type { FastifyPluginAsync } from 'fastify';
2
+
3
+ export const healthRoutes: FastifyPluginAsync = async (app) => {
4
+ app.get('/', async () => {
5
+ return {
6
+ status: 'ok',
7
+ timestamp: new Date().toISOString(),
8
+ service: '{{projectName}}-api',
9
+ };
10
+ });
11
+ };
@@ -0,0 +1,43 @@
1
+ import type { FastifyPluginAsync } from 'fastify';
2
+
3
+ export const userRoutes: FastifyPluginAsync = async (app) => {
4
+ // Example protected route - verify GitHat tokens here
5
+ app.get('/me', async (request, reply) => {
6
+ // Get the Authorization header
7
+ const authHeader = request.headers.authorization;
8
+ if (!authHeader?.startsWith('Bearer ')) {
9
+ return reply.status(401).send({ error: 'Unauthorized' });
10
+ }
11
+
12
+ const token = authHeader.slice(7);
13
+
14
+ // Verify the token with GitHat API
15
+ try {
16
+ const response = await fetch('{{apiUrl}}/auth/verify', {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'X-Publishable-Key': process.env.GITHAT_PUBLISHABLE_KEY || '',
21
+ },
22
+ body: JSON.stringify({ token }),
23
+ });
24
+
25
+ if (!response.ok) {
26
+ return reply.status(401).send({ error: 'Invalid token' });
27
+ }
28
+
29
+ const { user, org } = await response.json();
30
+ return { user, org };
31
+ } catch (error) {
32
+ app.log.error('Token verification failed:', error);
33
+ return reply.status(500).send({ error: 'Authentication failed' });
34
+ }
35
+ });
36
+
37
+ // Example: Get user profile
38
+ app.get<{ Params: { id: string } }>('/:id', async (request) => {
39
+ const { id } = request.params;
40
+ // TODO: Implement user lookup
41
+ return { id, message: 'User lookup not implemented' };
42
+ });
43
+ };
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "resolveJsonModule": true
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY=pk_live_your_key_here
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,6 @@
1
+ # GitHat Configuration
2
+ GITHAT_PUBLISHABLE_KEY={{#if publishableKey}}{{publishableKey}}{{else}}pk_live_your_key_here{{/if}}
3
+
4
+ # Server
5
+ PORT=3001
6
+ CORS_ORIGIN=http://localhost:3000
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@{{projectName}}/api",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@githat/nextjs": "^0.2.2",
14
+ "@hono/node-server": "^1.13.0",
15
+ "hono": "^4.6.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^22.0.0",
19
+ "tsx": "^4.19.0",
20
+ "typescript": "^5.9.0"
21
+ }
22
+ }
@@ -0,0 +1,35 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { Hono } from 'hono';
3
+ import { cors } from 'hono/cors';
4
+ import { logger } from 'hono/logger';
5
+ import { healthRoutes } from './routes/health.js';
6
+ import { userRoutes } from './routes/users.js';
7
+
8
+ const app = new Hono();
9
+
10
+ // Middleware
11
+ app.use('*', logger());
12
+ app.use('*', cors({
13
+ origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
14
+ credentials: true,
15
+ }));
16
+
17
+ // Routes
18
+ app.route('/health', healthRoutes);
19
+ app.route('/users', userRoutes);
20
+
21
+ // 404 handler
22
+ app.notFound((c) => c.json({ error: 'Not found' }, 404));
23
+
24
+ // Error handler
25
+ app.onError((err, c) => {
26
+ console.error(err);
27
+ return c.json({ error: 'Internal server error' }, 500);
28
+ });
29
+
30
+ const port = Number(process.env.PORT) || 3001;
31
+ console.log(`🚀 API server running at http://localhost:${port}`);
32
+
33
+ serve({ fetch: app.fetch, port });
34
+
35
+ export default app;
@@ -0,0 +1,11 @@
1
+ import { Hono } from 'hono';
2
+
3
+ export const healthRoutes = new Hono();
4
+
5
+ healthRoutes.get('/', (c) => {
6
+ return c.json({
7
+ status: 'ok',
8
+ timestamp: new Date().toISOString(),
9
+ service: '{{projectName}}-api',
10
+ });
11
+ });
@@ -0,0 +1,43 @@
1
+ import { Hono } from 'hono';
2
+
3
+ // Example protected route - verify GitHat tokens here
4
+ export const userRoutes = new Hono();
5
+
6
+ userRoutes.get('/me', async (c) => {
7
+ // Get the Authorization header
8
+ const authHeader = c.req.header('Authorization');
9
+ if (!authHeader?.startsWith('Bearer ')) {
10
+ return c.json({ error: 'Unauthorized' }, 401);
11
+ }
12
+
13
+ const token = authHeader.slice(7);
14
+
15
+ // Verify the token with GitHat API
16
+ try {
17
+ const response = await fetch('{{apiUrl}}/auth/verify', {
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ 'X-Publishable-Key': process.env.GITHAT_PUBLISHABLE_KEY || '',
22
+ },
23
+ body: JSON.stringify({ token }),
24
+ });
25
+
26
+ if (!response.ok) {
27
+ return c.json({ error: 'Invalid token' }, 401);
28
+ }
29
+
30
+ const { user, org } = await response.json();
31
+ return c.json({ user, org });
32
+ } catch (error) {
33
+ console.error('Token verification failed:', error);
34
+ return c.json({ error: 'Authentication failed' }, 500);
35
+ }
36
+ });
37
+
38
+ // Example: Get user profile
39
+ userRoutes.get('/:id', async (c) => {
40
+ const id = c.req.param('id');
41
+ // TODO: Implement user lookup
42
+ return c.json({ id, message: 'User lookup not implemented' });
43
+ });
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true,
12
+ "resolveJsonModule": true
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,5 @@
1
+ # GitHat Configuration
2
+ NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY=pk_live_your_key_here
3
+
4
+ # API URL
5
+ NEXT_PUBLIC_API_URL=http://localhost:3001
@@ -0,0 +1,5 @@
1
+ # GitHat Configuration
2
+ NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY={{#if publishableKey}}{{publishableKey}}{{else}}pk_live_your_key_here{{/if}}
3
+
4
+ # API URL (points to the api app)
5
+ NEXT_PUBLIC_API_URL=http://localhost:3001
@@ -0,0 +1,11 @@
1
+ {{#if includeForgotPassword}}
2
+ import { ForgotPasswordForm } from '@githat/nextjs';
3
+
4
+ export default function ForgotPasswordPage() {
5
+ return (
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}}>
7
+ <ForgotPasswordForm signInUrl="/sign-in" />
8
+ </main>
9
+ );
10
+ }
11
+ {{/if}}
@@ -0,0 +1,11 @@
1
+ {{#if includeForgotPassword}}
2
+ import { ResetPasswordForm } from '@githat/nextjs';
3
+
4
+ export default function ResetPasswordPage() {
5
+ return (
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}}>
7
+ <ResetPasswordForm signInUrl="/sign-in" />
8
+ </main>
9
+ );
10
+ }
11
+ {{/if}}
@@ -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,11 @@
1
+ {{#if includeEmailVerification}}
2
+ import { VerifyEmailStatus } from '@githat/nextjs';
3
+
4
+ export default function VerifyEmailPage() {
5
+ return (
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}}>
7
+ <VerifyEmailStatus afterVerifyUrl="/dashboard" />
8
+ </main>
9
+ );
10
+ }
11
+ {{/if}}
@@ -0,0 +1,9 @@
1
+ {{#if includeDashboard}}
2
+ import { withAuth } from '@githat/nextjs/server';
3
+
4
+ async function DashboardLayout({ children }{{#if typescript}}: { children: React.ReactNode }{{/if}}) {
5
+ return <>{children}</>;
6
+ }
7
+
8
+ export default withAuth(DashboardLayout);
9
+ {{/if}}
@@ -0,0 +1,27 @@
1
+ {{#if includeDashboard}}
2
+ 'use client';
3
+ import { useGitHat, UserButton } from '@githat/nextjs';
4
+
5
+ export default function DashboardPage() {
6
+ const { user, org } = useGitHat();
7
+
8
+ return (
9
+ <div {{#if useTailwind}}className="p-8"{{else}}style=\{{ padding: '2rem' }}{{/if}}>
10
+ <div {{#if useTailwind}}className="flex justify-between items-center mb-8"{{else}}style=\{{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '2rem' }}{{/if}}>
11
+ <h1 {{#if useTailwind}}className="text-2xl font-bold"{{else}}style=\{{ fontSize: '1.5rem', fontWeight: 700 }}{{/if}}>Dashboard</h1>
12
+ <UserButton />
13
+ </div>
14
+ <div {{#if useTailwind}}className="grid gap-4 md:grid-cols-2"{{else}}style=\{{ display: 'grid', gap: '1rem' }}{{/if}}>
15
+ <div {{#if useTailwind}}className="p-4 rounded-lg border border-zinc-800 bg-zinc-900"{{else}}style=\{{ padding: '1rem', borderRadius: '0.5rem', border: '1px solid #27272a', background: '#18181b' }}{{/if}}>
16
+ <h2 {{#if useTailwind}}className="font-semibold mb-2"{{else}}style=\{{ fontWeight: 600, marginBottom: '0.5rem' }}{{/if}}>User</h2>
17
+ <p {{#if useTailwind}}className="text-zinc-400"{{else}}style=\{{ color: '#a1a1aa' }}{{/if}}>{user?.email}</p>
18
+ </div>
19
+ <div {{#if useTailwind}}className="p-4 rounded-lg border border-zinc-800 bg-zinc-900"{{else}}style=\{{ padding: '1rem', borderRadius: '0.5rem', border: '1px solid #27272a', background: '#18181b' }}{{/if}}>
20
+ <h2 {{#if useTailwind}}className="font-semibold mb-2"{{else}}style=\{{ fontWeight: 600, marginBottom: '0.5rem' }}{{/if}}>Organization</h2>
21
+ <p {{#if useTailwind}}className="text-zinc-400"{{else}}style=\{{ color: '#a1a1aa' }}{{/if}}>{org?.name || 'Personal'}</p>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ );
26
+ }
27
+ {{/if}}
@@ -0,0 +1,20 @@
1
+ {{#if useTailwind}}
2
+ @import "tailwindcss";
3
+ {{/if}}
4
+
5
+ * {
6
+ box-sizing: border-box;
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ body {
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
13
+ background: #09090b;
14
+ color: #fafafa;
15
+ }
16
+
17
+ a {
18
+ color: inherit;
19
+ text-decoration: none;
20
+ }
@@ -0,0 +1,26 @@
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
+ <GitHatProvider config=\{{
15
+ publishableKey: process.env.NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY || '',
16
+ signInUrl: '/sign-in',
17
+ signUpUrl: '/sign-up',
18
+ afterSignInUrl: '/dashboard',
19
+ afterSignOutUrl: '/',
20
+ }}>
21
+ {children}
22
+ </GitHatProvider>
23
+ </body>
24
+ </html>
25
+ );
26
+ }
@@ -0,0 +1,18 @@
1
+ import { SignInButton, SignUpButton } from '@githat/nextjs';
2
+
3
+ export default function Home() {
4
+ return (
5
+ <main {{#if useTailwind}}className="flex flex-col items-center justify-center min-h-screen gap-6 bg-[#09090b] text-[#fafafa]"{{else}}style=\{{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', gap: '1.5rem', background: '#09090b', color: '#fafafa' }}{{/if}}>
6
+ <h1 {{#if useTailwind}}className="text-4xl font-bold"{{else}}style=\{{ fontSize: '2.5rem', fontWeight: 700 }}{{/if}}>
7
+ Welcome to {{businessName}}
8
+ </h1>
9
+ <p {{#if useTailwind}}className="text-zinc-400 max-w-lg text-center"{{else}}style=\{{ color: '#a1a1aa', maxWidth: '32rem', textAlign: 'center' }}{{/if}}>
10
+ {{description}}
11
+ </p>
12
+ <div {{#if useTailwind}}className="flex gap-4"{{else}}style=\{{ display: 'flex', gap: '1rem' }}{{/if}}>
13
+ <SignInButton />
14
+ <SignUpButton />
15
+ </div>
16
+ </main>
17
+ );
18
+ }
@@ -0,0 +1,15 @@
1
+ import type { NextConfig } from 'next';
2
+
3
+ const nextConfig: NextConfig = {
4
+ // Proxy API calls to the backend in development
5
+ async rewrites() {
6
+ return [
7
+ {
8
+ source: '/api/:path*',
9
+ destination: `${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'}/:path*`,
10
+ },
11
+ ];
12
+ },
13
+ };
14
+
15
+ export default nextConfig;