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
1,167 changes: 596 additions & 571 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

130 changes: 83 additions & 47 deletions src/lib/command-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function validateSelections(selections: Set<string>): string[] {
);
}

const routers = ["tanstack-router", "react-router"];
const routers = ["tanstack", "react-router"];
const selectedRouters = routers.filter((router) => selections.has(router));
if (selectedRouters.length > 1) {
warnings.push(
Expand All @@ -48,8 +48,7 @@ const FRAMEWORKS_WITH_TAILWIND = [
"nextjs",
"expo-uniwind",
"shadcn",
"tanstack-router",
"tanstack-start",
"tanstack",
"react-router",
"astro",
"svelte",
Expand Down Expand Up @@ -160,24 +159,41 @@ export function generateCommands(
description: description,
});
needsSeparateCd = true;
} else if (selections.has("tanstack-start")) {
steps.push({
label: "Create TanStack Start project",
command: `${pmx} create-tanstack-app@latest ${projectName}`,
description: "Initialize a new TanStack Start project",
});
needsSeparateCd = true;
} else if (selections.has("tanstack-router")) {
const viteTemplate = selections.has("typescript") ? "react-ts" : "react";
} else if (selections.has("tanstack")) {
let tanstackCmd = `npx @tanstack/cli@latest create ${projectName} --package-manager ${pm}`;

const flags: string[] = [];

if (selections.has("better-auth")) flags.push("better-auth");
if (selections.has("clerk")) flags.push("clerk");
if (selections.has("eslint")) flags.push("eslint");
if (selections.has("biome")) flags.push("biome");
if (selections.has("shadcn")) flags.push("shadcn");
if (selections.has("neon")) flags.push("neon");
if (selections.has("convex")) flags.push("convex");
if (selections.has("prisma")) flags.push("prisma");
if (selections.has("drizzle")) flags.push("drizzle");
if (selections.has("orpc")) flags.push("orpc");
if (selections.has("trpc")) flags.push("trpc");

if (flags.length > 0) {
tanstackCmd += ` --add-ons ${flags.join(",")}`;
}
// --no-git sempre
if (!selections.has("git-init")) {
tanstackCmd += " --no-git";
}

const description = selections.has("typescript")
? "Initialize a new React project with Vite and TypeScript"
: "Initialize a new React project with Vite";

steps.push({
label: "Create React + Vite project with TanStack Router",
command: `${pm} create vite@latest ${projectName} -- --template ${viteTemplate}`,
label: "Create React + Vite project with TanStack",
command: tanstackCmd,
description: description,
});

needsSeparateCd = true;
} else if (selections.has("react-router")) {
const viteTemplate = selections.has("typescript") ? "react-ts" : "react";
Expand All @@ -187,7 +203,7 @@ export function generateCommands(

steps.push({
label: "Create React + Vite project with React Router",
command: `${pm} create vite@latest ${projectName} -- --template ${viteTemplate}`,
command: `${pm} create ${pm === "npm" ? "vite@latest" : "vite"} ${projectName} ${pm === "npm" ? "--" : ""} --template ${viteTemplate}`,
description: description,
});
needsSeparateCd = true;
Expand Down Expand Up @@ -252,7 +268,7 @@ export function generateCommands(

const isMonorepo =
(selections.has("nextjs") ||
selections.has("tanstack-router") ||
selections.has("tanstack") ||
selections.has("react-router")) &&
(selections.has("express") ||
selections.has("fastify") ||
Expand Down Expand Up @@ -280,11 +296,6 @@ export function generateCommands(
const deps: string[] = [];
const devDeps: string[] = [];

if (selections.has("tanstack-router") && !selections.has("tanstack-start")) {
deps.push("@tanstack/react-router");
devDeps.push("@tanstack/router-plugin");
}

if (selections.has("react-router")) {
deps.push("react-router-dom");
}
Expand All @@ -305,7 +316,7 @@ export function generateCommands(
}

// API layer
if (selections.has("trpc")) {
if (selections.has("trpc") && !selections.has("tanstack")) {
deps.push(
"@trpc/server",
"@trpc/client",
Expand All @@ -314,7 +325,7 @@ export function generateCommands(
);
}

if (selections.has("orpc")) {
if (selections.has("orpc") && !selections.has("tanstack")) {
deps.push(
"@orpc/server",
"@orpc/client",
Expand All @@ -323,7 +334,7 @@ export function generateCommands(
);
}

if (selections.has("drizzle")) {
if (selections.has("drizzle") && !selections.has("tanstack")) {
deps.push("drizzle-orm");
devDeps.push("drizzle-kit");

Expand All @@ -336,7 +347,7 @@ export function generateCommands(
}
}

if (selections.has("prisma")) {
if (selections.has("prisma") && !selections.has("tanstack")) {
deps.push("@prisma/client");
devDeps.push("prisma");
}
Expand All @@ -346,17 +357,14 @@ export function generateCommands(
}

// Auth
if (selections.has("better-auth")) {
if (selections.has("better-auth") && !selections.has("tanstack")) {
deps.push("better-auth");
}

if (selections.has("clerk")) {
if (selections.has("nextjs")) {
deps.push("@clerk/nextjs");
} else if (
selections.has("tanstack-router") ||
selections.has("react-router")
) {
} else if (selections.has("react-router")) {
deps.push("@clerk/clerk-react");
} else if (
selections.has("expo-bare") ||
Expand All @@ -375,7 +383,7 @@ export function generateCommands(
deps.push("lucia", "@lucia-auth/adapter-drizzle");
}

if (selections.has("shadcn")) {
if (selections.has("shadcn") && !selections.has("tanstack")) {
deps.push("class-variance-authority", "clsx", "tailwind-merge");
}

Expand Down Expand Up @@ -413,9 +421,7 @@ export function generateCommands(
steps[0]?.command.includes("--typescript")) ||
selections.has("nuxt") ||
selections.has("astro") ||
selections.has("tanstack-start") ||
(selections.has("tanstack-router") &&
steps[0]?.command.includes("react-ts")) ||
(selections.has("tanstack") && steps[0]?.command.includes("react-ts")) ||
(selections.has("react-router") &&
steps[0]?.command.includes("react-ts")) ||
(selections.has("svelte") && steps[0]?.command.includes("sv create")) ||
Expand All @@ -430,7 +436,6 @@ export function generateCommands(
steps[0]?.command.includes("--typescript")) ||
selections.has("nuxt") ||
selections.has("astro") ||
selections.has("tanstack-start") ||
(selections.has("hono") && steps[0]?.command.includes("create hono")) ||
(selections.has("elysia") && steps[0]?.command.includes("create elysia"));

Expand All @@ -454,11 +459,19 @@ export function generateCommands(
}
}

if (selections.has("tailwindcss") && !selections.has("nextjs")) {
if (
selections.has("tailwindcss") &&
!selections.has("nextjs") &&
!selections.has("tanstack")
) {
devDeps.push("tailwindcss", "@tailwindcss/vite");
}

if (selections.has("biome") && !selections.has("nextjs")) {
if (
selections.has("biome") &&
!selections.has("nextjs") &&
!selections.has("tanstack")
) {
devDeps.push("@biomejs/biome");
}

Expand Down Expand Up @@ -517,7 +530,7 @@ export function generateCommands(
});
}

if (selections.has("shadcn")) {
if (selections.has("shadcn") && !selections.has("tanstack")) {
steps.push({
label: "Initialize shadcn/ui",
command: `${pmx} shadcn@latest init`,
Expand All @@ -539,15 +552,19 @@ export function generateCommands(
});
}

if (selections.has("prisma")) {
if (selections.has("prisma") && !selections.has("tanstack")) {
steps.push({
label: "Initialize Prisma",
command: `${pmx} prisma init`,
description: "Set up Prisma ORM",
});
}

if (selections.has("biome") && !selections.has("nextjs")) {
if (
selections.has("biome") &&
!selections.has("nextjs") &&
!selections.has("tanstack")
) {
steps.push({
label: "Initialize Biome",
command: `${pmx} ${pmx === "npx" ? "@biomejs/biome" : "biome"} init`,
Expand All @@ -571,7 +588,7 @@ export function generateCommands(
});
}

if (selections.has("git-init")) {
if (selections.has("git-init") && !selections.has("tanstack")) {
steps.push({
label: "Initialize Git",
command: "git init",
Expand Down Expand Up @@ -637,13 +654,32 @@ export function generateSingleCommand(
return `${pmx} degit solidjs/templates/${solidTemplate} ${projectName}`;
}

if (selections.has("tanstack-start")) {
return `${pmx} create-tanstack-app@latest ${projectName}`;
}
if (selections.has("tanstack")) {
let tanstackCmd = `npx @tanstack/cli@latest create ${projectName} --package-manager ${pm}`;

if (selections.has("tanstack-router")) {
const viteTemplate = selections.has("typescript") ? "react-ts" : "react";
return `${pm} create vite@latest ${projectName} -- --template ${viteTemplate}`;
const flags: string[] = [];

if (selections.has("better-auth")) flags.push("better-auth");
if (selections.has("clerk")) flags.push("clerk");
if (selections.has("eslint")) flags.push("eslint");
if (selections.has("biome")) flags.push("biome");
if (selections.has("shadcn")) flags.push("shadcn");
if (selections.has("neon")) flags.push("neon");
if (selections.has("convex")) flags.push("convex");
if (selections.has("prisma")) flags.push("prisma");
if (selections.has("drizzle")) flags.push("drizzle");
if (selections.has("orpc")) flags.push("orpc");
if (selections.has("trpc")) flags.push("trpc");

if (flags.length > 0) {
tanstackCmd += ` --add-ons ${flags.join(",")}`;
}
// --no-git sempre
if (!selections.has("git-init")) {
tanstackCmd += " --no-git";
}

return tanstackCmd;
}

if (selections.has("react-router")) {
Expand Down
17 changes: 4 additions & 13 deletions src/lib/stack-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const categories: Category[] = [
singleSelect: true,
technologies: [
{
id: "tanstack-router",
name: "TanStack Router",
id: "tanstack",
name: "TanStack",
description: "Modern type-safe router for React",
icon: "https://tanstack.com/favicon.ico",
color: "#FFA171",
Expand All @@ -39,14 +39,6 @@ export const categories: Category[] = [
color: "#CA4245",
category: "frontend",
},
{
id: "tanstack-start",
name: "TanStack Start",
description: "Full-stack React and Solid framework",
icon: "https://tanstack.com/favicon.ico",
color: "#FFA171",
category: "frontend",
},
{
id: "nextjs",
name: "Next.js",
Expand All @@ -63,7 +55,7 @@ export const categories: Category[] = [
icon: "https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nuxt/nuxt-original.svg",
color: "#00DC82",
category: "frontend",
incompatibleWith: ["nextjs", "react-router", "tanstack-router"],
incompatibleWith: ["nextjs", "react-router", "tanstack"],
},
{
id: "svelte",
Expand Down Expand Up @@ -850,7 +842,7 @@ export const presets: Preset[] = [
name: "Fullstack React",
description: "Modern fullstack React setup",
selections: [
"tanstack-router",
"tanstack",
"no-native",
"hono",
"bun",
Expand All @@ -872,7 +864,6 @@ export const presets: Preset[] = [
name: "Edge-First",
description: "Optimized for edge computing",
selections: [
"tanstack-start",
"no-native",
"hono",
"cloudflare-workers",
Expand Down
4 changes: 2 additions & 2 deletions src/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"support_stackbuilder": "Apoie o Stack Builder",
"support_description": "Ajude-nos a manter este projeto gratuito e de código aberto. Sua contribuição faz diferença.",
"share": "Compartilhar",
"support": "Suporte",
"support": "Contribuir",
"github_sponsors": "Patrocinadores GitHub",
"github_sponsors_desc": "Suporte mensal ou único",
"github_sponsors_desc": "Apoio mensal ou único",
"buy_me_coffee": "Compre-me um café",
"buy_me_coffee_desc": "Contribuição única e rápida",
"thank_you_support": "Obrigado por apoiar o código aberto!",
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ function FolderStructure({
selections.has("astro") ||
selections.has("svelte") ||
selections.has("solid") ||
selections.has("tanstack-start") ||
selections.has("tanstack-router") ||
selections.has("tanstack") ||
selections.has("react-router") ||
selections.has("expo-bare") ||
selections.has("expo-uniwind") ||
Expand Down
Loading