-
Notifications
You must be signed in to change notification settings - Fork 1
HeroUI and Tailwind v4 Setup | Development #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2e4dba9
9ba300e
6943490
c727666
39065d0
70da204
52ca7b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -176,3 +176,33 @@ export async function configureTailwindForHeroUI(projectPath: string) { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| await sourceFile.save(); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| export async function configureGlobalCssForHeroUI(projectPath: string) { | ||||||||||||||||||||||||||||||||||
| const cssPath = path.join(projectPath, "src/app/globals.css"); | ||||||||||||||||||||||||||||||||||
| if (!fs.existsSync(cssPath)) return; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| let content = await fs.readFile(cssPath, "utf-8"); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Check if it's already configured to avoid duplication | ||||||||||||||||||||||||||||||||||
| if (content.includes("@plugin './hero.ts';")) return; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| if (content.includes("@plugin './hero.ts';")) return; | |
| const heroPluginPattern = /@plugin\s+["']\.\/hero\.ts["']\s*;?/; | |
| if (heroPluginPattern.test(content)) return; |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @source directive uses a relative path that starts from src/app/globals.css and navigates up to node_modules. However, if the hero.ts file is created at the project root (as done in scaffold.ts line 618), the path relationship may be inconsistent. The @plugin directive references './hero.ts' which is relative to the CSS file location, but hero.ts is created at the project root, not at src/app/hero.ts. This path mismatch will cause the plugin to not be found at runtime.
| if (content.includes("@plugin './hero.ts';")) return; | |
| // Replace default tailwind import with v4 setup | |
| // We assume standard create-next-app output which usually starts with directives | |
| // Or just prepend/replace the top part. | |
| const v4Setup = `@import "tailwindcss"; | |
| @plugin './hero.ts'; | |
| if (content.includes("@plugin '../../hero.ts';")) return; | |
| // Replace default tailwind import with v4 setup | |
| // We assume standard create-next-app output which usually starts with directives | |
| // Or just prepend/replace the top part. | |
| const v4Setup = `@import "tailwindcss"; | |
| @plugin '../../hero.ts'; |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The String.prototype.replace() method only replaces the first occurrence by default. If the globals.css file contains multiple instances of @import "tailwindcss"; (which could happen in edge cases or user-modified files), only the first one would be replaced, potentially leaving duplicate or conflicting imports in the file.
| content = content.replace('@import "tailwindcss";', v4Setup); | |
| let replaced = false; | |
| content = content.replace(/@import "tailwindcss";/g, () => { | |
| if (!replaced) { | |
| replaced = true; | |
| return v4Setup; | |
| } | |
| return ""; | |
| }); |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the fallback case where no standard Tailwind import is found, the v4 setup is prepended to the entire existing content. This could result in the new directives being inserted in the middle of an existing CSS rule or comment block, potentially breaking the CSS. Consider adding validation to ensure the content structure is appropriate before prepending, or add a newline separator to reduce the risk of CSS syntax errors.
| content = v4Setup + content; | |
| const separator = | |
| content.startsWith("\n") || content.startsWith("\r\n") ? "" : "\n"; | |
| content = v4Setup + separator + content; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -55,7 +55,11 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getDlxCommand, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PackageManager, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "./lib/pm.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { addProviderToLayout, configureTailwindForHeroUI } from "./lib/ast.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| addProviderToLayout, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| configureTailwindForHeroUI, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| configureGlobalCssForHeroUI, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "./lib/ast.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { DependencyCollector } from "./lib/deps.js"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import prompts from "prompts"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -244,6 +248,13 @@ export const scaffoldProject = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spinner.fail("Installation failed"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.red("\nError:"), error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.yellow("\nTroubleshooting Tips:")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.white(" • If you see 'EACCES' or permission errors, try running:")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.cyan(" sudo chown -R $(whoami) ~/.npm")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.white(" • If you see 'EEXIST' or cache errors, try:")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.cyan(" npm cache clean --force")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+252
to
+256
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(chalk.yellow("\nTroubleshooting Tips:")); | |
| console.log(chalk.white(" • If you see 'EACCES' or permission errors, try running:")); | |
| console.log(chalk.cyan(" sudo chown -R $(whoami) ~/.npm")); | |
| console.log(chalk.white(" • If you see 'EEXIST' or cache errors, try:")); | |
| console.log(chalk.cyan(" npm cache clean --force")); | |
| const ownershipDir = | |
| pm === "yarn" | |
| ? "~/.cache/yarn" | |
| : pm === "pnpm" | |
| ? "~/.pnpm-store" | |
| : pm === "bun" | |
| ? "~/.bun" | |
| : "~/.npm"; | |
| const cacheCommand = | |
| pm === "yarn" | |
| ? "yarn cache clean" | |
| : pm === "pnpm" | |
| ? "pnpm store prune" | |
| : pm === "bun" | |
| ? "bun install --force" | |
| : "npm cache clean --force"; | |
| console.log(chalk.yellow("\nTroubleshooting Tips:")); | |
| console.log( | |
| chalk.white(" • If you see 'EACCES' or permission errors, try running:") | |
| ); | |
| console.log( | |
| chalk.cyan(` sudo chown -R $(whoami) ${ownershipDir}`) | |
| ); | |
| console.log( | |
| chalk.white(" • If you see 'EEXIST' or cache errors, try:") | |
| ); | |
| console.log(chalk.cyan(` ${cacheCommand}`)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function
configureGlobalCssForHeroUIlacks documentation. Adding a JSDoc comment would help explain its purpose, parameters, return value, and any assumptions it makes (such as the expected structure of globals.css or the relationship between hero.ts location and CSS file location).