From 0e4f38a3c9a4d0911d3da91bfb9cf1726aa34afc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:47:01 +0000 Subject: [PATCH 01/13] Initial plan From fbb902c6035dfadfb7ae6dee5fd54a9a37786f4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:06:29 +0000 Subject: [PATCH 02/13] Add Storybook support via boilerplate hook pattern Co-authored-by: magne4000 <1098371+magne4000@users.noreply.github.com> --- .github/workflows/tests-entry.yml | 12 ++++++ boilerplates/storybook/bati.config.ts | 15 +++++++ boilerplates/storybook/hooks/after.ts | 10 +++++ boilerplates/storybook/package.json | 24 +++++++++++ boilerplates/storybook/tsconfig.json | 8 ++++ packages/cli/rules.ts | 3 ++ packages/cli/turbo.json | 1 + packages/features/src/categories.ts | 5 +++ packages/features/src/features.ts | 18 ++++++++ packages/features/src/rules/enum.ts | 2 + packages/features/src/rules/rules.ts | 6 +++ .../tests/tests/FRAMEWORK+storybook.spec.ts | 41 +++++++++++++++++++ pnpm-lock.yaml | 13 ++++++ website/components/RulesMessages.tsx | 13 ++++++ 14 files changed, 171 insertions(+) create mode 100644 boilerplates/storybook/bati.config.ts create mode 100644 boilerplates/storybook/hooks/after.ts create mode 100644 boilerplates/storybook/package.json create mode 100644 boilerplates/storybook/tsconfig.json create mode 100644 packages/tests/tests/FRAMEWORK+storybook.spec.ts diff --git a/.github/workflows/tests-entry.yml b/.github/workflows/tests-entry.yml index ba2879d85..850d39df9 100644 --- a/.github/workflows/tests-entry.yml +++ b/.github/workflows/tests-entry.yml @@ -223,6 +223,9 @@ jobs: - sentry--solid--eslint--biome--oxlint - sentry--react--eslint--biome--oxlint - sentry--vue--eslint--biome--oxlint + - solid--storybook--eslint + - react--storybook--eslint + - vue--storybook--eslint - react--vercel--hono--eslint--biome--oxlint - react--vercel--h3--eslint--biome--oxlint - react--vercel--express--eslint--biome--oxlint @@ -683,6 +686,15 @@ jobs: - destination: sentry--vue--eslint--biome--oxlint flags: --sentry --vue --eslint --biome --oxlint test-files: FRAMEWORK+sentry.spec.ts + - destination: solid--storybook--eslint + flags: --solid --storybook --eslint + test-files: FRAMEWORK+storybook.spec.ts + - destination: react--storybook--eslint + flags: --react --storybook --eslint + test-files: FRAMEWORK+storybook.spec.ts + - destination: vue--storybook--eslint + flags: --vue --storybook --eslint + test-files: FRAMEWORK+storybook.spec.ts - destination: react--vercel--hono--eslint--biome--oxlint flags: --react --vercel --hono --eslint --biome --oxlint test-files: FRAMEWORK+vercel.spec.ts diff --git a/boilerplates/storybook/bati.config.ts b/boilerplates/storybook/bati.config.ts new file mode 100644 index 000000000..d9d962b3a --- /dev/null +++ b/boilerplates/storybook/bati.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "@batijs/core/config"; + +export default defineConfig({ + if(meta) { + return meta.BATI.has("storybook"); + }, + nextSteps(_meta, packageManager) { + return [ + { + type: "command", + step: `${packageManager} storybook`, + }, + ]; + }, +}); diff --git a/boilerplates/storybook/hooks/after.ts b/boilerplates/storybook/hooks/after.ts new file mode 100644 index 000000000..983f93c53 --- /dev/null +++ b/boilerplates/storybook/hooks/after.ts @@ -0,0 +1,10 @@ +import { execSync } from "node:child_process"; +import { packageManager } from "@batijs/core"; +import type { VikeMeta } from "@batijs/core"; + +export default async function onafter(cwd: string, meta: VikeMeta) { + const isInteractive = !meta.BATI_IS_CI && !meta.BATI_TEST; + const pm = packageManager(); + const command = `${pm.exec} storybook@latest init${isInteractive ? "" : " --yes"}`; + execSync(command, { cwd, stdio: "inherit" }); +} diff --git a/boilerplates/storybook/package.json b/boilerplates/storybook/package.json new file mode 100644 index 000000000..5ee9f9f38 --- /dev/null +++ b/boilerplates/storybook/package.json @@ -0,0 +1,24 @@ +{ + "name": "@batijs/storybook", + "private": true, + "version": "0.0.1", + "description": "", + "type": "module", + "scripts": { + "check-types": "tsc --noEmit", + "build": "bati-compile-boilerplate" + }, + "keywords": [], + "author": "", + "license": "MIT", + "devDependencies": { + "@batijs/compile": "workspace:*", + "@types/node": "^20.19.37" + }, + "dependencies": { + "@batijs/core": "workspace:*" + }, + "files": [ + "dist/" + ] +} diff --git a/boilerplates/storybook/tsconfig.json b/boilerplates/storybook/tsconfig.json new file mode 100644 index 000000000..b1dad9140 --- /dev/null +++ b/boilerplates/storybook/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": ["../tsconfig.base.json"], + "compilerOptions": { + "types": ["@types/node", "@batijs/core/types"], + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "baseUrl": "." + } +} diff --git a/packages/cli/rules.ts b/packages/cli/rules.ts index 66c067ed5..e84e7d5bb 100644 --- a/packages/cli/rules.ts +++ b/packages/cli/rules.ts @@ -63,4 +63,7 @@ Choose one of them or remove selected Server`, `${inverse(bold("shadcn/ui"))} integration is tied to ${inverse(bold("TailwindCSS"))}. Using another CSS library with it may have unpredictable behaviour.`, ), [RulesMessage.INFO_STACKBLITZ_COMPAT]: null, + [RulesMessage.ERROR_STORYBOOK_R_UI_FRAMEWORK]: error( + `${inverse(bold("Storybook"))} is only supported with ${inverse(bold("React"))}, ${inverse(bold("Vue"))}, or ${inverse(bold("Solid"))}`, + ), } satisfies Record; diff --git a/packages/cli/turbo.json b/packages/cli/turbo.json index 1a3ba35ce..eadf2ad74 100644 --- a/packages/cli/turbo.json +++ b/packages/cli/turbo.json @@ -40,6 +40,7 @@ "@batijs/solid#build", "@batijs/solid-sentry#build", "@batijs/sqlite#build", + "@batijs/storybook#build", "@batijs/tailwindcss#build", "@batijs/telefunc#build", "@batijs/trpc#build", diff --git a/packages/features/src/categories.ts b/packages/features/src/categories.ts index 41fad08c1..36a3c9d2f 100644 --- a/packages/features/src/categories.ts +++ b/packages/features/src/categories.ts @@ -73,6 +73,11 @@ tailored for Vike.`, group: categoriesGroups.Utilities, description: `Coming soon: Error Tracking solution for frontend and backend`, }, + { + label: "Tooling", + group: categoriesGroups.Utilities, + description: `Additional tooling to improve your developer experience.`, + }, ] as const satisfies ReadonlyArray; export type CategoryLabels = (typeof categories)[number]["label"]; diff --git a/packages/features/src/features.ts b/packages/features/src/features.ts index a07ed4b53..bcbe95903 100644 --- a/packages/features/src/features.ts +++ b/packages/features/src/features.ts @@ -596,6 +596,24 @@ export const features = [ url: "https://logrocket.com", disabled: true, }, + + // Tooling + { + category: "Tooling", + label: "Storybook", + flag: "storybook", + image: + "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIwLjg3ZW0iIGhlaWdodD0iMWVtIiB2aWV3Qm94PSIwIDAgMjU2IDI5NiI+PHBhdGggZmlsbD0iI0ZGNDc4NSIgZD0iTTAgMjkyLjI3VjMuNzJMMTcuNDggMEwyNTMuOTkgOS4wOHYyNzcuNThsLTM3LjQ1IDguMTRMMCwyOTIuMjdaIi8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE2Ni41NSA2Ny40MWwxLjg5LTQ1LjQ3bDM5LjkgMTIuNTd2MzUuNjdsLTQxLjc5LTIuNzdabS04Ni44MSAxNy4yNmMtLjU2IDEwLjAzIDI2LjIzIDEwLjQxIDMxLjE1IDE0LjMzYzE0Ljg5IDExLjQ3IDExLjM2IDI4LjEyIDEwLjkgNDMuNzVjMTUuMTUtMzIuMzcgNTEuNTEtMTguNDUgNjEuMjgtMjguNDhjMi4wMy0yLjExIDMuMTYtNS4wNyAzLjM4LTguNDFsMi45NiAyLjI1Yy4wNiAyNC42Ny0xNC40NCAzOS43OC0zOC43NiA0NC42MWwtMjAuMzUgMy45NUMxMjAuNjMgMTYxLjYzIDEwNiAxNjcuNSA5NiAxNzguNjZsLS4xOS4yM2MtMTEuNzEgMTQuMi0xNS45IDMzLjM2LTE1Ljk2IDQ1LjY3Yy0yNy41Ni0xNS40Ni0yNi43Ni0xMjguMTkgLjU5LTE0MC4xTTIwNy42IDkwLjY1YzguMTMgOS4zMiAxMC4xOSAyMy44NiA5LjM4IDM4LjU5Yy0xLjc0IDMxLjUyLTI0LjI1IDUwLjMtNjEuMiA1Mi41OGwtNS43OC4zOGMtMjIuNzkgMS41Mi0yOS4yMSAxNS4zMS0yOC4xNSAzMi4yNGMxLjI4IDIwLjA3IDEzLjE3IDI3LjE0IDI4LjE1IDI3LjE0YzIxLjYyIDAgNDEuMTItMTMuMzYgNDEuMjktMzYuMjhsMS4yOS4wOGMuMDYgMjEuMjYtMTUuMjkgMzkuNzItMzguNzggNDQuNTlsLTIwLjM1IDMuOTVDMTIwLjYzIDI1NS41IDEwNiAyNjEuMzYgOTYgMjcyLjUzYzE1LjA2LTY1Ljk3IDY4LjE2LTYyLjg2IDEwOC42MS02NS4xM2wyNi45OC0xLjc5YzE4Ljc1LTEuNCAyOS4zNy0xNC43MSAyOS4zNy0zMy43N2MwLTEuMTQtLjAzLTIuMi0uMDgtMy4zN2MtLjg3LTIzLjMyLTE2LjAxLTM5LjEtMzkuNTItNDUuMDVjLTkuNzUtMi41My0yMS0zLjcyLTMxLjE1LTMuNzJjLTEyLjQgMC0yMi41LTEwLjYzLTIyLjUtMjMuNjhzMTAuMS0yMy42OCAyMi41LTIzLjY4YzEzLjMzIDAgMjIuMDIgNi41NCAyMi45MSAxOC40OGM3LjItNC45MyAyNy4wMy01LjQ5IDM3LjM2IDEuNzNhMy4yNiAzLjI2IDAgMCAxLTMuMzktNS4zNWMtMTcuOTctMTAuNjMtNDAuNDItMTEuNDEtNDguMzQgMy4yOGMtMi4xLTQuOTktNy4wMi0xMS44OC0xMi4xNy0xMy44OWMxNS4yMS0xNy4yOSA0NS43OC0xMy40NiA2MS43NyA1LjA0WiIvPjwvc3ZnPg==", + url: "https://storybook.js.org", + tagline: "Build UI components and pages in isolation", + repo: "storybookjs/storybook", + links: [ + { + label: "Docs", + href: "https://storybook.js.org/docs", + }, + ], + }, ] as const satisfies ReadonlyArray>; export const flags = features.map((f) => f.flag); diff --git a/packages/features/src/rules/enum.ts b/packages/features/src/rules/enum.ts index c6745c5b8..251dda6ab 100644 --- a/packages/features/src/rules/enum.ts +++ b/packages/features/src/rules/enum.ts @@ -26,4 +26,6 @@ export enum RulesMessage { // --- INFO // Some tools do not work on Stackblitz INFO_STACKBLITZ_COMPAT, + // Storybook requires a supported UI framework (React, Vue, or Solid) + ERROR_STORYBOOK_R_UI_FRAMEWORK, } diff --git a/packages/features/src/rules/rules.ts b/packages/features/src/rules/rules.ts index d50c95d78..1a6612f6a 100644 --- a/packages/features/src/rules/rules.ts +++ b/packages/features/src/rules/rules.ts @@ -59,4 +59,10 @@ export default [ filter(RulesMessage.INFO_STACKBLITZ_COMPAT, (fts) => { return fts.has("drizzle") || fts.has("sqlite") || fts.has("kysely") || fts.has("cloudflare"); }), + filter(RulesMessage.ERROR_STORYBOOK_R_UI_FRAMEWORK, (fts) => { + if (fts.has("storybook")) { + return !fts.has("react") && !fts.has("vue") && !fts.has("solid"); + } + return false; + }), ] satisfies Rule[]; diff --git a/packages/tests/tests/FRAMEWORK+storybook.spec.ts b/packages/tests/tests/FRAMEWORK+storybook.spec.ts new file mode 100644 index 000000000..0ee8c2511 --- /dev/null +++ b/packages/tests/tests/FRAMEWORK+storybook.spec.ts @@ -0,0 +1,41 @@ +import { describeBati } from "@batijs/tests-utils"; + +export const matrix = [["solid", "react", "vue"], "storybook", "eslint"]; + +await describeBati(({ test, expect }) => { + test("storybook config files", async () => { + const fs = await import("node:fs/promises"); + const path = await import("node:path"); + + const storybookDir = process.cwd(); + + const configExtensions = ["ts", "js", "mjs", "cjs"]; + let configFileExists = false; + + for (const ext of configExtensions) { + const configPath = path.join(storybookDir, ".storybook", `main.${ext}`); + try { + await fs.access(configPath); + configFileExists = true; + break; + } catch { + // Continue to next extension + } + } + + expect(configFileExists).toBe(true); + }); + + test("storybook scripts", async () => { + const fs = await import("node:fs/promises"); + const path = await import("node:path"); + + const cwd = process.cwd(); + + const packageJsonPath = path.join(cwd, "package.json"); + const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8")); + + expect(packageJson.scripts.storybook).toBeTruthy(); + expect(packageJson.scripts["build-storybook"]).toBeTruthy(); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 935f484e1..2f20de9a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -974,6 +974,19 @@ importers: specifier: ^4.21.0 version: 4.21.0 + boilerplates/storybook: + dependencies: + '@batijs/core': + specifier: workspace:* + version: link:../../packages/core + devDependencies: + '@batijs/compile': + specifier: workspace:* + version: file:packages/compile(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + '@types/node': + specifier: ^20.19.37 + version: 20.19.37 + boilerplates/tailwindcss: dependencies: '@batijs/core': diff --git a/website/components/RulesMessages.tsx b/website/components/RulesMessages.tsx index 23f1fea64..c9a9022fc 100644 --- a/website/components/RulesMessages.tsx +++ b/website/components/RulesMessages.tsx @@ -226,4 +226,17 @@ export const rulesMessages = { // biome-ignore lint/complexity/noUselessFragments: Valid TS return <>; }), + [RulesMessage.ERROR_STORYBOOK_R_UI_FRAMEWORK]: error(() => { + return ( + + Storybook is only supported with React,{" "} + Vue, or Solid. +
    +
  • + Either pick one of these UI frameworks or unselect Storybook +
  • +
+
+ ); + }), } satisfies Record; From 139623a91ef572aa45429e015dcd2d0305dd9c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:11:15 +0100 Subject: [PATCH 03/13] =?UTF-8?q?c=C8=9Fore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../drizzle/files/database/drizzle/queries/todos.ts | 11 +++++++---- boilerplates/shared-todo/files/pages/todo/+data.ts | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/boilerplates/drizzle/files/database/drizzle/queries/todos.ts b/boilerplates/drizzle/files/database/drizzle/queries/todos.ts index 16b07ac5a..360179bec 100644 --- a/boilerplates/drizzle/files/database/drizzle/queries/todos.ts +++ b/boilerplates/drizzle/files/database/drizzle/queries/todos.ts @@ -14,10 +14,13 @@ export function insertTodo( } export function getAllTodos( - db: BATI.If<{ - "!BATI.hasD1": ReturnType; - _: ReturnType; - }>, + db: BATI.If< + { + "!BATI.hasD1": ReturnType; + _: ReturnType; + }, + "union" + >, ) { return db.select().from(todoTable).all(); } diff --git a/boilerplates/shared-todo/files/pages/todo/+data.ts b/boilerplates/shared-todo/files/pages/todo/+data.ts index 192a5fc1d..a6b1325e9 100644 --- a/boilerplates/shared-todo/files/pages/todo/+data.ts +++ b/boilerplates/shared-todo/files/pages/todo/+data.ts @@ -10,7 +10,7 @@ export type Data = Awaited>; export async function data(_pageContext: PageContextServer) { if (BATI.has("drizzle")) { - const todoItemsInitial = drizzleQueries.getAllTodos(_pageContext.db); + const todoItemsInitial = await drizzleQueries.getAllTodos(_pageContext.db); return { todoItemsInitial }; } else if (BATI.has("sqlite") && !BATI.hasD1) { From 1585c9d1dcfdc36ac23694d22f4a718a98475737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:13:24 +0100 Subject: [PATCH 04/13] fix: storybook logo --- packages/features/src/features.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/features/src/features.ts b/packages/features/src/features.ts index bcbe95903..39fde43d6 100644 --- a/packages/features/src/features.ts +++ b/packages/features/src/features.ts @@ -603,7 +603,7 @@ export const features = [ label: "Storybook", flag: "storybook", image: - "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIwLjg3ZW0iIGhlaWdodD0iMWVtIiB2aWV3Qm94PSIwIDAgMjU2IDI5NiI+PHBhdGggZmlsbD0iI0ZGNDc4NSIgZD0iTTAgMjkyLjI3VjMuNzJMMTcuNDggMEwyNTMuOTkgOS4wOHYyNzcuNThsLTM3LjQ1IDguMTRMMCwyOTIuMjdaIi8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE2Ni41NSA2Ny40MWwxLjg5LTQ1LjQ3bDM5LjkgMTIuNTd2MzUuNjdsLTQxLjc5LTIuNzdabS04Ni44MSAxNy4yNmMtLjU2IDEwLjAzIDI2LjIzIDEwLjQxIDMxLjE1IDE0LjMzYzE0Ljg5IDExLjQ3IDExLjM2IDI4LjEyIDEwLjkgNDMuNzVjMTUuMTUtMzIuMzcgNTEuNTEtMTguNDUgNjEuMjgtMjguNDhjMi4wMy0yLjExIDMuMTYtNS4wNyAzLjM4LTguNDFsMi45NiAyLjI1Yy4wNiAyNC42Ny0xNC40NCAzOS43OC0zOC43NiA0NC42MWwtMjAuMzUgMy45NUMxMjAuNjMgMTYxLjYzIDEwNiAxNjcuNSA5NiAxNzguNjZsLS4xOS4yM2MtMTEuNzEgMTQuMi0xNS45IDMzLjM2LTE1Ljk2IDQ1LjY3Yy0yNy41Ni0xNS40Ni0yNi43Ni0xMjguMTkgLjU5LTE0MC4xTTIwNy42IDkwLjY1YzguMTMgOS4zMiAxMC4xOSAyMy44NiA5LjM4IDM4LjU5Yy0xLjc0IDMxLjUyLTI0LjI1IDUwLjMtNjEuMiA1Mi41OGwtNS43OC4zOGMtMjIuNzkgMS41Mi0yOS4yMSAxNS4zMS0yOC4xNSAzMi4yNGMxLjI4IDIwLjA3IDEzLjE3IDI3LjE0IDI4LjE1IDI3LjE0YzIxLjYyIDAgNDEuMTItMTMuMzYgNDEuMjktMzYuMjhsMS4yOS4wOGMuMDYgMjEuMjYtMTUuMjkgMzkuNzItMzguNzggNDQuNTlsLTIwLjM1IDMuOTVDMTIwLjYzIDI1NS41IDEwNiAyNjEuMzYgOTYgMjcyLjUzYzE1LjA2LTY1Ljk3IDY4LjE2LTYyLjg2IDEwOC42MS02NS4xM2wyNi45OC0xLjc5YzE4Ljc1LTEuNCAyOS4zNy0xNC43MSAyOS4zNy0zMy43N2MwLTEuMTQtLjAzLTIuMi0uMDgtMy4zN2MtLjg3LTIzLjMyLTE2LjAxLTM5LjEtMzkuNTItNDUuMDVjLTkuNzUtMi41My0yMS0zLjcyLTMxLjE1LTMuNzJjLTEyLjQgMC0yMi41LTEwLjYzLTIyLjUtMjMuNjhzMTAuMS0yMy42OCAyMi41LTIzLjY4YzEzLjMzIDAgMjIuMDIgNi41NCAyMi45MSAxOC40OGM3LjItNC45MyAyNy4wMy01LjQ5IDM3LjM2IDEuNzNhMy4yNiAzLjI2IDAgMCAxLTMuMzktNS4zNWMtMTcuOTctMTAuNjMtNDAuNDItMTEuNDEtNDguMzQgMy4yOGMtMi4xLTQuOTktNy4wMi0xMS44OC0xMi4xNy0xMy44OWMxNS4yMS0xNy4yOSA0NS43OC0xMy40NiA2MS43NyA1LjA0WiIvPjwvc3ZnPg==", + "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY0IDY0Ij48dGl0bGU+aWNvbi1zdG9yeWJvb2stc3F1YXJlPC90aXRsZT48ZGVmcz48cGF0aCBpZD0icGF0aC0xIiBkPSJNMS45NDY0OTk1NSw1Ny4xMzA5NDcyIEwwLjAwMjI1OTczMTE2LDUuOTU0NzY2NjMgQy0wLjA2MTk1MDg4MzMsNC4yNjQ2MTgxNCAxLjI0OTkyMjg4LDIuODMyMjM2OTcgMi45NTg3MTUxOSwyLjcyNjczNDE4IEw0Ny4wMjI2NTM4LDAuMDA2MTc2Mjg0OTEgQzQ4Ljc2MjAwMDUsLTAuMTAxMjEyOTYgNTAuMjYwMTQ1OCwxLjIwNDYyOTggNTAuMzY4ODU1LDIuOTIyODU3NzEgQzUwLjM3Mjk1MDUsMi45ODc1OTM5MSA1MC4zNzUsMy4wNTI0NDA2MyA1MC4zNzUsMy4xMTczMDMxNSBMNTAuMzc1LDU4Ljg4MjgwMjggQzUwLjM3NSw2MC42MDQzODMxIDQ4Ljk2MjIyOTYsNjIgNDcuMjE5NDg5NCw2MiBDNDcuMTcyMjc3Niw2MiA0Ny4xMjUwNzIxLDYxLjk5ODk1MzQgNDcuMDc3OTA4LDYxLjk5Njg2MDYgTDQuOTU4MjA5MDQsNjAuMTI4MDk5NyBDMy4zMTc4MTMzMyw2MC4wNTUzMTg5IDIuMDA4MDgyMDMsNTguNzUxOTE4IDEuOTQ2NDk5NTUsNTcuMTMwOTQ3MiBaIi8+PC9kZWZzPjxnIGlkPSJpY29uLXN0b3J5Ym9vay1zcXVhcmUiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiPjxnIGlkPSJpY29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3LjAwMDAwMCwgMS4wMDAwMDApIj48cGF0aCBpZD0iQ29tYmluZWQtU2hhcGUiIGZpbGw9IiNGRjQ3ODUiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTUwLjM2ODg1NSwyLjkyMjg1NzcxIEM1MC4zNzI5NTA1LDIuOTg3NTkzOTEgNTAuMzc1LDMuMDUyNDQwNjMgNTAuMzc1LDMuMTE3MzAzMTUgTDUwLjM3NSw1OC44ODI4MDI4IEM1MC4zNzUsNjAuNjA0MzgzMSA0OC45NjIyMjk2LDYyIDQ3LjIxOTQ4OTQsNjIgQzQ3LjE3MjI3NzYsNjIgNDcuMTI1MDcyMSw2MS45OTg5NTM0IDQ3LjA3NzkwOCw2MS45OTY4NjA2IEw0Ljk1ODIwOTA0LDYwLjEyODA5OTcgQzMuMzE3ODEzMzMsNjAuMDU1MzE4OSAyLjAwODA4MjAzLDU4Ljc1MTkxOCAxLjk0NjQ5OTU1LDU3LjEzMDk0NzIgTDAuMDAyMjU5NzMxMTYsNS45NTQ3NjY2MyBDLTAuMDYxOTUwODgzMyw0LjI2NDYxODE0IDEuMjQ5OTIyODgsMi44MzIyMzY5NyAyLjk1ODcxNTE5LDIuNzI2NzM0MTggTDM3LjQ5OSwwLjU5NCBMMzcuMTk4MTMyNCw3LjYyMDc4NzY2IEMzNy4xOTQ3MjI3LDcuNzAxNzk2NjQgMzcuMjEyODIyNCw3Ljc4MTc4NzMxIDM3LjI0OTk4NjksNy44NTMwNTUyNSBMMzcuMjkzNDE1OCw3LjkyMTEzMDI2IEMzNy40NTA1Mjk2LDguMTI1NzM2MzcgMzcuNzQ1ODAwMiw4LjE2NTc4Mjg4IDM3Ljk1MjkyMDksOC4wMTA1NzY3IEwzNy45NTI5MjA5LDguMDEwNTc2NyBMNDAuNzE1ODE5NSw1Ljk0MDE5Njc4IEw0My4wNDkzOTY1LDcuNzU2MTg1MzcgQzQzLjEzNjgzODgsNy44MjQyMzI3OSA0My4yNDU4NjM0LDcuODU5NDY1ODQgNDMuMzU3MTEwNiw3Ljg1NTYyODEzIEM0My42MTY5MjEzLDcuODQ2NjY1NTMgNDMuODIwMTg0NCw3LjYzMTMzOTEgNDMuODExMTExNSw3LjM3NDY4MzE2IEw0My44MTExMTE1LDcuMzc0NjgzMTYgTDQzLjU1LDAuMjIgTDQ3LjAyMjY1MzgsMC4wMDYxNzYyODQ5MSBDNDguNzYyMDAwNSwtMC4xMDEyMTI5NiA1MC4yNjAxNDU4LDEuMjA0NjI5OCA1MC4zNjg4NTUsMi45MjI4NTc3MSBaIi8+PG1hc2sgaWQ9Im1hc2stMiIgZmlsbD0iI2ZmZiI+PHVzZSB4bGluazpocmVmPSIjcGF0aC0xIi8+PC9tYXNrPjxwYXRoIGlkPSJTIiBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0yOC45MzM4Mzc0LDIzLjQ4MTQzMzEgQzI4LjkzMzgzNzQsMjQuNjk0ODAyOCAzNy4xMzAwNTExLDI0LjExMzI2NjQgMzguMjMwMzIwNiwyMy4yNjA5NTc4IEMzOC4yMzAzMjA2LDE0Ljk5ODE5OTUgMzMuNzg0MTc2NCwxMC42NTYyNSAyNS42NDI1MzU5LDEwLjY1NjI1IEMxNy41MDA4OTUyLDEwLjY1NjI1IDEyLjkzOTI2NjgsMTUuMDY1NzU0MiAxMi45MzkyNjY4LDIxLjY4MDAxNCBDMTIuOTM5MjY2OCwzMy4xOTk4NDk5IDI4LjUyOTY0MjQsMzMuNDIwMzI1MSAyOC41Mjk2NDI0LDM5LjcwMzg3MiBDMjguNTI5NjQyNCw0MS40Njc2NzQ1IDI3LjY2MzUxMDUsNDIuNTE0OTMyMyAyNS43NTgwMjAxLDQyLjUxNDkzMjMgQzIzLjI3NTEwODQsNDIuNTE0OTMyMyAyMi4yOTM0OTIyLDQxLjI1MDQ2OTIgMjIuNDA4OTc2NSwzNi45NTEyMDA0IEMyMi40MDg5NzY1LDM2LjAxODUzMDQgMTIuOTM5MjY2OCwzNS43Mjc3NjIxIDEyLjY1MDU1NjEsMzYuOTUxMjAwNCBDMTEuOTE1MzgxMiw0Ny4zNjk4NTkxIDE4LjQyNDc2OTMsNTAuMzc1IDI1Ljg3MzUwNDQsNTAuMzc1IEMzMy4wOTEyNzA5LDUwLjM3NSAzOC43NSw0Ni41Mzg2MDY5IDM4Ljc1LDM5LjU5MzYzNDEgQzM4Ljc1LDI3LjI0NzAxNTkgMjIuOTI4NjU1NiwyNy41Nzc3Mjg5IDIyLjkyODY1NTYsMjEuNDU5NTM4NyBDMjIuOTI4NjU1NiwxOC45NzkxOTEyIDI0Ljc3NjQwMzksMTguNjQ4NDc4MyAyNS44NzM1MDQ0LDE4LjY0ODQ3ODMgQzI3LjAyODM0NywxOC42NDg0NzgzIDI5LjEwNzA2MzgsMTguODUxNDUxMyAyOC45MzM4Mzc0LDIzLjQ4MTQzMzEgWiIgbWFzaz0idXJsKCNtYXNrLTIpIi8+PHBhdGggaWQ9ImJvb2ttYXJrIiBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0zNi44MTI5MTY5LDcuMjc0MDYxMDYgTDM3LjEyMTUyMzMsMC4zNjY4MTQ5NzQgTDQzLjMyNjE1MDMsMCBMNDMuNTkzNDUwMyw3LjAzMjIyNjUzIEM0My42MDI3NTMxLDcuMjg0NDI5NDMgNDMuMzk0MzM5OSw3LjQ5NjAxOTkxIDQzLjEyNzk0NjQsNy41MDQ4MjcgQzQzLjAxMzg4MDQsNy41MDg1OTgxMiA0Mi45MDIwOTM1LDcuNDczOTc2MzcgNDIuODEyNDM1Niw3LjQwNzEwOTU5IEw0MC40MTk3MzIzLDUuNjIyNjI4ODEgTDM3LjU4NjgyOTYsNy42NTcwODcxOCBDMzcuMzc0NDYxMSw3LjgwOTYwMDUgMzcuMDcxNzA5Miw3Ljc3MDI0ODggMzYuOTEwNjE0Niw3LjU2OTE5MjY2IEMzNi44NDI4MDE4LDcuNDg0NTU4MDQgMzYuODA4MjU1NSw3LjM4MDE5OSAzNi44MTI5MTY5LDcuMjc0MDYxMDYgWiIgbWFzaz0idXJsKCNtYXNrLTIpIi8+PC9nPjwvZz48L3N2Zz4=", url: "https://storybook.js.org", tagline: "Build UI components and pages in isolation", repo: "storybookjs/storybook", From b3f9e610770845038e5450c73dbd374f4c3d26b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:16:49 +0100 Subject: [PATCH 05/13] chore --- boilerplates/storybook/hooks/after.ts | 4 ++-- packages/features/src/features.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/boilerplates/storybook/hooks/after.ts b/boilerplates/storybook/hooks/after.ts index 983f93c53..e0bb61b3d 100644 --- a/boilerplates/storybook/hooks/after.ts +++ b/boilerplates/storybook/hooks/after.ts @@ -1,10 +1,10 @@ import { execSync } from "node:child_process"; -import { packageManager } from "@batijs/core"; import type { VikeMeta } from "@batijs/core"; +import { packageManager } from "@batijs/core"; export default async function onafter(cwd: string, meta: VikeMeta) { const isInteractive = !meta.BATI_IS_CI && !meta.BATI_TEST; const pm = packageManager(); - const command = `${pm.exec} storybook@latest init${isInteractive ? "" : " --yes"}`; + const command = `${pm.exec} storybook@latest init --no-dev${isInteractive ? "" : " --yes"}`; execSync(command, { cwd, stdio: "inherit" }); } diff --git a/packages/features/src/features.ts b/packages/features/src/features.ts index 39fde43d6..e909cdb51 100644 --- a/packages/features/src/features.ts +++ b/packages/features/src/features.ts @@ -605,7 +605,7 @@ export const features = [ image: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY0IDY0Ij48dGl0bGU+aWNvbi1zdG9yeWJvb2stc3F1YXJlPC90aXRsZT48ZGVmcz48cGF0aCBpZD0icGF0aC0xIiBkPSJNMS45NDY0OTk1NSw1Ny4xMzA5NDcyIEwwLjAwMjI1OTczMTE2LDUuOTU0NzY2NjMgQy0wLjA2MTk1MDg4MzMsNC4yNjQ2MTgxNCAxLjI0OTkyMjg4LDIuODMyMjM2OTcgMi45NTg3MTUxOSwyLjcyNjczNDE4IEw0Ny4wMjI2NTM4LDAuMDA2MTc2Mjg0OTEgQzQ4Ljc2MjAwMDUsLTAuMTAxMjEyOTYgNTAuMjYwMTQ1OCwxLjIwNDYyOTggNTAuMzY4ODU1LDIuOTIyODU3NzEgQzUwLjM3Mjk1MDUsMi45ODc1OTM5MSA1MC4zNzUsMy4wNTI0NDA2MyA1MC4zNzUsMy4xMTczMDMxNSBMNTAuMzc1LDU4Ljg4MjgwMjggQzUwLjM3NSw2MC42MDQzODMxIDQ4Ljk2MjIyOTYsNjIgNDcuMjE5NDg5NCw2MiBDNDcuMTcyMjc3Niw2MiA0Ny4xMjUwNzIxLDYxLjk5ODk1MzQgNDcuMDc3OTA4LDYxLjk5Njg2MDYgTDQuOTU4MjA5MDQsNjAuMTI4MDk5NyBDMy4zMTc4MTMzMyw2MC4wNTUzMTg5IDIuMDA4MDgyMDMsNTguNzUxOTE4IDEuOTQ2NDk5NTUsNTcuMTMwOTQ3MiBaIi8+PC9kZWZzPjxnIGlkPSJpY29uLXN0b3J5Ym9vay1zcXVhcmUiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiPjxnIGlkPSJpY29uIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3LjAwMDAwMCwgMS4wMDAwMDApIj48cGF0aCBpZD0iQ29tYmluZWQtU2hhcGUiIGZpbGw9IiNGRjQ3ODUiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTUwLjM2ODg1NSwyLjkyMjg1NzcxIEM1MC4zNzI5NTA1LDIuOTg3NTkzOTEgNTAuMzc1LDMuMDUyNDQwNjMgNTAuMzc1LDMuMTE3MzAzMTUgTDUwLjM3NSw1OC44ODI4MDI4IEM1MC4zNzUsNjAuNjA0MzgzMSA0OC45NjIyMjk2LDYyIDQ3LjIxOTQ4OTQsNjIgQzQ3LjE3MjI3NzYsNjIgNDcuMTI1MDcyMSw2MS45OTg5NTM0IDQ3LjA3NzkwOCw2MS45OTY4NjA2IEw0Ljk1ODIwOTA0LDYwLjEyODA5OTcgQzMuMzE3ODEzMzMsNjAuMDU1MzE4OSAyLjAwODA4MjAzLDU4Ljc1MTkxOCAxLjk0NjQ5OTU1LDU3LjEzMDk0NzIgTDAuMDAyMjU5NzMxMTYsNS45NTQ3NjY2MyBDLTAuMDYxOTUwODgzMyw0LjI2NDYxODE0IDEuMjQ5OTIyODgsMi44MzIyMzY5NyAyLjk1ODcxNTE5LDIuNzI2NzM0MTggTDM3LjQ5OSwwLjU5NCBMMzcuMTk4MTMyNCw3LjYyMDc4NzY2IEMzNy4xOTQ3MjI3LDcuNzAxNzk2NjQgMzcuMjEyODIyNCw3Ljc4MTc4NzMxIDM3LjI0OTk4NjksNy44NTMwNTUyNSBMMzcuMjkzNDE1OCw3LjkyMTEzMDI2IEMzNy40NTA1Mjk2LDguMTI1NzM2MzcgMzcuNzQ1ODAwMiw4LjE2NTc4Mjg4IDM3Ljk1MjkyMDksOC4wMTA1NzY3IEwzNy45NTI5MjA5LDguMDEwNTc2NyBMNDAuNzE1ODE5NSw1Ljk0MDE5Njc4IEw0My4wNDkzOTY1LDcuNzU2MTg1MzcgQzQzLjEzNjgzODgsNy44MjQyMzI3OSA0My4yNDU4NjM0LDcuODU5NDY1ODQgNDMuMzU3MTEwNiw3Ljg1NTYyODEzIEM0My42MTY5MjEzLDcuODQ2NjY1NTMgNDMuODIwMTg0NCw3LjYzMTMzOTEgNDMuODExMTExNSw3LjM3NDY4MzE2IEw0My44MTExMTE1LDcuMzc0NjgzMTYgTDQzLjU1LDAuMjIgTDQ3LjAyMjY1MzgsMC4wMDYxNzYyODQ5MSBDNDguNzYyMDAwNSwtMC4xMDEyMTI5NiA1MC4yNjAxNDU4LDEuMjA0NjI5OCA1MC4zNjg4NTUsMi45MjI4NTc3MSBaIi8+PG1hc2sgaWQ9Im1hc2stMiIgZmlsbD0iI2ZmZiI+PHVzZSB4bGluazpocmVmPSIjcGF0aC0xIi8+PC9tYXNrPjxwYXRoIGlkPSJTIiBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0yOC45MzM4Mzc0LDIzLjQ4MTQzMzEgQzI4LjkzMzgzNzQsMjQuNjk0ODAyOCAzNy4xMzAwNTExLDI0LjExMzI2NjQgMzguMjMwMzIwNiwyMy4yNjA5NTc4IEMzOC4yMzAzMjA2LDE0Ljk5ODE5OTUgMzMuNzg0MTc2NCwxMC42NTYyNSAyNS42NDI1MzU5LDEwLjY1NjI1IEMxNy41MDA4OTUyLDEwLjY1NjI1IDEyLjkzOTI2NjgsMTUuMDY1NzU0MiAxMi45MzkyNjY4LDIxLjY4MDAxNCBDMTIuOTM5MjY2OCwzMy4xOTk4NDk5IDI4LjUyOTY0MjQsMzMuNDIwMzI1MSAyOC41Mjk2NDI0LDM5LjcwMzg3MiBDMjguNTI5NjQyNCw0MS40Njc2NzQ1IDI3LjY2MzUxMDUsNDIuNTE0OTMyMyAyNS43NTgwMjAxLDQyLjUxNDkzMjMgQzIzLjI3NTEwODQsNDIuNTE0OTMyMyAyMi4yOTM0OTIyLDQxLjI1MDQ2OTIgMjIuNDA4OTc2NSwzNi45NTEyMDA0IEMyMi40MDg5NzY1LDM2LjAxODUzMDQgMTIuOTM5MjY2OCwzNS43Mjc3NjIxIDEyLjY1MDU1NjEsMzYuOTUxMjAwNCBDMTEuOTE1MzgxMiw0Ny4zNjk4NTkxIDE4LjQyNDc2OTMsNTAuMzc1IDI1Ljg3MzUwNDQsNTAuMzc1IEMzMy4wOTEyNzA5LDUwLjM3NSAzOC43NSw0Ni41Mzg2MDY5IDM4Ljc1LDM5LjU5MzYzNDEgQzM4Ljc1LDI3LjI0NzAxNTkgMjIuOTI4NjU1NiwyNy41Nzc3Mjg5IDIyLjkyODY1NTYsMjEuNDU5NTM4NyBDMjIuOTI4NjU1NiwxOC45NzkxOTEyIDI0Ljc3NjQwMzksMTguNjQ4NDc4MyAyNS44NzM1MDQ0LDE4LjY0ODQ3ODMgQzI3LjAyODM0NywxOC42NDg0NzgzIDI5LjEwNzA2MzgsMTguODUxNDUxMyAyOC45MzM4Mzc0LDIzLjQ4MTQzMzEgWiIgbWFzaz0idXJsKCNtYXNrLTIpIi8+PHBhdGggaWQ9ImJvb2ttYXJrIiBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0zNi44MTI5MTY5LDcuMjc0MDYxMDYgTDM3LjEyMTUyMzMsMC4zNjY4MTQ5NzQgTDQzLjMyNjE1MDMsMCBMNDMuNTkzNDUwMyw3LjAzMjIyNjUzIEM0My42MDI3NTMxLDcuMjg0NDI5NDMgNDMuMzk0MzM5OSw3LjQ5NjAxOTkxIDQzLjEyNzk0NjQsNy41MDQ4MjcgQzQzLjAxMzg4MDQsNy41MDg1OTgxMiA0Mi45MDIwOTM1LDcuNDczOTc2MzcgNDIuODEyNDM1Niw3LjQwNzEwOTU5IEw0MC40MTk3MzIzLDUuNjIyNjI4ODEgTDM3LjU4NjgyOTYsNy42NTcwODcxOCBDMzcuMzc0NDYxMSw3LjgwOTYwMDUgMzcuMDcxNzA5Miw3Ljc3MDI0ODggMzYuOTEwNjE0Niw3LjU2OTE5MjY2IEMzNi44NDI4MDE4LDcuNDg0NTU4MDQgMzYuODA4MjU1NSw3LjM4MDE5OSAzNi44MTI5MTY5LDcuMjc0MDYxMDYgWiIgbWFzaz0idXJsKCNtYXNrLTIpIi8+PC9nPjwvZz48L3N2Zz4=", url: "https://storybook.js.org", - tagline: "Build UI components and pages in isolation", + tagline: "Build, test & document components", repo: "storybookjs/storybook", links: [ { From ab5b500513fdb864e26fca2640e5b8cf7769311a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:26:00 +0100 Subject: [PATCH 06/13] chore: sort hooks --- packages/cli/index.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/cli/index.ts b/packages/cli/index.ts index 54a299d24..78a9dc188 100644 --- a/packages/cli/index.ts +++ b/packages/cli/index.ts @@ -431,9 +431,16 @@ function checkRules(flags: string[]) { } } -async function retrieveHooks(hooks: string[]): Promise> { +async function retrieveHooks(hooks: Map): Promise> { const map = new Map<"after", Hook[]>(); - for (const hook of hooks) { + const sortedHooks = Array.from(hooks.entries()).sort(([b1], [b2]) => { + if (b1.config.enforce === "pre") return 1; + if (b1.config.enforce === "post") return -1; + if (b2.config.enforce === "pre") return -1; + if (b2.config.enforce === "post") return 1; + return 0; + }); + for (const [, hook] of sortedHooks) { for await (const file of walk(hook)) { const parsed = parse(file); const importFile = isWin ? `file://${file}` : file; @@ -512,7 +519,7 @@ async function run() { const args = await checkArguments(commandContext.args); const sources: string[] = []; - const hooks: string[] = []; + const hooks = new Map(); const flags = [ ...new Set( Object.entries(args) @@ -556,7 +563,7 @@ async function run() { sources.push(join(dir, bl.folder, "files")); } if (bl.subfolders.includes("hooks")) { - hooks.push(join(dir, bl.folder, "hooks")); + hooks.set(bl, join(dir, bl.folder, "hooks")); } } From 344303711d259c71b4bf17f80fdb8bc3061ddf28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:27:12 +0100 Subject: [PATCH 07/13] chore --- boilerplates/drizzle/files/database/drizzle/queries/todos.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boilerplates/drizzle/files/database/drizzle/queries/todos.ts b/boilerplates/drizzle/files/database/drizzle/queries/todos.ts index 360179bec..ceadf3aff 100644 --- a/boilerplates/drizzle/files/database/drizzle/queries/todos.ts +++ b/boilerplates/drizzle/files/database/drizzle/queries/todos.ts @@ -13,7 +13,7 @@ export function insertTodo( return db.insert(todoTable).values({ text }); } -export function getAllTodos( +export async function getAllTodos( db: BATI.If< { "!BATI.hasD1": ReturnType; From 8227e4e08404c610c043f23da879f77dbce9da08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 14:33:09 +0100 Subject: [PATCH 08/13] chore --- .github/workflows/tests-entry.yml | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/.github/workflows/tests-entry.yml b/.github/workflows/tests-entry.yml index 850d39df9..488123a25 100644 --- a/.github/workflows/tests-entry.yml +++ b/.github/workflows/tests-entry.yml @@ -94,6 +94,8 @@ jobs: - solid--daisyui--eslint--biome--oxlint - react--daisyui--eslint--biome--oxlint - vue--daisyui--eslint--biome--oxlint + - react--h3--auth0--cloudflare--eslint--biome--oxlint + - react--hono--auth0--cloudflare--eslint--biome--oxlint - solid--express--authjs--eslint--biome--oxlint - react--express--authjs--eslint--biome--oxlint - vue--express--authjs--eslint--biome--oxlint @@ -106,6 +108,18 @@ jobs: - solid--fastify--authjs--eslint--biome--oxlint - react--fastify--authjs--eslint--biome--oxlint - vue--fastify--authjs--eslint--biome--oxlint + - solid--express--auth0--eslint--biome--oxlint + - react--express--auth0--eslint--biome--oxlint + - vue--express--auth0--eslint--biome--oxlint + - solid--h3--auth0--eslint--biome--oxlint + - react--h3--auth0--eslint--biome--oxlint + - vue--h3--auth0--eslint--biome--oxlint + - solid--hono--auth0--eslint--biome--oxlint + - react--hono--auth0--eslint--biome--oxlint + - vue--hono--auth0--eslint--biome--oxlint + - solid--fastify--auth0--eslint--biome--oxlint + - react--fastify--auth0--eslint--biome--oxlint + - vue--fastify--auth0--eslint--biome--oxlint - solid--h3--trpc--drizzle--cloudflare--eslint--biome--oxlint - solid--hono--trpc--drizzle--cloudflare--eslint--biome--oxlint - solid--h3--telefunc--drizzle--cloudflare--eslint--biome--oxlint @@ -283,6 +297,12 @@ jobs: - destination: vue--daisyui--eslint--biome--oxlint flags: --vue --daisyui --eslint --biome --oxlint test-files: FRAMEWORK+CSS.spec.ts + - destination: react--h3--auth0--cloudflare--eslint--biome--oxlint + flags: --react --h3 --auth0 --cloudflare --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: react--hono--auth0--cloudflare--eslint--biome--oxlint + flags: --react --hono --auth0 --cloudflare --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts - destination: solid--express--authjs--eslint--biome--oxlint flags: --solid --express --authjs --eslint --biome --oxlint test-files: FRAMEWORK+SERVER+AUTH.spec.ts @@ -319,6 +339,42 @@ jobs: - destination: vue--fastify--authjs--eslint--biome--oxlint flags: --vue --fastify --authjs --eslint --biome --oxlint test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: solid--express--auth0--eslint--biome--oxlint + flags: --solid --express --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: react--express--auth0--eslint--biome--oxlint + flags: --react --express --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: vue--express--auth0--eslint--biome--oxlint + flags: --vue --express --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: solid--h3--auth0--eslint--biome--oxlint + flags: --solid --h3 --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: react--h3--auth0--eslint--biome--oxlint + flags: --react --h3 --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: vue--h3--auth0--eslint--biome--oxlint + flags: --vue --h3 --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: solid--hono--auth0--eslint--biome--oxlint + flags: --solid --hono --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: react--hono--auth0--eslint--biome--oxlint + flags: --react --hono --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: vue--hono--auth0--eslint--biome--oxlint + flags: --vue --hono --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: solid--fastify--auth0--eslint--biome--oxlint + flags: --solid --fastify --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: react--fastify--auth0--eslint--biome--oxlint + flags: --react --fastify --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts + - destination: vue--fastify--auth0--eslint--biome--oxlint + flags: --vue --fastify --auth0 --eslint --biome --oxlint + test-files: FRAMEWORK+SERVER+AUTH.spec.ts - destination: solid--h3--trpc--drizzle--cloudflare--eslint--biome--oxlint flags: --solid --h3 --trpc --drizzle --cloudflare --eslint --biome --oxlint From e5f585cf20838154868f1998d0c84fc97690be68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 15:40:23 +0100 Subject: [PATCH 09/13] fix(storybook): skip installation --- boilerplates/storybook/hooks/after.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boilerplates/storybook/hooks/after.ts b/boilerplates/storybook/hooks/after.ts index e0bb61b3d..c8856f37d 100644 --- a/boilerplates/storybook/hooks/after.ts +++ b/boilerplates/storybook/hooks/after.ts @@ -5,6 +5,6 @@ import { packageManager } from "@batijs/core"; export default async function onafter(cwd: string, meta: VikeMeta) { const isInteractive = !meta.BATI_IS_CI && !meta.BATI_TEST; const pm = packageManager(); - const command = `${pm.exec} storybook@latest init --no-dev${isInteractive ? "" : " --yes"}`; + const command = `${pm.exec} storybook@latest init --skip-install --no-dev${isInteractive ? "" : " --yes"}`; execSync(command, { cwd, stdio: "inherit" }); } From f710967d2e7fb683806e66f9f217d9b682af0a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 16:13:21 +0100 Subject: [PATCH 10/13] chore --- boilerplates/eslint/files/eslint.config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boilerplates/eslint/files/eslint.config.ts b/boilerplates/eslint/files/eslint.config.ts index cef4a50ae..68bcd9d10 100644 --- a/boilerplates/eslint/files/eslint.config.ts +++ b/boilerplates/eslint/files/eslint.config.ts @@ -19,6 +19,8 @@ export default tseslint.config( "cdk.out/*", //# BATI.has("cloudflare") "worker-configuration.d.ts", + //# BATI.has("storybook") + "stories/*", // JS files at the root of the project "*.js", "*.cjs", From 18ac6d4b86af1dbf05aece14107160a2371d07d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 16:29:54 +0100 Subject: [PATCH 11/13] knip --- boilerplates/storybook/bati.config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boilerplates/storybook/bati.config.ts b/boilerplates/storybook/bati.config.ts index d9d962b3a..817756f45 100644 --- a/boilerplates/storybook/bati.config.ts +++ b/boilerplates/storybook/bati.config.ts @@ -12,4 +12,7 @@ export default defineConfig({ }, ]; }, + knip: { + ignoreDependencies: ["playwright", "@vitest/coverage-v8"], + }, }); From b839281e5849290e19efe4a0204c1d3808e74ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 16:42:51 +0100 Subject: [PATCH 12/13] chore --- boilerplates/storybook/hooks/after.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/boilerplates/storybook/hooks/after.ts b/boilerplates/storybook/hooks/after.ts index c8856f37d..09ede47d3 100644 --- a/boilerplates/storybook/hooks/after.ts +++ b/boilerplates/storybook/hooks/after.ts @@ -1,4 +1,6 @@ import { execSync } from "node:child_process"; +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; import type { VikeMeta } from "@batijs/core"; import { packageManager } from "@batijs/core"; @@ -7,4 +9,19 @@ export default async function onafter(cwd: string, meta: VikeMeta) { const pm = packageManager(); const command = `${pm.exec} storybook@latest init --skip-install --no-dev${isInteractive ? "" : " --yes"}`; execSync(command, { cwd, stdio: "inherit" }); + + if (!isInteractive && meta.BATI.has("solid")) { + // SolidJS typings are not correct + await replaceInFile( + join(cwd, "stories/Page.stories.ts"), + "type Story = StoryObj;", + "type Story = StoryObj>;", + ); + } +} + +async function replaceInFile(path: string, searchValue: string, replaceValue: string) { + let content = await readFile(path, "utf8"); + content = content.replace(searchValue, replaceValue); + await writeFile(path, content, "utf8"); } From 34ecb65e2486cacca4b4ee1c6bf1175b9cb7f7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Charles?= Date: Thu, 12 Mar 2026 17:19:53 +0100 Subject: [PATCH 13/13] chore --- packages/tests/src/common.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/tests/src/common.ts b/packages/tests/src/common.ts index cfb041edc..9a02da900 100644 --- a/packages/tests/src/common.ts +++ b/packages/tests/src/common.ts @@ -27,7 +27,10 @@ export async function updatePackageJson( pkgjson.scripts["lint:oxlint"] = "oxlint --max-warnings 0 --type-aware --ignore-pattern '*.spec.ts' --ignore-path .gitignore ."; } - pkgjson.scripts.typecheck = "tsc --noEmit"; + // Storybook create .ts files that imports .vue files, and tsc complains about that + if (!flags.includes("storybook") || !flags.includes("vue")) { + pkgjson.scripts.typecheck = "tsc --noEmit"; + } pkgjson.devDependencies ??= {}; pkgjson.devDependencies.vitest = packageJson.devDependencies.vitest; pkgjson.devDependencies.knip = packageJson.devDependencies.knip;