@opengrind/config (1.3.1)

Published 2026-08-11 13:31:12 +02:00 by forgejo

Installation

@opengrind:registry=
npm install @opengrind/config@1.3.1
"@opengrind/config": "1.3.1"

About this package

@opengrind/config

Shared ESLint, Prettier, lefthook, rustfmt and EditorConfig settings for the Open Grind repositories.

Install

Point the scope at the Forgejo registry in bunfig.toml:

[install.scopes]
"@opengrind" = { url = "https://git.opengrind.org/api/packages/open-grind/npm/" }
bun add -d @opengrind/config

Consumers declare only eslint and prettier. Every plugin is a dependency of this package and resolves from it.

Keep it in devDependencies. It is lint-time only and must never enter a bundler's import graph, or it becomes part of a reproducible build.

ESLint

SvelteKit app:

import { sveltekit } from "@opengrind/config/eslint/svelte";
import { defineConfig } from "eslint/config";

import svelteConfig from "./svelte.config.js";

export default defineConfig(
	...sveltekit({
		svelteConfig,
		tailwindEntry: "src/layout.css",
		vendoredGlob: "src/lib/components/ui/**",
		ignores: [
			"src-tauri/",
			"reverse/",
			"docs/",
			"contrib/",
			"static/",
			"scripts/",
		],
	}),
);

svelteConfig is passed in because a repo's svelte.config.js may run arbitrary code at import time, so this package cannot import it.

Browser extension:

import { webextension } from "@opengrind/config/eslint/webext";

export default webextension();

Plain TypeScript:

import { typescriptBase } from "@opengrind/config/eslint";

Prettier

// prettier.config.js
import { sveltekit } from "@opengrind/config/prettier/svelte";

export default sveltekit({ tailwindStylesheet: "./src/layout.css" });

Non-Svelte repos can use the package.json field instead:

{ "prettier": "@opengrind/config/prettier" }

Git hooks

Every repo uses lefthook, installed as a dev dependency so it bootstraps with bun install:

bun add -d lefthook
bunx lefthook install
# lefthook.yml
extends:
  - node_modules/@opengrind/config/lefthook.yml

Clippy and cargo test are not shared, because they need a manifest path that differs per repo (src-tauri/Cargo.toml in the Tauri apps, the root in the library crates), and a consumer cannot correct a shared command because the shared file wins on a name clash. Each Rust repo adds its own:

pre-commit:
  commands:
    clippy:
      glob: "*.rs"
      run: cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets

A repo can add commands and can opt out of a shared one with skip: true, but it cannot override a shared command's run.

Clippy runs without -D warnings, deny warnings in CI instead.

rustfmt and EditorConfig

rustfmt has no extends mechanism and does not read .editorconfig, so these two ship as files to copy:

cp node_modules/@opengrind/config/rustfmt.toml rustfmt.toml
cp node_modules/@opengrind/config/editorconfig .editorconfig

Guard against drift in CI:

diff -q rustfmt.toml node_modules/@opengrind/config/rustfmt.toml
diff -q .editorconfig node_modules/@opengrind/config/editorconfig

The comparison is against the pinned package, so it needs no network and fails only after you bump the version.

max_line_length = 80 matches Prettier's default printWidth and rustfmt's max_width. Prettier reads .editorconfig, so changing it reformats the tree.

Releasing

OG_REGISTRY_TOKEN=<forgejo-token> bun publish

Bump version first. The registry rejects a re-publish of an existing name and version.

Dependencies

Dependencies

ID Version
@eslint/js 10.0.1
eslint-config-prettier 10.1.8
eslint-plugin-better-tailwindcss 4.6.0
eslint-plugin-perfectionist 5.9.0
eslint-plugin-svelte 3.17.1
globals 17.6.0
prettier-plugin-svelte 3.5.1
prettier-plugin-tailwindcss 0.8.0
typescript-eslint 8.59.2

Peer dependencies

ID Version
eslint >=9
prettier >=3.5
Details
npm
2026-08-11 13:31:12 +02:00
427
Open Grind Governance (https://opengrind.org/governance)
MIT
latest
6 KiB
Assets (1)
Versions (5) View all
1.3.1 2026-08-11
1.3.0 2026-08-06
1.2.0 2026-08-06
1.1.0 2026-08-06
1.0.0 2026-08-06