ESLint v9 & Stylistic Padding Enforcement
This repository strictly rejects default Prettier formatting in favor of highly customized structural spacing rules powered by ESLint v9 Flat Config and the @stylistic/eslint-plugin.
When to Use
- Generating new code and needing to understand the spacing format.
- Troubleshooting linting errors related to empty lines.
- Adding a new package to the monorepo and setting up its formatting rules.
- Whenever an AI agent or developer tries to install or format code with Prettier.
⚠️ Gotchas & Critical Rules
- NEVER use Prettier: Prettier forcibly collapses multiple empty lines into a maximum of 1 empty line. This violates our strict project requirement of 3 blank lines after imports and 2 blank lines between blocks.
- ESLint Handles Everything: We rely entirely on
eslintwith the--fixflag to resolve spacing. - AI Formatting Requirements: All code generated by AI agents must natively respect these custom line spacings. Do not rely on ESLint to fix generated code if you can write it correctly in the first place.
Core Setup: @stylistic/padding-line-between-statements
The spacing enforcement relies on this specific configuration inside packages/config-eslint:
"@stylistic/padding-line-between-statements": [
"error",
// Always 3 lines after imports
{ blankLine: "always", prev: "import", next: "*" },
{ blankLine: "always", prev: "import", next: "*" },
{ blankLine: "always", prev: "import", next: "*" },
// Always 2 lines before logical blocks (functions, types, classes)
{ blankLine: "always", prev: "*", next: "function" },
{ blankLine: "always", prev: "*", next: "function" },
{ blankLine: "always", prev: "*", next: "type" },
{ blankLine: "always", prev: "*", next: "type" },
{ blankLine: "always", prev: "*", next: "interface" },
{ blankLine: "always", prev: "*", next: "interface" },
]
Note: In ESLint, repeating the blankLine: "always" target multiple times tells the linter to expect multiple consecutive lines. We complement this with "@stylistic/no-multiple-empty-lines": ["error", { "max": 4 }] to avoid conflicting limits.
Bootstrap Formatting Script
Because ESLint's --fix isn't always perfect at inserting missing multi-line padding across dense legacy codebases, we have a Node script that structurally injects the gaps using Regex before linting.
# Run the rough structural insertion
node .agents/skills/custom-formatting/scripts/force-spacing.mjs ./apps/web-app/src/components
# Polish and finish with exact ESLint AST resolution
pnpm turbo run lint -- --fix
AI Native Code Generation
When producing code snippets or updating existing code in your context window, insert literal newline characters (\n\n\n) correctly! E.g.
import React from 'react';
import { Button } from '@ivannikov-pro/ui';
export function MyComponent() {
return <Button />;
}
export type MyComponentProps = {
active: boolean;
};
Markdown Table Formatting
While the primary focus of this skill is TS/JS spacing, the same philosophy of human-readable formatting applies to all markdown files in the repo.
Aligned Tables
Tables in .md files (skills, workflows, docs, playbooks) must have padded, aligned columns. The separator row (---) must span the widest content in each column.
<!-- ❌ Wrong — compressed, hard to scan in raw markdown -->
| Tool | Purpose |
| ------------- | ------------------- |
| **pnpm** | Package manager |
| **Turborepo** | Build orchestration |
<!-- ✅ Correct — aligned, easy to read -->
| Tool | Purpose |
| ------------- | ------------------- |
| **pnpm** | Package manager |
| **Turborepo** | Build orchestration |
Mermaid Diagram Labels
Never use \n or <br/> for multi-line labels in Mermaid graph nodes — they render inconsistently or literally. Use short node labels and add a legend table below the diagram.
Verification & Automation
Unlike TS/JS formatting (which ESLint enforces automatically), markdown table alignment is enforced via a custom script. When creating or editing .md files, or if you spot compressed tables (|---|), you can run the following script to automatically pad and align them:
# Format tables in a specific file or directory
node .agents/skills/custom-formatting/scripts/format-tables.mjs ./docs/ARCHITECTURE.md
To quickly find compressed tables in the repo:
grep -rn '|---|' .agents/ docs/ packages/ --include="*.md"