create-z3 0.0.10 → 0.0.13

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.
Files changed (76) hide show
  1. package/dist/index.js +232 -79
  2. package/package.json +4 -2
  3. package/templates/nextjs/README.md +242 -18
  4. package/templates/nextjs/components.json +24 -0
  5. package/templates/nextjs/convex/_generated/api.d.ts +65 -0
  6. package/templates/nextjs/convex/_generated/api.js +23 -0
  7. package/templates/nextjs/convex/_generated/dataModel.d.ts +60 -0
  8. package/templates/nextjs/convex/_generated/server.d.ts +143 -0
  9. package/templates/nextjs/convex/_generated/server.js +93 -0
  10. package/templates/nextjs/convex/auth/adapter/index.ts +222 -0
  11. package/templates/nextjs/convex/auth/adapter/utils.ts +597 -0
  12. package/templates/nextjs/convex/auth/api.ts +8 -0
  13. package/templates/nextjs/convex/auth/config.ts +10 -0
  14. package/templates/nextjs/convex/auth/db.ts +299 -0
  15. package/templates/nextjs/convex/auth/index.ts +54 -0
  16. package/templates/nextjs/convex/auth/plugins/index.ts +9 -0
  17. package/templates/nextjs/convex/auth/sessions.ts +60 -0
  18. package/templates/nextjs/convex/convex.config.ts +5 -0
  19. package/templates/nextjs/convex/http.ts +28 -0
  20. package/templates/nextjs/convex/schema.ts +69 -0
  21. package/templates/nextjs/eslint.config.mjs +157 -0
  22. package/templates/nextjs/next.config.ts +10 -0
  23. package/templates/nextjs/package.json +43 -11
  24. package/templates/nextjs/pnpm-workspace.yaml +5 -0
  25. package/templates/nextjs/postcss.config.mjs +7 -0
  26. package/templates/nextjs/public/favicons/favicon.ico +0 -0
  27. package/templates/nextjs/public/file.svg +1 -0
  28. package/templates/nextjs/public/globe.svg +1 -0
  29. package/templates/nextjs/public/next.svg +1 -0
  30. package/templates/nextjs/public/vercel.svg +1 -0
  31. package/templates/nextjs/public/window.svg +1 -0
  32. package/templates/nextjs/src/app/(frontend)/@auth/(...)auth/[pathname]/page.tsx +13 -0
  33. package/templates/nextjs/src/app/(frontend)/@auth/(...)auth/[pathname]/view.tsx +23 -0
  34. package/templates/nextjs/src/app/(frontend)/@auth/default.tsx +3 -0
  35. package/templates/nextjs/src/app/(frontend)/@auth/page.tsx +3 -0
  36. package/templates/nextjs/src/app/(frontend)/auth/[pathname]/page.tsx +13 -0
  37. package/templates/nextjs/src/app/(frontend)/auth/[pathname]/view.tsx +11 -0
  38. package/templates/nextjs/src/app/(frontend)/globals.css +65 -0
  39. package/templates/nextjs/src/app/(frontend)/layout.tsx +53 -0
  40. package/templates/nextjs/src/app/(frontend)/page.tsx +5 -0
  41. package/templates/nextjs/src/app/api/auth/[...all]/route.ts +6 -0
  42. package/templates/nextjs/src/app/favicon.ico +0 -0
  43. package/templates/nextjs/src/auth/client.tsx +50 -0
  44. package/templates/nextjs/src/auth/server.ts +54 -0
  45. package/templates/nextjs/src/auth/types.ts +3 -0
  46. package/templates/nextjs/src/auth/utils.ts +33 -0
  47. package/templates/nextjs/src/components/component-example.tsx +501 -0
  48. package/templates/nextjs/src/components/example.tsx +54 -0
  49. package/templates/nextjs/src/components/providers/client.tsx +13 -0
  50. package/templates/nextjs/src/components/providers/convex.tsx +34 -0
  51. package/templates/nextjs/src/components/providers/server.tsx +14 -0
  52. package/templates/nextjs/src/components/ui/alert-dialog.tsx +175 -0
  53. package/templates/nextjs/src/components/ui/badge.tsx +48 -0
  54. package/templates/nextjs/src/components/ui/button.tsx +53 -0
  55. package/templates/nextjs/src/components/ui/card.tsx +94 -0
  56. package/templates/nextjs/src/components/ui/combobox.tsx +292 -0
  57. package/templates/nextjs/src/components/ui/dialog.tsx +151 -0
  58. package/templates/nextjs/src/components/ui/dropdown-menu.tsx +254 -0
  59. package/templates/nextjs/src/components/ui/field.tsx +227 -0
  60. package/templates/nextjs/src/components/ui/input-group.tsx +149 -0
  61. package/templates/nextjs/src/components/ui/input.tsx +20 -0
  62. package/templates/nextjs/src/components/ui/label.tsx +20 -0
  63. package/templates/nextjs/src/components/ui/select.tsx +192 -0
  64. package/templates/nextjs/src/components/ui/separator.tsx +25 -0
  65. package/templates/nextjs/src/components/ui/textarea.tsx +18 -0
  66. package/templates/nextjs/src/db/constants/auth.ts +6 -0
  67. package/templates/nextjs/src/db/constants/index.ts +45 -0
  68. package/templates/nextjs/src/env.mjs +48 -0
  69. package/templates/nextjs/src/lib/auth/server.ts +15 -0
  70. package/templates/nextjs/src/lib/utils.ts +6 -0
  71. package/templates/nextjs/src/proxy.ts +21 -0
  72. package/templates/nextjs/tsconfig.json +42 -0
  73. package/templates/tanstack-start/convex/auth/adapter/index.ts +1 -1
  74. package/templates/tanstack-start/convex/auth/index.ts +1 -1
  75. package/templates/tanstack-start/package.json +1 -0
  76. package/templates/nextjs/src/.gitkeep +0 -1
package/dist/index.js CHANGED
@@ -72,7 +72,10 @@ async function copyTemplate(framework, targetPath) {
72
72
  const __filename2 = fileURLToPath(import.meta.url);
73
73
  const __dirname2 = dirname(__filename2);
74
74
  const templateDir = framework === "tanstack" ? "tanstack-start" : "nextjs";
75
- const templatePath = join(__dirname2, "../templates", templateDir);
75
+ let templatePath = join(__dirname2, "../../templates", templateDir);
76
+ if (!fs2.existsSync(templatePath)) {
77
+ templatePath = join(__dirname2, "../templates", templateDir);
78
+ }
76
79
  await fs2.copy(templatePath, targetPath, {
77
80
  overwrite: false,
78
81
  errorOnExist: false
@@ -1725,25 +1728,25 @@ function getAdditionalProviders() {
1725
1728
 
1726
1729
  // src/installers/string-utils.ts
1727
1730
  import fs3 from "fs-extra";
1728
- var DEFAULT_THEME = `--background: 0 0% 100%;
1729
- --foreground: 240 10% 3.9%;
1730
- --card: 0 0% 100%;
1731
- --card-foreground: 240 10% 3.9%;
1732
- --popover: 0 0% 100%;
1733
- --popover-foreground: 240 10% 3.9%;
1734
- --primary: 240 5.9% 10%;
1735
- --primary-foreground: 0 0% 98%;
1736
- --secondary: 240 4.8% 95.9%;
1737
- --secondary-foreground: 240 5.9% 10%;
1738
- --muted: 240 4.8% 95.9%;
1739
- --muted-foreground: 240 3.8% 46.1%;
1740
- --accent: 240 4.8% 95.9%;
1741
- --accent-foreground: 240 5.9% 10%;
1742
- --destructive: 0 84.2% 60.2%;
1743
- --destructive-foreground: 0 0% 98%;
1744
- --border: 240 5.9% 90%;
1745
- --input: 240 5.9% 90%;
1746
- --ring: 240 5.9% 10%;
1731
+ var DEFAULT_THEME = `--background: 100% 0.000 0;
1732
+ --foreground: 3.9% 0.006 240;
1733
+ --card: 100% 0.000 0;
1734
+ --card-foreground: 3.9% 0.006 240;
1735
+ --popover: 100% 0.000 0;
1736
+ --popover-foreground: 3.9% 0.006 240;
1737
+ --primary: 10% 0.003 240;
1738
+ --primary-foreground: 98% 0.000 0;
1739
+ --secondary: 95.9% 0.002 240;
1740
+ --secondary-foreground: 10% 0.003 240;
1741
+ --muted: 95.9% 0.002 240;
1742
+ --muted-foreground: 46.1% 0.002 240;
1743
+ --accent: 95.9% 0.002 240;
1744
+ --accent-foreground: 10% 0.003 240;
1745
+ --destructive: 60.2% 0.168 0;
1746
+ --destructive-foreground: 98% 0.000 0;
1747
+ --border: 90% 0.003 240;
1748
+ --input: 90% 0.003 240;
1749
+ --ring: 10% 0.003 240;
1747
1750
  --radius: 0.5rem;`;
1748
1751
  function detectIndentation(line) {
1749
1752
  const match = line.match(/^(\s*)/);
@@ -1927,6 +1930,129 @@ import { join as join2 } from "path";
1927
1930
  import { execa } from "execa";
1928
1931
  import ora from "ora";
1929
1932
  import crypto from "crypto";
1933
+
1934
+ // src/utils/tweakcn-converter.ts
1935
+ import fs4 from "fs-extra";
1936
+ import convert from "color-convert";
1937
+ async function convertTweakCNToOKLCH(options) {
1938
+ const { source, format = "oklch" } = options;
1939
+ const cssContent = await fetchOrReadCSS(source);
1940
+ const colors = parseColorsFromCSS(cssContent);
1941
+ const convertedColors = colors.map((color) => ({
1942
+ ...color,
1943
+ oklch: convertColorToOKLCH(color.value)
1944
+ }));
1945
+ return generateCSSOutput(convertedColors, format);
1946
+ }
1947
+ async function fetchOrReadCSS(source) {
1948
+ if (source.startsWith("http://") || source.startsWith("https://")) {
1949
+ try {
1950
+ const response = await fetch(source);
1951
+ if (!response.ok) {
1952
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1953
+ }
1954
+ return await response.text();
1955
+ } catch (error) {
1956
+ throw new Error(
1957
+ `Failed to fetch CSS from URL: ${error instanceof Error ? error.message : "Unknown error"}`
1958
+ );
1959
+ }
1960
+ }
1961
+ try {
1962
+ return await fs4.readFile(source, "utf-8");
1963
+ } catch (error) {
1964
+ throw new Error(
1965
+ `Failed to read CSS from file: ${error instanceof Error ? error.message : "Unknown error"}`
1966
+ );
1967
+ }
1968
+ }
1969
+ function parseColorsFromCSS(css) {
1970
+ const colors = [];
1971
+ const cssVarRegex = /--([\w-]+)\s*:\s*([^;]+);/g;
1972
+ let match;
1973
+ while ((match = cssVarRegex.exec(css)) !== null) {
1974
+ const name = `--${match[1]}`;
1975
+ const value = match[2].trim();
1976
+ if (isColorValue(value)) {
1977
+ colors.push({ name, value });
1978
+ }
1979
+ }
1980
+ return colors;
1981
+ }
1982
+ function isColorValue(value) {
1983
+ if (value.startsWith("#")) {
1984
+ return true;
1985
+ }
1986
+ if (value.startsWith("rgb(") || value.startsWith("rgba(")) {
1987
+ return true;
1988
+ }
1989
+ if (value.startsWith("hsl(") || value.startsWith("hsla(")) {
1990
+ return true;
1991
+ }
1992
+ if (value.startsWith("oklch(")) {
1993
+ return true;
1994
+ }
1995
+ if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(value)) {
1996
+ return true;
1997
+ }
1998
+ return false;
1999
+ }
2000
+ function convertColorToOKLCH(colorValue) {
2001
+ const trimmed = colorValue.trim();
2002
+ if (trimmed.startsWith("oklch(")) {
2003
+ const match = trimmed.match(/oklch\(([\d.]+%?)\s+([\d.]+)\s+([\d.]+)\)/);
2004
+ if (match) {
2005
+ return `${match[1]} ${match[2]} ${match[3]}`;
2006
+ }
2007
+ }
2008
+ let rgb;
2009
+ try {
2010
+ if (trimmed.startsWith("#")) {
2011
+ rgb = convert.hex.rgb(trimmed.slice(1));
2012
+ } else if (trimmed.startsWith("rgb(") || trimmed.startsWith("rgba(")) {
2013
+ const match = trimmed.match(/rgba?\((\d+),?\s*(\d+),?\s*(\d+)/);
2014
+ if (!match) throw new Error("Invalid RGB format");
2015
+ rgb = [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
2016
+ } else if (trimmed.startsWith("hsl(") || trimmed.startsWith("hsla(")) {
2017
+ const match = trimmed.match(/hsla?\((\d+),?\s*(\d+)%?,?\s*(\d+)%?/);
2018
+ if (!match) throw new Error("Invalid HSL format");
2019
+ const hsl2 = [
2020
+ parseInt(match[1]),
2021
+ parseInt(match[2]),
2022
+ parseInt(match[3])
2023
+ ];
2024
+ rgb = convert.hsl.rgb(hsl2);
2025
+ } else if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(trimmed)) {
2026
+ const parts = trimmed.split(/\s+/);
2027
+ const h2 = parseFloat(parts[0]);
2028
+ const s = parseFloat(parts[1].replace("%", ""));
2029
+ const l2 = parseFloat(parts[2].replace("%", ""));
2030
+ rgb = convert.hsl.rgb([h2, s, l2]);
2031
+ } else {
2032
+ return trimmed;
2033
+ }
2034
+ const hsl = convert.rgb.hsl(rgb);
2035
+ const l = hsl[2];
2036
+ const c = hsl[1] / 100 * 0.4;
2037
+ const h = hsl[0];
2038
+ return `${l}% ${c.toFixed(3)} ${h}`;
2039
+ } catch (error) {
2040
+ console.warn(`Failed to convert color "${colorValue}": ${error instanceof Error ? error.message : "Unknown error"}`);
2041
+ return trimmed;
2042
+ }
2043
+ }
2044
+ function generateCSSOutput(colors, format) {
2045
+ if (colors.length === 0) {
2046
+ return "";
2047
+ }
2048
+ const declarations = colors.map((color) => {
2049
+ const value = format === "oklch" && color.oklch ? color.oklch : color.value;
2050
+ return `${color.name}: ${value};`;
2051
+ }).join("\n");
2052
+ return declarations;
2053
+ }
2054
+
2055
+ // src/installers/base.ts
1930
2056
  var FrameworkInstaller = class {
1931
2057
  /**
1932
2058
  * Constructor for FrameworkInstaller
@@ -1947,24 +2073,22 @@ var FrameworkInstaller = class {
1947
2073
  }
1948
2074
  /**
1949
2075
  * Detect the package manager used to invoke the CLI
1950
- * Checks npm_config_user_agent environment variable
2076
+ * Checks environment variables set by package managers
1951
2077
  *
1952
- * @returns Detected package manager, defaults to 'npm'
2078
+ * @returns Detected package manager ('npm', 'yarn', 'pnpm', or 'bun')
1953
2079
  */
1954
2080
  detectPackageManager() {
1955
- const userAgent = process.env.npm_config_user_agent || "";
1956
- if (userAgent.includes("pnpm")) {
1957
- return "pnpm";
1958
- } else if (userAgent.includes("yarn")) {
1959
- return "yarn";
1960
- } else if (userAgent.includes("bun")) {
1961
- return "bun";
2081
+ const userAgent = process.env.npm_config_user_agent;
2082
+ if (userAgent) {
2083
+ if (userAgent.includes("pnpm")) return "pnpm";
2084
+ if (userAgent.includes("yarn")) return "yarn";
2085
+ if (userAgent.includes("bun")) return "bun";
1962
2086
  }
1963
2087
  return "npm";
1964
2088
  }
1965
2089
  /**
1966
2090
  * Install project dependencies using detected package manager
1967
- * Shows progress with ora spinner
2091
+ * Shows progress spinner during installation
1968
2092
  */
1969
2093
  async installDependencies() {
1970
2094
  const packageManager = this.detectPackageManager();
@@ -1974,21 +2098,21 @@ var FrameworkInstaller = class {
1974
2098
  cwd: this.targetPath,
1975
2099
  stdio: "pipe"
1976
2100
  });
1977
- spinner.succeed(`Dependencies installed with ${packageManager}`);
2101
+ spinner.succeed("Dependencies installed successfully");
1978
2102
  } catch (error) {
1979
- spinner.fail(`Failed to install dependencies with ${packageManager}`);
2103
+ spinner.fail("Failed to install dependencies");
1980
2104
  throw new Error(
1981
2105
  `Dependency installation failed: ${error instanceof Error ? error.message : "Unknown error"}`
1982
2106
  );
1983
2107
  }
1984
2108
  }
1985
2109
  /**
1986
- * Format generated files using the project's format command
1987
- * Runs after all file modifications to ensure consistent code style
2110
+ * Format code using project's formatter (Prettier via package.json script)
2111
+ * Non-blocking - continues even if formatting fails
1988
2112
  */
1989
2113
  async formatCode() {
1990
2114
  const packageManager = this.detectPackageManager();
1991
- const spinner = ora("Formatting generated files...").start();
2115
+ const spinner = ora("Formatting code...").start();
1992
2116
  try {
1993
2117
  await execa(packageManager, ["run", "format"], {
1994
2118
  cwd: this.targetPath,
@@ -2072,13 +2196,15 @@ Make sure you are authenticated with GitHub CLI (run "gh auth login")`
2072
2196
  return crypto.randomBytes(32).toString("hex");
2073
2197
  }
2074
2198
  /**
2075
- * Fetch TweakCN theme CSS from URL
2199
+ * Fetch TweakCN theme CSS from URL and convert to OKLCH format
2076
2200
  * Handles network errors and provides retry suggestions
2201
+ * Optionally converts fetched theme through OKLCH converter for consistent color format
2077
2202
  *
2078
2203
  * @param url - URL to fetch theme from
2079
- * @returns Theme CSS content
2204
+ * @param convertToOklch - Whether to convert theme colors to OKLCH format (default: true)
2205
+ * @returns Theme CSS content in OKLCH format (if conversion enabled)
2080
2206
  */
2081
- async fetchThemeFromUrl(url) {
2207
+ async fetchThemeFromUrl(url, convertToOklch = true) {
2082
2208
  const spinner = ora("Fetching TweakCN theme...").start();
2083
2209
  try {
2084
2210
  const response = await fetch(url);
@@ -2087,6 +2213,23 @@ Make sure you are authenticated with GitHub CLI (run "gh auth login")`
2087
2213
  }
2088
2214
  const content = await response.text();
2089
2215
  spinner.succeed("TweakCN theme fetched");
2216
+ if (convertToOklch) {
2217
+ const convertSpinner = ora("Converting theme to OKLCH format...").start();
2218
+ try {
2219
+ const convertedContent = await convertTweakCNToOKLCH({
2220
+ source: url,
2221
+ format: "oklch"
2222
+ });
2223
+ convertSpinner.succeed("Theme converted to OKLCH format");
2224
+ return convertedContent;
2225
+ } catch (convertError) {
2226
+ convertSpinner.warn("OKLCH conversion failed, using raw theme CSS");
2227
+ console.warn(
2228
+ `Warning: Failed to convert theme to OKLCH: ${convertError instanceof Error ? convertError.message : "Unknown error"}`
2229
+ );
2230
+ return content;
2231
+ }
2232
+ }
2090
2233
  return content;
2091
2234
  } catch (error) {
2092
2235
  spinner.fail("Failed to fetch TweakCN theme");
@@ -2111,55 +2254,65 @@ Please check the URL and your internet connection, then try again.`
2111
2254
  copySpinner.fail("Failed to copy template files");
2112
2255
  throw error;
2113
2256
  }
2114
- if (options.emailPasswordAuth || options.oauthProviders.length > 0) {
2115
- const authSpinner = ora("Configuring authentication...").start();
2116
- try {
2117
- await this.updateOAuthConfig(options.oauthProviders, options.emailPasswordAuth);
2257
+ const authSpinner = ora("Configuring authentication...").start();
2258
+ try {
2259
+ await this.updateOAuthConfig(options.oauthProviders, options.emailPasswordAuth);
2260
+ if (options.emailPasswordAuth || options.oauthProviders.length > 0) {
2118
2261
  authSpinner.succeed("Authentication configuration updated");
2119
- } catch (error) {
2120
- authSpinner.fail("Failed to configure authentication");
2121
- throw error;
2262
+ } else {
2263
+ authSpinner.succeed("Authentication placeholders cleaned up");
2122
2264
  }
2265
+ } catch (error) {
2266
+ authSpinner.fail("Failed to configure authentication");
2267
+ throw error;
2123
2268
  }
2124
- if (options.oauthProviders.length > 0) {
2125
- const oauthUISpinner = ora("Configuring OAuth UI...").start();
2126
- try {
2127
- await this.updateOAuthUIConfig(options.oauthProviders);
2269
+ const oauthUISpinner = ora("Configuring OAuth UI...").start();
2270
+ try {
2271
+ await this.updateOAuthUIConfig(options.oauthProviders);
2272
+ if (options.oauthProviders.length > 0) {
2128
2273
  oauthUISpinner.succeed("OAuth UI configuration updated");
2129
- } catch (error) {
2130
- oauthUISpinner.fail("Failed to configure OAuth UI");
2131
- throw error;
2274
+ } else {
2275
+ oauthUISpinner.succeed("OAuth UI placeholders cleaned up");
2132
2276
  }
2277
+ } catch (error) {
2278
+ oauthUISpinner.fail("Failed to configure OAuth UI");
2279
+ throw error;
2133
2280
  }
2134
- if (options.oauthProviders.length > 0) {
2135
- const envSpinner = ora("Updating .env.example...").start();
2136
- try {
2137
- await this.updateEnvExample(options.oauthProviders);
2281
+ const envSpinner = ora("Updating .env.example...").start();
2282
+ try {
2283
+ await this.updateEnvExample(options.oauthProviders);
2284
+ if (options.oauthProviders.length > 0) {
2138
2285
  envSpinner.succeed(".env.example updated");
2139
- } catch (error) {
2140
- envSpinner.fail("Failed to update .env.example");
2141
- throw error;
2286
+ } else {
2287
+ envSpinner.succeed(".env.example placeholders cleaned up");
2142
2288
  }
2289
+ } catch (error) {
2290
+ envSpinner.fail("Failed to update .env.example");
2291
+ throw error;
2143
2292
  }
2144
- if (options.oauthProviders.length > 0) {
2145
- const envTsSpinner = ora("Updating typed env configuration...").start();
2146
- try {
2147
- await this.updateEnvTs(options.oauthProviders);
2293
+ const envTsSpinner = ora("Updating typed env configuration...").start();
2294
+ try {
2295
+ await this.updateEnvTs(options.oauthProviders);
2296
+ if (options.oauthProviders.length > 0) {
2148
2297
  envTsSpinner.succeed("Typed env configuration updated");
2149
- } catch (error) {
2150
- envTsSpinner.fail("Failed to update typed env configuration");
2151
- throw error;
2298
+ } else {
2299
+ envTsSpinner.succeed("Typed env placeholders cleaned up");
2152
2300
  }
2301
+ } catch (error) {
2302
+ envTsSpinner.fail("Failed to update typed env configuration");
2303
+ throw error;
2153
2304
  }
2154
- if (options.oauthProviders.length > 0) {
2155
- const readmeSpinner = ora("Updating README...").start();
2156
- try {
2157
- await this.updateReadme(options.oauthProviders);
2305
+ const readmeSpinner = ora("Updating README...").start();
2306
+ try {
2307
+ await this.updateReadme(options.oauthProviders);
2308
+ if (options.oauthProviders.length > 0) {
2158
2309
  readmeSpinner.succeed("README updated");
2159
- } catch (error) {
2160
- readmeSpinner.fail("Failed to update README");
2161
- throw error;
2310
+ } else {
2311
+ readmeSpinner.succeed("README placeholders cleaned up");
2162
2312
  }
2313
+ } catch (error) {
2314
+ readmeSpinner.fail("Failed to update README");
2315
+ throw error;
2163
2316
  }
2164
2317
  const themeSpinner = ora("Applying theme...").start();
2165
2318
  try {
@@ -2167,16 +2320,17 @@ Please check the URL and your internet connection, then try again.`
2167
2320
  if (options.tweakcnTheme) {
2168
2321
  if (options.tweakcnTheme.type === "url") {
2169
2322
  themeContent = await this.fetchThemeFromUrl(options.tweakcnTheme.content);
2323
+ } else if (options.tweakcnTheme.type === "css") {
2324
+ themeContent = options.tweakcnTheme.content;
2170
2325
  } else {
2171
2326
  themeContent = options.tweakcnTheme.content;
2172
2327
  }
2328
+ await this.applyTweakCNTheme(themeContent);
2329
+ themeSpinner.succeed("TweakCN theme applied");
2173
2330
  } else {
2174
- themeContent = DEFAULT_THEME;
2331
+ await this.applyTweakCNTheme(DEFAULT_THEME);
2332
+ themeSpinner.succeed("Default theme applied");
2175
2333
  }
2176
- await this.applyTweakCNTheme(themeContent);
2177
- themeSpinner.succeed(
2178
- options.tweakcnTheme ? "TweakCN theme applied" : "Default theme applied"
2179
- );
2180
2334
  } catch (error) {
2181
2335
  themeSpinner.fail("Failed to apply theme");
2182
2336
  throw error;
@@ -2186,7 +2340,6 @@ Please check the URL and your internet connection, then try again.`
2186
2340
  }
2187
2341
  if (options.installDependencies) {
2188
2342
  await this.installDependencies();
2189
- await this.formatCode();
2190
2343
  }
2191
2344
  }
2192
2345
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-z3",
3
- "version": "0.0.10",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "description": "CLI for scaffolding Z3 Stack applications (TanStack/Next.js + Convex + Better Auth)",
6
6
  "bin": {
@@ -25,7 +25,8 @@
25
25
  "ora": "^8.1.0",
26
26
  "execa": "^9.5.2",
27
27
  "sort-package-json": "^2.10.0",
28
- "validate-npm-package-name": "^5.0.0"
28
+ "validate-npm-package-name": "^5.0.0",
29
+ "color-convert": "^2.0.1"
29
30
  },
30
31
  "devDependencies": {
31
32
  "typescript": "^5.7.0",
@@ -33,6 +34,7 @@
33
34
  "@types/node": "^22.0.0",
34
35
  "@types/fs-extra": "^11.0.0",
35
36
  "@types/validate-npm-package-name": "^4.0.0",
37
+ "@types/color-convert": "^2.0.3",
36
38
  "vitest": "^2.0.0"
37
39
  },
38
40
  "engines": {