update stack builder icons and ui

This commit is contained in:
Aman Varshney
2025-04-21 00:51:33 +05:30
parent b36316bb2a
commit b0e19a54c5
5 changed files with 70 additions and 66 deletions

View File

@@ -1,20 +1,5 @@
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_408_139" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="180" height="180">
<circle cx="90" cy="90" r="90" fill="black"/>
</mask>
<g mask="url(#mask0_408_139)">
<circle cx="90" cy="90" r="87" fill="black" stroke="white" stroke-width="6"/>
<path d="M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z" fill="url(#paint0_linear_408_139)"/>
<rect x="115" y="54" width="12" height="72" fill="url(#paint1_linear_408_139)"/>
</g>
<defs>
<linearGradient id="paint0_linear_408_139" x1="109" y1="116.5" x2="144.5" y2="160.5" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_408_139" x1="121" y1="54" x2="120.799" y2="106.875" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 64 55.425" width="64" height="55.425" version="1.0" xmlns="http://www.w3.org/2000/svg">
<rect id="background" width="100%" height="100%" fill="none" />
<path id="emblem" d="m32 0-14.255 24.69c5.409-1.6676 11.228-1.9148 16.869-0.58434l4.8177 1.1372-4.5328 19.22-4.8247-1.1372c-5.9293-1.3987-11.628 1.716-14.036 6.6851l-4.4595-2.1575c3.4034-7.0291 11.424-11.285 19.636-9.3476l2.2595-9.579c-8.0938-1.9081-16.624-9e-3 -23.145 5.153-6.5204 5.1607-10.329 13.028-10.329 21.344l64 7.9e-4z" fill="#60a5fa" stroke-linecap="square" stroke-width="4.8768" style="paint-order:markers fill stroke" />
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 652 B

View File

@@ -0,0 +1 @@
<svg fill="none" height="170" viewBox="0 0 201 170" width="201" xmlns="http://www.w3.org/2000/svg"><path d="m100.055 170c-2.1901 0-18.2001-12.8-21.3001-16.45-2.44 3.73-6.44 7.96-6.44 7.96-11.05-5.57-25.17-20.06-27.83-25.13-2.62-5-12.13-62.58-12.39-79.3-.34-9.41 5.85-28.49 67.9601-28.49 62.11 0 68.29 19.08 67.96 28.49-.25 16.72-9.76 74.3-12.39 79.3-2.66 5.07-16.78 19.56-27.83 25.13 0 0-4-4.23-6.44-7.96-3.1 3.65-19.11 16.45-21.3 16.45z" fill="#1ebca1"/><path d="m100.055 132.92c-20.7301 0-33.9601-10.95-33.9601-10.95l1.91-26.67-21.75-1.94-3.91-31.55h115.4301l-3.91 31.55-21.75 1.94 1.91 26.67s-13.23 10.95-33.96 10.95z" fill="#183134"/><path d="m121.535 75.79 78.52-27.18c-4.67-27.94-29.16-48.61-29.16-48.61v30.78l-14.54 3.75-9.11-10.97-7.8 15.34-39.38 10.16-39.3801-10.16-7.8-15.34-9.11 10.97-14.54-3.75v-30.78s-24.50997 20.67-29.1799684 48.61l78.5199684 27.18-2.8 37.39c6.7 1.7 13.75 3.39 24.2801 3.39 10.53 0 17.57-1.69 24.27-3.39l-2.8-37.39z" fill="#4ff8d2"/></svg>

After

Width:  |  Height:  |  Size: 972 B

View File

@@ -77,7 +77,11 @@ const TechIcon = ({
icon,
name,
className,
}: { icon: string; name: string; className?: string }) => {
}: {
icon: string;
name: string;
className?: string;
}) => {
if (icon.startsWith("/icon/")) {
return (
<Image
@@ -154,6 +158,7 @@ const StackArchitect = () => {
const isPWACompat = hasPWACompatibleFrontend(nextStack.frontend);
const isNative = hasNativeFrontend(nextStack.frontend);
// Database/ORM/Auth/DB Setup auto-fix
if (nextStack.database === "none") {
if (nextStack.orm !== "none") {
nextStack.orm = "none";
@@ -167,13 +172,11 @@ const StackArchitect = () => {
nextStack.dbSetup = "none";
changed = true;
}
} else if (nextStack.database === "mongodb") {
if (nextStack.orm !== "prisma") {
nextStack.orm = "prisma";
changed = true;
}
}
if (nextStack.database === "mongodb" && nextStack.orm !== "prisma") {
nextStack.orm = "prisma";
changed = true;
}
if (nextStack.dbSetup === "turso") {
if (nextStack.database !== "sqlite") {
nextStack.database = "sqlite";
@@ -183,7 +186,8 @@ const StackArchitect = () => {
nextStack.orm = "drizzle";
changed = true;
}
} else if (nextStack.dbSetup === "prisma-postgres") {
}
if (nextStack.dbSetup === "prisma-postgres") {
if (nextStack.database !== "postgres") {
nextStack.database = "postgres";
changed = true;
@@ -192,7 +196,8 @@ const StackArchitect = () => {
nextStack.orm = "prisma";
changed = true;
}
} else if (nextStack.dbSetup === "mongodb-atlas") {
}
if (nextStack.dbSetup === "mongodb-atlas") {
if (nextStack.database !== "mongodb") {
nextStack.database = "mongodb";
changed = true;
@@ -201,29 +206,26 @@ const StackArchitect = () => {
nextStack.orm = "prisma";
changed = true;
}
} else if (nextStack.dbSetup === "neon") {
if (nextStack.database !== "postgres") {
nextStack.database = "postgres";
changed = true;
}
}
if (nextStack.dbSetup === "neon" && nextStack.database !== "postgres") {
nextStack.database = "postgres";
changed = true;
}
// API auto-fix for Native
if (isNative && nextStack.api !== "trpc") {
nextStack.api = "trpc";
changed = true;
}
// Addons auto-fix
const incompatibleAddons: string[] = [];
if (!isPWACompat) {
incompatibleAddons.push("pwa", "tauri");
}
if (!isPWACompat) incompatibleAddons.push("pwa", "tauri");
const originalAddonsLength = nextStack.addons.length;
nextStack.addons = nextStack.addons.filter(
(addon) => !incompatibleAddons.includes(addon),
);
if (nextStack.addons.length !== originalAddonsLength) {
changed = true;
}
if (nextStack.addons.length !== originalAddonsLength) changed = true;
if (
nextStack.addons.includes("husky") &&
!nextStack.addons.includes("biome")
@@ -233,24 +235,17 @@ const StackArchitect = () => {
changed = true;
}
// Examples auto-fix
const incompatibleExamples: string[] = [];
if (!isWeb) {
incompatibleExamples.push("todo", "ai");
}
if (nextStack.database === "none") {
incompatibleExamples.push("todo");
}
if (nextStack.backendFramework === "elysia") {
if (!isWeb) incompatibleExamples.push("todo", "ai");
if (nextStack.database === "none") incompatibleExamples.push("todo");
if (nextStack.backendFramework === "elysia")
incompatibleExamples.push("ai");
}
const originalExamplesLength = nextStack.examples.length;
nextStack.examples = nextStack.examples.filter(
(ex) => !incompatibleExamples.includes(ex),
);
if (nextStack.examples.length !== originalExamplesLength) {
changed = true;
}
if (nextStack.examples.length !== originalExamplesLength) changed = true;
return changed ? nextStack : currentStack;
});
@@ -368,7 +363,9 @@ const StackArchitect = () => {
}
}
return `${base} ${projectName}${flags.length > 0 ? ` ${flags.join(" ")}` : ""}`;
return `${base} ${projectName}${
flags.length > 0 ? ` ${flags.join(" ")}` : ""
}`;
}, []);
useEffect(() => {
@@ -386,7 +383,7 @@ const StackArchitect = () => {
if (isNative && stack.frontend.length > 1) {
notes.frontend.notes.push(
"React Native requires the tRPC API when used with other frontends. oRPC will be disabled.",
"React Native requires the tRPC API when used with other frontends. oRPC will be disabled. (temporarily)",
);
if (stack.api !== "trpc") notes.frontend.hasIssue = true;
}
@@ -963,7 +960,9 @@ const StackArchitect = () => {
.map((tech) => (
<span
key={`${category}-${tech.id}`}
className={`inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs ${getBadgeColors(category)}`}
className={`inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs ${getBadgeColors(
category,
)}`}
>
<TechIcon
icon={tech.icon}
@@ -995,7 +994,9 @@ const StackArchitect = () => {
return (
<span
key={`${category}-${tech.id}`}
className={`inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs ${getBadgeColors(category)}`}
className={`inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs ${getBadgeColors(
category,
)}`}
>
<TechIcon
icon={tech.icon}
@@ -1064,10 +1065,18 @@ const StackArchitect = () => {
{notesInfo?.notes && notesInfo.notes.length > 0 && (
<div
className={`mb-4 rounded-md border p-3 ${notesInfo.hasIssue ? "border-orange-200 bg-orange-50 dark:border-orange-800 dark:bg-orange-900/20" : "border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/20"}`}
className={`mb-4 rounded-md border p-3 ${
notesInfo.hasIssue
? "border-orange-200 bg-orange-50 dark:border-orange-800 dark:bg-orange-900/20"
: "border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/20"
}`}
>
<div
className={`mb-1 flex items-center gap-2 font-medium text-xs sm:text-sm ${notesInfo.hasIssue ? "text-orange-800 dark:text-orange-300" : "text-blue-800 dark:text-blue-300"}`}
className={`mb-1 flex items-center gap-2 font-medium text-xs sm:text-sm ${
notesInfo.hasIssue
? "text-orange-800 dark:text-orange-300"
: "text-blue-800 dark:text-blue-300"
}`}
>
<InfoIcon className="h-4 w-4 flex-shrink-0" />
<span>
@@ -1077,7 +1086,11 @@ const StackArchitect = () => {
</span>
</div>
<ul
className={`list-inside list-disc space-y-1 text-xs ${notesInfo.hasIssue ? "text-orange-700 dark:text-orange-400" : "text-blue-700 dark:text-blue-400"}`}
className={`list-inside list-disc space-y-1 text-xs ${
notesInfo.hasIssue
? "text-orange-700 dark:text-orange-400"
: "text-blue-700 dark:text-blue-400"
}`}
>
{notesInfo.notes.map((note, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
@@ -1108,7 +1121,7 @@ const StackArchitect = () => {
categoryKey as keyof typeof TECH_OPTIONS,
tech.id,
);
const isDisabled = !!disabledReason;
const isDisabled = !!disabledReason && !isSelected;
return (
<motion.div
@@ -1120,7 +1133,11 @@ const StackArchitect = () => {
} ${
isSelected
? "border-blue-400 bg-blue-100 ring-1 ring-blue-300 dark:border-blue-600 dark:bg-blue-900/40 dark:ring-blue-700"
: `border-gray-300 dark:border-gray-700 ${!isDisabled ? "hover:border-gray-400 hover:bg-gray-200/50 dark:hover:border-gray-600 dark:hover:bg-gray-800/50" : ""}`
: `border-gray-300 dark:border-gray-700 ${
!isDisabled
? "hover:border-gray-400 hover:bg-gray-200/50 dark:hover:border-gray-600 dark:hover:bg-gray-800/50"
: ""
}`
}`}
title={
isDisabled

View File

@@ -35,8 +35,9 @@ export const TECH_OPTIONS = {
},
{
id: "tanstack-start",
name: "TanStack Start",
description: "Quick starter template from TanStack",
name: "TanStack Start (beta)",
description:
"Full-stack React and Solid framework powered by TanStack Router",
icon: "/icon/tanstack.svg",
color: "from-purple-400 to-purple-600",
default: false,
@@ -61,7 +62,7 @@ export const TECH_OPTIONS = {
id: "none",
name: "No Frontend",
description: "API-only backend",
icon: "⚙️", // Keep emoji for missing icon
icon: "⚙️",
color: "from-gray-400 to-gray-600",
default: false,
},
@@ -181,7 +182,7 @@ export const TECH_OPTIONS = {
id: "turso",
name: "Turso",
description: "SQLite cloud database powered by libSQL",
icon: "/icon/sqlite.svg",
icon: "/icon/turso.svg",
color: "from-pink-400 to-pink-600",
},
{
@@ -195,7 +196,7 @@ export const TECH_OPTIONS = {
id: "prisma-postgres",
name: "Prisma PostgreSQL",
description: "Set up PostgreSQL with Prisma",
icon: "/icon/postgres.svg",
icon: "/icon/prisma.svg",
color: "from-indigo-400 to-indigo-600",
},
{

View File

@@ -14,7 +14,7 @@
},
"apps/cli": {
"name": "create-better-t-stack",
"version": "2.0.8",
"version": "2.0.10",
"bin": {
"create-better-t-stack": "dist/index.js",
},