@majordigital/create-acorn 1.0.8 → 1.1.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.
@@ -100,8 +100,10 @@ async function scaffoldNextApp() {
100
100
  // Add .npmrc with legacy-peer-deps so all npm installs (including Slice Machine) work with React 19
101
101
  writeFileSync(join(process.cwd(), '.npmrc'), 'legacy-peer-deps=true\n');
102
102
 
103
- // Remove postcss config generated by create-next-app (not needed with Tailwind v4)
103
+ // Remove configs generated by create-next-app that we replace
104
104
  try { rmSync(join(process.cwd(), 'postcss.config.mjs')); } catch {}
105
+ try { rmSync(join(process.cwd(), 'next.config.ts')); } catch {}
106
+ try { rmSync(join(process.cwd(), 'next.config.js')); } catch {}
105
107
 
106
108
  // Copy Acorn template files (src/, public/, config files) over the Next.js scaffold
107
109
  console.log('Copying Acorn boilerplate...');
@@ -125,11 +127,15 @@ async function scaffoldNextApp() {
125
127
  console.log('Acorn dependencies installed.');
126
128
  console.log('');
127
129
 
128
- console.log('Installing Biome for linting...');
130
+ console.log('Installing Biome, commitlint, and lefthook...');
129
131
  await runCommand('npm', ['install', '--save-dev', '--save-exact', '@biomejs/biome']);
130
- await runCommand('npx', ['@biomejs/biome', 'init']);
132
+ await runCommand('npm', ['install', '--save-dev',
133
+ '@commitlint/cli', '@commitlint/config-conventional', '@commitlint/types', 'lefthook'
134
+ ]);
135
+ // Remove default biome.json if created — we use biome.jsonc from the template
136
+ try { rmSync(join(process.cwd(), 'biome.json')); } catch {}
131
137
  console.log('');
132
- console.log('Biome configured successfully.');
138
+ console.log('Biome, commitlint, and lefthook configured.');
133
139
  console.log('');
134
140
  }
135
141
 
@@ -207,6 +213,131 @@ async function setupPrismic() {
207
213
  console.log('');
208
214
  }
209
215
 
216
+ function generateReadme(projectName, cms) {
217
+ const title = projectName || 'Project Title';
218
+
219
+ const shared = `# ${title}
220
+
221
+ ## Introduction 📖
222
+
223
+ ## 📋 Prerequisites
224
+
225
+ - **Node.js**: v20.19.0 or higher
226
+ - **npm**: v10.8.2 or higher
227
+
228
+ ## Running This Project 🚀
229
+ `;
230
+
231
+ const prismic = `
232
+ This website is built using the [NextJS](https://nextjs.org/) framework, utilising [TypeScript](https://www.typescriptlang.org/) to strongly check types/props and provide helpful intelisense, and the utility-first CSS framework [Tailwind](https://tailwindcss.com/) as the styling library and the headless CMS [Prismic](https://prismic.io/).
233
+
234
+ To run this project, follow the instructions below:
235
+
236
+ 1. Open the terminal, and navigate the root directory for this project.
237
+ 2. Add in the environment variables in a \`.env\` file. More information found in the next section.
238
+ 3. Run \`npm install\`, and wait for dependencies to install.
239
+ 4. Run \`npm run dev\`, where a local instance of this website will be initiated e.g localhost:3000
240
+ 5. Run \`npm run slicemachine\`, where a local instance of slicemachine will be initiated e.g localhost:9999
241
+
242
+ ## Environment Variables 🔒
243
+
244
+ There are a few environmental variables required to run this project. As mentioned previously, each website setup requires it's own \`.env\` file within it's root directory.
245
+
246
+ To manage environment variables, follow these guidelines:
247
+
248
+ - Use \`.env\` for both local and production environments.
249
+ - The \`.env.development\` file will only be used for development builds.
250
+ - You can either:
251
+ - Include a \`.env.production\` file for production-specific configurations, **or**
252
+ - Use a single \`.env\` file that serves both local and production needs.
253
+
254
+ Make sure to configure your environment files appropriately based on your project's requirements.
255
+
256
+ The required variables are:
257
+
258
+ - **PRISMIC_ACCESS_TOKEN**: Found within the relevant project on our Prismic account
259
+ - **SITE_URL**: A full url path for the domain of this project, e.g. https://search-seven.netlify.app
260
+ `;
261
+
262
+ const storyblok = `
263
+ This website is built using the [NextJS](https://nextjs.org/) framework, utilising [TypeScript](https://www.typescriptlang.org/) to strongly check types/props and provide helpful intelisense, and the utility-first CSS framework [Tailwind](https://tailwindcss.com/) as the styling library and the headless CMS [Storyblok](https://www.storyblok.com/).
264
+
265
+ ## 🛠️ Installation
266
+
267
+ 1. **Install dependencies**
268
+
269
+ \`\`\`bash
270
+ npm install
271
+ \`\`\`
272
+
273
+ 2. **Set up environment variables**
274
+
275
+ Create \`.env.local\` file in the root directory:
276
+
277
+ \`\`\`env
278
+ NEXT_PUBLIC_STORYBLOK_ACCESS_TOKEN=your_preview_token
279
+ STORYBLOK_SPACE_ID=your_space_id
280
+ NEXT_PUBLIC_STORYBLOK_TOKEN_VERSION=draft # or 'published' for production
281
+ \`\`\`
282
+
283
+ 3. **Start the development server**
284
+
285
+ \`\`\`bash
286
+ npm run dev
287
+ \`\`\`
288
+
289
+ The site will be available at \`http://localhost:3000\`
290
+
291
+ 4. **Run Storybook** (optional)
292
+
293
+ \`\`\`bash
294
+ npm run storybook
295
+ \`\`\`
296
+
297
+ Storybook will be available at \`http://localhost:6006\`
298
+ `;
299
+
300
+ const dato = `
301
+ This website is built using the [NextJS](https://nextjs.org/) framework, utilising [TypeScript](https://www.typescriptlang.org/) to strongly check types/props and provide helpful intelisense, and the utility-first CSS framework [Tailwind](https://tailwindcss.com/) as the styling library and the headless CMS [DatoCMS](https://www.datocms.com/).
302
+
303
+ ## 🛠️ Installation
304
+
305
+ 1. **Install dependencies**
306
+
307
+ \`\`\`bash
308
+ npm install
309
+ \`\`\`
310
+
311
+ 2. **Set up environment variables**
312
+
313
+ Create \`.env.local\` file in the root directory:
314
+
315
+ \`\`\`env
316
+ DATOCMS_API_TOKEN=your_api_token
317
+ DATOCMS_PREVIEW_SECRET=your_preview_secret
318
+ SITE_URL=http://localhost:3000
319
+ \`\`\`
320
+
321
+ 3. **Start the development server**
322
+
323
+ \`\`\`bash
324
+ npm run dev
325
+ \`\`\`
326
+
327
+ The site will be available at \`http://localhost:3000\`
328
+ `;
329
+
330
+ const cmsSection = cms === 'prismic' ? prismic : cms === 'storyblok' ? storyblok : dato;
331
+
332
+ const footer = `
333
+ ## Contacts 🧑‍💻
334
+
335
+ The primary contact for this project is [Davs Howard](mailto:davs@majordigital.com).
336
+ `;
337
+
338
+ return shared + cmsSection + footer;
339
+ }
340
+
210
341
  async function main() {
211
342
  printHeader();
212
343
  let selection = parseNonInteractiveArg();
@@ -237,6 +368,38 @@ async function main() {
237
368
  console.log('This run only confirms selection for non-Prismic options.');
238
369
  console.log('');
239
370
  }
371
+
372
+ // Generate .env.example
373
+ const envExamples = {
374
+ prismic: `PRISMIC_ACCESS_TOKEN=
375
+ SITE_URL=
376
+ `,
377
+ storyblok: `STORYBLOK_SPACE_ID=
378
+ STORYBLOK_PREVIEW_TOKEN=
379
+ STORYBLOK_PERSONAL_ACCESS_TOKEN=
380
+ NEXT_PUBLIC_STORYBLOK_PUBLIC_TOKEN=
381
+ NEXT_PUBLIC_STORYBLOK_TOKEN_VERSION="draft"
382
+ STORYBLOK_WEBHOOK_TOKEN=
383
+ INTERNAL_PREVIEW_SECRET=
384
+ INTERNAL_PREVIEW_API_KEY=
385
+ NEXT_PUBLIC_SITE_URL=
386
+ NEXT_PUBLIC_HUBSPOT_PORTAL_ID=
387
+ `,
388
+ dato: `DATOCMS_API_TOKEN=
389
+ DATOCMS_PREVIEW_SECRET=
390
+ SITE_URL=
391
+ `,
392
+ };
393
+ writeFileSync(join(process.cwd(), '.env.example'), envExamples[selection.key]);
394
+ console.log('.env.example generated.');
395
+ console.log('');
396
+
397
+ // Generate project README
398
+ const projectName = basename(process.cwd());
399
+ const readme = generateReadme(projectName, selection.key);
400
+ writeFileSync(join(process.cwd(), 'README.md'), readme);
401
+ console.log('README.md generated.');
402
+ console.log('');
240
403
  }
241
404
 
242
405
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majordigital/create-acorn",
3
- "version": "1.0.8",
3
+ "version": "1.1.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",
@@ -0,0 +1,105 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false
10
+ },
11
+ "formatter": {
12
+ "enabled": true,
13
+ "indentWidth": 4,
14
+ "indentStyle": "tab",
15
+ "lineWidth": 80,
16
+ "lineEnding": "lf"
17
+ },
18
+ "linter": {
19
+ "enabled": true,
20
+ "domains": {
21
+ "react": "recommended",
22
+ "next": "recommended"
23
+ },
24
+ "rules": {
25
+ "style": {
26
+ "noNonNullAssertion": "off"
27
+ },
28
+ "correctness": {
29
+ "noUnusedImports": {
30
+ "level": "error",
31
+ "fix": "safe",
32
+ "options": {}
33
+ },
34
+ "noUnusedVariables": "error",
35
+ "useUniqueElementIds": "error"
36
+ },
37
+ "complexity": {
38
+ "noUselessFragments": {
39
+ "level": "warn",
40
+ "fix": "safe",
41
+ "options": {}
42
+ }
43
+ },
44
+ "suspicious": {
45
+ "noExplicitAny": "off",
46
+ "noImplicitAnyLet": "off",
47
+ "noConsole": {
48
+ "fix": "unsafe",
49
+ "level": "error",
50
+ "options": {}
51
+ },
52
+ "noUnknownAtRules": "off"
53
+ },
54
+ "nursery": {
55
+ "useSortedClasses": {
56
+ "level": "error",
57
+ "fix": "safe",
58
+ "options": {
59
+ "functions": ["clsx"]
60
+ }
61
+ }
62
+ }
63
+ }
64
+ },
65
+ "javascript": {
66
+ "formatter": {
67
+ "quoteStyle": "single",
68
+ "trailingCommas": "es5",
69
+ "semicolons": "always",
70
+ "arrowParentheses": "asNeeded"
71
+ }
72
+ },
73
+ "css": {
74
+ "formatter": {
75
+ "quoteStyle": "single"
76
+ },
77
+ "parser": {
78
+ "tailwindDirectives": true
79
+ }
80
+ },
81
+ "assist": {
82
+ "enabled": true,
83
+ "actions": {
84
+ "source": {
85
+ "organizeImports": {
86
+ "level": "on",
87
+ "options": {
88
+ "groups": [
89
+ ":NODE:",
90
+ ":BLANK_LINE:",
91
+ [":PACKAGE:", ":PACKAGE_WITH_PROTOCOL:"],
92
+ ":BLANK_LINE:",
93
+ ":ALIAS:",
94
+ ":BLANK_LINE:",
95
+ ":PATH:",
96
+ ":BLANK_LINE:",
97
+ ":URL:"
98
+ ]
99
+ }
100
+ }
101
+ }
102
+ }
103
+ },
104
+ "overrides": []
105
+ }
@@ -0,0 +1,7 @@
1
+ import type { UserConfig } from '@commitlint/types';
2
+
3
+ const commitlintConfig: UserConfig = {
4
+ extends: ['@commitlint/config-conventional'],
5
+ };
6
+
7
+ export default commitlintConfig;
@@ -0,0 +1,15 @@
1
+ pre-commit:
2
+ parallel: true
3
+ commands:
4
+ check-js:
5
+ glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
6
+ run: npx biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
7
+ stage_fixed: true
8
+ check-toml:
9
+ glob: "*.toml"
10
+ run: test -z "{staged_files}" || (npx taplo format {staged_files} && git update-index --again)
11
+
12
+ commit-msg:
13
+ scripts:
14
+ "commitlint.sh":
15
+ runner: bash
@@ -1,6 +1,11 @@
1
- /** @type {import('next').NextConfig} */
1
+ import type { NextConfig } from 'next';
2
+ import bundleAnalyzer from '@next/bundle-analyzer';
2
3
 
3
- const baseConfig = {
4
+ const withBundleAnalyzer = bundleAnalyzer({
5
+ enabled: process.env.ANALYZE === 'true',
6
+ });
7
+
8
+ const baseConfig: NextConfig = {
4
9
  poweredByHeader: false,
5
10
  reactStrictMode: true,
6
11
  trailingSlash: false,
@@ -22,7 +27,7 @@ const baseConfig = {
22
27
 
23
28
  return config;
24
29
  },
25
-
30
+
26
31
  images: {
27
32
  remotePatterns: [
28
33
  {
@@ -41,8 +46,4 @@ const baseConfig = {
41
46
  },
42
47
  };
43
48
 
44
- const withBundleAnalyzer = require('@next/bundle-analyzer')({
45
- enabled: process.env.ANALYZE === 'true',
46
- });
47
-
48
- module.exports = withBundleAnalyzer(baseConfig);
49
+ export default withBundleAnalyzer(baseConfig);
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -0,0 +1,5 @@
1
+ declare module '*.svg' {
2
+ import type { FC, SVGProps } from 'react';
3
+ const content: FC<SVGProps<SVGSVGElement>>;
4
+ export default content;
5
+ }