@krizaka/config
Le kit qualité de chaque dépôt TypeScript : configs ESLint, preset dependency-cruiser, bases tsconfig, Prettier et le cliquet de dette.
Installer
npm install @krizaka/configAussi publié en sous-chemins : @krizaka/config/eslint, @krizaka/config/eslint/next, @krizaka/config/eslint/krizaka-ui, @krizaka/config/eslint/no-locale-ternary, @krizaka/config/eslint/stack, @krizaka/config/eslint/ui-warnings, @krizaka/config/eslint/env-names, @krizaka/config/eslint/plugin, @krizaka/config/dependency-cruiser, @krizaka/config/covered-domains, @krizaka/config/covered-domains.json, @krizaka/config/known-violations, @krizaka/config/patterns, @krizaka/config/ratchet, @krizaka/config/prettier, @krizaka/config/tsconfig/base.json, @krizaka/config/tsconfig/react-library.json, @krizaka/config/tsconfig/next.json, @krizaka/config/tsconfig/react-native.json, @krizaka/config/editorconfig.
Le README ci-dessous est celui du paquet sur npm, en anglais.
The shared configuration of every Krizaka JavaScript repository. ESLint flat configs (base, Next.js, the four UI
rules, the three stack rules, no locale ternary), the dependency-cruiser boundary, tsconfig bases, Prettier,
EditorConfig — and krizaka-ratchet, the counter that keeps the UI and stack debts from coming back.
Adopt it in three lines
npm install -D @krizaka/config eslint typescript # + eslint-config-next for a Next.js app, prettier if you format// eslint.config.mjs — a Next.js app (a library: `krizakaBase` from "@krizaka/config/eslint")
import { krizakaNext } from "@krizaka/config/eslint/next";
import { krizakaUi } from "@krizaka/config/eslint/krizaka-ui";
import { noLocaleTernary } from "@krizaka/config/eslint/no-locale-ternary";
import { krizakaStack } from "@krizaka/config/eslint/stack";
export default [...krizakaNext, ...krizakaUi(), ...krizakaStack(), ...noLocaleTernary()];// .dependency-cruiser.cjs — « Krizaka first », cycles, unresolvable imports, dev dependencies, plus the app's own rules
module.exports = { extends: "@krizaka/config/dependency-cruiser", forbidden: [] };// tsconfig.json — base · react-library · next · react-native
{ "extends": "@krizaka/config/tsconfig/next.json", "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] }Prettier: export { default } from "@krizaka/config/prettier"; in prettier.config.js (120 columns, double quotes,
trailing commas). EditorConfig: cp node_modules/@krizaka/config/.editorconfig ..
eslint ^9 and typescript ^5 are peer dependencies; eslint-config-next (Next.js apps) and prettier are optional
peers. The plugins (typescript-eslint, eslint-plugin-react-hooks, eslint-plugin-simple-import-sort) come with
the package.
What is inside
| Export | What it gives |
|---|---|
@krizaka/config/eslint | krizakaBase: @eslint/js + typescript-eslint recommended, React hooks, import ordering (a warning, autofixable), ignores of generated output, _-prefixed unused arguments allowed. |
@krizaka/config/eslint/next | krizakaNext: eslint-config-next (core web vitals + TypeScript, which already carry typescript-eslint, React hooks and import) + the same basics. |
@krizaka/config/eslint/krizaka-ui | krizakaUi(options?): the four UI rules below. Also krizakaUiRules and krizakaUiRestrictedSyntax(options?). |
@krizaka/config/eslint/no-locale-ternary | noLocaleTernary(options?): krizaka/no-locale-ternary — no locale === "fr" ? … : … outside routing code. |
@krizaka/config/eslint/ui-warnings | krizakaUiWarnings(options?): the same two debts as named plugin rules, as warnings — krizaka/no-light-variant (no light:: tokens do the theming) and krizaka/no-raw-palette (no bg-zinc-900, text-violet-400: a role; allow families). krizaka-ratchet counts them (light, palette), so a product adopts them now and brings the counts to 0. |
@krizaka/config/eslint/stack | krizakaStack(options?): the three stack rules below (warnings). Also STACK_RULES. |
@krizaka/config/eslint/plugin | krizakaPlugin: the krizaka plugin carrying every rule, for a hand-written config. |
@krizaka/config/dependency-cruiser | The shared dependency-cruiser config, generated from the covered-domains map: one krizaka-first-<domain> rule per domain (dates, i18n, query, icons, ui), no-circular, not-to-unresolvable, not-to-dev-dep. .withOptions({ exemptFrom }) for a monorepo whose own packages are the facades. |
@krizaka/config/covered-domains · /covered-domains.json | The covered-domains map (one data file) and its helpers: the message, the patterns, the Markdown table of « Use Krizaka first ». |
krizaka-known-violations (bin) · @krizaka/config/known-violations | The known violations of dependency-cruiser, which only shrink, see below. |
@krizaka/config/tsconfig/*.json | base (strict, ES2022, bundler resolution), react-library (+ DOM, react-jsx), next (+ the Next plugin, noEmit, incremental), react-native (jsx: react-native, customConditions; with Expo: "extends": ["expo/tsconfig.base", "@krizaka/config/tsconfig/react-native.json"]). |
@krizaka/config/prettier · .editorconfig | The formatting. |
krizaka-ratchet (bin) | The debt counter, see below. |
The four UI rules
On every string literal inside a className (in cn(…), a ternary…), with no plugin — no-restricted-syntax
selectors:
- No raw palette colour —
bg-zinc-900,text-violet-400/80: use a role of@krizaka/tailwind(bg-surface-1,text-fg-secondary,border-border-default,text-accent,text-danger). - No
light:— a theme is a set of tokens; a dark island takes.theme-darkon its ancestor. - No arbitrary
[var(--…)]utility — the variable has a utility in@krizaka/tailwind. - No template literal in
className—cn(…)merges the classes and lets the override win.
krizakaUi({
allow: ["emerald"], // palette families tolerated for documented, isolated cases
files: ["**/*.{jsx,tsx}"], // default
ignores: ["app/og/**"], // e.g. generated OG images
severity: "error", // "warn" while the ratchet brings the debt down
});Flat config replaces a rule's options instead of concatenating them: a repository that already sets
no-restricted-syntax merges both lists with krizakaUiRestrictedSyntax(). no-locale-ternary is a plugin rule for
that reason — it composes with anything.
The stack rules
From ADR-001 — the TanStack engines run headless, behind
@krizaka/* facades; a product never imports them. Warnings: krizaka-ratchet counts the same patterns, so an app
adopts them before it is clean and brings each count to 0 by the end of its adoption.
krizaka/no-fetch-in-client-effect— afetch/krizakaFetchinside auseEffect(oruseLayoutEffect) of a"use client"file: render the first screen in a Server Component, read the rest with@krizaka/query.krizaka/no-local-table-or-form— a<table>, or a<form>of more than one field (native fields and the field primitives of@krizaka/ui; a hidden or submit<input>is not a field): useDataTableandcreateKrizakaForm. A search box or a one-field newsletter stays a plain form.
krizakaStack({
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"], // default
ignores: ["packages/**"], // e.g. the facades of a monorepo
severity: "warn", // default; "error" once the app's counts are at 0
maxFormFields: 1, // default
});« Krizaka first » — the refused imports (dependency-cruiser)
Part of the stack ADR and of krizaka-ui#609, in one tool: dependency-cruiser carries every refused import (an import
is an edge: it catches re-exports and dynamic imports, and the same file holds the layers); ESLint keeps the framework
rules above. The ESLint rule krizaka/no-direct-tanstack-import is retired: @tanstack/* is krizaka-first-query.
The covered-domains map is covered-domains.json, the single source. Each domain names its Krizaka home and what is
refused in an app; the preset generates krizaka-first-<domain> from it, and the page « Use Krizaka first » of
ui.krizaka.com is laid out from it (coveredDomainsMarkdown()).
| Domain | Krizaka home | Refused in an app | Rule |
|---|---|---|---|
| Dates, times, local days | @krizaka/intl (formatting, localDay), @krizaka/time (arithmetic; a facade created on the first real need, krizaka-ts#76) | date-fns*, @date-fns/*, dayjs, luxon, moment, moment-timezone | krizaka-first-dates |
| Words, languages | @krizaka/i18n | i18next*, react-i18next, next-intl, next-i18next, react-intl, @formatjs/*, @lingui/*, i18n-js, typesafe-i18n | krizaka-first-i18n |
| Data fetching, cache, tables, forms, virtual lists | @krizaka/query, @krizaka/ui, @krizaka/pacer | @tanstack/* | krizaka-first-query |
| Icons | @krizaka/icons | lucide-react, react-icons, @heroicons/* | krizaka-first-icons |
| Interface primitives | @krizaka/ui | @radix-ui/*, radix-ui | krizaka-first-ui |
An entry is a package (dayjs, and its subpaths), a prefix (date-fns*) or a scope (@tanstack/*). It matches the
resolved file and the module as written when it cannot be resolved (a package the app does not declare), never a local
folder of the same name. A Krizaka package is exempt: it is the facade. In an app that is the packages in
node_modules; in a monorepo that holds its own Krizaka packages, say where they live:
// .dependency-cruiser.cjs of a monorepo (krizaka-ui, krizaka-ts)
module.exports = require("@krizaka/config/dependency-cruiser").withOptions({ exemptFrom: ["(^|/)packages/"] });Every message names the home and ends « Missing function? add it to the package first. » — a missing function is added
to the Krizaka package, never worked around with the library. Run it with depcruise --output-type err-long <folders>
to read the message (err prints the rule name only). Beside the domains, the preset owes every repository
no-circular, not-to-unresolvable (declare the dependency, or fix the path; set options.tsConfig for path aliases)
and not-to-dev-dep (tests, stories, scripts and tool configs may import devDependencies). Run depcruise from the
workspace that owns the package.json.
Known violations (they only shrink)
An app that adopts the rules late records what it already breaks, and the debt only goes down:
krizaka-known-violations init src app # once, in the adoption pull request: writes .dependency-cruiser-known-violations.json
depcruise src app --config .dependency-cruiser.cjs --ignore-known .dependency-cruiser-known-violations.json # lint: new violations fail
krizaka-known-violations check src app # lint: also fails on a recorded violation that is fixed ("lock the gain")
krizaka-known-violations update src app # removes the fixed ones; NEVER adds one, and fails while a new one existsThe file is the format of depcruise-baseline, so --ignore-known reads it. init refuses to overwrite it; there is
no command that records a new violation. It replaces the directTanstackImport counter of krizaka-ratchet, which
stays only for repositories that have not moved yet.
noLocaleTernary({ files, routing }): routing lists the files allowed to compare locales (default: proxy.ts,
middleware.ts, i18n.ts, seo.ts, app/[locale]/layout.tsx, I18nProvider.tsx).
Environment variable names (krizaka/env-name)
Environment variables are named by bounded context (krizaka/.github#46): <CONTEXT>_<THING> with CONTEXT one of
APP_ DATABASE_ AUTH_ MEDIA_ MAIL_ PUSH_ PAYMENTS_ REALTIME_ ABUSE_ OBSERVABILITY_ AI_ OPERATOR_.
The rule — on in krizakaBase and krizakaNext — refuses a name read through process.env.X, process.env["X"] or
import.meta.env.X that starts (after NEXT_PUBLIC_, EXPO_PUBLIC_ or VITE_) with:
- a product: the organisation's name, the repository's own (the first word of its package.json name,
acme-monorepo→ACME_), or one you name — a deployment already says which product it is; - a vendor (
BUNNY_,MAILGUN_,RESEND_,STRIPE_,GOOGLE_,EXPO_,REDIS_…): the vendor is a value (MEDIA_STORAGE_PROVIDER=bunny,MAIL_PROVIDER=mailgun) and its settings sit under the context (MEDIA_STORAGE_API_KEY,MAIL_API_KEY).
The platforms' own names (GITHUB_TOKEN, EAS_BUILD, …) pass. Tune it with
envNames({ products, vendors, allow }) from @krizaka/config/eslint/env-names; envNamePrefixProblem(name) gives
the same verdict to a script (a .env.example or deployment spec check).
The ratchet
A repository with debt cannot turn the rules on in one pull request. The ratchet lets it adopt them now: it counts
the four UI debts and the four stack debts, records the counts in lint-ratchet.json at the root, and fails when a
count goes up. Every migration pull request lowers them; when a count reaches zero, the matching rule becomes a
strict error.
npx krizaka-ratchet --init # once: creates lint-ratchet.json with today's counts — commit it
npx krizaka-ratchet # locally: compares (exit 1 when a count went up)
npx krizaka-ratchet --update # after a migration: lowers the recorded counts (never raises them), records new counters — commit it
npx krizaka-ratchet --json # in CI: the same check, machine-readable| Counter | Pattern (same regex as the ESLint rule) |
|---|---|
palette | \b(bg|text|border|from|via|to|ring|shadow|fill|stroke)-(zinc|slate|…|indigo)-[0-9] |
light | \blight: |
arbitraryVar | \[var\(-- |
classNameTemplate | className=\{\s*` |
fetchInClientEffect | in a file opening with "use client": fetch( / krizakaFetch( between the parentheses of a useEffect( / useLayoutEffect( |
directTanstackImport | from / import / import( / require( of "@tanstack/…" |
localTableOrForm | <table, and <form … </form> holding more fields than maxFormFields (default 1) |
retiredImport | an import of a dependency listed in retire (e.g. ["framer-motion"]): the way out of a dependency |
routeStateSelection | a Tabs / chip group / choice grid / segmented switch (incl. RadioGroup.Root variant="segmented") / toggle group of a view driven by local state (value, defaultValue, onValueChange) without routeKey, and without // @ephemeral: <reason>: the URL is the state |
The UI counters scan app/**/*.tsx, components/**/*.tsx and src/**/*.tsx by default (node_modules, dist,
.next never), or the globs given on the command line; the stack counters scan every source file (js, jsx, mjs,
ts, tsx, mts) of app, components, src, lib, hooks and features (stackGlobs). --init stores both
in the file so that every later run counts the same set. A file written before the stack counters still checks; the
next --update records them at their current value.
The counts apply the regex to the whole source text — a class held in a constant or a cn() argument counts too —
so the ratchet is never looser than the rule. Exit codes: 0 ok, 1 a count went up, 2 usage or file error.
// lint-ratchet.json
{
"globs": ["app/**/*.tsx", "components/**/*.tsx", "src/**/*.tsx"],
"stackGlobs": ["app/**/*.{js,jsx,mjs,ts,tsx,mts}", "…"],
"allow": [], // optional: same families as krizakaUi({ allow })
"retire": ["framer-motion"], // optional: dependencies on their way out
"maxFormFields": 1, // optional: same option as krizakaStack({ maxFormFields })
"counters": {
"palette": 2400, "light": 1151, "arbitraryVar": 0, "classNameTemplate": 128,
"fetchInClientEffect": 41, "directTanstackImport": 3, "localTableOrForm": 38, "retiredImport": 4
}
}The CI step, after the install:
- run: npx krizaka-ratchet --jsonLicense
Exports
Les 0 noms que le paquet exporte, lus dans ses types.
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/eslint
| Nom | Nature | Ce que c’est |
|---|---|---|
default | constante | |
KRIZAKA_IGNORES | constante | Generated or vendored output, never linted. |
krizakaBase | constante | |
krizakaCommon | constante | Shared by krizakaBase and krizakaNext: ignores, globals, import ordering. |
@krizaka/config/eslint/next
| Nom | Nature | Ce que c’est |
|---|---|---|
default | constante | |
krizakaNext | constante |
@krizaka/config/eslint/krizaka-ui
| Nom | Nature | Ce que c’est |
|---|---|---|
default | fonction | Flat config: the four UI rules on the given files. |
krizakaUi | fonction | Flat config: the four UI rules on the given files. |
krizakaUiRestrictedSyntax | fonction | The no-restricted-syntax entries, for a repository that already uses that rule and must merge both lists (flat config replaces a rule's options, it never c… |
krizakaUiRules | constante | The rule set, for a spread into a config object's rules. |
@krizaka/config/eslint/no-locale-ternary
| Nom | Nature | Ce que c’est |
|---|---|---|
default | fonction | Flat config: krizaka/no-locale-ternary on the given files, except routing code. |
DEFAULT_ROUTING_FILES | constante | Routing files that legitimately compare locales (the krizaka.com layout, a common convention). |
krizakaPlugin | constante | |
LOCALE_TERNARY_SELECTORS | constante | The selectors of no-locale-ternary, also usable in no-restricted-syntax. |
noLocaleTernary | fonction | Flat config: krizaka/no-locale-ternary on the given files, except routing code. |
@krizaka/config/eslint/stack
| Nom | Nature | Ce que c’est |
|---|---|---|
default | fonction | Flat config: the stack rules on an app's sources. |
krizakaStack | fonction | Flat config: the stack rules on an app's sources. |
STACK_RULES | constante | The rule names, as configured. |
@krizaka/config/eslint/ui-warnings
| Nom | Nature | Ce que c’est |
|---|---|---|
default | fonction | Flat config: the two named UI rules on a product's components. |
krizakaUiWarnings | fonction | Flat config: the two named UI rules on a product's components. |
UI_WARNING_RULES | constante | The rule names, as configured. |
@krizaka/config/eslint/env-names
| Nom | Nature | Ce que c’est |
|---|---|---|
default | fonction | Flat config: krizaka/env-name on the given files. |
ENV_PLATFORM_NAMES | constante | Names the platforms set themselves (GitHub Actions, EAS): read, never chosen. |
ENV_PRODUCT_PREFIXES | constante | The organisation's name is never a prefix; a repository's own product is found from its package.json (below) and a config may name more (products): a deplo… |
ENV_VENDOR_PREFIXES | constante | Vendors: a vendor is a value (MEDIA_STORAGE_PROVIDER=bunny, MAIL_PROVIDER=mailgun), never a name. |
envNamePrefixProblem | fonction | The prefix that makes an environment variable name refused, or null. |
envNames | fonction | Flat config: krizaka/env-name on the given files. |
krizakaPlugin | constante | |
ownProductPrefix | fonction | The product a repository is: the first word of the nearest package.json's name, scope removed (acme-monorepo → ACME, @org/acme-admin → ACME); null for a… |
@krizaka/config/eslint/plugin
| Nom | Nature | Ce que c’est |
|---|---|---|
default | constante | |
krizakaPlugin | constante |
@krizaka/config/dependency-cruiser
| Nom | Nature | Ce que c’est |
|---|---|---|
withOptions | type |
@krizaka/config/covered-domains
| Nom | Nature | Ce que c’est |
|---|---|---|
CoveredDomain | type | |
coveredDomains | constante | The domains, in the order of the map. |
coveredDomainsMarkdown | fonction | The table of the page « Use Krizaka first » (Markdown), generated from the map. |
domainMessage | fonction | The message of a domain: what is refused, the Krizaka home, and what to do when the function is missing. |
domainPattern | fonction | One pattern for a whole domain. |
MISSING_FUNCTION | constante | The last thing every message says. |
refusedPattern | fonction | The dependency-cruiser to.path regular expression of a refused entry. |
ruleName | fonction | The name of the dependency-cruiser rule of a domain. |
@krizaka/config/covered-domains.json
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/known-violations
| Nom | Nature | Ce que c’est |
|---|---|---|
compare | fonction | Compare the recorded violations with the current ones. |
CONFIG_FILE | constante | |
currentViolations | fonction | Run dependency-cruiser without the known file and read every violation (the baseline report). |
keyOf | fonction | The identity of a violation, as depcruise matches it: the rule, the two ends, and the cycle's modules. |
KNOWN_FILE | constante | |
runKnownViolations | fonction | check | update | init. |
shrink | fonction | What update writes: the recorded violations that still happen. |
Violation | type |
@krizaka/config/patterns
| Nom | Nature | Ce que c’est |
|---|---|---|
ARBITRARY_VAR_SOURCE | constante | bg-[var(--surface-1)] — the variable has a utility in |
balancedArguments | fonction | The text between the parenthesis that opens at open and the one that closes it, skipping strings and comments. |
CLASSNAME_TEMPLATE_SOURCE | constante | className=\{…${x}\} — the ratchet's text approximation of the TemplateLiteral rule. |
COLOR_UTILITIES | constante | Utilities that take a colour. |
countFormFields | fonction | The value-holding fields inside a form's source text. |
EFFECT_CALL_SOURCE | constante | The opening of an effect call: useEffect(, React.useLayoutEffect(. |
EFFECT_NAMES_SOURCE | constante | The names the ESLint rule matches (callee identifier or member property). |
EPHEMERAL_SOURCE | constante | The justification that keeps a local selection: `// |
FETCH_CALL_SOURCE | constante | A fetch call: fetch(, window.fetch(, krizakaFetch( — never refetch(. |
FETCH_NAMES_SOURCE | constante | |
FORM_FIELD_TAGS | constante | The elements that hold a value in a form: native fields and the field primitives of @krizaka/ui. |
importSource | fonction | An import of one of the given packages (or scopes ending in /): from "x", import "x", import("x"), require("x"), export … from "x". |
isLocalSelection | fonction | Is this opening tag a selection driven by local state? |
LIGHT_VARIANT_SOURCE | constante | light:bg-white — a theme is a set of tokens, never a variant. |
LOCAL_SELECTION_PROPS | constante | The props that make a selection local: its own value, its starting value, its change handler. |
PALETTE_FAMILIES | constante | Tailwind palette families a product never writes: a component reads a role (bg-surface-1, text-accent…). |
paletteSource | fonction | bg-zinc-900, text-violet-400/80… — a raw palette step. |
ROUTE_KEY_PROP | constante | The prop that binds it to the URL. |
SELECTION_COMPONENTS | constante | The selection components whose choice belongs in the URL: tabs, a segmented switch, toggle groups, chip groups, choice tiles. |
selectionTags | fonction | The opening tags (<Tabs.Root … >) of the selection components in a source text, each with the line above it. |
TABLE_OR_FORM_SOURCE | constante | A <table or <form element written in an app (JSX or HTML). |
TANSTACK_SCOPE | constante | The headless engines that only enter through a @krizaka/* package. |
USE_CLIENT_SOURCE | constante | A "use client" directive heading the file (after comments). |
@krizaka/config/ratchet
| Nom | Nature | Ce que c’est |
|---|---|---|
CounterName | type | |
counterPatterns | fonction | |
Counters | type | |
COUNTERS | constante | Every counter, in report order. |
countRepository | fonction | Counts the debts under root: the UI counters in the files of globs, the stack counters in those of stackGlobs. |
countSource | fonction | Counts the four UI debts in one source text. |
countStackSource | fonction | Counts the stack debts in one source text: fetch calls inside the effects of a "use client" file, imports of @tanstack/*, hand-written tables and forms o… |
DEFAULT_GLOBS | constante | |
DEFAULT_STACK_GLOBS | constante | The stack counters read every source file: data hooks and fetchers live in .ts too. |
RATCHET_FILE | constante | |
RatchetError | classe | A usage or file error (exit code 2), as opposed to a counter going up (exit code 1). |
RatchetFile | type | |
RatchetResult | type | |
runRatchet | fonction | Runs the ratchet. |
STACK_COUNTERS | constante | The stack counters (the three rules of krizakaStack, and the dependencies to retire), in report order. |
StackCounterName | type | |
UI_COUNTERS | constante | The UI counters (the four rules of krizakaUi), in report order. |
UiCounterName | type |
@krizaka/config/prettier
| Nom | Nature | Ce que c’est |
|---|---|---|
default | constante |
@krizaka/config/tsconfig/base.json
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/tsconfig/react-library.json
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/tsconfig/next.json
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/tsconfig/react-native.json
| Nom | Nature | Ce que c’est |
|---|
@krizaka/config/editorconfig
| Nom | Nature | Ce que c’est |
|---|
Paquet
| Version sur npm | 0.8.0 (npm) |
| Licence | Apache-2.0 |
| Node.js | >=22 |
| Dépendances | @eslint/js ^9.39.0 |
| Dépendances à fournir | eslint ^9 |
| Code source | config |
Journal des versions
0.8.0
Minor changes
-
@krizaka/confignow lives in krizaka-ts (the quality kit is not UI), with its history. Same name, same exports, same behaviour; the repository, bug tracker and homepage links change. Releases are published from krizaka-ts. -
« Krizaka first » (krizaka-ui#609, #612): the covered-domains map (
covered-domains.json, dates, i18n, query, icons, ui: each names its Krizaka home and the refused imports) and the dependency-cruiser preset generated from it, onekrizaka-first-<domain>rule per domain, withno-circular,not-to-unresolvableandnot-to-dev-dep. The message names the Krizaka home and says « Missing function? add it to the package first. »..withOptions({ exemptFrom })for a monorepo's own packages. Newkrizaka-known-violations(init,check,update): a known-violations baseline that only shrinks. New exports@krizaka/config/covered-domainsand/known-violations;dependency-cruiseris now a dependency.Breaking: the ESLint rule
krizaka/no-direct-tanstack-importis retired (and leavesSTACK_RULES): the TanStack import iskrizaka-first-queryin dependency-cruiser, one tool only.krizaka-no-direct-tanstackis replaced by it.
0.7.0
Minor changes
- #496
64ede61Thanks @krizaka-agents! - Peer rangeeslint: ^9 || ^10(and@eslint/jslikewise). The ESLint suite and the lint of the package pass under both ESLint 9.39 and 10.13 (krizaka-ui#141).
0.6.0
Minor changes
-
#488
c4a6ce1Thanks @krizaka-agents! - The URL is the state, made impossible to forget (Oussama, 2026-10-22: « changer les tabs doit changer les routes »).- New
@krizaka/ui/router:useRouteState(key, { values, default, history })keeps a value in a search parameter, typed from anas constlist (an unknown value reads as the default, the default is never written, other parameters are kept);RouteStateProvidertakes your router's adapter once (the History API is the default); purereadRouteValue/writeRouteValue. routeKey(+routeValues) onTabs.Root,Chip.Group(single) andChoiceGrid: they bind to the URL, nouseState. Local state stays for ephemeral UI only.@krizaka/config: the rulekrizaka/route-state-selection(inkrizakaStack(), severity of the stack, only pages and route components) refuses a Tabs / Chip.Group / ChoiceGrid / SegmentedControl / ToggleGroup driven by local state withoutrouteKey, unless the line carries// @ephemeral: <reason>; the ratchet counts it asrouteStateSelection(only goes down).
- New
0.5.0
Minor changes
-
#486
0b1d80dThanks @krizaka-agents! - No more family switcher: krizaka.com is the only way back between the Krizaka sites (Oussama, 2026-10-22).NavBar.Familyis deprecated (removed in the next minor once no site uses it).SiteFooterlists the family on the hub only:familynow defaults tocurrent === "krizaka", so every other site's footer holds its own columns, the legal links and one quiet « A Krizaka project » line linking to www.krizaka.com. Newproductsprop filters the hub's Products column (krizaka.com's focus products), replacing CSS that hid links by URL.@krizaka/config: thekrizaka/no-family-switcherrule (an error inkrizakaStack()) refusesNavBar.Familyso it does not come back.
0.4.2
Patch changes
- #467
af54020Thanks @krizaka-agents! - Vercel is retired: its platform variable names are no longer allowed by the env-name rule (aVERCEL_variable is refused like any vendor name).
0.4.1
Patch changes
- #179
e3bcc51Thanks @oussamaABID! - The documentation moved to https://ui.krizaka.com, built from this repository (apps/site) at every change: the packages'homepage(what npm shows) and READMEs point there —@krizaka/tokensto /foundations/tokens,@krizaka/iconsto /foundations/icons,@krizaka/fontsto /foundations/typography, the packages without UI to /packages/<name>.
0.4.0
Minor changes
- #169
c08ae66Thanks @oussamaABID! - Two named ESLint rules for the adoption:krizaka/no-light-variant(refuse Tailwindlight:in products — tokens do the theming) andkrizaka/no-raw-palette(refusebg-zinc-900,text-violet-400… — use a role;allowfamilies for isolated cases), registered on thekrizakaplugin and shipped as warnings bykrizakaUiWarnings()(@krizaka/config/eslint/ui-warnings).krizaka-ratchetalready counts the same patterns (light,palette): a product adopts the warnings now and brings both counts to 0.krizakaUi()stays the strict set.
0.3.1
Patch changes
- #143
d0e43fdThanks @oussamaABID! - Package homepage points to the documentation on krizaka.com (the page the npm listing links to is the one that explains the package).
0.3.0
Minor changes
- #129
86484f5Thanks @oussamaABID! -krizaka/env-name: environment variables are named by bounded context (krizaka/.github#46) —<CONTEXT>_<THING>, never after a product (the organisation's, the repository's own read from its package.json, or one a config names) nor a vendor (BUNNY_,MAILGUN_,GOOGLE_,EXPO_…: a vendor is a value,MAIL_PROVIDER=mailgun). It readsprocess.env.X,process.env["X"]andimport.meta.env.X, sees throughNEXT_PUBLIC_/EXPO_PUBLIC_/VITE_, lets the platforms' own names through (GITHUB_TOKEN,VERCEL_URL,EAS_BUILD…), and is on inkrizakaBaseandkrizakaNext;envNames({ products, vendors, allow })(@krizaka/config/eslint/env-names) tunes it.@krizaka/realtime's error and docs nameREALTIME_REDIS_URL,@krizaka/push's docsPUSH_ACCESS_TOKEN.
0.2.0
Minor changes
- #109
406e62cThanks @oussamaABID! - The stack rules of ADR-001 (TanStack under@krizaka/*facades):krizakaStack()(@krizaka/config/eslint/stack) brings three warnings —krizaka/no-fetch-in-client-effect(afetch/krizakaFetchin auseEffectof a"use client"file),krizaka/no-direct-tanstack-import(any@tanstack/*import outside a@krizaka/*package) andkrizaka/no-local-table-or-form(a<table>, or a<form>of more than one field).krizaka-ratchetcounts the same patterns (fetchInClientEffect,directTanstackImport,localTableOrForm) and the imports of the dependencies listed underretire(retiredImport); alint-ratchet.jsonwithout them still checks, and--updaterecords them. New@krizaka/config/dependency-cruiser: the shared boundary (krizaka-no-direct-tanstack) an appextends. Everykrizaka/*rule now lives in one plugin object (@krizaka/config/eslint/plugin), so the configs compose.
0.1.0
Minor changes
- #7
8446ac9Thanks @oussamaABID! - Initial release: the shared configuration of every Krizaka JavaScript repository — ESLint flat configs (krizakaBase,krizakaNext, the four UI ruleskrizakaUi(options?)with a palette allowlist,noLocaleTernary), tsconfig bases (base,react-library,next,react-native), Prettier, EditorConfig, andkrizaka-ratchet, the counter that fails when the UI debt goes up (--init,--update,--json).