Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/fresh-tools-locks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"create-karkas": minor
---

Refresh the generated project for Nub 0.9, Vite+ 1.1, Vitest 5, React 19.3,
Storybook 10.6, MSW 3, and Panda 2. Include the matching deduplicated lockfile,
share Vite+ through a Vite override, and remove the unused legacy Panda Studio
package. Update the Storybook actors and Park UI recipes for the new APIs.
6 changes: 3 additions & 3 deletions .config/hk.pkl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
amends "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Config.pkl"
import "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Builtins.pkl"
amends "package://github.com/jdx/hk/releases/download/v2.5.0/hk@2.5.0#/Config.pkl"
import "package://github.com/jdx/hk/releases/download/v2.5.0/hk@2.5.0#/Builtins.pkl"

local format = new Step {
check = "mise run format:check"
Expand All @@ -16,7 +16,7 @@ local typecheck = new Step {
}

local fallow = new Step {
check = "nub exec fallow --config .config/fallow.toml --fail-on-issues --format json --quiet >/dev/null"
check = "mise run lint:fallow:audit >/dev/null"
}

local hygieneSteps = new Mapping<String, Step> {
Expand Down
2 changes: 1 addition & 1 deletion .config/mise/conf.d/_config.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
min_version = "2026.4.18" # required for [deps] (renamed from [prepare])

[tools]
"npm:@nubjs/nub" = "0.7.5"
"npm:@nubjs/nub" = "0.9.6"
node = "lts"
jq = "latest"
vp = "latest"
Expand Down
4 changes: 4 additions & 0 deletions .config/mise/conf.d/tasks-quality.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ run = "mise run //apps/demo:lint:steiger"
description = "Check dead code, duplication, and coverage-aware complexity"
run = [{ tasks = ["lint:fallow:dead-code", "lint:fallow:dupes", "lint:fallow:health"] }]

[tasks."lint:fallow:audit"]
description = "Audit changes against the target/default branch"
run = "bash .config/scripts/fallow-audit.sh"

[tasks."lint:fallow:dead-code"]
description = "Check dead-code findings against the Fallow baseline"
run = "nub exec fallow dead-code --config .config/fallow.toml --fail-on-issues"
Expand Down
25 changes: 25 additions & 0 deletions .config/scripts/fallow-audit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Compare PR changes with the target/default branch, never the feature upstream.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/../.."

base="${FALLOW_AUDIT_BASE:-}"
if [[ -z "$base" && -n "${GITHUB_BASE_REF:-}" ]]; then
base="refs/remotes/origin/${GITHUB_BASE_REF}"
fi

if [[ -z "$base" ]]; then
for candidate in refs/remotes/origin/HEAD refs/remotes/origin/main refs/remotes/origin/master refs/heads/main refs/heads/master; do
if git rev-parse --verify --quiet --end-of-options "${candidate}^{commit}" >/dev/null; then
base="$candidate"
break
fi
done
fi

if [[ -z "$base" ]] || ! git rev-parse --verify --quiet --end-of-options "${base}^{commit}" >/dev/null; then
printf 'No usable Fallow audit base%s. Fetch the target/default branch or set FALLOW_AUDIT_BASE to an available Git ref.\n' "${base:+ ($base)}" >&2
exit 2
fi

exec nub exec fallow audit --base "$base" --config .config/fallow.toml --format json --quiet
6 changes: 3 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup Nub
uses: nubjs/setup-nub@47e5e7393d50f4e9544ddaf756aa277972afba2d # v0
uses: nubjs/setup-nub@c7b970ec04655a2f0a111cd436cc182a3b660e7a # v0.6.0
with:
cache-dependency-path: '**/pnpm-lock.yaml'

- name: Setup mise
uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
install: true
cache: true
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Setup Nub
uses: nubjs/setup-nub@47e5e7393d50f4e9544ddaf756aa277972afba2d # v0
uses: nubjs/setup-nub@c7b970ec04655a2f0a111cd436cc182a3b660e7a # v0.6.0
with:
cache-dependency-path: '**/pnpm-lock.yaml'

- name: Setup mise
uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
install: true
cache: true
Expand All @@ -49,10 +49,10 @@ jobs:
run: mise run //packages/create-karkas:build

- name: Create release PR or publish to npm
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
uses: changesets/action@ae32849d5ba541f9ae29e40e22a623bc13562f51 # v2.1.2
with:
version: nub exec changeset version
publish: nub run release
version-script: nub exec changeset version
publish-script: nub run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
12 changes: 6 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Setup Nub
uses: nubjs/setup-nub@47e5e7393d50f4e9544ddaf756aa277972afba2d # v0
uses: nubjs/setup-nub@c7b970ec04655a2f0a111cd436cc182a3b660e7a # v0.6.0
with:
cache-dependency-path: '**/pnpm-lock.yaml'

- name: Setup mise
uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
uses: jdx/mise-action@2d8d4cafcbd33be2ea37d2b6f5ad595363d1f1ca # v5.1.1
with:
install: true
cache: true
Expand All @@ -38,9 +38,9 @@ jobs:
run: nub ci

- name: Run Fallow audit
uses: fallow-rs/fallow@8c5618273a1c514abede395ba9cc1de37a158425 # v2.83.0
uses: fallow-rs/fallow@fccff887da0d83db1711379e0a3696dfc2460fdd # v3.33.1
with:
version: 2.83.0
version: 3.33.1
command: audit
config: .config/fallow.toml
format: json
Expand All @@ -58,7 +58,7 @@ jobs:
CI: true

- name: Upload coverage reports
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: success()
with:
name: coverage-reports
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ progress*.txt
# vitest browser-mode failure screenshots
__screenshots__/
.vitest-attachments/
.vitest/

# APM dependencies
apm_modules/
Expand Down
6 changes: 3 additions & 3 deletions apm.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ dependencies:
- repo_url: apphane-dev/kahraman
name: kahraman
host: github.com
resolved_commit: fb984ed4c2f3b7bf77414d03526f6353a8f894f5
resolved_ref: v0.3.1
resolved_commit: ca3197939ca7b87ffa3c78fc70e5d8ba5eb018cf
resolved_ref: v0.4.0
version: unknown
package_type: skill_bundle
deployed_files:
- .agents/skills/kahraman-storybook-testing
- .agents/skills/kahraman-storybook-testing/SKILL.md
deployed_file_hashes:
.agents/skills/kahraman-storybook-testing/SKILL.md: sha256:92883384858f07732f62e04b679f7c0d3750beb2c5eac26a4b92da0c7d87c3eb
content_hash: sha256:e271e09b53f348ac1e86e3a4bd9906433a1295ad5d2f043470940f101c6a7220
content_hash: sha256:506d3e418e1e5fe3aa25d4e2cc3e86017b57aa1ed68846b9c23f4f6731f8e95e
- repo_url: cursor/plugins
name: typescript-best-practices
host: github.com
Expand Down
2 changes: 1 addition & 1 deletion apm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 1.0.0
dependencies:
apm:
- reatom/reatom#v1001
- apphane-dev/kahraman#v0.3.1
- apphane-dev/kahraman#v0.4.0
- cursor/plugins/pstack/skills/unslop#main
- cursor/plugins/pstack/skills/typescript-best-practices#main
targets:
Expand Down
15 changes: 9 additions & 6 deletions apps/demo/.storybook/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,15 @@ so manual Storybook rendering is untouched.
- **Abort guard** (`abortErrorGuard.ts`) — the `beforeEach` teardown drains
Reatom `AbortError`s and **throws** if any leaked during a story; the decorator
clears them on unmount. A story that leaks an abort will fail loudly.
- **Diagnostics** — `configureDiagnostics(parameters['kahraman'])` runs in the
existing `beforeEach`, so kahraman's tamed element-not-found output is active
for every story **and** per-story `parameters.kahraman` overrides
(`captureRoleListing`, `maxLength`, a custom `getElementError`) take effect.
Don't reintroduce a module-top `configureDiagnostics()` call — it would ignore
those overrides.
- **Diagnostics** — the kahraman preview addon is registered in
`definePreview.addons` (`kahramanAddon`, typed as
`PreviewAddon<{ parameters: KahramanParameters }>`, which also gives story
files their `meta.story()` / `.test()` typing). The addon's own `beforeEach`
runs `configureDiagnostics` per story, so kahraman's tamed element-not-found
output is active for every story **and** per-story `parameters.kahraman`
overrides (`captureRoleListing`, `maxLength`, a custom `getElementError`)
take effect. Don't reintroduce a module-top `configureDiagnostics()` call —
it would ignore those overrides.

## Scripts

Expand Down
Binary file modified apps/demo/.storybook/abortErrorGuard.ts
Binary file not shown.
16 changes: 11 additions & 5 deletions apps/demo/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import '../src/setup'

import '../src/index.css'

import type { KahramanParameters } from 'kahraman/preview'
import type { PreviewAddon } from 'storybook/internal/csf'

import { reatomContext } from '@reatom/react'
import addonA11y from '@storybook/addon-a11y'
import { definePreview } from '@storybook/react-vite'
import { configureDiagnostics } from 'kahraman/preview'
import kahraman from 'kahraman'
import addonMsw from 'msw-storybook-addon'
import { setupWorker } from 'msw/browser'

Expand Down Expand Up @@ -38,7 +41,7 @@ const nativeHTMLElementFocus = globalThis.HTMLElement
async function setupMswWorker() {
const worker = setupWorker(...handlersArray)
await worker.start({
onUnhandledRequest: 'bypass',
onUnhandledFrame: 'bypass',
quiet: true,
serviceWorker: {
url: `${import.meta.env['BASE_URL']}mockServiceWorker.js`,
Expand Down Expand Up @@ -70,13 +73,17 @@ function ReatomDecorator({
clearAbortErrors()
queueMicrotask(clearAbortErrors)
}
// oxlint-disable-next-line react/exhaustive-effect-dependencies -- the cleanup must run when the frame is replaced
}, [frame])

return <reatomContext.Provider value={frame}>{children}</reatomContext.Provider>
}

// Name the addon's public parameter type for TypeScript composite-project inference.
const kahramanAddon: PreviewAddon<{ parameters: KahramanParameters }> = kahraman()

const preview = definePreview({
addons: [addonA11y(), addonMsw(setupMswWorker)],
addons: [addonA11y(), addonMsw(setupMswWorker), kahramanAddon],
decorators: [
(Story, { parameters }) => (
<ReatomDecorator
Expand All @@ -96,15 +103,14 @@ const preview = definePreview({
a11y: { test: 'todo' },
},
// fallow-ignore-next-line complexity
beforeEach: async ({ globals, parameters }) => {
beforeEach: async ({ globals }) => {
// Run before a story mounts, so Zag observes the native focus method.
if (nativeHTMLElementFocus) {
Object.defineProperty(HTMLElement.prototype, 'focus', {
configurable: true,
value: nativeHTMLElementFocus,
})
}
configureDiagnostics(parameters['kahraman'])
clearAbortErrors()
if (!(globalThis as Record<string, unknown>)['__vitest_worker__']) return
const { page } = await import('vite-plus/test/browser')
Expand Down
3 changes: 2 additions & 1 deletion apps/demo/mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ run = "nub exec vp test run"

[tasks."test:coverage"]
description = "Run tests with coverage"
env = { NODE_OPTIONS = "--max-old-space-size=1024" }
run = "nub exec vp test run --coverage --maxWorkers 1"

[tasks.format]
Expand All @@ -153,7 +154,7 @@ run = "nub exec vp lint --fix"

[tasks.typecheck]
description = "Type check demo with TypeScript 7"
run = "nub exec tsc -b"
run = "nub {{ vars.repo_root }}/node_modules/@typescript/native/bin/tsc -b"

[tasks."lint:steiger"]
description = "Check demo FSD architecture with steiger"
Expand Down
60 changes: 31 additions & 29 deletions apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,51 +31,53 @@
"validate": "mise run validate"
},
"dependencies": {
"@ark-ui/react": "5.38.1",
"@ark-ui/react": "5.39.3",
"@icons-pack/react-simple-icons": "^13.15.1",
"@reatom/core": "^1001.3.0",
"@reatom/react": "^1001.0.1",
"idb-keyval": "^6.3.0",
"kahraman": "^0.3.1",
"lucide-react": "^1.41.0",
"msw": "2.15.0",
"react": "^19.2.8",
"react-dom": "^19.2.8"
"kahraman": "^0.4.0",
"lucide-react": "^1.56.0",
"msw": "3.0.3",
"react": "^19.3.0",
"react-dom": "^19.3.0"
},
"devDependencies": {
"@feature-sliced/steiger-plugin": "^0.7.0",
"@inlang/paraglide-js": "^2.25.0",
"@pandacss/dev": "^1.12.1",
"@pandacss/studio": "^1.12.1",
"@storybook/addon-a11y": "~10.6.0",
"@storybook/addon-docs": "~10.6.0",
"@storybook/addon-vitest": "~10.6.0",
"@storybook/react-vite": "~10.6.0",
"@feature-sliced/steiger-plugin": "^0.8.0",
"@inlang/paraglide-js": "^2.27.0",
"@pandacss/dev": "^2.2.0",
"@pandacss/preset-base": "^2.2.0",
"@pandacss/preset-panda": "^2.2.0",
"@storybook/addon-a11y": "~10.6.2",
"@storybook/addon-docs": "~10.6.2",
"@storybook/addon-vitest": "~10.6.2",
"@storybook/react": "~10.6.2",
"@storybook/react-vite": "~10.6.2",
"@total-typescript/ts-reset": "^0.6.1",
"@types/react": "^19.2.18",
"@types/react-dom": "19.2.7",
"@types/react": "^19.3.0",
"@types/react-dom": "19.3.0",
"@typescript/native": "npm:typescript@^7.0.2",
"@vitejs/plugin-react": "^6.1.1",
"@vitest/browser-playwright": "4.1.11",
"@vitest/coverage-v8": "4.1.11",
"fallow": "^3.22.0",
"msw-storybook-addon": "^3.0.0",
"playwright": "^1.63.0",
"steiger": "^0.6.0",
"storybook": "~10.6.0",
"@vitejs/plugin-react": "^6.1.2",
"@vitest/browser-playwright": "5.0.3",
"@vitest/coverage-v8": "5.0.3",
"fallow": "^3.33.1",
"msw-storybook-addon": "^3.0.3",
"playwright": "^1.64.0",
"steiger": "^0.7.0",
"storybook": "~10.6.2",
"typescript": "npm:@typescript/typescript6@^6.0.2",
"vite": "^8.2.2",
"vite-plus": "^0.3.0",
"vitest": "4.1.11"
"vite": "npm:@voidzero-dev/vite-plus-core@^1.1.0",
"vite-plus": "^1.1.0",
"vitest": "5.0.3"
},
"devEngines": {
"packageManager": {
"name": "nub",
"version": "^0.7.5",
"version": "^0.9.6",
"onFail": "warn"
}
},
"packageManager": "nub@0.7.5",
"packageManager": "nub@0.9.6",
"msw": {
"workerDirectory": [
"public"
Expand Down
1 change: 1 addition & 0 deletions apps/demo/panda.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ assert(outdir, 'PANDA_OUTDIR env var is not set')

export default defineConfig({
jsxFramework: 'react',
presets: ['@pandacss/preset-base', '@pandacss/preset-panda'],
// Whether to use css reset
preflight: true,

Expand Down
Loading
Loading