@amirulabu/create-recurring-rabbit-app 0.0.0-alpha → 0.2.13

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 (35) hide show
  1. package/dist/index.js +63 -30
  2. package/package.json +16 -4
  3. package/templates/default/README.md +22 -21
  4. package/templates/default/app.config.ts +9 -0
  5. package/templates/default/docs/adding-features.md +4 -4
  6. package/templates/default/docs/adr/006-use-tailwind-css-v4-with-shadcn-ui.md +3 -3
  7. package/templates/default/docs/database.md +10 -6
  8. package/templates/default/docs/deployment.md +7 -7
  9. package/templates/default/docs/troubleshooting.md +22 -20
  10. package/templates/default/drizzle.config.ts +6 -4
  11. package/templates/default/src/app/__root.tsx +14 -11
  12. package/templates/default/src/app/api/auth/get-session.ts +26 -0
  13. package/templates/default/src/app/api/health.ts +44 -0
  14. package/templates/default/src/app/auth/forgot-password.tsx +3 -3
  15. package/templates/default/src/app/auth/login.tsx +3 -3
  16. package/templates/default/src/app/auth/register.tsx +3 -3
  17. package/templates/default/src/app/auth/reset-password.tsx +5 -5
  18. package/templates/default/src/app/auth/verify-email.tsx +1 -1
  19. package/templates/default/src/app/client.tsx +9 -0
  20. package/templates/default/src/app/dashboard/index.tsx +14 -45
  21. package/templates/default/src/app/router.ts +4 -0
  22. package/templates/default/src/app/ssr.tsx +9 -0
  23. package/templates/default/src/components/features/dashboard/stats-widget.tsx +35 -0
  24. package/templates/default/src/components/features/dashboard/user-profile.tsx +41 -0
  25. package/templates/default/src/components/layout/footer.tsx +42 -0
  26. package/templates/default/src/components/layout/header.tsx +5 -3
  27. package/templates/default/src/components/layout/sidebar.tsx +3 -3
  28. package/templates/default/src/components/ui/README.md +80 -0
  29. package/templates/default/src/lib/api.ts +10 -4
  30. package/templates/default/src/lib/auth.ts +37 -1
  31. package/templates/default/src/server/api/routers/dashboard.ts +6 -6
  32. package/templates/default/src/server/api/trpc.ts +11 -7
  33. package/templates/default/src/server/auth/config.ts +24 -0
  34. package/templates/default/src/server/db/migrate.ts +22 -2
  35. package/templates/default/src/server/db/seed.ts +0 -5
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from 'commander';
3
- import path4 from 'path';
3
+ import path from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { existsSync, promises, mkdirSync, readFileSync } from 'fs';
6
6
  import ora from 'ora';
@@ -16,10 +16,10 @@ async function copyTemplateFiles(templateDir, targetDir) {
16
16
  const entries = await fs.readdir(src);
17
17
  await fs.mkdir(dest, { recursive: true });
18
18
  for (const entry of entries) {
19
- await copyRecursive(path4.join(src, entry), path4.join(dest, entry));
19
+ await copyRecursive(path.join(src, entry), path.join(dest, entry));
20
20
  }
21
21
  } else {
22
- await fs.mkdir(path4.dirname(dest), { recursive: true });
22
+ await fs.mkdir(path.dirname(dest), { recursive: true });
23
23
  await fs.copyFile(src, dest);
24
24
  }
25
25
  };
@@ -29,7 +29,7 @@ async function copyDirectory(src, dest) {
29
29
  await copyTemplateFiles(src, dest);
30
30
  }
31
31
  async function generatePackageJson(targetDir, config) {
32
- const packageJsonPath = path4.join(targetDir, "package.json");
32
+ const packageJsonPath = path.join(targetDir, "package.json");
33
33
  const packageJson = {
34
34
  name: config.name,
35
35
  version: config.version ?? "0.1.0",
@@ -40,6 +40,7 @@ async function generatePackageJson(targetDir, config) {
40
40
  build: "vinxi build",
41
41
  start: "vinxi start",
42
42
  "db:generate": "drizzle-kit generate",
43
+ "db:push": "drizzle-kit push",
43
44
  "db:migrate": "drizzle-kit migrate",
44
45
  "db:studio": "drizzle-kit studio",
45
46
  "db:seed": "tsx src/server/db/seed.ts",
@@ -96,8 +97,30 @@ async function generatePackageJson(targetDir, config) {
96
97
  tailwindcss: "^3.4.0",
97
98
  tsx: "^4.7.0",
98
99
  typescript: "^5.3.3",
99
- vinxi: "^0.4.0",
100
+ vinxi: "^0.3.0",
100
101
  ...config.devDependencies
102
+ },
103
+ pnpm: {
104
+ overrides: {
105
+ "@tanstack/react-router": "~1.120.0",
106
+ "@tanstack/react-start-client": "~1.120.0",
107
+ "@tanstack/react-start-plugin": "~1.120.0",
108
+ "@tanstack/react-start-server": "~1.120.0",
109
+ "@tanstack/router-core": "~1.120.0",
110
+ "@tanstack/router-generator": "~1.120.0",
111
+ "@tanstack/router-plugin": "~1.120.0",
112
+ "@tanstack/start-client-core": "~1.120.0",
113
+ "@tanstack/start-plugin-core": "~1.120.0",
114
+ "@tanstack/start-server-core": "~1.120.0",
115
+ "@tanstack/server-functions-plugin": "~1.120.0",
116
+ "@tanstack/directive-functions-plugin": "~1.120.0",
117
+ "@tanstack/start-api-routes": "~1.120.0",
118
+ "@tanstack/start-server-functions-client": "~1.120.0",
119
+ "@tanstack/start-server-functions-fetcher": "~1.120.0",
120
+ "@tanstack/start-server-functions-handler": "~1.120.0",
121
+ "@tanstack/router-utils": "~1.120.0",
122
+ "@tanstack/history": "~1.120.0"
123
+ }
101
124
  }
102
125
  };
103
126
  await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
@@ -137,7 +160,7 @@ async function detectPackageManager() {
137
160
  function getInstallCommand(packageManager) {
138
161
  switch (packageManager) {
139
162
  case "pnpm":
140
- return "pnpm install";
163
+ return "pnpm install --ignore-workspace";
141
164
  case "yarn":
142
165
  return "yarn";
143
166
  case "npm":
@@ -157,25 +180,41 @@ function installDependencies(projectPath, packageManager) {
157
180
  if (packageManager === "pnpm") {
158
181
  const rebuildSpinner = ora("Building native modules...").start();
159
182
  try {
160
- execSync("pnpm rebuild better-sqlite3", {
183
+ execSync("pnpm rebuild --force better-sqlite3", {
161
184
  cwd: projectPath,
162
185
  stdio: "inherit"
163
186
  });
164
187
  rebuildSpinner.succeed(chalk2.green("\u2713 Native modules built"));
165
188
  } catch {
166
- rebuildSpinner.warn(
167
- chalk2.yellow("\u26A0 Native module build failed, trying alternative method...")
168
- );
189
+ rebuildSpinner.warn(chalk2.yellow("\u26A0 Force rebuild failed, trying pnpm approve-builds..."));
169
190
  try {
170
- execSync("npx node-gyp rebuild --directory node_modules/better-sqlite3", {
191
+ execSync("yes | pnpm approve-builds better-sqlite3", {
192
+ cwd: projectPath,
193
+ stdio: "inherit"
194
+ });
195
+ execSync("pnpm rebuild --force better-sqlite3", {
171
196
  cwd: projectPath,
172
197
  stdio: "inherit"
173
198
  });
174
199
  rebuildSpinner.succeed(chalk2.green("\u2713 Native modules built"));
175
200
  } catch {
176
201
  rebuildSpinner.warn(
177
- chalk2.yellow("\u26A0 Native module build failed, may affect database functionality")
202
+ chalk2.yellow("\u26A0 Native module build failed, trying alternative method...")
178
203
  );
204
+ try {
205
+ execSync("npx node-gyp rebuild --directory node_modules/better-sqlite3", {
206
+ cwd: projectPath,
207
+ stdio: "inherit"
208
+ });
209
+ rebuildSpinner.succeed(chalk2.green("\u2713 Native modules built"));
210
+ } catch {
211
+ rebuildSpinner.fail(chalk2.red("\u2717 Native module build failed"));
212
+ throw new Error(
213
+ `Failed to build native modules. This is required for database functionality.
214
+ Try running manually: cd ${projectPath} && pnpm rebuild --force better-sqlite3
215
+ Or use npm instead: cd ${projectPath} && npm install`
216
+ );
217
+ }
179
218
  }
180
219
  }
181
220
  }
@@ -201,7 +240,7 @@ function generateSecret(length = 32) {
201
240
  return crypto.randomBytes(length).toString("base64");
202
241
  }
203
242
  async function generateEnvFile(targetDir, options = {}) {
204
- const envPath = path4.join(targetDir, ".env.local");
243
+ const envPath = path.join(targetDir, ".env.local");
205
244
  const secret = generateSecret(32);
206
245
  const content = [
207
246
  `# Database`,
@@ -224,7 +263,7 @@ async function generateEnvFile(targetDir, options = {}) {
224
263
  await fs.writeFile(envPath, content);
225
264
  }
226
265
  function loadEnvFile(projectPath) {
227
- const envPath = path4.join(projectPath, ".env.local");
266
+ const envPath = path.join(projectPath, ".env.local");
228
267
  const env = {};
229
268
  try {
230
269
  const content = readFileSync(envPath, "utf-8");
@@ -247,18 +286,13 @@ function loadEnvFile(projectPath) {
247
286
  async function initializeDatabase(projectPath) {
248
287
  const spinner = ora("Initializing database...").start();
249
288
  try {
250
- const dataDir = path4.join(projectPath, "data");
289
+ const dataDir = path.join(projectPath, "data");
251
290
  if (!existsSync(dataDir)) {
252
291
  mkdirSync(dataDir, { recursive: true });
253
292
  spinner.text = "Data directory created";
254
293
  }
255
294
  const env = loadEnvFile(projectPath);
256
- await runNpmScript(
257
- projectPath,
258
- "./node_modules/.bin/drizzle-kit push",
259
- "Creating database schema...",
260
- env
261
- );
295
+ await runNpmScript(projectPath, "npx drizzle-kit push", "Creating database schema...", env);
262
296
  spinner.succeed("Database initialized successfully");
263
297
  const seedSpinner = ora("Seeding database with sample data...").start();
264
298
  await runSeedScript(projectPath, env);
@@ -298,14 +332,13 @@ ${errorOutput}`));
298
332
  }
299
333
  async function runSeedScript(projectPath, env) {
300
334
  return new Promise((resolve, reject) => {
301
- const tsxPath = path4.join(projectPath, "node_modules/.bin/tsx");
302
- const seedScriptPath = path4.join(projectPath, "src/server/db/seed.ts");
303
- const command = process.platform === "win32" ? "node" : tsxPath;
304
- const args = process.platform === "win32" ? [tsxPath, seedScriptPath] : [seedScriptPath];
335
+ const seedScriptPath = path.join(projectPath, "src/server/db/seed.ts");
336
+ const command = "npx";
337
+ const args = ["tsx", seedScriptPath];
305
338
  const child = spawn(command, args, {
306
339
  cwd: projectPath,
307
340
  stdio: "inherit",
308
- shell: process.platform === "win32",
341
+ shell: true,
309
342
  env: { ...process.env, ...env }
310
343
  });
311
344
  child.on("close", (code) => {
@@ -477,7 +510,7 @@ function validateProjectName(name) {
477
510
  if (RESERVED_NAMES.has(name)) {
478
511
  throw new CLIError(`Invalid project name: "${name}" is a reserved name`);
479
512
  }
480
- const parts = name.split(path4.sep);
513
+ const parts = name.split(path.sep);
481
514
  const baseName = parts[parts.length - 1];
482
515
  if (baseName !== name) {
483
516
  throw new CLIError("Invalid project name: cannot contain path separators");
@@ -495,15 +528,15 @@ async function cleanupProject(projectPath) {
495
528
 
496
529
  // src/commands/create.ts
497
530
  var __filename2 = fileURLToPath(import.meta.url);
498
- var __dirname2 = path4.dirname(__filename2);
499
- var TEMPLATE_DIR = path4.join(__dirname2, "../../templates/default");
531
+ var __dirname2 = path.dirname(__filename2);
532
+ var TEMPLATE_DIR = path.join(__dirname2, "../templates/default");
500
533
  async function scaffoldProject(projectName, targetPath) {
501
534
  const spinner = ora("Creating project structure...").start();
502
535
  let projectPath = "";
503
536
  let projectCreated = false;
504
537
  try {
505
538
  validateProjectName(projectName);
506
- projectPath = path4.join(targetPath, projectName);
539
+ projectPath = path.join(targetPath, projectName);
507
540
  if (existsSync(projectPath)) {
508
541
  spinner.fail(`Directory ${projectName} already exists. Please choose a different name.`);
509
542
  throw new Error(`Directory ${projectName} already exists`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amirulabu/create-recurring-rabbit-app",
3
- "version": "0.0.0-alpha",
3
+ "version": "0.2.13",
4
4
  "description": "CLI tool to scaffold micro-SaaS apps with TanStack Start, tRPC, Drizzle, and Better-auth",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,11 @@
12
12
  "files": [
13
13
  "bin",
14
14
  "dist",
15
- "templates"
15
+ "templates",
16
+ "README.md",
17
+ "CHANGELOG.md",
18
+ "LICENSE",
19
+ ".npmrc"
16
20
  ],
17
21
  "scripts": {
18
22
  "dev": "tsx src/index.ts",
@@ -21,7 +25,13 @@
21
25
  "typecheck": "tsc --noEmit",
22
26
  "lint": "eslint . --ext .ts,.tsx",
23
27
  "lint:fix": "eslint . --ext .ts,.tsx --fix",
24
- "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\""
28
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
29
+ "test": "vitest",
30
+ "test:ui": "vitest --ui",
31
+ "test:run": "vitest run",
32
+ "prepublishOnly": "pnpm build && pnpm test:run",
33
+ "pack": "npm pack --dry-run",
34
+ "publish": "npm publish --provenance false"
25
35
  },
26
36
  "dependencies": {
27
37
  "chalk": "^5.3.0",
@@ -35,7 +45,9 @@
35
45
  "@typescript-eslint/parser": "^8.53.1",
36
46
  "eslint": "^9.39.2",
37
47
  "tsup": "^8.0.1",
38
- "tsx": "^4.7.0"
48
+ "tsx": "^4.7.0",
49
+ "vitest": "^1.0.4",
50
+ "@vitest/ui": "^1.0.4"
39
51
  },
40
52
  "engines": {
41
53
  "node": ">=18.0.0"
@@ -6,10 +6,10 @@
6
6
 
7
7
  ```bash
8
8
  # Install dependencies
9
- npm install
9
+ pnpm install
10
10
 
11
11
  # Start development server
12
- npm run dev
12
+ pnpm dev
13
13
 
14
14
  # Open http://localhost:3000 and create an account
15
15
  ```
@@ -37,25 +37,26 @@ src/
37
37
 
38
38
  ```bash
39
39
  # Development
40
- npm run dev # Start development server
41
- npm run build # Build for production
42
- npm run start # Start production server
40
+ pnpm dev # Start development server
41
+ pnpm build # Build for production
42
+ pnpm start # Start production server
43
43
 
44
44
  # Bundle Analysis
45
- npm run build:analyze # Build with bundle analyzer (opens stats.html)
45
+ pnpm build:analyze # Build with bundle analyzer (opens stats.html)
46
46
 
47
47
  # Database
48
- npm run db:generate # Generate migration files
49
- npm run db:migrate # Apply migrations
50
- npm run db:studio # Open Drizzle Studio
51
- npm run db:seed # Seed database with sample data
48
+ pnpm db:generate # Generate migration files
49
+ pnpm db:push # Push schema changes to SQLite (recommended for dev)
50
+ pnpm db:migrate # Apply migration files (for PostgreSQL production)
51
+ pnpm db:studio # Open Drizzle Studio
52
+ pnpm db:seed # Seed database with sample data
52
53
 
53
54
  # Code Quality
54
- npm run typecheck # Run TypeScript checks
55
- npm run lint # Run ESLint
56
- npm run lint:fix # Fix ESLint issues
57
- npm run format # Format code with Prettier
58
- npm run clean # Clean build artifacts
55
+ pnpm typecheck # Run TypeScript checks
56
+ pnpm lint # Run ESLint
57
+ pnpm lint:fix # Fix ESLint issues
58
+ pnpm format # Format code with Prettier
59
+ pnpm clean # Clean build artifacts
59
60
  ```
60
61
 
61
62
  ## Environment Setup
@@ -84,7 +85,7 @@ Optional variables (production):
84
85
  Analyze your bundle size to identify large dependencies and optimize performance:
85
86
 
86
87
  ```bash
87
- npm run build:analyze
88
+ pnpm build:analyze
88
89
  ```
89
90
 
90
91
  This will build your application and generate a `stats.html` file in build output directory (`.vinxi`). Open this file in your browser to explore:
@@ -106,7 +107,7 @@ Monitor application performance to identify bottlenecks:
106
107
 
107
108
  ```bash
108
109
  # Run Lighthouse CI to check performance budgets
109
- npm run lighthouse
110
+ pnpm lighthouse
110
111
  ```
111
112
 
112
113
  The project includes performance monitoring tools:
@@ -160,8 +161,8 @@ export function MyComponent() {
160
161
  **Database Tables**
161
162
 
162
163
  1. Define schema in `src/server/db/schema.ts`
163
- 2. Generate migration: `npm run db:generate`
164
- 3. Apply migration: `npm run db:migrate`
164
+ 2. Generate migration: `pnpm db:generate`
165
+ 3. Apply migration: `pnpm db:push` (SQLite dev) or `pnpm db:generate && pnpm db:migrate` (PostgreSQL prod)
165
166
 
166
167
  ```typescript
167
168
  export const posts = sqliteTable('posts', {
@@ -255,7 +256,7 @@ Railway provides built-in PostgreSQL hosting.
255
256
  When deploying to production with PostgreSQL:
256
257
 
257
258
  ```bash
258
- npm run db:migrate
259
+ pnpm db:generate && pnpm db:migrate
259
260
  ```
260
261
 
261
262
  Make sure to test migrations locally with PostgreSQL before deploying.
@@ -307,7 +308,7 @@ Use `drizzle-kit push` instead of `drizzle-kit migrate` for SQLite to avoid mult
307
308
  If you get "database is locked" errors:
308
309
 
309
310
  ```bash
310
- npm run clean
311
+ pnpm clean
311
312
  # Then restart dev server
312
313
  ```
313
314
 
@@ -1,5 +1,9 @@
1
1
  import { defineConfig } from '@tanstack/start/config'
2
2
  import { visualizer } from 'rollup-plugin-visualizer'
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
3
7
 
4
8
  export default defineConfig({
5
9
  tsr: {
@@ -16,5 +20,10 @@ export default defineConfig({
16
20
  template: 'treemap',
17
21
  }),
18
22
  ],
23
+ resolve: {
24
+ alias: {
25
+ '@': path.resolve(__dirname, './src'),
26
+ },
27
+ },
19
28
  },
20
29
  })
@@ -3,8 +3,8 @@
3
3
  ## Creating New Database Tables
4
4
 
5
5
  1. **Define schema** in `src/server/db/schema.ts`
6
- 2. **Generate migration** with `npm run db:generate`
7
- 3. **Apply migration** with `npm run db:migrate`
6
+ 2. **Generate migration** with `pnpm db:generate`
7
+ 3. **Apply migration** with `pnpm db:push` (SQLite) or `pnpm db:generate && pnpm db:migrate` (PostgreSQL)
8
8
 
9
9
  Example:
10
10
 
@@ -380,7 +380,7 @@ function MyComponent() {
380
380
 
381
381
  ### Stripe for Payments
382
382
 
383
- 1. Install Stripe SDK: `npm install stripe`
383
+ 1. Install Stripe SDK: `pnpm add stripe`
384
384
  2. Add environment variable: `STRIPE_SECRET_KEY`
385
385
  3. Create webhook handler in `src/app/api/stripe-webhook.ts`
386
386
  4. Add procedures to handle payments
@@ -425,7 +425,7 @@ await resend.emails.send({
425
425
 
426
426
  ## Testing New Features
427
427
 
428
- 1. **Add table** → `npm run db:generate && npm run db:migrate`
428
+ 1. **Add table** → `pnpm db:generate && pnpm db:push` (SQLite) or `pnpm db:generate && pnpm db:migrate` (PostgreSQL)
429
429
  2. **Add tRPC procedure** → Test in tRPC DevTools
430
430
  3. **Add UI component** → Test in isolation
431
431
  4. **Add page** → Test navigation and rendering
@@ -1,4 +1,4 @@
1
- # ADR-006: Use Tailwind CSS v4 with shadcn/ui
1
+ # ADR-006: Use Tailwind CSS v3 with shadcn/ui
2
2
 
3
3
  ## Status
4
4
 
@@ -10,7 +10,7 @@ Need styling system with rapid development and professional components
10
10
 
11
11
  ## Decision
12
12
 
13
- Use Tailwind CSS v4 with shadcn/ui components
13
+ Use Tailwind CSS v3.4 with shadcn/ui components
14
14
 
15
15
  ## Consequences
16
16
 
@@ -19,4 +19,4 @@ Use Tailwind CSS v4 with shadcn/ui components
19
19
 
20
20
  ## Implementation
21
21
 
22
- Configure Tailwind v4, install shadcn/ui components, use for all UI
22
+ Configure Tailwind v3.4, install shadcn/ui components, use for all UI
@@ -180,13 +180,17 @@ const db = drizzle(pool, { schema })
180
180
 
181
181
  ```bash
182
182
  # Generate migration files
183
- npm run db:generate
183
+ pnpm db:generate
184
184
 
185
185
  # Apply migrations
186
- npm run db:migrate
186
+ # For SQLite (development): recommended to use push
187
+ pnpm db:push
188
+
189
+ # For PostgreSQL (production): use generate + migrate
190
+ pnpm db:generate && pnpm db:migrate
187
191
 
188
192
  # Open Drizzle Studio to browse database
189
- npm run db:studio
193
+ pnpm db:studio
190
194
  ```
191
195
 
192
196
  ### Migration Files
@@ -324,7 +328,7 @@ Tips:
324
328
  The seed script creates sample users and dashboard data:
325
329
 
326
330
  ```bash
327
- npm run db:seed
331
+ pnpm db:seed
328
332
  ```
329
333
 
330
334
  Seed data location: `src/server/db/seed.ts`
@@ -340,7 +344,7 @@ Seed data location: `src/server/db/seed.ts`
340
344
  **Solution:**
341
345
 
342
346
  ```bash
343
- npm run clean
347
+ pnpm clean
344
348
  # This removes WAL files and restarts clean
345
349
  ```
346
350
 
@@ -354,7 +358,7 @@ npm run clean
354
358
 
355
359
  1. Review migration file in `drizzle/migrations/`
356
360
  2. Test migration on backup first
357
- 3. Rollback if needed: `npm run db:migrate:down` (if configured)
361
+ 3. For schema changes, consider using a new migration instead of rolling back
358
362
 
359
363
  ### Slow Queries
360
364
 
@@ -64,11 +64,11 @@ railway up
64
64
  FROM node:18-alpine
65
65
  WORKDIR /app
66
66
  COPY package*.json ./
67
- RUN npm ci --only=production
67
+ RUN pnpm install --frozen-lockfile --prod
68
68
  COPY . .
69
- RUN npm run build
69
+ RUN pnpm build
70
70
  EXPOSE 3000
71
- CMD ["npm", "start"]
71
+ CMD ["pnpm", "start"]
72
72
  ```
73
73
 
74
74
  ```bash
@@ -262,13 +262,13 @@ const { data } = api.myQuery.useQuery({
262
262
  3. **Run Migrations**
263
263
 
264
264
  ```bash
265
- DATABASE_URL="postgres://..." npm run db:migrate
265
+ DATABASE_URL="postgres://..." pnpm db:generate && pnpm db:migrate
266
266
  ```
267
267
 
268
268
  4. **Build Production Bundle**
269
269
 
270
270
  ```bash
271
- npm run build
271
+ pnpm build
272
272
  ```
273
273
 
274
274
  5. **Deploy**
@@ -315,8 +315,8 @@ const { data } = api.myQuery.useQuery({
315
315
 
316
316
  **Solution:**
317
317
 
318
- 1. Run `npm run typecheck` locally
319
- 2. Run `npm run build` locally
318
+ 1. Run `pnpm typecheck` locally
319
+ 2. Run `pnpm build` locally
320
320
  3. Check build logs in platform dashboard
321
321
 
322
322
  #### Email Not Sending in Production
@@ -17,6 +17,8 @@ pnpm rebuild better-sqlite3
17
17
  **Solution 2:** Use npm/yarn instead
18
18
 
19
19
  ```bash
20
+ pnpm install
21
+ # or
20
22
  npm install
21
23
  # or
22
24
  yarn install
@@ -32,10 +34,10 @@ yarn install
32
34
 
33
35
  ```bash
34
36
  # Instead of:
35
- npm run db:migrate
37
+ pnpm db:generate && pnpm db:migrate
36
38
 
37
39
  # Use:
38
- npx drizzle-kit push
40
+ pnpm db:push
39
41
  ```
40
42
 
41
43
  ### Database Locked (SQLite)
@@ -47,7 +49,7 @@ npx drizzle-kit push
47
49
  **Solution:** Clean build artifacts
48
50
 
49
51
  ```bash
50
- npm run clean
52
+ pnpm clean
51
53
  # This removes data/*.db-shm and data/*.db-wal files
52
54
  ```
53
55
 
@@ -70,7 +72,7 @@ netstat -ano | findstr :3000
70
72
 
71
73
  ```bash
72
74
  # In app.config.ts or pass environment variable
73
- PORT=3001 npm run dev
75
+ PORT=3001 pnpm dev
74
76
  ```
75
77
 
76
78
  ## Installation Issues
@@ -84,14 +86,14 @@ PORT=3001 npm run dev
84
86
  **Solution 1:** Clear cache and reinstall
85
87
 
86
88
  ```bash
87
- rm -rf node_modules package-lock.json
88
- npm install
89
+ rm -rf node_modules package-lock.json pnpm-lock.yaml
90
+ pnpm install
89
91
  ```
90
92
 
91
93
  **Solution 2:** Use different registry
92
94
 
93
95
  ```bash
94
- npm install --registry=https://registry.npmjs.org
96
+ pnpm install --registry=https://registry.npmjs.org
95
97
  ```
96
98
 
97
99
  ### TypeScript Errors After Install
@@ -194,12 +196,12 @@ export const auth = betterAuth({
194
196
 
195
197
  ### Build Fails with TypeScript Errors
196
198
 
197
- **Error:** Type errors during `npm run build`
199
+ **Error:** Type errors during `pnpm build`
198
200
 
199
201
  **Solution 1:** Run typecheck first
200
202
 
201
203
  ```bash
202
- npm run typecheck
204
+ pnpm typecheck
203
205
  ```
204
206
 
205
207
  **Solution 2:** Check for `any` types
@@ -319,7 +321,7 @@ ls src/app/dashboard/index.tsx
319
321
 
320
322
  ```bash
321
323
  # Stop (Ctrl+C) and restart
322
- npm run dev
324
+ pnpm dev
323
325
  ```
324
326
 
325
327
  ### Page Load Slow
@@ -332,7 +334,7 @@ npm run dev
332
334
 
333
335
  ```bash
334
336
  # Run bundle analyzer
335
- npm run build:analyze
337
+ pnpm build:analyze
336
338
 
337
339
  # This will build and generate stats.html
338
340
  # Open the file in your browser to visualize bundle size
@@ -358,7 +360,7 @@ npm run build:analyze
358
360
  **Solution 1:** Use the build:analyze script
359
361
 
360
362
  ```bash
361
- npm run build:analyze
363
+ pnpm build:analyze
362
364
  ```
363
365
 
364
366
  This script automatically sets `ANALYZE_BUNDLE=true` and opens the visualization.
@@ -367,7 +369,7 @@ This script automatically sets `ANALYZE_BUNDLE=true` and opens the visualization
367
369
 
368
370
  ```bash
369
371
  # Build with analyzer
370
- ANALYZE_BUNDLE=true npm run build
372
+ ANALYZE_BUNDLE=true pnpm build
371
373
 
372
374
  # Then manually open the file
373
375
  # Find stats.html in .vinxi or build output directory
@@ -467,11 +469,11 @@ export default defineConfig({
467
469
 
468
470
  ```bash
469
471
  # Check terminal output for build errors
470
- npm run build:analyze
472
+ pnpm build:analyze
471
473
 
472
474
  # If there are errors, fix them first
473
- npm run typecheck
474
- npm run lint
475
+ pnpm typecheck
476
+ pnpm lint
475
477
  ```
476
478
 
477
479
  **Cause 2:** No code or empty routes
@@ -538,7 +540,7 @@ export default defineConfig({
538
540
  **Solution:** Run production build locally
539
541
 
540
542
  ```bash
541
- npm run build
543
+ pnpm build
542
544
  # Check for errors
543
545
  ```
544
546
 
@@ -571,7 +573,7 @@ node -v
571
573
 
572
574
  **Development:**
573
575
 
574
- - Terminal output from `npm run dev`
576
+ - Terminal output from `pnpm dev`
575
577
  - Browser console (DevTools)
576
578
  - tRPC DevTools
577
579
  - React DevTools
@@ -596,7 +598,7 @@ node -v
596
598
  - Restart server after changes
597
599
 
598
600
  3. **Check database**
599
- - Run `npm run db:studio` to browse database
601
+ - Run `pnpm db:studio` to browse database
600
602
  - Verify data exists
601
603
  - Check for corrupted data
602
604
 
@@ -642,7 +644,7 @@ node -v
642
644
  When reporting issues, include:
643
645
 
644
646
  1. **Node.js version:** `node -v`
645
- 2. **Package manager:** `npm -v` or `pnpm -v`
647
+ 2. **Package manager:** `pnpm -v`
646
648
  3. **Operating system:** Mac/Linux/Windows
647
649
  4. **Error message:** Full error from console
648
650
  5. **Steps to reproduce:** What you did before error