@totaland/create-starter-kit 2.0.1 → 2.0.3
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/README.md +27 -3
- package/bin/index.js +82 -25
- package/package.json +6 -2
- package/templates/backend/pnpm-lock.yaml +0 -4240
- package/templates/frontend/pnpm-lock.yaml +0 -2011
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @totaland/create-starter-kit
|
|
2
2
|
|
|
3
|
-
Scaffolding tool for creating new starter-kit projects with a choice between backend
|
|
3
|
+
Scaffolding tool for creating new starter-kit projects with a choice between backend, frontend, or fullstack templates.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- ✨ Interactive template selection (backend or
|
|
7
|
+
- ✨ Interactive template selection (backend, frontend, or fullstack)
|
|
8
8
|
- 🎯 CLI argument support for automation
|
|
9
9
|
- 📦 Clean, production-ready templates
|
|
10
10
|
- 🚀 Quick project initialization
|
|
@@ -20,6 +20,7 @@ pnpm create @totaland/starter-kit my-new-project
|
|
|
20
20
|
You'll be prompted to select a template:
|
|
21
21
|
- **Backend** - Express.js + TypeScript + Drizzle ORM + Scalar API docs
|
|
22
22
|
- **Frontend** - React + Vite + TypeScript + Tailwind CSS v4 + shadcn/ui + TanStack Query
|
|
23
|
+
- **Fullstack** - Both Backend and Frontend in one project
|
|
23
24
|
|
|
24
25
|
### With Template Argument
|
|
25
26
|
|
|
@@ -31,6 +32,9 @@ pnpm create @totaland/starter-kit my-backend backend
|
|
|
31
32
|
|
|
32
33
|
# Create frontend project
|
|
33
34
|
pnpm create @totaland/starter-kit my-frontend frontend
|
|
35
|
+
|
|
36
|
+
# Create fullstack project (both backend and frontend)
|
|
37
|
+
pnpm create @totaland/starter-kit my-app fullstack
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
### Alternative Package Managers
|
|
@@ -107,10 +111,29 @@ pnpm dev
|
|
|
107
111
|
pnpm dlx shadcn@latest add button card dialog
|
|
108
112
|
```
|
|
109
113
|
|
|
114
|
+
### Fullstack Template
|
|
115
|
+
|
|
116
|
+
Creates both backend and frontend in separate subdirectories.
|
|
117
|
+
|
|
118
|
+
**After Creation:**
|
|
119
|
+
```bash
|
|
120
|
+
cd my-app
|
|
121
|
+
|
|
122
|
+
# Run backend
|
|
123
|
+
cd backend
|
|
124
|
+
pnpm install
|
|
125
|
+
pnpm dev
|
|
126
|
+
|
|
127
|
+
# Run frontend (in another terminal)
|
|
128
|
+
cd frontend
|
|
129
|
+
pnpm install
|
|
130
|
+
pnpm dev
|
|
131
|
+
```
|
|
132
|
+
|
|
110
133
|
## What It Does
|
|
111
134
|
|
|
112
135
|
1. ✅ Creates a new directory with your project name
|
|
113
|
-
2. ✅ Copies the selected template (backend or
|
|
136
|
+
2. ✅ Copies the selected template (backend, frontend, or both for fullstack)
|
|
114
137
|
3. ✅ Updates the `package.json` name field to match your project name
|
|
115
138
|
4. ✅ Provides next steps for installation and running the project
|
|
116
139
|
|
|
@@ -139,6 +162,7 @@ To test this locally before publishing:
|
|
|
139
162
|
# Or specify template directly
|
|
140
163
|
pnpm create @totaland/starter-kit test-backend backend
|
|
141
164
|
pnpm create @totaland/starter-kit test-frontend frontend
|
|
165
|
+
pnpm create @totaland/starter-kit test-fullstack fullstack
|
|
142
166
|
```
|
|
143
167
|
|
|
144
168
|
## Publishing
|
package/bin/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const templateArg = process.argv[3]; // Optional template argument
|
|
|
21
21
|
if (!projectName) {
|
|
22
22
|
console.error('Error: Please provide a project name');
|
|
23
23
|
console.log('Usage: pnpm create @totaland/starter-kit <project-name> [template]');
|
|
24
|
-
console.log('Templates: backend, frontend');
|
|
24
|
+
console.log('Templates: backend, frontend, fullstack');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -47,8 +47,30 @@ const TEMPLATES = {
|
|
|
47
47
|
description: 'React + Vite with TypeScript, Tailwind CSS v4, shadcn/ui, and TanStack Query',
|
|
48
48
|
dir: 'frontend',
|
|
49
49
|
},
|
|
50
|
+
fullstack: {
|
|
51
|
+
name: 'Fullstack',
|
|
52
|
+
description: 'Both Backend and Frontend templates combined',
|
|
53
|
+
dirs: ['backend', 'frontend'],
|
|
54
|
+
},
|
|
50
55
|
};
|
|
51
56
|
|
|
57
|
+
// Directories and files to exclude when copying
|
|
58
|
+
const EXCLUDE = new Set([
|
|
59
|
+
'node_modules',
|
|
60
|
+
'.git',
|
|
61
|
+
'dist',
|
|
62
|
+
'build',
|
|
63
|
+
'.turbo',
|
|
64
|
+
'.next',
|
|
65
|
+
'.nuxt',
|
|
66
|
+
'.output',
|
|
67
|
+
'.cache',
|
|
68
|
+
'coverage',
|
|
69
|
+
'.env',
|
|
70
|
+
'.env.local',
|
|
71
|
+
'.DS_Store',
|
|
72
|
+
]);
|
|
73
|
+
|
|
52
74
|
// Function to recursively copy directory
|
|
53
75
|
function copyDir(src, dest) {
|
|
54
76
|
mkdirSync(dest, { recursive: true });
|
|
@@ -56,6 +78,11 @@ function copyDir(src, dest) {
|
|
|
56
78
|
const entries = readdirSync(src, { withFileTypes: true });
|
|
57
79
|
|
|
58
80
|
for (const entry of entries) {
|
|
81
|
+
// Skip excluded files and directories
|
|
82
|
+
if (EXCLUDE.has(entry.name)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
59
86
|
const srcPath = join(src, entry.name);
|
|
60
87
|
const destPath = join(dest, entry.name);
|
|
61
88
|
|
|
@@ -75,10 +102,11 @@ async function promptTemplate() {
|
|
|
75
102
|
});
|
|
76
103
|
|
|
77
104
|
console.log('\n📦 Select a template:\n');
|
|
78
|
-
console.log('1. Backend
|
|
79
|
-
console.log('2. Frontend
|
|
105
|
+
console.log('1. Backend - Express.js + TypeScript + Drizzle ORM');
|
|
106
|
+
console.log('2. Frontend - React + Vite + Tailwind CSS v4 + shadcn/ui');
|
|
107
|
+
console.log('3. Fullstack - Both Backend and Frontend\n');
|
|
80
108
|
|
|
81
|
-
const answer = await rl.question('Enter your choice (1 or
|
|
109
|
+
const answer = await rl.question('Enter your choice (1, 2, or 3): ');
|
|
82
110
|
rl.close();
|
|
83
111
|
|
|
84
112
|
if (answer === '1' || answer.toLowerCase() === 'backend') {
|
|
@@ -87,6 +115,9 @@ async function promptTemplate() {
|
|
|
87
115
|
if (answer === '2' || answer.toLowerCase() === 'frontend') {
|
|
88
116
|
return 'frontend';
|
|
89
117
|
}
|
|
118
|
+
if (answer === '3' || answer.toLowerCase() === 'fullstack') {
|
|
119
|
+
return 'fullstack';
|
|
120
|
+
}
|
|
90
121
|
|
|
91
122
|
console.error('Invalid choice. Please run the command again.');
|
|
92
123
|
process.exit(1);
|
|
@@ -102,7 +133,7 @@ async function main() {
|
|
|
102
133
|
templateKey = templateArg.toLowerCase();
|
|
103
134
|
if (!TEMPLATES[templateKey]) {
|
|
104
135
|
console.error(`Error: Invalid template "${templateArg}"`);
|
|
105
|
-
console.log('Available templates: backend, frontend');
|
|
136
|
+
console.log('Available templates: backend, frontend, fullstack');
|
|
106
137
|
process.exit(1);
|
|
107
138
|
}
|
|
108
139
|
} else {
|
|
@@ -111,37 +142,63 @@ async function main() {
|
|
|
111
142
|
}
|
|
112
143
|
|
|
113
144
|
const template = TEMPLATES[templateKey];
|
|
114
|
-
const templateDir = join(templatesDir, template.dir);
|
|
115
|
-
|
|
116
|
-
// Verify template directory exists
|
|
117
|
-
if (!existsSync(templateDir)) {
|
|
118
|
-
console.error(`Error: Template directory not found: ${templateDir}`);
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
145
|
|
|
122
146
|
console.log(`\n🚀 Creating ${template.name} project: ${projectName}`);
|
|
123
147
|
console.log(`📁 ${template.description}\n`);
|
|
124
148
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
149
|
+
// Handle fullstack (multiple templates) or single template
|
|
150
|
+
if (template.dirs) {
|
|
151
|
+
// Fullstack: copy each template to a subdirectory
|
|
152
|
+
for (const dir of template.dirs) {
|
|
153
|
+
const templateDir = join(templatesDir, dir);
|
|
154
|
+
if (!existsSync(templateDir)) {
|
|
155
|
+
console.error(`Error: Template directory not found: ${templateDir}`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
const subTargetDir = join(targetDir, dir);
|
|
159
|
+
copyDir(templateDir, subTargetDir);
|
|
160
|
+
|
|
161
|
+
// Update package.json name for each sub-project
|
|
162
|
+
const packageJsonPath = join(subTargetDir, 'package.json');
|
|
163
|
+
if (existsSync(packageJsonPath)) {
|
|
164
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
165
|
+
packageJson.name = `${projectName}-${dir}`;
|
|
166
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// Single template
|
|
171
|
+
const templateDir = join(templatesDir, template.dir);
|
|
172
|
+
if (!existsSync(templateDir)) {
|
|
173
|
+
console.error(`Error: Template directory not found: ${templateDir}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
copyDir(templateDir, targetDir);
|
|
177
|
+
|
|
178
|
+
// Update package.json with the new project name
|
|
179
|
+
const packageJsonPath = join(targetDir, 'package.json');
|
|
180
|
+
if (existsSync(packageJsonPath)) {
|
|
181
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
182
|
+
packageJson.name = projectName;
|
|
183
|
+
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
184
|
+
}
|
|
134
185
|
}
|
|
135
186
|
|
|
136
187
|
console.log('✅ Project created successfully!\n');
|
|
137
188
|
console.log('📝 Next steps:');
|
|
138
189
|
console.log(` cd ${projectName}`);
|
|
139
|
-
|
|
140
|
-
|
|
190
|
+
if (templateKey === 'fullstack') {
|
|
191
|
+
console.log(' cd backend && pnpm install && pnpm dev');
|
|
192
|
+
console.log(' cd frontend && pnpm install && pnpm dev\n');
|
|
193
|
+
} else {
|
|
194
|
+
console.log(' pnpm install');
|
|
195
|
+
console.log(' pnpm dev\n');
|
|
196
|
+
}
|
|
141
197
|
|
|
142
|
-
if (templateKey === 'frontend') {
|
|
198
|
+
if (templateKey === 'frontend' || templateKey === 'fullstack') {
|
|
143
199
|
console.log('💡 Tip: Add shadcn/ui components with:');
|
|
144
|
-
|
|
200
|
+
const cdPath = templateKey === 'fullstack' ? 'cd frontend && ' : '';
|
|
201
|
+
console.log(` ${cdPath}pnpm dlx shadcn@latest add button card dialog\n`);
|
|
145
202
|
}
|
|
146
203
|
} catch (error) {
|
|
147
204
|
console.error('Error creating project:', error.message);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totaland/create-starter-kit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Scaffolding tool for creating new starter-kit projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
"bin",
|
|
14
14
|
"templates"
|
|
15
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"sync-templates": "node scripts/sync-templates.js",
|
|
18
|
+
"prepublishOnly": "node scripts/sync-templates.js"
|
|
19
|
+
},
|
|
16
20
|
"keywords": [
|
|
17
21
|
"starter-kit",
|
|
18
22
|
"scaffold",
|
|
@@ -21,4 +25,4 @@
|
|
|
21
25
|
"dependencies": {
|
|
22
26
|
"fast-glob": "^3.3.2"
|
|
23
27
|
}
|
|
24
|
-
}
|
|
28
|
+
}
|