@majordigital/create-acorn 1.1.5 → 1.2.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.
package/README.md CHANGED
@@ -10,7 +10,17 @@ It eliminates the repetitive setup that comes with every new project — framewo
10
10
  npx @majordigital/create-acorn@latest
11
11
  ```
12
12
 
13
- The CLI walks you through selecting a headless CMS and scaffolds a complete, opinionated project in seconds.
13
+ The CLI prompts you for a project name, creates the directory, then walks you through selecting a headless CMS scaffolding a complete, opinionated project in seconds.
14
+
15
+ ```
16
+ ? What is the name of your project? (my-acorn-app)
17
+ ? Which headless CMS would you like to use?
18
+ 1) Prismic
19
+ 2) Storyblok
20
+ 3) Dato
21
+ ```
22
+
23
+ The project name is also used as the default CMS space/repository name.
14
24
 
15
25
  ## What's Inside
16
26
 
@@ -55,9 +65,9 @@ src/
55
65
  For CI pipelines or scripted setups:
56
66
 
57
67
  ```bash
58
- npx @majordigital/create-acorn@latest --cms prismic --repo my-repo
59
- npx @majordigital/create-acorn@latest --cms storyblok
60
- npx @majordigital/create-acorn@latest --cms dato
68
+ npx @majordigital/create-acorn@latest --name my-project --cms prismic --repo my-repo
69
+ npx @majordigital/create-acorn@latest --name my-project --cms storyblok
70
+ npx @majordigital/create-acorn@latest --name my-project --cms dato
61
71
  ```
62
72
 
63
73
  ## Generated Project Files
@@ -4,7 +4,7 @@ import readline from 'node:readline';
4
4
  import { argv, exit } from 'node:process';
5
5
  import { spawn } from 'node:child_process';
6
6
  import { basename, join, dirname } from 'node:path';
7
- import { readFileSync, writeFileSync, cpSync, rmSync } from 'node:fs';
7
+ import { readFileSync, writeFileSync, cpSync, rmSync, mkdirSync, existsSync } from 'node:fs';
8
8
  import { fileURLToPath } from 'node:url';
9
9
 
10
10
  const CMS_CHOICES = [
@@ -142,14 +142,9 @@ async function scaffoldNextApp() {
142
142
  console.log('');
143
143
  }
144
144
 
145
- async function setupPrismic() {
145
+ async function setupPrismic(projectName) {
146
146
  const nonInteractiveRepo = parseFlag('repo');
147
- const cwdName = basename(process.cwd())
148
- .toLowerCase()
149
- .replace(/[^a-z0-9-]/g, '-')
150
- .replace(/-{2,}/g, '-')
151
- .replace(/^-+|-+$/g, '');
152
- const defaultBase = cwdName && cwdName !== 'acorn' ? cwdName : 'acorn';
147
+ const defaultBase = projectName && projectName !== 'acorn' ? projectName : 'acorn';
153
148
  const prefixed = defaultBase.startsWith('majordigital-') ? defaultBase : `majordigital-${defaultBase}`;
154
149
  const suggested = nonInteractiveRepo || prefixed;
155
150
 
@@ -352,6 +347,26 @@ The primary contact for this project is [Davs Howard](mailto:davs@majordigital.c
352
347
 
353
348
  async function main() {
354
349
  printHeader();
350
+
351
+ // Prompt for project name first
352
+ const nameFromFlag = parseFlag('name');
353
+ let projectDir = nameFromFlag;
354
+ if (!projectDir) {
355
+ projectDir = await ask('What is the name of your project?', 'my-acorn-app');
356
+ }
357
+
358
+ // Sanitise to a valid directory name
359
+ projectDir = projectDir
360
+ .toLowerCase()
361
+ .replace(/[^a-z0-9-]/g, '-')
362
+ .replace(/-{2,}/g, '-')
363
+ .replace(/^-+|-+$/g, '');
364
+
365
+ if (!projectDir) {
366
+ console.error('Invalid project name.');
367
+ exit(1);
368
+ }
369
+
355
370
  let selection = parseNonInteractiveArg();
356
371
  if (!selection) {
357
372
  selection = await promptInteractive();
@@ -366,11 +381,23 @@ async function main() {
366
381
  console.log(`You selected: ${selection.label}`);
367
382
  console.log('');
368
383
 
384
+ console.log(`- Project: ${projectDir}`);
369
385
  console.log('- Framework: Next.js 15');
370
386
  console.log('- UI base: Acorn components');
371
387
  console.log(`- CMS: ${selection.label}`);
372
388
  console.log('');
373
389
 
390
+ // Create project directory and work inside it
391
+ const targetDir = join(process.cwd(), projectDir);
392
+ if (existsSync(targetDir)) {
393
+ console.error(`Directory "${projectDir}" already exists. Please choose a different name or remove it.`);
394
+ exit(1);
395
+ }
396
+ mkdirSync(targetDir, { recursive: true });
397
+ process.chdir(targetDir);
398
+ console.log(`Created directory: ${projectDir}`);
399
+ console.log('');
400
+
374
401
  await scaffoldNextApp();
375
402
 
376
403
  // Generate .env.example and README before CMS setup (CMS setup may block if user starts Slice Machine)
@@ -397,14 +424,13 @@ SITE_URL=
397
424
  writeFileSync(join(process.cwd(), '.env.example'), envExamples[selection.key]);
398
425
  console.log('.env.example generated.');
399
426
 
400
- const projectName = basename(process.cwd());
401
- const readme = generateReadme(projectName, selection.key);
427
+ const readme = generateReadme(projectDir, selection.key);
402
428
  writeFileSync(join(process.cwd(), 'README.md'), readme);
403
429
  console.log('README.md generated.');
404
430
  console.log('');
405
431
 
406
432
  if (selection.key === 'prismic') {
407
- await setupPrismic();
433
+ await setupPrismic(projectDir);
408
434
  } else {
409
435
  console.log(`CMS preset ${selection.label} scaffolding is coming next.`);
410
436
  console.log('This run only confirms selection for non-Prismic options.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majordigital/create-acorn",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "Interactive scaffold for Acorn with Storyblok/Prismic/DatoCMS, TypeScript, and Tailwind.",
5
5
  "bin": {
6
6
  "create-acorn": "bin/create-acorn.mjs",