create-better-t-stack 3.14.1 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +1 -1
- package/dist/{src-CSz9J82Z.mjs → src-CGRVv8L3.mjs} +44 -11
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Follow the prompts to configure your project or use the `--yes` flag for default
|
|
|
41
41
|
| **Database Setup** | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup) |
|
|
42
42
|
| **Authentication** | Better-Auth (email/password, with more options coming soon) |
|
|
43
43
|
| **Styling** | Tailwind CSS with shadcn/ui components |
|
|
44
|
-
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Starlight (documentation site)<br>• Biome (linting and formatting)<br>• Husky (Git hooks)<br>• Turborepo (optimized builds)
|
|
44
|
+
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Starlight (documentation site)<br>• Biome (linting and formatting)<br>• Lefthook, Husky (Git hooks)<br>• Turborepo (optimized builds) |
|
|
45
45
|
| **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
|
|
46
46
|
| **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation |
|
|
47
47
|
|
|
@@ -58,7 +58,7 @@ Options:
|
|
|
58
58
|
--auth Include authentication
|
|
59
59
|
--no-auth Exclude authentication
|
|
60
60
|
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, native-bare, native-uniwind, native-unistyles, none)
|
|
61
|
-
--addons <types...> Additional addons (pwa, tauri, starlight, biome, husky, turborepo, fumadocs, ultracite, oxlint, none)
|
|
61
|
+
--addons <types...> Additional addons (pwa, tauri, starlight, biome, lefthook, husky, turborepo, fumadocs, ultracite, oxlint, none)
|
|
62
62
|
--examples <types...> Examples to include (todo, ai, none)
|
|
63
63
|
--git Initialize git repository
|
|
64
64
|
--no-git Skip git initialization
|
|
@@ -193,7 +193,7 @@ npx create-better-t-stack --frontend none --backend hono --api trpc --database n
|
|
|
193
193
|
- **ORM 'none'**: Can be used when you want to handle database operations manually or use a different ORM.
|
|
194
194
|
- **Runtime 'none'**: Only available with Convex backend or when backend is 'none'.
|
|
195
195
|
- **Cloudflare Workers runtime**: Only compatible with Hono backend, Drizzle ORM (or no ORM), and SQLite database (with D1 setup). Not compatible with MongoDB.
|
|
196
|
-
- **Addons 'none'**: Skips all addons (PWA, Tauri, Starlight, Biome, Husky, Turborepo).
|
|
196
|
+
- **Addons 'none'**: Skips all addons (PWA, Tauri, Starlight, Biome, Lefthook,Husky, Turborepo).
|
|
197
197
|
- **Examples 'none'**: Skips all example implementations (todo, AI chat).
|
|
198
198
|
- **SvelteKit, Nuxt, and SolidJS** frontends are only compatible with oRPC API layer
|
|
199
199
|
- **PWA support** requires React with TanStack Router, React Router, or SolidJS
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -62,6 +62,7 @@ declare const router: {
|
|
|
62
62
|
tauri: "tauri";
|
|
63
63
|
starlight: "starlight";
|
|
64
64
|
biome: "biome";
|
|
65
|
+
lefthook: "lefthook";
|
|
65
66
|
husky: "husky";
|
|
66
67
|
ruler: "ruler";
|
|
67
68
|
turborepo: "turborepo";
|
|
@@ -142,7 +143,7 @@ declare const router: {
|
|
|
142
143
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self";
|
|
143
144
|
runtime: "none" | "bun" | "node" | "workers";
|
|
144
145
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid")[];
|
|
145
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt")[];
|
|
146
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt")[];
|
|
146
147
|
examples: ("none" | "todo" | "ai")[];
|
|
147
148
|
auth: "none" | "better-auth" | "clerk";
|
|
148
149
|
payments: "none" | "polar";
|
|
@@ -180,7 +181,7 @@ declare const router: {
|
|
|
180
181
|
backend: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self";
|
|
181
182
|
runtime: "none" | "bun" | "node" | "workers";
|
|
182
183
|
frontend: ("none" | "tanstack-router" | "react-router" | "tanstack-start" | "next" | "nuxt" | "native-bare" | "native-uniwind" | "native-unistyles" | "svelte" | "solid")[];
|
|
183
|
-
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt")[];
|
|
184
|
+
addons: ("none" | "pwa" | "tauri" | "starlight" | "biome" | "lefthook" | "husky" | "ruler" | "turborepo" | "fumadocs" | "ultracite" | "oxlint" | "opentui" | "wxt")[];
|
|
184
185
|
examples: ("none" | "todo" | "ai")[];
|
|
185
186
|
auth: "none" | "better-auth" | "clerk";
|
|
186
187
|
payments: "none" | "polar";
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-
|
|
2
|
+
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-CGRVv8L3.mjs";
|
|
3
3
|
|
|
4
4
|
export { EMBEDDED_TEMPLATES, TEMPLATE_COUNT, VirtualFileSystem, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, router, sponsors };
|
|
@@ -79,6 +79,7 @@ const ADDON_COMPATIBILITY = {
|
|
|
79
79
|
],
|
|
80
80
|
biome: [],
|
|
81
81
|
husky: [],
|
|
82
|
+
lefthook: [],
|
|
82
83
|
turborepo: [],
|
|
83
84
|
starlight: [],
|
|
84
85
|
ultracite: [],
|
|
@@ -584,6 +585,10 @@ function getAddonDisplay(addon) {
|
|
|
584
585
|
label = "Ruler";
|
|
585
586
|
hint = "Centralize your AI rules";
|
|
586
587
|
break;
|
|
588
|
+
case "lefthook":
|
|
589
|
+
label = "Lefthook";
|
|
590
|
+
hint = "Fast and powerful Git hooks manager";
|
|
591
|
+
break;
|
|
587
592
|
case "husky":
|
|
588
593
|
label = "Husky";
|
|
589
594
|
hint = "Modern native Git hooks made easy";
|
|
@@ -619,7 +624,8 @@ const ADDON_GROUPS = {
|
|
|
619
624
|
"biome",
|
|
620
625
|
"oxlint",
|
|
621
626
|
"ultracite",
|
|
622
|
-
"husky"
|
|
627
|
+
"husky",
|
|
628
|
+
"lefthook"
|
|
623
629
|
],
|
|
624
630
|
Documentation: ["starlight", "fumadocs"],
|
|
625
631
|
Extensions: [
|
|
@@ -2553,11 +2559,15 @@ const AGENTS = {
|
|
|
2553
2559
|
crush: { label: "Crush" },
|
|
2554
2560
|
qwen: { label: "Qwen" },
|
|
2555
2561
|
"amazon-q-cli": { label: "Amazon Q CLI" },
|
|
2556
|
-
firebender: { label: "Firebender" }
|
|
2562
|
+
firebender: { label: "Firebender" },
|
|
2563
|
+
"cursor-cli": { label: "Cursor CLI" },
|
|
2564
|
+
"mistral-vibe": { label: "Mistral Vibe" },
|
|
2565
|
+
vercel: { label: "Vercel" }
|
|
2557
2566
|
};
|
|
2558
2567
|
const HOOKS = {
|
|
2559
2568
|
cursor: { label: "Cursor" },
|
|
2560
|
-
windsurf: { label: "Windsurf" }
|
|
2569
|
+
windsurf: { label: "Windsurf" },
|
|
2570
|
+
claude: { label: "Claude" }
|
|
2561
2571
|
};
|
|
2562
2572
|
function getFrameworksFromFrontend(frontend) {
|
|
2563
2573
|
const frameworkMap = {
|
|
@@ -2576,7 +2586,7 @@ function getFrameworksFromFrontend(frontend) {
|
|
|
2576
2586
|
for (const f of frontend) if (f !== "none" && frameworkMap[f]) frameworks.add(frameworkMap[f]);
|
|
2577
2587
|
return Array.from(frameworks);
|
|
2578
2588
|
}
|
|
2579
|
-
async function setupUltracite(config,
|
|
2589
|
+
async function setupUltracite(config, gitHooks) {
|
|
2580
2590
|
const { packageManager, projectDir, frontend } = config;
|
|
2581
2591
|
try {
|
|
2582
2592
|
log.info("Setting up Ultracite...");
|
|
@@ -2632,7 +2642,11 @@ async function setupUltracite(config, hasHusky) {
|
|
|
2632
2642
|
if (editors.length > 0) ultraciteArgs.push("--editors", ...editors);
|
|
2633
2643
|
if (agents.length > 0) ultraciteArgs.push("--agents", ...agents);
|
|
2634
2644
|
if (hooks.length > 0) ultraciteArgs.push("--hooks", ...hooks);
|
|
2635
|
-
if (
|
|
2645
|
+
if (gitHooks.length > 0) {
|
|
2646
|
+
const integrations = [...gitHooks];
|
|
2647
|
+
if (gitHooks.includes("husky")) integrations.push("lint-staged");
|
|
2648
|
+
ultraciteArgs.push("--integrations", ...integrations);
|
|
2649
|
+
}
|
|
2636
2650
|
const args = getPackageExecutionArgs(packageManager, `ultracite@latest ${ultraciteArgs.join(" ")} --skip-install`);
|
|
2637
2651
|
const s = spinner();
|
|
2638
2652
|
s.start("Running Ultracite init command...");
|
|
@@ -2722,22 +2736,28 @@ async function setupAddons(config) {
|
|
|
2722
2736
|
const hasUltracite = addons.includes("ultracite");
|
|
2723
2737
|
const hasBiome = addons.includes("biome");
|
|
2724
2738
|
const hasHusky = addons.includes("husky");
|
|
2739
|
+
const hasLefthook = addons.includes("lefthook");
|
|
2725
2740
|
const hasOxlint = addons.includes("oxlint");
|
|
2726
|
-
if (
|
|
2741
|
+
if (hasUltracite) {
|
|
2742
|
+
const gitHooks = [];
|
|
2743
|
+
if (hasHusky) gitHooks.push("husky");
|
|
2744
|
+
if (hasLefthook) gitHooks.push("lefthook");
|
|
2745
|
+
await setupUltracite(config, gitHooks);
|
|
2746
|
+
} else {
|
|
2727
2747
|
if (hasBiome) await setupBiome(projectDir);
|
|
2728
2748
|
if (hasOxlint) await setupOxlint(projectDir, config.packageManager);
|
|
2729
|
-
if (hasHusky) {
|
|
2749
|
+
if (hasHusky || hasLefthook) {
|
|
2730
2750
|
let linter;
|
|
2731
2751
|
if (hasOxlint) linter = "oxlint";
|
|
2732
2752
|
else if (hasBiome) linter = "biome";
|
|
2733
|
-
await setupHusky(projectDir, linter);
|
|
2753
|
+
if (hasHusky) await setupHusky(projectDir, linter);
|
|
2754
|
+
if (hasLefthook) await setupLefthook(projectDir);
|
|
2734
2755
|
}
|
|
2735
2756
|
}
|
|
2736
2757
|
if (addons.includes("starlight")) await setupStarlight(config);
|
|
2737
2758
|
if (addons.includes("fumadocs")) await setupFumadocs(config);
|
|
2738
2759
|
if (addons.includes("opentui")) await setupTui(config);
|
|
2739
2760
|
if (addons.includes("wxt")) await setupWxt(config);
|
|
2740
|
-
if (hasUltracite) await setupUltracite(config, hasHusky);
|
|
2741
2761
|
if (addons.includes("ruler")) await setupRuler(config);
|
|
2742
2762
|
}
|
|
2743
2763
|
async function setupBiome(projectDir) {
|
|
@@ -2773,6 +2793,12 @@ async function setupHusky(projectDir, linter) {
|
|
|
2773
2793
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
2774
2794
|
}
|
|
2775
2795
|
}
|
|
2796
|
+
async function setupLefthook(projectDir) {
|
|
2797
|
+
await addPackageDependency({
|
|
2798
|
+
devDependencies: ["lefthook"],
|
|
2799
|
+
projectDir
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2776
2802
|
|
|
2777
2803
|
//#endregion
|
|
2778
2804
|
//#region src/utils/env-utils.ts
|
|
@@ -3851,11 +3877,13 @@ async function displayPostInstallInstructions(config) {
|
|
|
3851
3877
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
|
|
3852
3878
|
const cdCmd = `cd ${relativePath}`;
|
|
3853
3879
|
const hasHusky = addons?.includes("husky");
|
|
3854
|
-
const
|
|
3880
|
+
const hasLefthook = addons?.includes("lefthook");
|
|
3881
|
+
const hasGitHooksOrLinting = addons?.includes("husky") || addons?.includes("biome") || addons?.includes("lefthook") || addons?.includes("oxlint");
|
|
3855
3882
|
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
|
|
3856
3883
|
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
3857
3884
|
const huskyInstructions = hasHusky ? getHuskyInstructions(runCmd) : "";
|
|
3858
|
-
const
|
|
3885
|
+
const lefthookInstructions = hasLefthook ? getLefthookInstructions(packageManager) : "";
|
|
3886
|
+
const lintingInstructions = hasGitHooksOrLinting ? getLintingInstructions(runCmd) : "";
|
|
3859
3887
|
const nativeInstructions = (frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles")) && backend !== "none" ? getNativeInstructions(isConvex, isBackendSelf, frontend || [], runCmd) : "";
|
|
3860
3888
|
const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
|
|
3861
3889
|
const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
|
|
@@ -3910,6 +3938,7 @@ async function displayPostInstallInstructions(config) {
|
|
|
3910
3938
|
if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
|
|
3911
3939
|
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
|
|
3912
3940
|
if (huskyInstructions) output += `\n${huskyInstructions.trim()}\n`;
|
|
3941
|
+
if (lefthookInstructions) output += `\n${lefthookInstructions.trim()}\n`;
|
|
3913
3942
|
if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
|
|
3914
3943
|
if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
|
|
3915
3944
|
if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
|
|
@@ -3938,6 +3967,10 @@ function getHuskyInstructions(runCmd) {
|
|
|
3938
3967
|
function getLintingInstructions(runCmd) {
|
|
3939
3968
|
return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
|
|
3940
3969
|
}
|
|
3970
|
+
function getLefthookInstructions(packageManager) {
|
|
3971
|
+
const cmd = packageManager === "npm" ? "npx" : packageManager;
|
|
3972
|
+
return `${pc.bold("Git hooks with Lefthook:")}\n${pc.cyan("•")} Install hooks: ${cmd} lefthook install\n`;
|
|
3973
|
+
}
|
|
3941
3974
|
async function getDatabaseInstructions(database, orm, runCmd, _runtime, dbSetup, serverDeploy, _backend) {
|
|
3942
3975
|
const instructions = [];
|
|
3943
3976
|
if (dbSetup === "docker") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-t-stack/template-generator": "^3.
|
|
74
|
-
"@better-t-stack/types": "^3.
|
|
73
|
+
"@better-t-stack/template-generator": "^3.15.0",
|
|
74
|
+
"@better-t-stack/types": "^3.15.0",
|
|
75
75
|
"@clack/core": "^0.5.0",
|
|
76
76
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
77
77
|
"@orpc/server": "^1.13.0",
|