create-alistt69-kit 0.3.1 โ 0.3.2
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 +9 -8
- package/package.json +1 -1
- package/src/core/parse-cli-args.js +1 -1
- package/src/core/render-project-readme.js +11 -0
- package/src/features/agents-md/files/AGENTS.md +37 -0
- package/src/features/agents-md/index.js +14 -0
- package/src/features/autoprefixer/index.js +13 -0
- package/src/features/eslint/index.js +14 -0
- package/src/features/index.js +2 -0
- package/src/features/prerender/index.js +17 -1
- package/src/features/react-router/index.js +15 -0
- package/src/features/stylelint/index.js +14 -0
- package/src/utils/agents-md.js +53 -0
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ It generates a ready-to-run **React + TypeScript + Webpack** starter with a prac
|
|
|
38
38
|
| [Stylelint](https://stylelint.io/) | Stylesheet linting | Optional |
|
|
39
39
|
| [Autoprefixer](https://github.com/postcss/autoprefixer) | Automatic CSS vendor prefixes | Optional |
|
|
40
40
|
| [React Router](https://reactrouter.com/) | Client-side routing | Optional |
|
|
41
|
+
| [AGENTS.md](https://agents.md/) | Root instructions file for AI coding agents | Optional |
|
|
41
42
|
| [Puppeteer](https://pptr.dev/) + [serve-handler](https://github.com/vercel/serve-handler) | Static HTML prerender after production build | Optional |
|
|
42
43
|
|
|
43
44
|
## ๐ฏ Why use it?
|
|
@@ -166,14 +167,14 @@ npm create alistt69-kit@latest my-app -- --defaults --overwrite
|
|
|
166
167
|
|
|
167
168
|
## โ๏ธ CLI options
|
|
168
169
|
|
|
169
|
-
| Option
|
|
170
|
-
|
|
171
|
-
| `--defaults`
|
|
172
|
-
| `--overwrite`
|
|
173
|
-
| `--no-install`
|
|
174
|
-
| `--features <list>` | โ
|
|
175
|
-
| `--pm <name>`
|
|
176
|
-
| `--help`
|
|
170
|
+
| Option | Alias | Description |
|
|
171
|
+
|---------------------|--------|-------------|
|
|
172
|
+
| `--defaults` | `-def` | Skip prompts, use defaults |
|
|
173
|
+
| `--overwrite` | โ | Overwrite target directory if it exists |
|
|
174
|
+
| `--no-install` | โ | Skip dependency installation |
|
|
175
|
+
| `--features <list>` | โ | Enable specific features (`agents-md`, `eslint`, `stylelint`, `autoprefixer`, `react-router`, `prerender`) |
|
|
176
|
+
| `--pm <name>` | โ | Choose package manager (`npm`, `pnpm`, `yarn`) |
|
|
177
|
+
| `--help` | `-h` | Show help |
|
|
177
178
|
|
|
178
179
|
## ๐งช Default behavior
|
|
179
180
|
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ export function formatHelpMessage() {
|
|
|
31
31
|
' -def, --defaults Skip prompts and use defaults',
|
|
32
32
|
' --overwrite Overwrite target directory if it exists',
|
|
33
33
|
' --no-install Do not install dependencies',
|
|
34
|
-
' --features <comma-list> Example: eslint,stylelint,react-router,prerender',
|
|
34
|
+
' --features <comma-list> Example: agents-md,eslint,stylelint,react-router,prerender',
|
|
35
35
|
' --features all Enable all features',
|
|
36
36
|
' --pm <npm|pnpm|yarn> Package manager',
|
|
37
37
|
' -h, --help Show help',
|
|
@@ -150,6 +150,17 @@ function formatProjectStructure(selectedFeatureIds) {
|
|
|
150
150
|
function formatFeatureSpecificSections({ selectedFeatureIds, packageManager }) {
|
|
151
151
|
const sections = [];
|
|
152
152
|
|
|
153
|
+
if (selectedFeatureIds.includes('agents-md')) {
|
|
154
|
+
sections.push([
|
|
155
|
+
'## AGENTS.md',
|
|
156
|
+
'',
|
|
157
|
+
'When `AGENTS.md` is enabled, the project includes a root instruction file for AI coding agents.',
|
|
158
|
+
'',
|
|
159
|
+
'- Base file: `AGENTS.md`',
|
|
160
|
+
'- Other selected features may append their own sections into this file automatically during scaffolding.',
|
|
161
|
+
].join('\n'));
|
|
162
|
+
}
|
|
163
|
+
|
|
153
164
|
if (selectedFeatureIds.includes('react-router')) {
|
|
154
165
|
sections.push([
|
|
155
166
|
'## Page generator',
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This project was scaffolded with `create-alistt69-kit`.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
- Install dependencies with the selected package manager.
|
|
10
|
+
- Start dev server with `npm run start`.
|
|
11
|
+
- Type-check with `npm run typecheck`.
|
|
12
|
+
|
|
13
|
+
## Base stack
|
|
14
|
+
|
|
15
|
+
- React
|
|
16
|
+
- TypeScript
|
|
17
|
+
- Webpack
|
|
18
|
+
- SCSS Modules
|
|
19
|
+
|
|
20
|
+
## General rules
|
|
21
|
+
|
|
22
|
+
- Keep code readable and explicit.
|
|
23
|
+
- Prefer small targeted changes over broad refactors.
|
|
24
|
+
- Do not rename public files or exported symbols unless required.
|
|
25
|
+
- Reuse existing project structure and conventions.
|
|
26
|
+
|
|
27
|
+
## Validation
|
|
28
|
+
|
|
29
|
+
Before finishing a task, run the relevant checks available in `package.json`.
|
|
30
|
+
|
|
31
|
+
## Project structure
|
|
32
|
+
|
|
33
|
+
- `src/app/` โ app bootstrap and providers
|
|
34
|
+
- `src/styles/` โ global styles
|
|
35
|
+
- `config/build/` โ webpack config parts
|
|
36
|
+
|
|
37
|
+
<!-- @agents-sections -->
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
|
|
4
|
+
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
|
|
6
|
+
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
|
+
const currentDirPath = dirname(currentFilePath);
|
|
8
|
+
|
|
9
|
+
export const agentsMdFeature = defineFeature({
|
|
10
|
+
id: 'agents-md',
|
|
11
|
+
title: 'AGENTS.md',
|
|
12
|
+
hint: 'Root instructions file for AI coding agents',
|
|
13
|
+
copyFiles: resolve(currentDirPath, 'files'),
|
|
14
|
+
});
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
4
|
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
import { appendAgentsSection } from '../../utils/agents-md.js';
|
|
5
6
|
|
|
6
7
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
8
|
const currentDirPath = dirname(currentFilePath);
|
|
@@ -16,4 +17,16 @@ export const autoprefixerFeature = defineFeature({
|
|
|
16
17
|
},
|
|
17
18
|
},
|
|
18
19
|
copyFiles: resolve(currentDirPath, 'files'),
|
|
20
|
+
async apply({ projectPath }) {
|
|
21
|
+
await appendAgentsSection(
|
|
22
|
+
projectPath,
|
|
23
|
+
'autoprefixer',
|
|
24
|
+
`
|
|
25
|
+
## CSS compatibility
|
|
26
|
+
|
|
27
|
+
- Vendor prefixing is handled by Autoprefixer.
|
|
28
|
+
- Do not add manual prefixes unless there is a confirmed need.
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
},
|
|
19
32
|
});
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
4
|
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
import { appendAgentsSection } from '../../utils/agents-md.js';
|
|
5
6
|
|
|
6
7
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
8
|
const currentDirPath = dirname(currentFilePath);
|
|
@@ -27,4 +28,17 @@ export const eslintFeature = defineFeature({
|
|
|
27
28
|
},
|
|
28
29
|
},
|
|
29
30
|
copyFiles: resolve(currentDirPath, 'files'),
|
|
31
|
+
async apply({ projectPath }) {
|
|
32
|
+
await appendAgentsSection(
|
|
33
|
+
projectPath,
|
|
34
|
+
'eslint',
|
|
35
|
+
`
|
|
36
|
+
## ESLint
|
|
37
|
+
|
|
38
|
+
- Lint code with \`npm run lint\`.
|
|
39
|
+
- Apply safe autofixes with \`npm run lint:fix\`.
|
|
40
|
+
- Prefer fixing root-cause issues instead of disabling rules.
|
|
41
|
+
`,
|
|
42
|
+
);
|
|
43
|
+
},
|
|
30
44
|
});
|
package/src/features/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { agentsMdFeature } from './agents-md/index.js';
|
|
1
2
|
import { autoprefixerFeature } from './autoprefixer/index.js';
|
|
2
3
|
import { eslintFeature } from './eslint/index.js';
|
|
3
4
|
import { prerenderFeature } from './prerender/index.js';
|
|
@@ -5,6 +6,7 @@ import { reactRouterFeature } from './react-router/index.js';
|
|
|
5
6
|
import { stylelintFeature } from './stylelint/index.js';
|
|
6
7
|
|
|
7
8
|
export const features = [
|
|
9
|
+
agentsMdFeature,
|
|
8
10
|
autoprefixerFeature,
|
|
9
11
|
eslintFeature,
|
|
10
12
|
prerenderFeature,
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
4
|
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
import { appendAgentsSection } from '../../utils/agents-md.js';
|
|
5
6
|
|
|
6
7
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
8
|
const currentDirPath = dirname(currentFilePath);
|
|
@@ -16,10 +17,25 @@ export const prerenderFeature = defineFeature({
|
|
|
16
17
|
'serve-handler': '^6.1.6',
|
|
17
18
|
},
|
|
18
19
|
scripts: {
|
|
20
|
+
build: 'npm run build:assets && npm run prerender',
|
|
19
21
|
'build:assets': 'webpack --env mode=production',
|
|
22
|
+
'build:prod': 'npm run build',
|
|
20
23
|
prerender: 'node ./scripts/prerender.mjs',
|
|
21
|
-
build: 'npm run build:assets && npm run prerender',
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
26
|
copyFiles: resolve(currentDirPath, 'files'),
|
|
27
|
+
async apply({ projectPath }) {
|
|
28
|
+
await appendAgentsSection(
|
|
29
|
+
projectPath,
|
|
30
|
+
'prerender',
|
|
31
|
+
`
|
|
32
|
+
## Prerender
|
|
33
|
+
|
|
34
|
+
- Production build runs in two steps: \`npm run build:assets\` then \`npm run prerender\`.
|
|
35
|
+
- Prerender route manifest lives in \`prerender.routes.mjs\`.
|
|
36
|
+
- Prerender script lives in \`scripts/prerender.mjs\`.
|
|
37
|
+
- When adding static routes, keep \`prerender.routes.mjs\` updated.
|
|
38
|
+
`,
|
|
39
|
+
);
|
|
40
|
+
},
|
|
25
41
|
});
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
4
|
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
import { appendAgentsSection } from '../../utils/agents-md.js';
|
|
5
6
|
|
|
6
7
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
8
|
const currentDirPath = dirname(currentFilePath);
|
|
@@ -19,4 +20,18 @@ export const reactRouterFeature = defineFeature({
|
|
|
19
20
|
},
|
|
20
21
|
},
|
|
21
22
|
copyFiles: resolve(currentDirPath, 'files'),
|
|
23
|
+
async apply({ projectPath }) {
|
|
24
|
+
await appendAgentsSection(
|
|
25
|
+
projectPath,
|
|
26
|
+
'react-router',
|
|
27
|
+
`
|
|
28
|
+
## React Router
|
|
29
|
+
|
|
30
|
+
- Routing is configured under \`src/app/providers/router/\`.
|
|
31
|
+
- Route-level pages live in \`src/pages/\`.
|
|
32
|
+
- Generate a new page with \`npm run generate:page -- <page-name>\`.
|
|
33
|
+
- Do not remove router marker comments used by the page generator unless you also disable auto-registration.
|
|
34
|
+
`,
|
|
35
|
+
);
|
|
36
|
+
},
|
|
22
37
|
});
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
4
|
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
import { appendAgentsSection } from '../../utils/agents-md.js';
|
|
5
6
|
|
|
6
7
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
8
|
const currentDirPath = dirname(currentFilePath);
|
|
@@ -21,4 +22,17 @@ export const stylelintFeature = defineFeature({
|
|
|
21
22
|
},
|
|
22
23
|
},
|
|
23
24
|
copyFiles: resolve(currentDirPath, 'files'),
|
|
25
|
+
async apply({ projectPath }) {
|
|
26
|
+
await appendAgentsSection(
|
|
27
|
+
projectPath,
|
|
28
|
+
'stylelint',
|
|
29
|
+
`
|
|
30
|
+
## Stylelint
|
|
31
|
+
|
|
32
|
+
- Lint styles with \`npm run lint:styles\`.
|
|
33
|
+
- Apply autofixes with \`npm run lint:styles:fix\`.
|
|
34
|
+
- Keep styles compatible with the existing SCSS modules setup.
|
|
35
|
+
`,
|
|
36
|
+
);
|
|
37
|
+
},
|
|
24
38
|
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { access, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const AGENTS_MD_PATH = 'AGENTS.md';
|
|
5
|
+
const SECTIONS_MARKER = '<!-- @agents-sections -->';
|
|
6
|
+
|
|
7
|
+
export function getAgentsMdPath(projectPath) {
|
|
8
|
+
return resolve(projectPath, AGENTS_MD_PATH);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function hasAgentsMd(projectPath) {
|
|
12
|
+
try {
|
|
13
|
+
await access(getAgentsMdPath(projectPath));
|
|
14
|
+
return true;
|
|
15
|
+
} catch (_) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function appendAgentsSection(projectPath, sectionKey, content) {
|
|
21
|
+
if (!(await hasAgentsMd(projectPath))) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const filepath = getAgentsMdPath(projectPath);
|
|
26
|
+
const fileContent = await readFile(filepath, 'utf8');
|
|
27
|
+
|
|
28
|
+
if (fileContent.includes(`<!-- @agents:${sectionKey} -->`)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const block = [
|
|
33
|
+
`<!-- @agents:${sectionKey} -->`,
|
|
34
|
+
content.trim(),
|
|
35
|
+
`<!-- /@agents:${sectionKey} -->`,
|
|
36
|
+
].join('\n');
|
|
37
|
+
|
|
38
|
+
let nextContent;
|
|
39
|
+
|
|
40
|
+
if (fileContent.includes(SECTIONS_MARKER)) {
|
|
41
|
+
nextContent = fileContent.replace(
|
|
42
|
+
SECTIONS_MARKER,
|
|
43
|
+
`${block}\n\n${SECTIONS_MARKER}`,
|
|
44
|
+
);
|
|
45
|
+
} else {
|
|
46
|
+
const trimmed = fileContent.trimEnd();
|
|
47
|
+
nextContent = `${trimmed}\n\n${block}\n`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
await writeFile(filepath, nextContent, 'utf8');
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|