forgedev 1.2.0 → 1.3.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.
Files changed (171) hide show
  1. package/README.md +57 -10
  2. package/bin/chainproof.js +126 -0
  3. package/package.json +25 -7
  4. package/src/chainproof-bridge.js +330 -0
  5. package/src/ci-mode.js +85 -0
  6. package/src/claude-configurator.js +86 -49
  7. package/src/cli.js +30 -7
  8. package/src/composer.js +159 -34
  9. package/src/doctor-checks-chainproof.js +106 -0
  10. package/src/doctor-checks.js +39 -20
  11. package/src/doctor-prompts.js +9 -9
  12. package/src/doctor.js +37 -4
  13. package/src/guided.js +3 -3
  14. package/src/index.js +31 -10
  15. package/src/init-mode.js +64 -11
  16. package/src/menu.js +178 -0
  17. package/src/prompts.js +5 -12
  18. package/src/recommender.js +134 -10
  19. package/src/scanner.js +57 -2
  20. package/src/uat-generator.js +204 -189
  21. package/src/update-check.js +9 -4
  22. package/src/update.js +1 -1
  23. package/src/utils.js +64 -5
  24. package/templates/ai/guardrails-py/backend/app/ai/__init__.py +29 -0
  25. package/templates/ai/guardrails-py/backend/app/ai/audit_log.py +133 -0
  26. package/templates/ai/guardrails-py/backend/app/ai/client.py.template +323 -0
  27. package/templates/ai/guardrails-py/backend/app/ai/health.py.template +157 -0
  28. package/templates/ai/guardrails-py/backend/app/ai/input_guard.py +98 -0
  29. package/templates/ai/guardrails-ts/src/lib/ai/audit-log.ts.template +164 -0
  30. package/templates/ai/guardrails-ts/src/lib/ai/client.ts.template +403 -0
  31. package/templates/ai/guardrails-ts/src/lib/ai/health.ts.template +165 -0
  32. package/templates/ai/guardrails-ts/src/lib/ai/index.ts.template +17 -0
  33. package/templates/ai/guardrails-ts/src/lib/ai/input-guard.ts.template +124 -0
  34. package/templates/auth/nextauth/src/lib/auth.ts.template +12 -7
  35. package/templates/backend/express/Dockerfile.template +18 -0
  36. package/templates/backend/express/package.json.template +33 -0
  37. package/templates/backend/express/src/index.ts.template +34 -0
  38. package/templates/backend/express/src/routes/health.ts.template +27 -0
  39. package/templates/backend/express/tsconfig.json +17 -0
  40. package/templates/backend/fastapi/backend/Dockerfile.template +5 -0
  41. package/templates/backend/fastapi/backend/app/api/health.py.template +1 -1
  42. package/templates/backend/fastapi/backend/app/core/config.py.template +1 -1
  43. package/templates/backend/fastapi/backend/app/core/errors.py +1 -1
  44. package/templates/backend/fastapi/backend/app/main.py.template +3 -1
  45. package/templates/backend/fastapi/backend/requirements.txt.template +2 -0
  46. package/templates/backend/hono/Dockerfile.template +18 -0
  47. package/templates/backend/hono/package.json.template +31 -0
  48. package/templates/backend/hono/src/index.ts.template +32 -0
  49. package/templates/backend/hono/src/routes/health.ts.template +27 -0
  50. package/templates/backend/hono/tsconfig.json +18 -0
  51. package/templates/base/docs/uat/UAT_TEMPLATE.md.template +1 -1
  52. package/templates/chainproof/base/.chainproof/config.json.template +11 -0
  53. package/templates/chainproof/base/.chainproof/mcp-server.mjs +310 -0
  54. package/templates/chainproof/base/.mcp.json +9 -0
  55. package/templates/chainproof/fastapi/.chainproof/middleware.json.template +14 -0
  56. package/templates/chainproof/nextjs/.chainproof/hooks.json.template +19 -0
  57. package/templates/chainproof/polyglot/.chainproof/config.json.template +21 -0
  58. package/templates/claude-code/agents/architect.md +25 -11
  59. package/templates/claude-code/agents/build-error-resolver.md +19 -5
  60. package/templates/claude-code/agents/chief-of-staff.md +42 -8
  61. package/templates/claude-code/agents/code-quality-reviewer.md +14 -0
  62. package/templates/claude-code/agents/database-reviewer.md +15 -1
  63. package/templates/claude-code/agents/deep-reviewer.md +191 -0
  64. package/templates/claude-code/agents/doc-updater.md +19 -5
  65. package/templates/claude-code/agents/docs-lookup.md +19 -5
  66. package/templates/claude-code/agents/e2e-runner.md +26 -12
  67. package/templates/claude-code/agents/enforcement-gate.md +102 -0
  68. package/templates/claude-code/agents/frontend-builder.md +188 -0
  69. package/templates/claude-code/agents/harness-optimizer.md +36 -1
  70. package/templates/claude-code/agents/loop-operator.md +27 -13
  71. package/templates/claude-code/agents/planner.md +21 -7
  72. package/templates/claude-code/agents/product-strategist.md +24 -10
  73. package/templates/claude-code/agents/production-readiness.md +14 -0
  74. package/templates/claude-code/agents/prompt-auditor.md +115 -0
  75. package/templates/claude-code/agents/refactor-cleaner.md +22 -8
  76. package/templates/claude-code/agents/security-reviewer.md +14 -0
  77. package/templates/claude-code/agents/spec-validator.md +15 -1
  78. package/templates/claude-code/agents/tdd-guide.md +21 -7
  79. package/templates/claude-code/agents/uat-validator.md +14 -0
  80. package/templates/claude-code/claude-md/base.md +14 -7
  81. package/templates/claude-code/claude-md/fastapi.md +8 -8
  82. package/templates/claude-code/claude-md/fullstack.md +6 -6
  83. package/templates/claude-code/claude-md/hono.md +18 -0
  84. package/templates/claude-code/claude-md/nextjs.md +5 -5
  85. package/templates/claude-code/claude-md/remix.md +18 -0
  86. package/templates/claude-code/commands/audit-security.md +14 -0
  87. package/templates/claude-code/commands/audit-spec.md +14 -0
  88. package/templates/claude-code/commands/audit-wiring.md +14 -0
  89. package/templates/claude-code/commands/build-fix.md +28 -0
  90. package/templates/claude-code/commands/build-ui.md +59 -0
  91. package/templates/claude-code/commands/code-review.md +53 -31
  92. package/templates/claude-code/commands/fix-loop.md +211 -0
  93. package/templates/claude-code/commands/full-audit.md +36 -8
  94. package/templates/claude-code/commands/generate-prd.md +1 -1
  95. package/templates/claude-code/commands/generate-sdd.md +74 -0
  96. package/templates/claude-code/commands/generate-uat.md +107 -35
  97. package/templates/claude-code/commands/help.md +68 -0
  98. package/templates/claude-code/commands/live-uat.md +268 -0
  99. package/templates/claude-code/commands/optimize-claude-md.md +15 -1
  100. package/templates/claude-code/commands/plan.md +3 -3
  101. package/templates/claude-code/commands/pre-pr.md +57 -19
  102. package/templates/claude-code/commands/product-strategist.md +21 -0
  103. package/templates/claude-code/commands/resume-session.md +10 -10
  104. package/templates/claude-code/commands/run-uat.md +59 -2
  105. package/templates/claude-code/commands/save-session.md +10 -10
  106. package/templates/claude-code/commands/simplify.md +36 -0
  107. package/templates/claude-code/commands/tdd.md +17 -18
  108. package/templates/claude-code/commands/verify-all.md +24 -0
  109. package/templates/claude-code/commands/verify-intent.md +55 -0
  110. package/templates/claude-code/commands/workflows.md +52 -40
  111. package/templates/claude-code/hooks/polyglot.json +10 -1
  112. package/templates/claude-code/hooks/python.json +10 -1
  113. package/templates/claude-code/hooks/scripts/autofix-polyglot.mjs +2 -2
  114. package/templates/claude-code/hooks/scripts/autofix-python.mjs +1 -1
  115. package/templates/claude-code/hooks/scripts/autofix-typescript.mjs +1 -1
  116. package/templates/claude-code/hooks/scripts/code-hygiene.mjs +293 -0
  117. package/templates/claude-code/hooks/scripts/pre-commit-gate.mjs +207 -0
  118. package/templates/claude-code/hooks/typescript.json +10 -1
  119. package/templates/claude-code/skills/ai-prompts/SKILL.md +119 -41
  120. package/templates/claude-code/skills/git-workflow/SKILL.md +5 -5
  121. package/templates/claude-code/skills/nextjs/SKILL.md +1 -1
  122. package/templates/claude-code/skills/playwright/SKILL.md +5 -5
  123. package/templates/claude-code/skills/security-api/SKILL.md +1 -1
  124. package/templates/claude-code/skills/security-web/SKILL.md +1 -1
  125. package/templates/claude-code/skills/testing-patterns/SKILL.md +9 -9
  126. package/templates/database/prisma-postgres/{.env.example → .env.example.template} +1 -0
  127. package/templates/database/sqlalchemy-postgres/{.env.example → .env.example.template} +1 -0
  128. package/templates/docs-portal/fastapi/backend/app/portal/__pycache__/docs_reader.cpython-314.pyc +0 -0
  129. package/templates/docs-portal/fastapi/backend/app/portal/docs_reader.py +201 -0
  130. package/templates/docs-portal/fastapi/backend/app/portal/html_renderer.py +229 -0
  131. package/templates/docs-portal/fastapi/backend/app/portal/router.py.template +35 -0
  132. package/templates/docs-portal/nextjs/src/app/portal/[category]/[slug]/page.tsx +81 -0
  133. package/templates/docs-portal/nextjs/src/app/portal/[category]/page.tsx +65 -0
  134. package/templates/docs-portal/nextjs/src/app/portal/layout.tsx.template +54 -0
  135. package/templates/docs-portal/nextjs/src/app/portal/page.tsx +85 -0
  136. package/templates/docs-portal/nextjs/src/components/portal/markdown-renderer.tsx +101 -0
  137. package/templates/docs-portal/nextjs/src/components/portal/mobile-portal-nav.tsx +81 -0
  138. package/templates/docs-portal/nextjs/src/components/portal/portal-nav.tsx +86 -0
  139. package/templates/docs-portal/nextjs/src/lib/docs.ts +139 -0
  140. package/templates/frontend/nextjs/package.json.template +3 -1
  141. package/templates/frontend/react/index.html.template +12 -0
  142. package/templates/frontend/react/package.json.template +34 -0
  143. package/templates/frontend/react/src/App.tsx.template +10 -0
  144. package/templates/frontend/react/src/index.css +1 -0
  145. package/templates/frontend/react/src/main.tsx +10 -0
  146. package/templates/frontend/react/tsconfig.json +17 -0
  147. package/templates/frontend/react/vite.config.ts.template +15 -0
  148. package/templates/frontend/react/vitest.config.ts +9 -0
  149. package/templates/frontend/remix/app/root.tsx.template +31 -0
  150. package/templates/frontend/remix/app/routes/_index.tsx.template +19 -0
  151. package/templates/frontend/remix/app/routes/api.health.ts.template +10 -0
  152. package/templates/frontend/remix/app/tailwind.css +1 -0
  153. package/templates/frontend/remix/package.json.template +39 -0
  154. package/templates/frontend/remix/tsconfig.json +18 -0
  155. package/templates/frontend/remix/vite.config.ts.template +7 -0
  156. package/templates/infra/github-actions/.github/workflows/ci.yml.template +3 -0
  157. package/docs/00-README.md +0 -310
  158. package/docs/01-universal-prompt-library.md +0 -1049
  159. package/docs/02-claude-code-mastery-playbook.md +0 -283
  160. package/docs/03-multi-agent-verification.md +0 -565
  161. package/docs/04-errata-and-verification-checklist.md +0 -284
  162. package/docs/05-universal-scaffolder-vision.md +0 -452
  163. package/docs/06-confidence-assessment-and-repo-prompt.md +0 -407
  164. package/docs/errata.md +0 -58
  165. package/docs/multi-agent-verification.md +0 -66
  166. package/docs/playbook.md +0 -95
  167. package/docs/prompt-library.md +0 -160
  168. package/docs/uat/UAT_CHECKLIST.csv +0 -9
  169. package/docs/uat/UAT_TEMPLATE.md +0 -163
  170. package/templates/claude-code/commands/done.md +0 -19
  171. /package/{docs/plans/.gitkeep → templates/docs-portal/fastapi/backend/app/portal/__init__.py} +0 -0
@@ -0,0 +1,139 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export interface DocFile {
5
+ slug: string;
6
+ title: string;
7
+ content: string;
8
+ category: string;
9
+ categoryLabel: string;
10
+ lastModified: Date;
11
+ }
12
+
13
+ export interface DocCategory {
14
+ id: string;
15
+ label: string;
16
+ description: string;
17
+ icon: string;
18
+ docs: { slug: string; title: string }[];
19
+ }
20
+
21
+ const DOCS_ROOT = path.join(process.cwd(), 'docs');
22
+
23
+ const CATEGORY_META: Record<string, { label: string; description: string; icon: string; order: number }> = {
24
+ prd: { label: 'Product', description: 'Product requirements and roadmap', icon: '📋', order: 1 },
25
+ sdd: { label: 'Architecture', description: 'System design and technical architecture', icon: '🏗️', order: 2 },
26
+ uat: { label: 'Testing', description: 'Test plans, results, and acceptance criteria', icon: '✅', order: 3 },
27
+ sessions: { label: 'Session Logs', description: 'Testing session results and bug reports', icon: '📝', order: 4 },
28
+ };
29
+
30
+ function extractTitle(content: string, filename: string): string {
31
+ // Try to get title from first H1
32
+ const match = content.match(/^#\s+(.+)$/m);
33
+ if (match) return match[1];
34
+
35
+ // Fall back to filename
36
+ return filename
37
+ .replace(/\.md$/, '')
38
+ .replace(/[-_]/g, ' ')
39
+ .replace(/\b\w/g, (c) => c.toUpperCase());
40
+ }
41
+
42
+ export function getCategories(): DocCategory[] {
43
+ if (!fs.existsSync(DOCS_ROOT)) return [];
44
+
45
+ const categories: DocCategory[] = [];
46
+ const entries = fs.readdirSync(DOCS_ROOT, { withFileTypes: true });
47
+
48
+ // Categorized docs (in subdirectories)
49
+ for (const entry of entries) {
50
+ if (!entry.isDirectory()) continue;
51
+
52
+ const categoryId = entry.name;
53
+ const categoryDir = path.join(DOCS_ROOT, categoryId);
54
+ const meta = CATEGORY_META[categoryId] || {
55
+ label: categoryId.charAt(0).toUpperCase() + categoryId.slice(1),
56
+ description: '',
57
+ icon: '📄',
58
+ order: 99,
59
+ };
60
+
61
+ const files = fs.readdirSync(categoryDir).filter((f) => f.endsWith('.md'));
62
+ if (files.length === 0) continue;
63
+
64
+ const docs = files.map((f) => {
65
+ const raw = fs.readFileSync(path.join(categoryDir, f), 'utf-8');
66
+ return {
67
+ slug: f.replace(/\.md$/, ''),
68
+ title: extractTitle(raw, f),
69
+ };
70
+ });
71
+
72
+ categories.push({ id: categoryId, ...meta, docs });
73
+ }
74
+
75
+ // Top-level markdown files go into a "General" category
76
+ const topLevelFiles = entries.filter((e) => !e.isDirectory() && e.name.endsWith('.md'));
77
+ if (topLevelFiles.length > 0) {
78
+ const docs = topLevelFiles.map((f) => {
79
+ const raw = fs.readFileSync(path.join(DOCS_ROOT, f.name), 'utf-8');
80
+ return {
81
+ slug: f.name.replace(/\.md$/, ''),
82
+ title: extractTitle(raw, f.name),
83
+ };
84
+ });
85
+ categories.push({
86
+ id: '_general',
87
+ label: 'General',
88
+ description: 'Project documentation',
89
+ icon: '📄',
90
+ docs,
91
+ });
92
+ }
93
+
94
+ // Sort by configured order
95
+ return categories.sort((a, b) => {
96
+ const orderA = CATEGORY_META[a.id]?.order ?? 99;
97
+ const orderB = CATEGORY_META[b.id]?.order ?? 99;
98
+ return orderA - orderB;
99
+ });
100
+ }
101
+
102
+ export function getDoc(category: string, slug: string): DocFile | null {
103
+ const dirPath = category === '_general' ? DOCS_ROOT : path.join(DOCS_ROOT, category);
104
+ const filePath = path.join(dirPath, `${slug}.md`);
105
+
106
+ // Prevent path traversal — resolved path must stay within DOCS_ROOT
107
+ const resolved = path.resolve(filePath);
108
+ const docsRoot = path.resolve(DOCS_ROOT);
109
+ if (!resolved.startsWith(docsRoot + path.sep)) return null;
110
+
111
+ if (!fs.existsSync(filePath)) return null;
112
+
113
+ const content = fs.readFileSync(filePath, 'utf-8');
114
+ const stat = fs.statSync(filePath);
115
+ const meta = CATEGORY_META[category] || { label: 'General', description: '', icon: '📄', order: 99 };
116
+
117
+ return {
118
+ slug,
119
+ title: extractTitle(content, `${slug}.md`),
120
+ content,
121
+ category,
122
+ categoryLabel: meta.label,
123
+ lastModified: stat.mtime,
124
+ };
125
+ }
126
+
127
+ export function getAllDocs(): DocFile[] {
128
+ const categories = getCategories();
129
+ const docs: DocFile[] = [];
130
+
131
+ for (const cat of categories) {
132
+ for (const doc of cat.docs) {
133
+ const full = getDoc(cat.id, doc.slug);
134
+ if (full) docs.push(full);
135
+ }
136
+ }
137
+
138
+ return docs;
139
+ }
@@ -21,7 +21,9 @@
21
21
  "react-dom": "^19.1.0",
22
22
  "@prisma/client": "^6.6.0",
23
23
  "clsx": "^2.1.1",
24
- "tailwind-merge": "^3.2.0"
24
+ "tailwind-merge": "^3.2.0",
25
+ "react-markdown": "^9.0.3",
26
+ "remark-gfm": "^4.0.0"
25
27
  },
26
28
  "devDependencies": {
27
29
  "typescript": "^5.8.3",
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{PROJECT_NAME_PASCAL}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "preview": "vite preview",
10
+ "lint": "eslint .",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest"
14
+ },
15
+ "dependencies": {
16
+ "react": "^19.1.0",
17
+ "react-dom": "^19.1.0",
18
+ "react-router-dom": "^7.5.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.8.3",
22
+ "@types/react": "^19.1.0",
23
+ "@types/react-dom": "^19.1.0",
24
+ "@vitejs/plugin-react": "^4.4.0",
25
+ "vite": "^6.3.0",
26
+ "tailwindcss": "^4.1.3",
27
+ "@tailwindcss/vite": "^4.1.3",
28
+ "eslint": "^9.25.0",
29
+ "vitest": "^3.1.1",
30
+ "@testing-library/react": "^16.3.0",
31
+ "@testing-library/jest-dom": "^6.6.0",
32
+ "jsdom": "^26.0.0"
33
+ }
34
+ }
@@ -0,0 +1,10 @@
1
+ export default function App() {
2
+ return (
3
+ <main className="min-h-screen flex items-center justify-center bg-gray-50">
4
+ <div className="text-center">
5
+ <h1 className="text-4xl font-bold text-gray-900">{{PROJECT_NAME_PASCAL}}</h1>
6
+ <p className="mt-4 text-lg text-gray-600">{{STACK_DESCRIPTION}}</p>
7
+ </div>
8
+ </main>
9
+ );
10
+ }
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -0,0 +1,10 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import App from './App';
4
+ import './index.css';
5
+
6
+ createRoot(document.getElementById('root')!).render(
7
+ <StrictMode>
8
+ <App />
9
+ </StrictMode>,
10
+ );
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true
15
+ },
16
+ "include": ["src"]
17
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tailwindcss()],
7
+ server: {
8
+ proxy: {
9
+ '/api': {
10
+ target: 'http://localhost:3001',
11
+ changeOrigin: true,
12
+ },
13
+ },
14
+ },
15
+ });
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'jsdom',
6
+ globals: true,
7
+ setupFiles: [],
8
+ },
9
+ });
@@ -0,0 +1,31 @@
1
+ import {
2
+ Links,
3
+ Meta,
4
+ Outlet,
5
+ Scripts,
6
+ ScrollRestoration,
7
+ } from '@remix-run/react';
8
+ import type { LinksFunction } from '@remix-run/node';
9
+ import stylesheet from './tailwind.css?url';
10
+
11
+ export const links: LinksFunction = () => [
12
+ { rel: 'stylesheet', href: stylesheet },
13
+ ];
14
+
15
+ export default function App() {
16
+ return (
17
+ <html lang="en">
18
+ <head>
19
+ <meta charSet="utf-8" />
20
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
21
+ <Meta />
22
+ <Links />
23
+ </head>
24
+ <body>
25
+ <Outlet />
26
+ <ScrollRestoration />
27
+ <Scripts />
28
+ </body>
29
+ </html>
30
+ );
31
+ }
@@ -0,0 +1,19 @@
1
+ import type { MetaFunction } from '@remix-run/node';
2
+
3
+ export const meta: MetaFunction = () => {
4
+ return [
5
+ { title: '{{PROJECT_NAME_PASCAL}}' },
6
+ { name: 'description', content: '{{STACK_DESCRIPTION}}' },
7
+ ];
8
+ };
9
+
10
+ export default function Index() {
11
+ return (
12
+ <main className="min-h-screen flex items-center justify-center bg-gray-50">
13
+ <div className="text-center">
14
+ <h1 className="text-4xl font-bold text-gray-900">{{PROJECT_NAME_PASCAL}}</h1>
15
+ <p className="mt-4 text-lg text-gray-600">{{STACK_DESCRIPTION}}</p>
16
+ </div>
17
+ </main>
18
+ );
19
+ }
@@ -0,0 +1,10 @@
1
+ import { json } from '@remix-run/node';
2
+
3
+ export function loader() {
4
+ return json({
5
+ status: 'ok',
6
+ timestamp: new Date().toISOString(),
7
+ uptime: process.uptime(),
8
+ service: '{{PROJECT_NAME}}',
9
+ });
10
+ }
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "remix vite:dev",
8
+ "build": "remix vite:build",
9
+ "start": "remix-serve ./build/server/index.js",
10
+ "lint": "eslint .",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest",
14
+ "db:push": "prisma db push",
15
+ "db:studio": "prisma studio",
16
+ "db:generate": "prisma generate"
17
+ },
18
+ "dependencies": {
19
+ "@remix-run/node": "^2.16.0",
20
+ "@remix-run/react": "^2.16.0",
21
+ "@remix-run/serve": "^2.16.0",
22
+ "react": "^19.1.0",
23
+ "react-dom": "^19.1.0",
24
+ "isbot": "^5.1.0",
25
+ "@prisma/client": "^6.6.0"
26
+ },
27
+ "devDependencies": {
28
+ "@remix-run/dev": "^2.16.0",
29
+ "typescript": "^5.8.3",
30
+ "@types/react": "^19.1.0",
31
+ "@types/react-dom": "^19.1.0",
32
+ "vite": "^6.3.0",
33
+ "tailwindcss": "^4.1.3",
34
+ "@tailwindcss/vite": "^4.1.3",
35
+ "eslint": "^9.25.0",
36
+ "prisma": "^6.6.0",
37
+ "vitest": "^3.1.1"
38
+ }
39
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "types": ["@remix-run/node", "vite/client"]
16
+ },
17
+ "include": ["app", "env.d.ts"]
18
+ }
@@ -0,0 +1,7 @@
1
+ import { vitePlugin as remix } from '@remix-run/dev';
2
+ import { defineConfig } from 'vite';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+
5
+ export default defineConfig({
6
+ plugins: [remix(), tailwindcss()],
7
+ });
@@ -43,6 +43,9 @@ jobs:
43
43
  - name: Type check
44
44
  run: {{TYPE_CHECK_COMMAND}}
45
45
 
46
+ - name: Build
47
+ run: {{BUILD_COMMAND}}
48
+
46
49
  - name: Test
47
50
  run: {{TEST_COMMAND}}
48
51
  env: