diff --git a/.changeset/use-ultracite-for-new-app-scripts.md b/.changeset/use-ultracite-for-new-app-scripts.md new file mode 100644 index 00000000..a78dab88 --- /dev/null +++ b/.changeset/use-ultracite-for-new-app-scripts.md @@ -0,0 +1,5 @@ +--- +"@proofkit/cli": patch +--- + +Update newly scaffolded apps to use Ultracite for linting and formatting by default, including the generated `lint` and `format` scripts and CLI formatting flow. diff --git a/.codex/environments/environment-2.toml b/.codex/environments/environment-2.toml new file mode 100644 index 00000000..ab328037 --- /dev/null +++ b/.codex/environments/environment-2.toml @@ -0,0 +1,11 @@ +# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY +version = 1 +name = "proofkit" + +[setup] +script = "" + +[[actions]] +name = "Run" +icon = "run" +command = "pnpm i" diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml new file mode 100644 index 00000000..ab328037 --- /dev/null +++ b/.codex/environments/environment.toml @@ -0,0 +1,11 @@ +# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY +version = 1 +name = "proofkit" + +[setup] +script = "" + +[[actions]] +name = "Run" +icon = "run" +command = "pnpm i" diff --git a/packages/better-auth/bin/intent.js b/packages/better-auth/bin/intent.js index 2cf2efab..1b21b8f6 100644 --- a/packages/better-auth/bin/intent.js +++ b/packages/better-auth/bin/intent.js @@ -4,17 +4,17 @@ // Commit this file, then add to your package.json: // "bin": { "intent": "./bin/intent.js" } try { - await import('@tanstack/intent/intent-library') + await import("@tanstack/intent/intent-library"); } catch (e) { - if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') { - console.error('@tanstack/intent is not installed.') - console.error('') - console.error('Install it as a dev dependency:') - console.error(' npm add -D @tanstack/intent') - console.error('') - console.error('Or run directly:') - console.error(' npx @tanstack/intent@latest list') - process.exit(1) + if (e?.code === "ERR_MODULE_NOT_FOUND" || e?.code === "MODULE_NOT_FOUND") { + console.error("@tanstack/intent is not installed."); + console.error(""); + console.error("Install it as a dev dependency:"); + console.error(" npm add -D @tanstack/intent"); + console.error(""); + console.error("Or run directly:"); + console.error(" npx @tanstack/intent@latest list"); + process.exit(1); } - throw e + throw e; } diff --git a/packages/cli/src/helpers/createProject.ts b/packages/cli/src/helpers/createProject.ts index cb354d95..a7dc2f6b 100644 --- a/packages/cli/src/helpers/createProject.ts +++ b/packages/cli/src/helpers/createProject.ts @@ -68,8 +68,8 @@ export const createBareProject = async ({ "tw-animate-css", "zod", ] as AvailableDependencies[]; - const SHADCN_BASE_DEV_DEPS = [] as AvailableDependencies[]; - const VITE_SHADCN_BASE_DEV_DEPS = ["@proofkit/typegen"] as AvailableDependencies[]; + const SHADCN_BASE_DEV_DEPS = ["ultracite"] as AvailableDependencies[]; + const VITE_SHADCN_BASE_DEV_DEPS = ["@proofkit/typegen", "ultracite"] as AvailableDependencies[]; const MANTINE_DEPS = [ "@mantine/core", @@ -79,7 +79,12 @@ export const createBareProject = async ({ "@mantine/notifications", "mantine-react-table", ] as AvailableDependencies[]; - const MANTINE_DEV_DEPS = ["postcss", "postcss-preset-mantine", "postcss-simple-vars"] as AvailableDependencies[]; + const MANTINE_DEV_DEPS = [ + "postcss", + "postcss-preset-mantine", + "postcss-simple-vars", + "ultracite", + ] as AvailableDependencies[]; if (state.ui === "mantine") { addPackageDependency({ @@ -124,6 +129,7 @@ export const createBareProject = async ({ } replaceTextInFiles(state.projectDir, "__PNPM_COMMAND__", pkgManagerCommand); + replaceTextInFiles(state.projectDir, "__PACKAGE_MANAGER__", pkgManager); return state.projectDir; }; diff --git a/packages/cli/src/installers/dependencyVersionMap.ts b/packages/cli/src/installers/dependencyVersionMap.ts index c5b53268..07beb009 100644 --- a/packages/cli/src/installers/dependencyVersionMap.ts +++ b/packages/cli/src/installers/dependencyVersionMap.ts @@ -102,6 +102,9 @@ export const dependencyVersionMap = { // Theme utilities "next-themes": "^0.4.6", + // Linting and formatting + ultracite: "^7.0.8", + // Zod zod: "^4", } as const; diff --git a/packages/cli/src/utils/formatting.ts b/packages/cli/src/utils/formatting.ts index 8522e45a..2c491be8 100644 --- a/packages/cli/src/utils/formatting.ts +++ b/packages/cli/src/utils/formatting.ts @@ -4,19 +4,19 @@ import type { Project } from "ts-morph"; import { state } from "~/state.js"; /** - * Formats all source files in a ts-morph Project using biome and saves the changes. + * Formats all source files in a ts-morph Project using ultracite and saves the changes. * @param project The ts-morph Project containing the files to format */ export async function formatAndSaveSourceFiles(project: Project) { await project.save(); // save files first try { - // Run biome format on the project directory - await execa("npx", ["@biomejs/biome", "format", "--write", state.projectDir], { + // Run ultracite fix on the project directory + await execa("npx", ["ultracite", "fix", "."], { cwd: state.projectDir, }); } catch (error) { if (state.debug) { - console.log("Error formatting files with biome"); + console.log("Error formatting files with ultracite"); console.error(error); } // Continue even if formatting fails diff --git a/packages/cli/template/nextjs-mantine/package.json b/packages/cli/template/nextjs-mantine/package.json index 31fad730..bfd349b2 100644 --- a/packages/cli/template/nextjs-mantine/package.json +++ b/packages/cli/template/nextjs-mantine/package.json @@ -6,8 +6,8 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "lint": "biome check", - "format": "biome format --write", + "lint": "ultracite check .", + "format": "ultracite fix .", "proofkit": "proofkit", "typegen": "proofkit typegen", "deploy": "proofkit deploy" @@ -35,7 +35,6 @@ "@types/node": "^20", "@types/react": "npm:types-react@19.0.12", "@types/react-dom": "npm:types-react-dom@19.0.4", - "@biomejs/biome": "2.3.11", "postcss": "^8.4.41", "ultracite": "7.0.8", "postcss-preset-mantine": "^1.17.0", diff --git a/packages/cli/template/nextjs-shadcn/package.json b/packages/cli/template/nextjs-shadcn/package.json index a61be86e..eca155fe 100644 --- a/packages/cli/template/nextjs-shadcn/package.json +++ b/packages/cli/template/nextjs-shadcn/package.json @@ -7,8 +7,8 @@ "build": "next build --turbopack", "proofkit": "proofkit", "start": "next start", - "lint": "biome check", - "format": "biome format --write" + "lint": "ultracite check .", + "format": "ultracite fix ." }, "dependencies": { "@radix-ui/react-slot": "^1.2.3", @@ -25,7 +25,6 @@ "tailwind-merge": "^3.3.1" }, "devDependencies": { - "@biomejs/biome": "2.3.11", "@tailwindcss/postcss": "^4", "@types/node": "^22", "@types/react": "^19", @@ -33,6 +32,6 @@ "tailwindcss": "^4", "tw-animate-css": "^1.3.7", "typescript": "^5", - "ultracite": "5.4.5" + "ultracite": "7.0.8" } } diff --git a/packages/cli/template/vite-wv/.claude/launch.json b/packages/cli/template/vite-wv/.claude/launch.json new file mode 100644 index 00000000..469bea0f --- /dev/null +++ b/packages/cli/template/vite-wv/.claude/launch.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Preview", + "runtimeExecutable": "__PACKAGE_MANAGER__", + "runtimeArgs": ["run", "dev"], + "cwd": "${workspaceFolder}", + "autoPort": true, + "port": 5175 + }, + { + "name": "Typegen", + "runtimeExecutable": "__PACKAGE_MANAGER__", + "runtimeArgs": ["run", "typegen"], + "cwd": "${workspaceFolder}" + } + ] +} diff --git a/packages/cli/template/vite-wv/package.json b/packages/cli/template/vite-wv/package.json index 786ef5b7..13a1ee7e 100644 --- a/packages/cli/template/vite-wv/package.json +++ b/packages/cli/template/vite-wv/package.json @@ -14,15 +14,16 @@ "typegen": "typegen", "typegen:ui": "typegen ui", "upload": "node ./scripts/upload.js", - "lint": "biome check .", - "format": "biome format --write ." + "lint": "ultracite check .", + "format": "ultracite fix ." }, "dependencies": { + "@tanstack/react-query": "^5.90.21", + "@tanstack/react-router": "^1.167.4", "react": "^19.2.4", "react-dom": "^19.2.4" }, "devDependencies": { - "@biomejs/biome": "2.4.7", "@proofkit/typegen": "^1.1.0-beta.16", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", @@ -30,6 +31,7 @@ "dotenv": "^17.3.1", "open": "^11.0.0", "typescript": "^5.9.3", + "ultracite": "7.0.8", "vite": "^7.3.1", "vite-plugin-singlefile": "^2.3.2" } diff --git a/packages/cli/template/vite-wv/src/App.tsx b/packages/cli/template/vite-wv/src/App.tsx index 7b96455e..b7b39848 100644 --- a/packages/cli/template/vite-wv/src/App.tsx +++ b/packages/cli/template/vite-wv/src/App.tsx @@ -30,7 +30,7 @@ const steps: readonly Step[] = [ export default function App() { return ( -
+
@@ -48,7 +48,7 @@ export default function App() {

This starter stays intentionally small, but it is already ready for Tailwind v4, shadcn component - installs, and later ProofKit typegen output. + installs, hash-based TanStack Router navigation, React Query, and later ProofKit typegen output.

diff --git a/packages/cli/template/vite-wv/src/main.tsx b/packages/cli/template/vite-wv/src/main.tsx index 71199209..f61aedf6 100644 --- a/packages/cli/template/vite-wv/src/main.tsx +++ b/packages/cli/template/vite-wv/src/main.tsx @@ -1,7 +1,11 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { RouterProvider } from "@tanstack/react-router"; import React from "react"; import ReactDOM from "react-dom/client"; -import App from "./App"; import "./index.css"; +import { router } from "./router"; + +const queryClient = new QueryClient(); const rootElement = document.getElementById("root"); if (!rootElement) { @@ -10,6 +14,8 @@ if (!rootElement) { ReactDOM.createRoot(rootElement).render( - + + + , ); diff --git a/packages/cli/template/vite-wv/src/router.tsx b/packages/cli/template/vite-wv/src/router.tsx new file mode 100644 index 00000000..d21c9dbe --- /dev/null +++ b/packages/cli/template/vite-wv/src/router.tsx @@ -0,0 +1,57 @@ +import { + Link, + Outlet, + createHashHistory, + createRootRoute, + createRoute, + createRouter, +} from "@tanstack/react-router"; +import App from "./App"; +import { QueryDemoPage } from "./routes/query-demo"; + +const rootRoute = createRootRoute({ + component: RootLayout, +}); + +const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: "/", + component: App, +}); + +const queryDemoRoute = createRoute({ + getParentRoute: () => rootRoute, + path: "/query", + component: QueryDemoPage, +}); + +const routeTree = rootRoute.addChildren([indexRoute, queryDemoRoute]); + +export const router = createRouter({ + routeTree, + history: createHashHistory(), +}); + +declare module "@tanstack/react-router" { + interface Register { + router: typeof router; + } +} + +function RootLayout() { + return ( +
+
+ +
+ +
+ ); +} diff --git a/packages/cli/template/vite-wv/src/routes/query-demo.tsx b/packages/cli/template/vite-wv/src/routes/query-demo.tsx new file mode 100644 index 00000000..833e629c --- /dev/null +++ b/packages/cli/template/vite-wv/src/routes/query-demo.tsx @@ -0,0 +1,37 @@ +import { useQuery } from "@tanstack/react-query"; +import { Link } from "@tanstack/react-router"; + +const getConnectionHint = async (): Promise => { + await new Promise((resolve) => setTimeout(resolve, 180)); + return "Use fmFetch or generated clients once your FileMaker file is ready."; +}; + +export function QueryDemoPage() { + const hintQuery = useQuery({ + queryKey: ["starter-connection-hint"], + queryFn: getConnectionHint, + }); + + return ( +
+
+

React Query ready

+

TanStack Query is preconfigured

+

+ This route is rendered by TanStack Router using hash history, which is recommended for FileMaker WebViewer + apps. +

+ +
+ {hintQuery.isLoading ? "Loading starter data..." : hintQuery.data} +
+ +
+ + Back to starter + +
+
+
+ ); +} diff --git a/packages/fmdapi/bin/intent.js b/packages/fmdapi/bin/intent.js index 2cf2efab..1b21b8f6 100644 --- a/packages/fmdapi/bin/intent.js +++ b/packages/fmdapi/bin/intent.js @@ -4,17 +4,17 @@ // Commit this file, then add to your package.json: // "bin": { "intent": "./bin/intent.js" } try { - await import('@tanstack/intent/intent-library') + await import("@tanstack/intent/intent-library"); } catch (e) { - if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') { - console.error('@tanstack/intent is not installed.') - console.error('') - console.error('Install it as a dev dependency:') - console.error(' npm add -D @tanstack/intent') - console.error('') - console.error('Or run directly:') - console.error(' npx @tanstack/intent@latest list') - process.exit(1) + if (e?.code === "ERR_MODULE_NOT_FOUND" || e?.code === "MODULE_NOT_FOUND") { + console.error("@tanstack/intent is not installed."); + console.error(""); + console.error("Install it as a dev dependency:"); + console.error(" npm add -D @tanstack/intent"); + console.error(""); + console.error("Or run directly:"); + console.error(" npx @tanstack/intent@latest list"); + process.exit(1); } - throw e + throw e; } diff --git a/packages/fmodata/src/cli/commands/query.ts b/packages/fmodata/src/cli/commands/query.ts index 413f3daa..476c1447 100644 --- a/packages/fmodata/src/cli/commands/query.ts +++ b/packages/fmodata/src/cli/commands/query.ts @@ -117,7 +117,13 @@ export function makeRecordsCommand(): Command { try { if (!(opts.where || opts.confirm)) { printResult( - { dryRun: true, action: "update", table: opts.table, affectsAllRows: true, hint: "Add --where to filter or --confirm to update all records" }, + { + dryRun: true, + action: "update", + table: opts.table, + affectsAllRows: true, + hint: "Add --where to filter or --confirm to update all records", + }, { pretty: globalOpts.pretty ?? false }, ); return; @@ -159,7 +165,13 @@ export function makeRecordsCommand(): Command { try { if (!(opts.where || opts.confirm)) { printResult( - { dryRun: true, action: "delete", table: opts.table, affectsAllRows: true, hint: "Add --where to filter or --confirm to delete all records" }, + { + dryRun: true, + action: "delete", + table: opts.table, + affectsAllRows: true, + hint: "Add --where to filter or --confirm to delete all records", + }, { pretty: globalOpts.pretty ?? false }, ); return; diff --git a/packages/webviewer/bin/intent.js b/packages/webviewer/bin/intent.js index 2cf2efab..1b21b8f6 100755 --- a/packages/webviewer/bin/intent.js +++ b/packages/webviewer/bin/intent.js @@ -4,17 +4,17 @@ // Commit this file, then add to your package.json: // "bin": { "intent": "./bin/intent.js" } try { - await import('@tanstack/intent/intent-library') + await import("@tanstack/intent/intent-library"); } catch (e) { - if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') { - console.error('@tanstack/intent is not installed.') - console.error('') - console.error('Install it as a dev dependency:') - console.error(' npm add -D @tanstack/intent') - console.error('') - console.error('Or run directly:') - console.error(' npx @tanstack/intent@latest list') - process.exit(1) + if (e?.code === "ERR_MODULE_NOT_FOUND" || e?.code === "MODULE_NOT_FOUND") { + console.error("@tanstack/intent is not installed."); + console.error(""); + console.error("Install it as a dev dependency:"); + console.error(" npm add -D @tanstack/intent"); + console.error(""); + console.error("Or run directly:"); + console.error(" npx @tanstack/intent@latest list"); + process.exit(1); } - throw e + throw e; }