# AI-Agent Prompt — Configure Linters for FastAPI (Python) + Next.js (TypeScript)
## Non-negotiables
- Only add **tooling** (linters/formatters/type checks). Do **not** change runtime behavior unless a linter autofix requires a safe mechanical edit.
- Changes must be **reproducible** via pinned versions and committed config files.
- After implementation, run the verification commands in the “Verification” section and ensure they pass.
## Why we’re doing this (brutal truth)
Linters/formatters catch a lot of AI-generated garbage (syntax mistakes, unused imports, unsafe patterns, inconsistent style). They **will not** catch most business-logic bugs. They reduce noise and prevent obvious failures from shipping — that’s it.
---
## Pin the “latest known” tool versions (as of 2025-12-18)
### Frontend (Node)
- Next.js: **16.0.10** :contentReference[oaicite:0]{index=0}
- ESLint: **9.39.2** :contentReference[oaicite:1]{index=1}
- Prettier: **3.7.4** :contentReference[oaicite:2]{index=2}
- eslint-config-next: **16.0.10** :contentReference[oaicite:3]{index=3}
- lint-staged (optional): **16.2.7** :contentReference[oaicite:4]{index=4}
### Backend (Python)
- Ruff: **0.14.9** :contentReference[oaicite:5]{index=5}
- pre-commit: **4.5.1** (optional, but recommended) :contentReference[oaicite:6]{index=6}
- Pyright: **1.1.407** (optional, but recommended) :contentReference[oaicite:7]{index=7}
---
## Step 0 — Detect project roots (zero guessing)
1. Locate the **Python backend root** = the directory that contains `pyproject.toml` (or the backend’s `pyproject.toml`).
2. Locate the **Next.js frontend root** = the directory that contains `package.json` + `next.config.*` (or `app/` / `pages/`).
Do all edits in the correct root(s).
---
# A) Python (FastAPI backend) — Ruff (+ optional pre-commit, optional Pyright)
## A1) Install Ruff (pinned)
In the backend root, add Ruff **0.14.9** to your dev dependencies using whichever dependency manager is already in the repo.
- Ruff is distributed on PyPI and installed via pip tooling. :contentReference[oaicite:8]{index=8}
**If the repo uses requirements files**, add:
- `requirements-dev.txt` (or equivalent):
- `ruff==0.14.9` :contentReference[oaicite:9]{index=9}
## A2) Configure Ruff in `pyproject.toml`
Ruff supports configuration in `pyproject.toml`. :contentReference[oaicite:10]{index=10}
Add (or merge) this in the backend `pyproject.toml`:
```toml
[tool.ruff]
line-length = 88
extend-exclude = [".venv", "venv", "dist", "build", ".mypy_cache", ".pytest_cache"]
[tool.ruff.lint]
# Start simple: keep Ruff defaults, only make it enforce import sorting.
# (Ruff can act as linter/formatter; keep config minimal to avoid breaking existing code.) :contentReference[oaicite:11]{index=11}
select = ["I"]
Then run:
Ruff’s PyPI docs show ruff check and ruff format usage patterns. (PyPI)
A3) OPTIONAL but recommended: pre-commit for Python¶
Install pre-commit (4.5.1). (PyPI)
Create .pre-commit-config.yaml in the backend root (or repo root if you run hooks repo-wide):
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.9
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
This exact Ruff pre-commit configuration format is documented on Ruff’s PyPI page. (PyPI)
Then run:
pre-commit autoupdate is the documented way to update hooks later. (Pre-Commit)
A4) OPTIONAL but recommended: Pyright type checking (Python)¶
Pyright supports config via pyrightconfig.json or [tool.pyright] in pyproject.toml, and pyrightconfig.json takes precedence if both exist. (GitHub)
To keep everything in one file, add to backend pyproject.toml:
[tool.pyright]
include = ["src"]
exclude = ["**/__pycache__", ".venv", "venv", "dist", "build"]
strict = ["src"]
Pyright’s official config docs describe include, exclude, and strict (strict enables most type-checking rules for those paths). (GitHub)
Run:
B) Next.js frontend — ESLint (Next.js 16) + Prettier (+ optional lint-staged)¶
B1) IMPORTANT: Next.js 16 removed next lint¶
Starting with Next.js 16, next lint is removed, and the eslint option in next.config.* is no longer needed and can be removed. (Next.js)
So: do not add next lint scripts. Use ESLint CLI.
B2) Install frontend dev dependencies (pinned)¶
In the frontend root:
eslint@9.39.2(npm)eslint-config-next@16.0.10(npm)prettier@3.7.4(npm)eslint-config-prettier@10.1.8(npm)
Next.js recommends eslint-config-prettier in flat config to avoid ESLint formatting conflicts with Prettier. (Next.js)
Security note (don’t ignore): multiple compromised versions of eslint-config-prettier have been reported (incl. 10.1.6 and 10.1.7). Pin to a safe version (current latest: 10.1.8). (npm)
B3) Create eslint.config.mjs (Next.js 16 flat config)¶
Create (or replace) eslint.config.mjs in the frontend root:
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
import prettier from "eslint-config-prettier/flat";
export default defineConfig([
...nextVitals,
...nextTs,
prettier,
// Override default ignores of eslint-config-next:
globalIgnores([
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
This structure (core-web-vitals, typescript config, prettier flat config, and globalIgnores list) is shown in the official Next.js ESLint configuration docs. (Next.js)
B4) Add scripts to package.json¶
In frontend package.json, add/ensure:
{
"scripts": {
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix",
"format": "prettier . --write",
"format:check": "prettier . --check"
}
}
ESLint CLI setup is documented by ESLint. (ESLint)
B5) OPTIONAL but recommended: enable TypeScript strict mode¶
In tsconfig.json (frontend root), set:
The TypeScript docs state that strict enables a wide range of strict type-checking behavior for stronger correctness guarantees. (typescriptlang.org)
B6) OPTIONAL but recommended: run lint only on staged files (lint-staged)¶
Install lint-staged@16.2.7. (npm)
Create .lintstagedrc.js in the frontend root (start from Next.js docs example; extend it if needed):
const path = require("path");
const buildEslintCommand = (filenames) =>
`eslint --fix ${filenames
.map((f) => `"${path.relative(process.cwd(), f)}"`)
.join(" ")}`;
module.exports = {
"*.{js,jsx,ts,tsx}": [buildEslintCommand],
};
This exact pattern is provided in the Next.js ESLint docs under “Running lint on staged files”. (Next.js)
Verification (must pass before you stop)¶
Backend (run in backend root)¶
Ruff supports check and format as shown in its docs. (PyPI)
If you enabled Pyright:
Pyright configuration and usage are documented. (GitHub)
Frontend (run in frontend root)¶
If you enabled TypeScript strict checks, also run your usual typecheck script (or add one).
Deliverables you must commit¶
Backend:
pyproject.tomlupdates (Ruff, optional Pyright config)- (optional)
.pre-commit-config.yaml
Frontend:
eslint.config.mjs(Next.js 16 flat config) (Next.js)package.jsonscript updates- (optional)
.lintstagedrc.js(Next.js) tsconfig.jsonstrict=true (optional) (typescriptlang.org)