Shared configs
Besides templates, the package ships three extendable configs — TypeScript, Oxlint, and Oxfmt — so every Fusion Stack project type-checks, lints, and formats the same way. Extend them from the package and override locally only where a project genuinely differs.
All three assume the package is installed (see Setup), plus the tools themselves:
bun add -D oxlint oxfmt @typescript/native-previewTypeScript
tsconfig.json can extend npm packages natively. The base enables strict (plus
noUncheckedIndexedAccess and friends), bundler-style module resolution, and the latest
lib/target — everything except runtime-specific settings, which stay per-project:
{
"extends": "@tikab-interactive/fusion-config/tsconfig.json",
"compilerOptions": {
"types": ["bun"] // runtime types are deliberately not in the base
},
"include": ["src"]
}Anything you set in local compilerOptions wins over the base.
Oxlint
The base is aggressive on purpose: correctness and suspicious report as errors, perf and
pedantic as warnings, with the typescript, unicorn, oxc, react, jsx-a11y, import,
and promise plugins active. Tests, e2e, scripts, and stories (**/*.test.*, **/*.spec.*,
**/e2e/**, **/scripts/**, **/*.stories.*) are exempt from size rules and
no-await-in-loop, and .tsx files get relaxed size limits since JSX composition inflates
line counts. A few rules are pre-tuned — for example eqeqeq is an error, except x == null,
which deliberately covers both null and undefined.
Create an oxlint.config.ts (requires a Node runtime ≥ 22.18; a directory can have either
this or .oxlintrc.json, not both):
import config from "@tikab-interactive/fusion-config/oxlint";
import { defineConfig } from "oxlint";
export default defineConfig({
extends: [config],
// ignorePatterns does NOT inherit through `extends` (root-config-only,
// like ESLint) — it must live here, in the project's own config.
ignorePatterns: ["**/node_modules"],
});Project-specific tuning goes next to extends and wins over the base. Keep a short comment on
why each deviation exists:
export default defineConfig({
extends: [config],
ignorePatterns: ["**/node_modules"],
rules: {
// Drizzle's relational-query callbacks shadow the imported
// `eq`/`and` operators by design.
"no-shadow": "off",
},
});Prefer JSON? extends in .oxlintrc.json only accepts relative paths (package imports are not
supported in the JSON format), but a path into node_modules works:
{
"extends": ["./node_modules/@tikab-interactive/fusion-config/configs/oxlint.json"],
"ignorePatterns": ["**/node_modules"]
}Oxfmt
Oxfmt has no extends mechanism yet
(oxc#16394), so the shared config is
imported and re-exported instead — spread it and put overrides after:
import config from "@tikab-interactive/fusion-config/oxfmt";
export default {
...config,
// project-specific overrides go here
};The base formats with tabs, with one carve-out: package.json stays 2-space-indented so
the formatter never fights bun add, which rewrites the file that way.
Scripts
Wire everything up once (tsgo is the native TypeScript preview — substitute tsc if the
project uses stock TypeScript):
{
"scripts": {
"typecheck": "tsgo --noEmit",
"lint": "oxlint",
"fmt": "oxfmt",
"fmt:check": "oxfmt --check"
}
}