@lupinum/website-config
Website config
Shared Vite+ and template ESLint configuration for Lupinum Nuxt websites.
Why use Website config?
One place for the lint and format settings of every Lupinum Nuxt website. Sites import two functions instead of copying config files, and Renovate rolls out every change as a normal dependency update.
Oxlint and oxfmt (through Vite+) check script code and format everything. ESLint checks only Vue <template> blocks, because oxlint cannot read them yet. The rules come from the Lupinum website handbook (standard F-07).
Requirements
- Node.js 22.14 or later, Node.js 24, or Node.js 26.
Installation
pnpm add -D @lupinum/website-config vite-plus eslint
The package brings the ESLint plugins (eslint-plugin-vue, eslint-plugin-vuejs-accessibility, typescript-eslint, @shadcn/lint) at versions tested together. Do not add them to the site yourself.
Vite+: format, lint, test
// vite.config.ts
import { defineConfig } from 'vite-plus'
import { lupinumVite } from '@lupinum/website-config'
export default defineConfig(lupinumVite())
This sets up:
- oxfmt for code, Vue files and CSS, with Tailwind class sorting.
content/**is never formatted, because oxfmt would rewrite MDC components. - oxlint for script code with the
vue,import,typescript,unicornandoxcplugins: correctness as errors, suspicious code as warnings, and type-aware rules in.tsfiles. Type errors are left tonuxt typecheck, because oxlint's type checker cannot resolve.vueimports. - Vitest for
app/**/*.test.tsandserver/**/*.test.ts.
All options are optional:
| Option | Default | Use |
|---|---|---|
stylesheet |
app/assets/css/main.css |
The Tailwind v4 entry file used to sort classes |
ignore |
[] |
Extra paths the formatter and linter skip |
rules |
{} |
Oxlint rules to add or change, merged over the defaults |
testInclude |
see above | Test file patterns |
ESLint: Vue templates only
ESLint checks Vue rules (:key in v-for, v-if with v-for, v-html), accessibility (alt, labels, keyboard handlers) and the shadcn design-system rules (no raw colors, arbitrary values, unknown classes, inline styles or restyled components).
// eslint.config.js
import { lupinumTemplateLint } from '@lupinum/website-config/eslint'
export default lupinumTemplateLint()
Run it on templates only: eslint --max-warnings=0 "app/**/*.vue".
| Option | Default | Use |
|---|---|---|
shadcn |
'error' |
Severity of the design-system rules. An existing site starts with 'warn' and tightens later. |
ignores |
[] |
Extra paths ESLint skips |
Flat-config objects after the options are appended and win over the defaults:
export default lupinumTemplateLint({}, { files: ['app/components/legacy/**'], rules: { 'shadcn/no-arbitrary-values': 'off' } })
Scripts
{
"lint:vue": "eslint --max-warnings=0 \"app/**/*.vue\"",
"typecheck": "nuxt typecheck",
"verify": "vp check && vp run lint:vue && vp run typecheck && vp test run --passWithNoTests && vp run generate"
}
Start Nuxt with vp run dev, never vp dev: the built-in command starts plain Vite. Nuxt prints NUXT_B5004 about vite.config.ts at startup. That is expected: Vite+ needs the file and Nuxt does not read it.
Contributing
Read CONTRIBUTING.md. Run pnpm verify before you open a pull request.
Support and security
Ask questions in the Lupinum OSS Discord. Report vulnerabilities privately as described in SECURITY.md.
License
MIT © Lupinum OG.
Related Packages
Shared lint, format, typecheck defaults, and vitest factory for Omniswift Vue/Nu...
ESLint plugin with rules that help validate proper imports.
This ESLint plugin enforces adding `.value` when accessing reactive values in th...
Shared ESLint flat configs (base, vue, astro, node, opt-in tailwind) + oxlint sk...
Version History
| Version | Released | License |
|---|---|---|
| 0.2.0 | MIT | |
| 0.1.0 | MIT |