@amirulabu/create-recurring-rabbit-app 0.2.13 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.npmrc ADDED
@@ -0,0 +1,15 @@
1
+ # npm publishing configuration
2
+ # See: https://docs.npmjs.com/cli/v9/using-npm/config
3
+
4
+ # Provenance for package security (requires GitHub Actions)
5
+ # https://docs.npmjs.com/generating-provenance-statements
6
+ provenance=true
7
+
8
+ # Always publish to public registry
9
+ registry=https://registry.npmjs.org/
10
+
11
+ # Scoped package is public
12
+ @amirulabu:registry=https://registry.npmjs.org/
13
+
14
+ # Access level for scoped package
15
+ access=public
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amirul Abu Bakar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # create-recurring-rabbit-app
2
+
3
+ > A production-ready CLI tool that scaffolds an opinionated micro‑SaaS starter with TanStack Start, tRPC, Drizzle, Better-auth, and Tailwind CSS.
4
+
5
+ **Current Version**: v0.2.13 | **Status**: ✅ Production Ready - Ready for Public Launch
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # Create a new project
11
+ npx @amirulabu/create-recurring-rabbit-app my-saas-app
12
+
13
+ # Navigate to project
14
+ cd my-saas-app
15
+
16
+ # Start development server
17
+ pnpm dev
18
+ ```
19
+
20
+ ## What's Included
21
+
22
+ The generated starter includes everything you need to build a micro-SaaS:
23
+
24
+ - 🔐 **Authentication** - Email/password with email verification via Better-auth
25
+ - 🗄️ **Database** - SQLite (development) / PostgreSQL (production) with Drizzle ORM
26
+ - 🌐 **Full-stack** - TanStack Start with tRPC for end-to-end type safety
27
+ - 🎨 **Styling** - Tailwind CSS with shadcn/ui components
28
+ - ⚡ **TypeScript** - Strict mode with path aliases and comprehensive type safety
29
+ - 🔧 **Developer Tools** - Hot reload, ESLint, Prettier, bundle analyzer, performance monitoring
30
+ - 📦 **CI/CD** - GitHub Actions workflows for automated testing and validation
31
+ - 📝 **Documentation** - Comprehensive guides, ADRs, and JSDoc comments
32
+ - 🧪 **Testing** - Vitest integration with 21 passing tests
33
+
34
+ ## CLI Usage
35
+
36
+ ```bash
37
+ npx @amirulabu/create-recurring-rabbit-app <project-name> [options]
38
+
39
+ Options:
40
+ -h, --help Display help
41
+ -V, --version Display version
42
+ ```
43
+
44
+ ## Generated App Tech Stack
45
+
46
+ | Category | Technology | Purpose |
47
+ | ------------------- | ----------------------- | -------------------------------------------------- |
48
+ | **Framework** | TanStack Start | Full-stack React framework with file-based routing |
49
+ | **API** | tRPC v11 | End-to-end type-safe APIs |
50
+ | **Database** | Drizzle ORM | Type-safe database queries |
51
+ | **Auth** | Better-auth | Authentication with email/password support |
52
+ | **Styling** | Tailwind CSS v4 | Utility-first CSS framework |
53
+ | **UI Components** | shadcn/ui | Accessible, customizable components |
54
+ | **Database (Dev)** | SQLite + better-sqlite3 | Zero-config local database |
55
+ | **Database (Prod)** | PostgreSQL | Production-ready database |
56
+
57
+ ## Project Structure
58
+
59
+ ```
60
+ create-recurring-rabbit-app/
61
+ ├── packages/
62
+ │ └── create-recurring-rabbit-stack/ # CLI tool
63
+ │ ├── bin/ # CLI entry point
64
+ │ ├── src/ # CLI source code
65
+ │ │ ├── commands/ # CLI commands
66
+ │ │ └── utils/ # CLI utilities
67
+ │ └── templates/ # App templates
68
+ │ └── default/ # Default template
69
+ │ ├── src/
70
+ │ │ ├── app/ # TanStack Start routes
71
+ │ │ ├── server/ # tRPC + DB + Auth
72
+ │ │ ├── components/ # UI components
73
+ │ │ └── lib/ # Shared utilities
74
+ │ ├── docs/ # Documentation
75
+ │ └── drizzle/ # Database migrations
76
+ ├── specs/ # Feature specifications
77
+ ├── IMPLEMENTATION_PLAN.md # Implementation status
78
+ └── README.md
79
+ ```
80
+
81
+ ## Monorepo Commands
82
+
83
+ ```bash
84
+ # Install dependencies
85
+ pnpm install
86
+
87
+ # Build CLI package
88
+ cd packages/create-recurring-rabbit-stack && pnpm build
89
+
90
+ # Run CLI in dev mode
91
+ pnpm dev [app-name]
92
+
93
+ # Typecheck all packages
94
+ pnpm typecheck
95
+
96
+ # Lint all packages
97
+ pnpm lint
98
+
99
+ # Format all files
100
+ pnpm format
101
+ ```
102
+
103
+ ## Development
104
+
105
+ ### Building the CLI
106
+
107
+ ```bash
108
+ cd packages/create-recurring-rabbit-stack
109
+ pnpm build
110
+ ```
111
+
112
+ ### Running the CLI in Development Mode
113
+
114
+ ```bash
115
+ pnpm dev my-test-app
116
+ ```
117
+
118
+ ### Testing the Generated Template
119
+
120
+ After running the CLI:
121
+
122
+ ```bash
123
+ cd my-test-app
124
+ npm install
125
+ npm run dev
126
+ ```
127
+
128
+ ## Documentation
129
+
130
+ The generated app includes comprehensive documentation:
131
+
132
+ - [Quick Start Guide](packages/create-recurring-rabbit-stack/templates/default/README.md) - Get started with your new app
133
+ - [Architecture Overview](packages/create-recurring-rabbit-stack/templates/default/docs/architecture.md) - System design and decisions
134
+ - [Architecture Decision Records](packages/create-recurring-rabbit-stack/templates/default/docs/adr/) - Key technical decisions and rationale
135
+ - [Adding Features](packages/create-recurring-rabbit-stack/templates/default/docs/adding-features.md) - Common patterns and examples
136
+ - [Deployment Guide](packages/create-recurring-rabbit-stack/templates/default/docs/deployment.md) - Platform-specific deployment instructions
137
+ - [Database Schema](packages/create-recurring-rabbit-stack/templates/default/docs/database.md) - Complete schema documentation
138
+ - [Troubleshooting](packages/create-recurring-rabbit-stack/templates/default/docs/troubleshooting.md) - Common issues and solutions
139
+ - [UI Components Reference](packages/create-recurring-rabbit-stack/templates/default/src/components/ui/README.md) - Available components and usage examples
140
+
141
+ ## Implementation Status
142
+
143
+ See [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for detailed implementation progress.
144
+
145
+ **Current Status**: Phase 9 Complete - Ready for Public Launch ✅
146
+
147
+ **Completed Phases**:
148
+
149
+ - ✅ All specifications completed
150
+ - ✅ All JTBD requirements addressed
151
+ - ✅ Core features implemented (CLI, template, database, auth, tRPC, UI)
152
+ - ✅ TypeScript errors resolved
153
+ - ✅ Critical runtime issues fixed
154
+ - ✅ Integration testing complete
155
+ - ✅ Build & deployment testing complete
156
+ - ✅ CI/CD workflows configured
157
+ - ✅ Package publishing ready with provenance
158
+
159
+ ## Contributing
160
+
161
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
162
+
163
+ ## Jobs to Be Done
164
+
165
+ This tool is designed to help solo developers:
166
+
167
+ 1. **Bootstrap a micro‑SaaS quickly** - Get a working full-stack baseline in days, not weeks
168
+ 2. **Avoid decision fatigue** - One opinionated stack with one "right way" to start
169
+ 3. **Start with production-shaped architecture** - Sensible defaults for structure, data access, auth boundaries
170
+ 4. **Eliminate "glue code"** - End-to-end types between UI → API → DB
171
+ 5. **Get database + migrations right** - Ready-to-run local dev DB with clear migration workflow
172
+ 6. **Have auth implemented correctly** - Better-auth integrated without reinventing it
173
+
174
+ See [JTBD.md](JTBD.md) for the complete Jobs to Be Done analysis.
175
+
176
+ ## License
177
+
178
+ MIT - See LICENSE file for details.
179
+
180
+ ## Related Projects
181
+
182
+ - [TanStack Start](https://tanstack.com/start/latest) - Full-stack React framework
183
+ - [tRPC](https://trpc.io/) - End-to-end typesafe APIs
184
+ - [Drizzle ORM](https://orm.drizzle.team/) - Type-safe SQL toolkit
185
+ - [Better-auth](https://www.better-auth.com/) - Authentication library
186
+ - [shadcn/ui](https://ui.shadcn.com/) - Re-usable components built with Radix UI
package/bin/index.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -39,6 +39,8 @@ async function generatePackageJson(targetDir, config) {
39
39
  dev: "vinxi dev",
40
40
  build: "vinxi build",
41
41
  start: "vinxi start",
42
+ test: "vitest",
43
+ "test:run": "vitest run",
42
44
  "db:generate": "drizzle-kit generate",
43
45
  "db:push": "drizzle-kit push",
44
46
  "db:migrate": "drizzle-kit migrate",
@@ -49,7 +51,7 @@ async function generatePackageJson(targetDir, config) {
49
51
  "lint:fix": "eslint . --ext .ts,.tsx --fix",
50
52
  format: 'prettier --write "src/**/*.{ts,tsx,json,css}"',
51
53
  clean: "rm -rf .vinxi dist data/*.db data/*.db-shm data/*.db-wal",
52
- "build:analyze": "ANALYZE_BUNDLE=true vinxi build",
54
+ "build:analyze": "ANALYZE=true vinxi build",
53
55
  lighthouse: "lhci autorun",
54
56
  ...config.scripts
55
57
  },
@@ -87,6 +89,8 @@ async function generatePackageJson(targetDir, config) {
87
89
  "@types/react-dom": "^18.2.0",
88
90
  "@typescript-eslint/eslint-plugin": "^6.0.0",
89
91
  "@typescript-eslint/parser": "^6.0.0",
92
+ "@vitejs/plugin-react": "^4.3.0",
93
+ "@vitest/coverage-v8": "^1.6.0",
90
94
  eslint: "^8.56.0",
91
95
  "eslint-plugin-react": "^7.32.0",
92
96
  "eslint-plugin-react-hooks": "^4.6.0",
@@ -98,6 +102,7 @@ async function generatePackageJson(targetDir, config) {
98
102
  tsx: "^4.7.0",
99
103
  typescript: "^5.3.3",
100
104
  vinxi: "^0.3.0",
105
+ vitest: "^1.6.0",
101
106
  ...config.devDependencies
102
107
  },
103
108
  pnpm: {
@@ -180,41 +185,28 @@ function installDependencies(projectPath, packageManager) {
180
185
  if (packageManager === "pnpm") {
181
186
  const rebuildSpinner = ora("Building native modules...").start();
182
187
  try {
183
- execSync("pnpm rebuild --force better-sqlite3", {
188
+ execSync("pnpm rebuild better-sqlite3", {
184
189
  cwd: projectPath,
185
190
  stdio: "inherit"
186
191
  });
187
192
  rebuildSpinner.succeed(chalk2.green("\u2713 Native modules built"));
188
193
  } catch {
189
- rebuildSpinner.warn(chalk2.yellow("\u26A0 Force rebuild failed, trying pnpm approve-builds..."));
194
+ rebuildSpinner.warn(
195
+ chalk2.yellow("\u26A0 Native module build failed, trying alternative method...")
196
+ );
190
197
  try {
191
- execSync("yes | pnpm approve-builds better-sqlite3", {
192
- cwd: projectPath,
193
- stdio: "inherit"
194
- });
195
- execSync("pnpm rebuild --force better-sqlite3", {
198
+ execSync("npx node-gyp rebuild --directory node_modules/better-sqlite3", {
196
199
  cwd: projectPath,
197
200
  stdio: "inherit"
198
201
  });
199
202
  rebuildSpinner.succeed(chalk2.green("\u2713 Native modules built"));
200
203
  } catch {
201
- rebuildSpinner.warn(
202
- chalk2.yellow("\u26A0 Native module build failed, trying alternative method...")
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
204
+ rebuildSpinner.fail(chalk2.red("\u2717 Native module build failed"));
205
+ throw new Error(
206
+ `Failed to build native modules. This is required for database functionality.
207
+ Try running manually: cd ${projectPath} && pnpm rebuild better-sqlite3
215
208
  Or use npm instead: cd ${projectPath} && npm install`
216
- );
217
- }
209
+ );
218
210
  }
219
211
  }
220
212
  }
@@ -529,7 +521,7 @@ async function cleanupProject(projectPath) {
529
521
  // src/commands/create.ts
530
522
  var __filename2 = fileURLToPath(import.meta.url);
531
523
  var __dirname2 = path.dirname(__filename2);
532
- var TEMPLATE_DIR = path.join(__dirname2, "../templates/default");
524
+ var TEMPLATE_DIR = path.join(__dirname2, "../../templates/default");
533
525
  async function scaffoldProject(projectName, targetPath) {
534
526
  const spinner = ora("Creating project structure...").start();
535
527
  let projectPath = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amirulabu/create-recurring-rabbit-app",
3
- "version": "0.2.13",
3
+ "version": "0.2.16",
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": {
@@ -18,21 +18,6 @@
18
18
  "LICENSE",
19
19
  ".npmrc"
20
20
  ],
21
- "scripts": {
22
- "dev": "tsx src/index.ts",
23
- "build": "tsup src/index.ts --format esm --clean",
24
- "start": "node dist/index.js",
25
- "typecheck": "tsc --noEmit",
26
- "lint": "eslint . --ext .ts,.tsx",
27
- "lint:fix": "eslint . --ext .ts,.tsx --fix",
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"
35
- },
36
21
  "dependencies": {
37
22
  "chalk": "^5.3.0",
38
23
  "commander": "^12.0.0",
@@ -51,5 +36,18 @@
51
36
  },
52
37
  "engines": {
53
38
  "node": ">=18.0.0"
39
+ },
40
+ "scripts": {
41
+ "dev": "tsx src/index.ts",
42
+ "build": "tsup src/index.ts --format esm --clean",
43
+ "start": "node dist/index.js",
44
+ "typecheck": "tsc --noEmit",
45
+ "lint": "eslint . --ext .ts,.tsx",
46
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
47
+ "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
48
+ "test": "vitest",
49
+ "test:ui": "vitest --ui",
50
+ "test:run": "vitest run",
51
+ "pack": "pnpm pack --dry-run"
54
52
  }
55
- }
53
+ }
@@ -14,7 +14,7 @@ export default defineConfig({
14
14
  plugins: [
15
15
  visualizer({
16
16
  filename: 'stats.html',
17
- open: process.env.ANALYZE_BUNDLE === 'true',
17
+ open: process.env.ANALYZE === 'true',
18
18
  gzipSize: true,
19
19
  brotliSize: true,
20
20
  template: 'treemap',
@@ -27,6 +27,11 @@
27
27
  "noImplicitOverride": true,
28
28
  "esModuleInterop": true,
29
29
  "skipLibCheck": true,
30
+ "plugins": [
31
+ {
32
+ "name": "@tanstack/start/plugin"
33
+ }
34
+ ],
30
35
  "paths": {
31
36
  "@/*": ["./src/*"]
32
37
  }
@@ -0,0 +1,33 @@
1
+ /// <reference types="vitest" />
2
+ import { defineConfig } from 'vitest/config'
3
+ import react from '@vitejs/plugin-react'
4
+ import path from 'path'
5
+
6
+ export default defineConfig({
7
+ plugins: [react()],
8
+ test: {
9
+ globals: true,
10
+ environment: 'node',
11
+ include: ['**/*.{test,spec}.{ts,tsx}'],
12
+ exclude: ['node_modules', 'dist', '.vinxi', '.output'],
13
+ coverage: {
14
+ provider: 'v8',
15
+ reporter: ['text', 'json', 'html'],
16
+ exclude: [
17
+ 'node_modules/',
18
+ 'dist/',
19
+ '.vinxi/',
20
+ '.output/',
21
+ '**/*.config.{ts,js}',
22
+ '**/*.d.ts',
23
+ '**/types/',
24
+ '**/test-utils/**',
25
+ ],
26
+ },
27
+ },
28
+ resolve: {
29
+ alias: {
30
+ '@': path.resolve(__dirname, './src'),
31
+ },
32
+ },
33
+ })