@mkappelhof/agent-instructions 0.0.0-stage → 1.0.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/CHANGELOG.md +1 -0
- package/README.md +33 -2
- package/astro.md +34 -0
- package/base.md +80 -0
- package/package.json +29 -3
- package/react.md +131 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @mkappelhof/agent-instructions
|
package/README.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Shared agent instructions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Project-level instructions for AI coding agents, covering code structure and conventions rather
|
|
4
|
+
than tool configuration. Pair them with the `AGENTS.md` files shipped by the config packages in
|
|
5
|
+
this repo, which describe the tool rules.
|
|
6
|
+
|
|
7
|
+
| File | For |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `base.md` | Every project: verifying instead of assuming, workflow, git, imports, TypeScript, design tokens, versioning |
|
|
10
|
+
| `react.md` | React and Next.js projects (components, contexts, i18next, SCSS modules, Vitest) |
|
|
11
|
+
| `astro.md` | Static Astro sites (rendering, styling, data, images) |
|
|
12
|
+
|
|
13
|
+
`react.md` and `astro.md` both tell agents to read `base.md` first, so you only need to reference
|
|
14
|
+
the file for your project type.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pnpm add -D @mkappelhof/agent-instructions
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Reference the file for your project type from the `AGENTS.md` at the root of your project:
|
|
23
|
+
|
|
24
|
+
```md
|
|
25
|
+
# AGENTS.md
|
|
26
|
+
|
|
27
|
+
## Conventions
|
|
28
|
+
|
|
29
|
+
- Follow `node_modules/@mkappelhof/agent-instructions/react.md`
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Put anything project-specific (architecture, extra commands, exceptions to the shared conventions)
|
|
33
|
+
in your own `AGENTS.md`. The shared files tell agents that the project's own instructions take
|
|
34
|
+
precedence.
|
package/astro.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Astro — agent instructions
|
|
2
|
+
|
|
3
|
+
Conventions for static Astro sites written in TypeScript and styled with SCSS. Everything in
|
|
4
|
+
[`base.md`](./base.md) applies as well; read it first.
|
|
5
|
+
|
|
6
|
+
The site ships static HTML/CSS with no client-side framework. Use small inline `<script>` tags only
|
|
7
|
+
where genuinely needed (e.g. a mobile nav toggle).
|
|
8
|
+
|
|
9
|
+
## Rendering
|
|
10
|
+
|
|
11
|
+
- Keep `output: 'static'` in `astro.config.mjs`: no server rendering and no framework islands
|
|
12
|
+
(`@astrojs/react` etc.). Reach for an inline `<script>` before adding a framework.
|
|
13
|
+
|
|
14
|
+
## Styling
|
|
15
|
+
|
|
16
|
+
- Write styles in component-scoped `<style lang="scss">` blocks.
|
|
17
|
+
- Import the design token stylesheet (see `base.md`) once, in the base layout.
|
|
18
|
+
|
|
19
|
+
## Data
|
|
20
|
+
|
|
21
|
+
- Keep content data in `src/data/` as typed TypeScript modules. Each data set (features, pricing,
|
|
22
|
+
FAQ, etc.) has a single source of truth there; pages render from it instead of repeating it.
|
|
23
|
+
- Generate derived output such as `llms.txt` and JSON-LD structured data from the same data
|
|
24
|
+
modules, so they can't drift from what the pages show.
|
|
25
|
+
- Values that come from outside the site (e.g. a product version or description from another
|
|
26
|
+
`package.json`) are read once in `astro.config.mjs` and exposed through `vite.define` constants.
|
|
27
|
+
Read them in the config file, because its `import.meta.url` stays reliable while app modules get
|
|
28
|
+
bundled and relocated. Never hardcode such values elsewhere.
|
|
29
|
+
|
|
30
|
+
## Images
|
|
31
|
+
|
|
32
|
+
- Keep images in `src/assets/` and render them with Astro's `<Image>` (or `<Picture>`) component
|
|
33
|
+
from `astro:assets` so they're optimized at build time. Never reference them as raw
|
|
34
|
+
`<img src>` paths.
|
package/base.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Base — agent instructions
|
|
2
|
+
|
|
3
|
+
Conventions that apply to every project type. `react.md` and `astro.md` build on this file. Where
|
|
4
|
+
the project's own `AGENTS.md` says something different, the project wins.
|
|
5
|
+
|
|
6
|
+
Tool rules (TypeScript, Biome, Stylelint) are described in the `AGENTS.md` of the matching
|
|
7
|
+
`@mkappelhof/*` config package. Follow those as well.
|
|
8
|
+
|
|
9
|
+
## Don't assume, verify or ask
|
|
10
|
+
|
|
11
|
+
- Base every claim and every change on what you have actually read: the code, the config, the
|
|
12
|
+
installed packages' docs, or the user's instructions. Do not invent files, functions, props,
|
|
13
|
+
scripts, config options, package APIs or CLI flags.
|
|
14
|
+
- Before you use an API, component, helper or token, check that it exists and how it is used in
|
|
15
|
+
this project (search the codebase, read the type definitions or the package's docs in
|
|
16
|
+
`node_modules`). Your training data may describe a different version.
|
|
17
|
+
- When the request is ambiguous, information is missing, or several reasonable interpretations
|
|
18
|
+
lead to different results, stop and ask the user a clarifying question instead of guessing.
|
|
19
|
+
Don't ask about things you can find out yourself by reading the code.
|
|
20
|
+
- If you make an assumption anyway (e.g. for a small detail that doesn't block the work), state it
|
|
21
|
+
explicitly in your reply so the user can correct it.
|
|
22
|
+
- Say "I don't know" or "I couldn't verify this" rather than presenting a guess as fact. Report
|
|
23
|
+
results honestly: if a check fails or a step was skipped, say so.
|
|
24
|
+
- Stay within the scope of the request. Don't add features, refactors or dependencies that weren't
|
|
25
|
+
asked for; suggest them instead.
|
|
26
|
+
|
|
27
|
+
## Working on a task
|
|
28
|
+
|
|
29
|
+
- Check the project's `package.json` for the available scripts (`dev`, `build`, `test`, lint and
|
|
30
|
+
type-check scripts) instead of guessing commands.
|
|
31
|
+
- A change is done when the type check, tests and linters pass for the files you changed.
|
|
32
|
+
- Never run `git commit`, create a branch, or push, unless you are explicitly asked to. Leave
|
|
33
|
+
changes as uncommitted working-tree edits and let the user commit, branch and push themselves.
|
|
34
|
+
|
|
35
|
+
## Imports
|
|
36
|
+
|
|
37
|
+
- Use **path aliases** for cross-directory imports, never relative `../../` paths. Check
|
|
38
|
+
`compilerOptions.paths` in the project's `tsconfig.json` for the available aliases (e.g.
|
|
39
|
+
`@components/*`, `@helpers/*`, or `@/*`).
|
|
40
|
+
|
|
41
|
+
## TypeScript
|
|
42
|
+
|
|
43
|
+
- Declare all types with `type`; do not use `interface`. Export a type when it is shared.
|
|
44
|
+
- Do not use double casts (`as unknown as T`) to silence TypeScript errors; narrow values to the
|
|
45
|
+
required type instead.
|
|
46
|
+
- Constants belong in `src/constants/`, never inline in components. Define sets of options as a
|
|
47
|
+
`SCREAMING_SNAKE_CASE` object with `as const` and derive the type from it:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// src/constants/sizes.ts
|
|
51
|
+
export const SIZES = {
|
|
52
|
+
SMALL: 'small',
|
|
53
|
+
MEDIUM: 'medium',
|
|
54
|
+
LARGE: 'large',
|
|
55
|
+
} as const;
|
|
56
|
+
|
|
57
|
+
export type Size = (typeof SIZES)[keyof typeof SIZES];
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Design tokens
|
|
61
|
+
|
|
62
|
+
- Design tokens are CSS custom properties, defined once in a global stylesheet. Reference them with
|
|
63
|
+
`var()`:
|
|
64
|
+
|
|
65
|
+
```scss
|
|
66
|
+
.root {
|
|
67
|
+
padding: var(--spacing-md);
|
|
68
|
+
color: var(--color-text-primary);
|
|
69
|
+
border-radius: var(--border-radius-sm);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- Do not use Sass variables (`$color-*`) or a `@use`d tokens module for design tokens.
|
|
74
|
+
- Never hardcode colors or spacing values; always use a design token. If a token is missing, add it
|
|
75
|
+
to the token stylesheet instead of inlining a value.
|
|
76
|
+
|
|
77
|
+
## Versioning
|
|
78
|
+
|
|
79
|
+
- If the project uses [Changesets](https://github.com/changesets/changesets) (a `.changeset/`
|
|
80
|
+
folder exists), every PR must include a changeset describing the change and its semver bump.
|
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mkappelhof/agent-instructions",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared instructions for AI coding agents working on React/Next.js and Astro projects",
|
|
5
|
+
"exports": {
|
|
6
|
+
"./base.md": "./base.md",
|
|
7
|
+
"./react.md": "./react.md",
|
|
8
|
+
"./astro.md": "./astro.md",
|
|
9
|
+
"./package.json": "./package.json"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"base.md",
|
|
13
|
+
"react.md",
|
|
14
|
+
"astro.md",
|
|
15
|
+
"README.md",
|
|
16
|
+
"CHANGELOG.md"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": "git@github.com:mkappelhof/frontend-tools.git",
|
|
20
|
+
"author": "Maurice Kappelhof <maurice@mauricekappelhof.nl>",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "echo 'no test step'"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"agents",
|
|
26
|
+
"agents.md",
|
|
27
|
+
"ai",
|
|
28
|
+
"react",
|
|
29
|
+
"nextjs",
|
|
30
|
+
"astro"
|
|
31
|
+
]
|
|
6
32
|
}
|
package/react.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# React / Next.js — agent instructions
|
|
2
|
+
|
|
3
|
+
Conventions for React projects (Vite, Next.js or another bundler) written in TypeScript and styled
|
|
4
|
+
with SCSS modules. Everything in [`base.md`](./base.md) applies as well; read it first.
|
|
5
|
+
|
|
6
|
+
## Project structure
|
|
7
|
+
|
|
8
|
+
- **`src/components/`** — Feature components, each co-located with its `.module.scss`.
|
|
9
|
+
- **`src/helpers/`** — Pure utility functions. Every function lives in its own dedicated helper file.
|
|
10
|
+
- **`src/contexts/`** — React context providers (`*.context.tsx`).
|
|
11
|
+
- **`src/constants/`** — Constants and option sets.
|
|
12
|
+
- **`src/interfaces/`** — Shared TypeScript types.
|
|
13
|
+
- **`src/i18n/`** — Localization: `config.ts` initializes i18next, `locales/<locale>.json` holds
|
|
14
|
+
the nested translation keys.
|
|
15
|
+
|
|
16
|
+
In a Next.js project the routes live in `src/app/`; keep route files thin and put reusable UI in
|
|
17
|
+
`src/components/`.
|
|
18
|
+
|
|
19
|
+
## Components
|
|
20
|
+
|
|
21
|
+
- Components are named arrow-function exports typed as `FC<Props>`, never `function` declarations.
|
|
22
|
+
- **One component per file.** Subcomponents get their own file.
|
|
23
|
+
- Type DOM-wrapping components with `ComponentPropsWithoutRef<'element'>` and wrappers with
|
|
24
|
+
`PropsWithChildren<Props>`.
|
|
25
|
+
- Destructure props in the parameter list instead of using `props.x`. Use default parameter values,
|
|
26
|
+
not `defaultProps` or `propTypes`.
|
|
27
|
+
- Always render text through the project's `Text` component (e.g. `@components/text/text`); never
|
|
28
|
+
place raw strings in bare DOM elements such as `<span>` or `<p>`.
|
|
29
|
+
- **Composition over configuration**: pass content as `children` rather than through content props
|
|
30
|
+
(`label`, `icon`, `text`).
|
|
31
|
+
- **Compound components**: build multi-part components using composition, not props. Keep
|
|
32
|
+
subcomponents in an `elements/` folder and re-export them from the parent module (no
|
|
33
|
+
`elements/index.ts` barrel). The parent manages state and shares it with its subcomponents
|
|
34
|
+
through a context.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// Usage of src/components/tabs/tabs.tsx
|
|
38
|
+
<Tabs defaultValue="account">
|
|
39
|
+
<Tabs.List>
|
|
40
|
+
<Tabs.Tab value="account">{t('settings.account')}</Tabs.Tab>
|
|
41
|
+
<Tabs.Tab value="billing">{t('settings.billing')}</Tabs.Tab>
|
|
42
|
+
</Tabs.List>
|
|
43
|
+
<Tabs.Panel value="account">...</Tabs.Panel>
|
|
44
|
+
<Tabs.Panel value="billing">...</Tabs.Panel>
|
|
45
|
+
</Tabs>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Naming
|
|
49
|
+
|
|
50
|
+
- Boolean props start with `is` or `has`: `isOpen`, `hasError`.
|
|
51
|
+
- `useState` pairs are named `[value, setValue]`.
|
|
52
|
+
- Event handler props are named `onX`, and the handlers you pass are named `handleX`:
|
|
53
|
+
`onClick={handleClick}`.
|
|
54
|
+
|
|
55
|
+
### JSX
|
|
56
|
+
|
|
57
|
+
- Import `clsx` as `classnames`: `import classnames from 'clsx'`. Compose class names as
|
|
58
|
+
`classnames(css.root, className)`.
|
|
59
|
+
- No useless braces: `variant="primary"`, not `variant={'primary'}`.
|
|
60
|
+
- Self-close elements without children: `<Icon />`, `<div />`.
|
|
61
|
+
- Only use a fragment (`<>…</>`) when you need to wrap several children.
|
|
62
|
+
- Every element in a list needs a stable `key`. Do not use the array index if items can reorder.
|
|
63
|
+
- Keep JSX nesting to 4 levels or fewer. Extract a component when it gets deeper.
|
|
64
|
+
|
|
65
|
+
## Contexts
|
|
66
|
+
|
|
67
|
+
Create all contexts in `src/contexts/` named `*.context.tsx`. A context file exports the context
|
|
68
|
+
value type, the context, a dedicated provider component, and a `use*Context` consumer hook that
|
|
69
|
+
throws when used outside its provider. Always consume a context through its hook, never with
|
|
70
|
+
`useContext` directly. Memoize the value you pass to a provider with `useMemo`; never pass a new
|
|
71
|
+
object or array literal.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// src/contexts/tabs.context.tsx
|
|
75
|
+
export type TabsContextValue = {
|
|
76
|
+
activeValue: string;
|
|
77
|
+
setActiveValue: (value: string) => void;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const TabsContext = createContext<TabsContextValue | undefined>(undefined);
|
|
81
|
+
|
|
82
|
+
export const TabsProvider: FC<PropsWithChildren<{ value: TabsContextValue }>> = ({ value, children }) => (
|
|
83
|
+
<TabsContext.Provider value={value}>{children}</TabsContext.Provider>
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
export const useTabsContext = (): TabsContextValue => {
|
|
87
|
+
const context = useContext(TabsContext);
|
|
88
|
+
|
|
89
|
+
if (!context) throw new Error('useTabsContext must be used within a TabsProvider');
|
|
90
|
+
|
|
91
|
+
return context;
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Next.js
|
|
96
|
+
|
|
97
|
+
- Components in `app/` are Server Components by default. Add `'use client'` only to the components
|
|
98
|
+
that need state, effects, browser APIs or context, and keep that boundary as low in the tree as
|
|
99
|
+
possible.
|
|
100
|
+
- Context providers are client components; wrap them in a small `'use client'` providers component
|
|
101
|
+
and render it from the layout.
|
|
102
|
+
- Use `next/link` for internal navigation, not a plain `<a href="/…">`.
|
|
103
|
+
- Use `next/image` instead of `<img>`, and `next/script` instead of a raw `<script>` tag.
|
|
104
|
+
- Load fonts with `next/font`, not `<link>` tags to font CDNs.
|
|
105
|
+
- Set page metadata with the Metadata API (`export const metadata` / `generateMetadata`). Do not
|
|
106
|
+
import `next/head` or `next/document` in `app/`.
|
|
107
|
+
|
|
108
|
+
## Localization
|
|
109
|
+
|
|
110
|
+
- Never hardcode user-facing text (labels, placeholders, aria-labels, messages). Add a key to the
|
|
111
|
+
matching group in the locale file (e.g. `src/i18n/locales/en-US.json`) and render it with
|
|
112
|
+
`const { t } = useTranslation()` from `react-i18next`.
|
|
113
|
+
- Interpolate values with `t('group.key', { name })`, matching `{{name}}` in the translation. Use
|
|
114
|
+
i18next `_one` / `_other` suffixed keys with `{ count }` for plurals.
|
|
115
|
+
- Non-component code (helpers, constants) returns a `TranslationKey` instead of translated text, so
|
|
116
|
+
the component can translate it.
|
|
117
|
+
|
|
118
|
+
## Styling
|
|
119
|
+
|
|
120
|
+
- Use SCSS modules (`.module.scss`) co-located with each component.
|
|
121
|
+
- Import the design token stylesheet (see `base.md`) once at the app root, e.g. in `main.tsx` or
|
|
122
|
+
the root `layout.tsx`.
|
|
123
|
+
|
|
124
|
+
## Testing
|
|
125
|
+
|
|
126
|
+
- Use **Vitest** with the JSDOM environment for unit tests.
|
|
127
|
+
- Co-locate tests with their source as `*.spec.ts` or `*.spec.tsx`.
|
|
128
|
+
- Every helper must have a unit test. Add or update the co-located `*.spec.ts` whenever you add or
|
|
129
|
+
change one.
|
|
130
|
+
- Test pure helpers directly. Mock browser APIs and external dependencies at module boundaries with
|
|
131
|
+
Vitest mocks.
|