From e32c081ad7c5e85a75c224cba8610012c47bffa0 Mon Sep 17 00:00:00 2001 From: TechTide AI Date: Thu, 21 May 2026 19:15:32 -0400 Subject: [PATCH 1/2] fix: add missing PostCSS config for Tailwind v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The project uses `@tailwindcss/postcss` (v4) and imports Tailwind via `@import tailwindcss` in globals.css, but no PostCSS configuration file existed to register the plugin. Without it, Next.js never processes the Tailwind directives and all utility classes are absent in production builds — resulting in completely unstyled output. Fixes #84 --- postcss.config.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 postcss.config.mjs diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..a869506 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +} + +export default config From 636e8963a2f5744fe82f38e609f269061dd121c0 Mon Sep 17 00:00:00 2001 From: TechTide AI Date: Tue, 23 Jun 2026 01:18:43 -0400 Subject: [PATCH 2/2] test: assert Tailwind v4 utilities are emitted in build output Adds scripts/assert-tailwind-css.mjs and a verify:css npm script, wired into CI after the build step. It scans the .next output for compiled Tailwind utilities (.flex, .grid, .items-center, .p-4, .text-sm) and fails if they are absent. This guards the exact regression this PR fixes (#84): a missing postcss.config.mjs lets `next build` succeed while silently emitting CSS with no Tailwind utilities, leaving the UI unstyled. The build alone does not catch this; the assertion does. --- .github/workflows/ci.yml | 3 ++ package.json | 1 + scripts/assert-tailwind-css.mjs | 64 +++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 scripts/assert-tailwind-css.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1f70e6..7abf770 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,6 @@ jobs: - name: Build run: pnpm run build + + - name: Verify Tailwind CSS compiled + run: pnpm run verify:css diff --git a/package.json b/package.json index 587c527..d29a21c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "start": "next start", "lint": "pnpm exec eslint .", "typecheck": "tsc --noEmit", + "verify:css": "node scripts/assert-tailwind-css.mjs", "format": "prettier --write ." }, "keywords": [ diff --git a/scripts/assert-tailwind-css.mjs b/scripts/assert-tailwind-css.mjs new file mode 100644 index 0000000..383c9cd --- /dev/null +++ b/scripts/assert-tailwind-css.mjs @@ -0,0 +1,64 @@ +// Asserts that the production build emitted compiled Tailwind v4 utility CSS. +// +// This is a regression guard for the bug fixed in PR #92 / issue #84: without a +// PostCSS config registering `@tailwindcss/postcss`, the `@import "tailwindcss"` +// directive in app/globals.css is never processed, so the build emits HTML with +// no Tailwind utility classes and the UI renders completely unstyled. +// +// Run AFTER `next build`. Scans the .next output for known utility classes that +// must be present whenever Tailwind v4 compilation is working. + +import { readdirSync, readFileSync, statSync } from 'node:fs' +import { join } from 'node:path' + +const BUILD_DIR = '.next' + +// Utilities used by the app's own components — if PostCSS processed Tailwind, +// these compile into real rules. If the config is missing, they are absent. +const REQUIRED_UTILITIES = ['.flex', '.grid', '.items-center', '.p-4', '.text-sm'] + +function collectCssFiles(dir) { + const out = [] + for (const entry of readdirSync(dir)) { + const full = join(dir, entry) + if (statSync(full).isDirectory()) { + out.push(...collectCssFiles(full)) + } else if (entry.endsWith('.css')) { + out.push(full) + } + } + return out +} + +function fail(message) { + console.error(`\n[assert-tailwind-css] FAIL: ${message}\n`) + process.exit(1) +} + +let cssFiles +try { + cssFiles = collectCssFiles(BUILD_DIR) +} catch { + fail(`build output "${BUILD_DIR}" not found — run \`pnpm build\` first.`) +} + +if (cssFiles.length === 0) { + fail('no CSS files emitted by the build — Tailwind/PostCSS is not running.') +} + +const allCss = cssFiles.map((f) => readFileSync(f, 'utf8')).join('\n') + +const missing = REQUIRED_UTILITIES.filter((cls) => !allCss.includes(`${cls}{`) && !allCss.includes(`${cls} `) && !allCss.includes(`${cls},`) && !allCss.includes(`${cls}:`)) + +if (missing.length > 0) { + fail( + `compiled CSS is missing expected Tailwind utilities: ${missing.join(', ')}.\n` + + 'This usually means postcss.config.mjs is missing or not registering ' + + '@tailwindcss/postcss, so `@import "tailwindcss"` was never processed.', + ) +} + +console.log( + `[assert-tailwind-css] OK: found Tailwind utilities (${REQUIRED_UTILITIES.join(', ')}) ` + + `in ${cssFiles.length} emitted CSS file(s).`, +)