---
id: "development-basis"
title: "Development basis"
description: "The shared lint, TypeScript and format configuration and the development standards. How they fit together, how a repository adopts them, and how it receives updates."
url: "/development-basis"
locale: "en"
revision: "75901eb684d84ef0"
---

# Development basis

The packages are one part of what Foundation hands over. The other is the **development basis**:
the configuration and the written standards that make code in different repositories look, check
and read the same. It has four parts:

| Part | What it is | In your repository | How it arrives |
| --- | --- | --- | --- |
| [eslint-config](/packages/eslint-config) | a package: the shared ESLint presets | `packages/eslint-config` | [managed source transfer](/receiving-packages) |
| [typescript-config](/packages/typescript-config) | a package: the shared TypeScript presets | `packages/typescript-config` | an unchanged copy of the folder |
| Prettier configuration | one file, `prettier.config.mjs`; not a package | `prettier.config.mjs` at the root | an unchanged copy of the file |
| Development standards | a folder of written standards and the way of working; not a package | `docs/standards/` | an unchanged copy of the folder |

Foundation maintains all four. Each has one source: the standards are their own text, the
configuration is its own files. This page explains how they work together; it does not restate
the standards.

## How they fit together

| Concern | Decided by | Checked by | A run fails when |
| --- | --- | --- | --- |
| formatting | `prettier.config.mjs` | `prettier --check` | any file deviates |
| lint rules | the presets of `eslint-config` | `eslint . --max-warnings 100` | there are more warnings than the threshold |
| types | the presets of `typescript-config` | `tsc --noEmit` | there is a single type error |
| everything else | the standards in `docs/standards/` | review, or a check of your own | your repository decides |

The three tools do not overlap: the lint presets switch every formatting rule off, so Prettier
alone decides whitespace, quotes and import order, and the lint rules run without type
information, so `tsc` alone decides about types.

The standards say which of their rules a tool enforces and which are a matter of review. The
overview is `CONFIG_STANDARDS.md`, section 5, in your copy of `docs/standards/`. A green tool run
proves only what that tool checks.

A check runs only where a command calls it. Without CI or a finishing command, the person who does
the work runs `format:check`, lint and the type-check.

## A new repository

1. **Workspace.** A pnpm workspace with `packages/*`, Node.js 26, and byte-exact checkouts:
   `packages/** -text` in `.gitattributes`.
2. **Standards.** Copy the folder `docs/standards/` from Foundation as a whole, unchanged, to the
   same path. Its `README.md` is the entry point. Your own rules go in your own documents (below).
3. **Prettier.** Copy `prettier.config.mjs` unchanged to your root. Install `prettier` and the three
   plugins the file names (`@ianvs/prettier-plugin-sort-imports`, `prettier-plugin-pkg`,
   `prettier-plugin-tailwindcss`) as root devDependencies, in the versions of Foundation's root
   `package.json`. Add the scripts:

   ```json
   {
     "scripts": {
       "format": "prettier --write \"**/*.{ts,tsx,md,json,js,mjs,css}\"",
       "format:check": "prettier --check \"**/*.{ts,tsx,md,json,js,mjs,css}\""
     }
   }
   ```

   Write your own `.prettierignore`. It excludes the bytes your repository does not format itself,
   at least:

   ```text
   .rps/
   tools/rps/
   packages/eslint-config/
   packages/typescript-config/
   prettier.config.mjs
   pnpm-lock.yaml
   ```

   plus every other managed package and your build output.
4. **Lint.** Receive `eslint-config`: [Getting started](/packages/eslint-config/getting-started).
5. **Types.** Copy `typescript-config`:
   [Getting started](/packages/typescript-config/getting-started).
6. **Your own documents.** A `README.md`, an `AGENTS.md` with your commands and limits, and
   `docs/DECISIONS.md` for your decisions, including every deviation from the basis.
7. **Record where it came from** (next section).

Then run `format:check`, lint and the type-check once, and read their counts.

## Record where it came from

For the parts that arrive as a copy there is no provenance file. Record them yourself, outside
`docs/standards/`, for example in your `docs/INDEX.md`:

```markdown
## Development basis

| Part                           | Source     | State or version | Taken over on |
| ------------------------------ | ---------- | ---------------- | ------------- |
| `docs/standards/`              | Foundation | <state>          | <date>        |
| `prettier.config.mjs`          | Foundation | <state>; plugins | <date>        |
| `@workspace/typescript-config` | Foundation | <version>        | <date>        |

Local additions: <documents, or "none">.
Deliberate deviations: <decisions, or "none">.
```

`eslint-config` is not in this table: its origin is in `.rps/provenance.json`, written by the
applier.

## An existing repository

- **Own configuration or standards.** Replace them part by part by the shared ones. Keep what is
  really your own as a local addition (below), and record each deliberate deviation as a decision.
- **An older copy of a part.** Replace it as a whole, never file by file, and compare with the
  source: `diff -rq` for a folder, `cmp` for `prettier.config.mjs`.
- **An unmanaged `packages/eslint-config`.** The applier will not write over it; see
  [Replacing your own copy](/packages/eslint-config/getting-started#replacing-your-own-copy).
- **Managed packages from another source.** Your repository has one provenance record from one
  source, so it cannot take `eslint-config` from Foundation separately. Ask the maintainer how your
  whole set moves.

Afterwards run every check. New findings from the shared configuration are work of your
repository; they are not solved by relaxing a rule or raising a threshold.

## Where local additions belong

| What | Where |
| --- | --- |
| lint ignores and stricter or tool rules | your `eslint.config.mjs`, after the preset ([Local additions](/packages/eslint-config/local-additions)) |
| files, paths, output, type packages | your `tsconfig.json` ([Extending](/packages/typescript-config/extending)) |
| files Prettier leaves alone | your `.prettierignore` |
| commands, limits, the state of your project | your `AGENTS.md` |
| a deviation from the basis | a decision in your `docs/DECISIONS.md` |
| rules that only your repository follows | a document of your own outside `docs/standards/`, which names the rule it adds to or deviates from, and why |

Never edit a copied part. A changed file in `docs/standards/`, in `prettier.config.mjs` or in a
configuration package is a defect, not a local variant.

## Where changes are made

Every change to the basis is made in Foundation: a rule, a plugin version, a compiler option, a
standard. A configuration package records it in its changelog. A rule that strengthens, relaxes or
removes a standard gets a decision there. If your repository finds a change that would serve every
repository, propose it to the maintainer of Foundation instead of keeping it locally.

## Receiving updates

You decide when you update. Each part is updated along the route it arrived by, and always as a
whole:

| Part | How to update | Check afterwards |
| --- | --- | --- |
| `eslint-config` | a bundle of your whole managed set ([Updating](/receiving-packages#updating)) | `verify-install`, then lint |
| `typescript-config` | replace the folder | `diff -rq` against the source, then the type-check |
| Prettier | replace the file, and the plugin versions with it | `cmp` against the source, `pnpm install`, `format:check` |
| standards | replace the folder | `diff -rq` against the source; read the changed rules |

Then update your record of where the copies came from. Read the changelog of a configuration
package before you update; the standards carry their state at the top of their `README.md`.

## Current state

The configuration routes above were tested in a new, temporary repository outside the source
repositories. Taking over the standards folder has been described and not yet carried out by
another repository.
