Repository: QwikDev/qwik
Pull request #7403: feat(cli): add ability to keep using tailwind v3
Author: login: maiieul
Created: 2025-03-08T15:22:21Z | Merged: 2025-03-11T19:31:24Z

<!--
The Qwik Team and Community appreciate all PRs. Thank you for your effort! Not all PRs can be merged, but those that meet the following criteria will be prioritized:

a) Core fixes, and

b) Framework functionality achievable only by the core.

If this PR can be done as a 3rd-Party Community Add-On, we encourage that for quicker adoption.

If you believe your functionality is valuable to the entire Qwik Community, discuss it in the Qwik Discord channels for potential inclusion in the core.

First of all, make sure your PR title is descriptive and matches our commit title guidelines.

Also make sure your PR follows all the guidelines in the [CONTRIBUTING.md](./CONTRIBUTING.md) document.

-->

# What is it?

<!-- pick one and remove the others -->

- Feature / enhancement

# Description

Some projects might not be able to use tailwind v4 yet. qwik-ui/styled hasn't been updated for tailwind v4 yet. I think even after updating to tailwind v4, we should keep a qwik-ui subdomain live for tailwind v3 for some time.

# Checklist

<!--
* delete the items that are not relevant, so it's easy to tell if the PR is ready to be merged
* add items that are relevant and need to be done before merging
-->

- [x] My code follows the [developer guidelines of this project](https://github.com/QwikDev/qwik/blob/main/CONTRIBUTING.md)
- [x] I performed a self-review of my own code
- [x] I added a changeset with `pnpm change`
- [x] I made corresponding changes to the Qwik docs
- [ ] I added new tests to cover the fix / functionality



Diff:
diff --git a/.changeset/pole-comfort-active.md b/.changeset/pole-comfort-active.md
new file mode 100644
index 00000000000..e1977ef96b8
--- /dev/null
+++ b/.changeset/pole-comfort-active.md
@@ -0,0 +1,5 @@
+---
+'@builder.io/qwik': patch
+---
+
+✨ Ability to keep using tailwind v3 through the cli
diff --git a/packages/docs/src/routes/docs/integrations/tailwind-v3/index.mdx b/packages/docs/src/routes/docs/integrations/tailwind-v3/index.mdx
new file mode 100644
index 00000000000..a6c44506161
--- /dev/null
+++ b/packages/docs/src/routes/docs/integrations/tailwind-v3/index.mdx
@@ -0,0 +1,71 @@
+---
+title: Tailwind | Integrations
+keywords: 'styles, styling'
+contributors:
+  - manucorporat
+  - leifermendez
+  - reemardelarosa
+  - mhevery
+  - nickclark
+  - igorbabko
+  - Benny-Nottonson
+  - mrhoodz
+  - NickClark
+  - adamdbradley
+  - sreeisalso
+  - maiieul
+updated_at: '2025-03-08T18:53:23Z'
+created_at: '2023-04-06T21:28:28Z'
+---
+
+import PackageManagerTabs from '~/components/package-manager-tabs/index.tsx';
+
+# Tailwind
+Tailwind is a CSS framework that provides us with single-purpose utility classes which are
+opinionated for the most part, and which help us design our web pages from right inside our
+markup or `.js/.jsx/.ts/.tsx/.mdx` files. [Tailwindcss Website](https://tailwindcss.com/)
+## Usage
+You can add Tailwind easily by using the following Qwik starter script:
+<PackageManagerTabs>
+<span q:slot="pnpm">
+```shell
+pnpm run qwik add tailwind-v3
+```
+</span>
+<span q:slot="npm">
+```shell
+npm run qwik add tailwind-v3
+```
+</span>
+<span q:slot="yarn">
+```shell
+yarn run qwik add tailwind-v3
+```
+</span>
+<span q:slot="bun">
+```shell
+bun run qwik add tailwind-v3
+```
+</span>
+</PackageManagerTabs>
+
+The previous command updates your app with the necessary dependencies.
+
+It also adds new files to your project folder:
+
+- `postcss.config.js`
+- `tailwind.config.js`
+- `.vscode/settings.json`
+
+and modifies your `src/global.css` to include
+
+```css title="src/global.css"
+
+# global.css file
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+...stuff...
+```
\ No newline at end of file
diff --git a/packages/docs/src/routes/docs/integrations/tailwind/index.mdx b/packages/docs/src/routes/docs/integrations/tailwind/index.mdx
index a5a44f90779..cdca6172e94 100644
--- a/packages/docs/src/routes/docs/integrations/tailwind/index.mdx
+++ b/packages/docs/src/routes/docs/integrations/tailwind/index.mdx
@@ -13,7 +13,8 @@ contributors:
   - NickClark
   - adamdbradley
   - sreeisalso
-updated_at: '2025-01-24T18:53:23Z'
+  - maiieul
+updated_at: '2025-03-08T18:53:23Z'
 created_at: '2023-04-06T21:28:28Z'
 ---
 
@@ -25,9 +26,11 @@ Tailwind is a CSS framework that provides us with single-purpose utility classes
 opinionated for the most part, and which help us design our web pages from right inside our
 markup or `.js/.jsx/.ts/.tsx/.mdx` files. [Tailwindcss Website](https://tailwindcss.com/)
 
+> This page contains updated instructions for tailwind v4. If you need to use tailwind v3, you can find the relevant documentation [here](/docs/integrations/tailwind-v3).
+
 ## Usage
 
-You can add Tailwind easily by using the following Qwik starter script:
+You can add Tailwind v4 easily by using the following Qwik starter script:
 
 <PackageManagerTabs>
 <span q:slot="pnpm">
@@ -53,7 +56,7 @@ bun run qwik add tailwind
 </PackageManagerTabs>
 
 The previous command updates your app with the necessary dependencies,
-and modifies following files
+and modifies the following files
 
 ```css title="src/global.css"
 
diff --git a/starters/README.md b/starters/README.md
index 1cf4e5b3917..3816b254af3 100644
--- a/starters/README.md
+++ b/starters/README.md
@@ -1,47 +1,30 @@
 # Starters
 
-This folder stores "starter" projects for the CLI. The idea is that during the CLI execution, the developer can choose a particular starter app and combine it with a specific server and features.
+This folder stores "starter" projects for the cli. The idea is that during the cli execution, the developer can choose a particular starter app and combine it with a specific server and features.
 
 All starters are based on `starters/apps/base`, including the `package.json` and `tsconfig.json`. Depending on the options the user selects, their starter merges into the `base` app.
 
 ## Developer
 
-Here are steps to try out the CLI in a local environment.
+Here are steps to try out the cli in a local environment.
 
-1. Build CLI:
+1. Build the cli:
 
-   ```
-   # pnpm build.cli
-   ```
-
-1. Run CLI:
-
-   ```
-   # node ./packages/create-qwik/dist/create-qwik.cjs
-   💫 Let's create a Qwik project 💫
-
-   ✔ Project name … todo-express
-   ✔ Select a starter › Todo
-   ✔ Select a server › Express
+```zsh
+pnpm build.cli
+```
 
-   ⭐️ Success! Project saved in todo-express directory
+2. Run the cli:
 
-   📟 Next steps:
-   cd todo-express
-   npm install
-   npm start
-   ```
+```zsh
+pnpm cli.qwik
+```
 
-1. Change to generated location
-   ```
-   cd todo-express
-   npm install
-   npm start
-   ```
+> If you want to test the cli on consumer repository, you can `pnpm link.dist` on the qwik monorepo, then `pnpm link --global @builder.io/qwik` on the consumer project, and finally run the cli from there.
 
-## Publishing `create-qwik` CLI Package
+## Publishing `create-qwik` cli Package
 
-The starter CLI is published at the same time as `@builder.io/qwik`. When published, the CLI will update the `base` app's package.json to point to the published version of Qwik.
+The starter cli is published at the same time as `@builder.io/qwik`. When published, the cli will update the `base` app's package.json to point to the published version of Qwik.
 
 The base app's package.json's devDependencies are updated with:
 
diff --git a/starters/features/tailwind-v3/.vscode/settings.json b/starters/features/tailwind-v3/.vscode/settings.json
new file mode 100644
index 00000000000..5a586b3d1ef
--- /dev/null
+++ b/starters/features/tailwind-v3/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+  "css.lint.unknownAtRules": "ignore"
+}
diff --git a/starters/features/tailwind-v3/package.json b/starters/features/tailwind-v3/package.json
new file mode 100644
index 00000000000..a2418146bd5
--- /dev/null
+++ b/starters/features/tailwind-v3/package.json
@@ -0,0 +1,21 @@
+{
+  "description": "Use Tailwind v3 in your Qwik app",
+  "__qwik__": {
+    "displayName": "Integration: Tailwind v3 (styling)",
+    "priority": -10,
+    "viteConfig": {},
+    "docs": [
+      "https://qwik.dev/integrations/integration/tailwind/",
+      "https://tailwindcss.com/docs/utility-first"
+    ],
+    "alwaysInRoot": [
+      ".vscode"
+    ]
+  },
+  "devDependencies": {
+    "autoprefixer": "^10.4.19",
+    "postcss": "^8.4.39",
+    "prettier-plugin-tailwindcss": "^0.5.4",
+    "tailwindcss": "^3.4.17"
+  }
+}
diff --git a/starters/features/tailwind-v3/postcss.config.cjs b/starters/features/tailwind-v3/postcss.config.cjs
new file mode 100644
index 00000000000..12a703d900d
--- /dev/null
+++ b/starters/features/tailwind-v3/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+};
diff --git a/starters/features/tailwind-v3/src/global.css b/starters/features/tailwind-v3/src/global.css
new file mode 100644
index 00000000000..b089ddbbc82
--- /dev/null
+++ b/starters/features/tailwind-v3/src/global.css
@@ -0,0 +1,7 @@
+/**
+ * Tailwind CSS imports
+ * View the full documentation at https://tailwindcss.com
+ */
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/starters/features/tailwind-v3/tailwind.config.js b/starters/features/tailwind-v3/tailwind.config.js
new file mode 100644
index 00000000000..2479ed4e88f
--- /dev/null
+++ b/starters/features/tailwind-v3/tailwind.config.js
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+  content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
+  theme: {
+    extend: {},
+  },
+  plugins: [],
+};
\ No newline at end of file
diff --git a/starters/features/tailwind/package.json b/starters/features/tailwind/package.json
index d1b3e5dda2c..829a56a7a02 100644
--- a/starters/features/tailwind/package.json
+++ b/starters/features/tailwind/package.json
@@ -1,7 +1,7 @@
 {
-  "description": "Use Tailwind in your Qwik app",
+  "description": "Use Tailwind v4 in your Qwik app",
   "__qwik__": {
-    "displayName": "Integration: Tailwind (styling)",
+    "displayName": "Integration: Tailwind v4 (styling)",
     "priority": -10,
         "viteConfig": {
             "imports": [


Reviews:
user: login: maiieul
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-08T16:52:27Z
user: login: maiieul
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-08T17:06:18Z
user: login: wmertens
body: ![LGTM](https://image.lgtmoon.dev/165367)
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-10T16:37:11Z
user: login: gioboa
body: Thanks, great idea :clap: 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-10T16:59:49Z
user: login: maiieul
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-11T19:31:17Z

Review comments:
diff_hunk: @@ -159,7 +159,7 @@ jobs:
             packages/eslint-plugin-qwik/dist
             packages/create-qwik/dist
           # note that all inputs need to be listed here, including qwik, for correct cache invalidation
-          key: ${{ hashfiles('qwik-key.txt', 'rust-key.txt', 'packages/qwik-city/**/*', 'packages/qwik-labs/**/*', 'packages/qwik-react/**/*', 'packages/eslint-plugin-qwik/**/*', 'packages/create-qwik/**/*', 'starters/apps/**/*', 'starters/features/**/*', 'starters/adapters/**/*', '!**/*.unit.*') }}
path: .github/workflows/ci.yml
user: login: maiieul
body: I had to remove `'starters/features/**/*'` for the build.qwik to spin up 🤔
created_at: 2025-03-08T16:52:26Z
author_association: MEMBER
diff_hunk: @@ -159,7 +159,7 @@ jobs:
             packages/eslint-plugin-qwik/dist
             packages/create-qwik/dist
           # note that all inputs need to be listed here, including qwik, for correct cache invalidation
-          key: ${{ hashfiles('qwik-key.txt', 'rust-key.txt', 'packages/qwik-city/**/*', 'packages/qwik-labs/**/*', 'packages/qwik-react/**/*', 'packages/eslint-plugin-qwik/**/*', 'packages/create-qwik/**/*', 'starters/apps/**/*', 'starters/features/**/*', 'starters/adapters/**/*', '!**/*.unit.*') }}
path: .github/workflows/ci.yml
user: login: maiieul
body: Hmmm seems the pkg.pr.new doesn't work anyways, so bringing this back.
created_at: 2025-03-08T17:06:18Z
author_association: MEMBER
diff_hunk: @@ -1,47 +1,30 @@
 # Starters
 
-This folder stores "starter" projects for the CLI. The idea is that during the CLI execution, the developer can choose a particular starter app and combine it with a specific server and features.
+This folder stores "starter" projects for the cli. The idea is that during the cli execution, the developer can choose a particular starter app and combine it with a specific server and features.
 
 All starters are based on `starters/apps/base`, including the `package.json` and `tsconfig.json`. Depending on the options the user selects, their starter merges into the `base` app.
 
 ## Developer
 
-Here are steps to try out the CLI in a local environment.
+Here are steps to try out the cli in a local environment.
 
-1. Build CLI:
+1. Build the cli:
 
-   ```
-   # pnpm build.cli
-   ```
-
-1. Run CLI:
-
-   ```
-   # node ./packages/create-qwik/dist/create-qwik.cjs
-   💫 Let's create a Qwik project 💫
-
-   ✔ Project name … todo-express
-   ✔ Select a starter › Todo
-   ✔ Select a server › Express
+```zsh
+pnpm build.cli
+```
 
-   ⭐️ Success! Project saved in todo-express directory
+2. Run the cli:
 
-   📟 Next steps:
-   cd todo-express
-   npm install
-   npm start
-   ```
+```zsh
+pnpm cli.qwik
+```
 
-1. Change to generated location
-   ```
-   cd todo-express
-   npm install
-   npm start
-   ```
+> If you want to test the cli on consumer repository, you can `pnpm link.dist` on the qwik monorepo, then `pnpm link --global @builder.io/qwik` on the consumer project, and finally run the cli from there.
 
-## Publishing `create-qwik` CLI Package
+## Publishing `create-qwik` cli Package
path: starters/README.md
user: login: gioboa
body: you changed CLI to lowercase but if I'm not wrong, this should be uppercase because it's an acronym. :thinking: 
created_at: 2025-03-10T16:59:31Z
author_association: MEMBER
diff_hunk: @@ -1,47 +1,30 @@
 # Starters
 
-This folder stores "starter" projects for the CLI. The idea is that during the CLI execution, the developer can choose a particular starter app and combine it with a specific server and features.
+This folder stores "starter" projects for the cli. The idea is that during the cli execution, the developer can choose a particular starter app and combine it with a specific server and features.
 
 All starters are based on `starters/apps/base`, including the `package.json` and `tsconfig.json`. Depending on the options the user selects, their starter merges into the `base` app.
 
 ## Developer
 
-Here are steps to try out the CLI in a local environment.
+Here are steps to try out the cli in a local environment.
 
-1. Build CLI:
+1. Build the cli:
 
-   ```
-   # pnpm build.cli
-   ```
-
-1. Run CLI:
-
-   ```
-   # node ./packages/create-qwik/dist/create-qwik.cjs
-   💫 Let's create a Qwik project 💫
-
-   ✔ Project name … todo-express
-   ✔ Select a starter › Todo
-   ✔ Select a server › Express
+```zsh
+pnpm build.cli
+```
 
-   ⭐️ Success! Project saved in todo-express directory
+2. Run the cli:
 
-   📟 Next steps:
-   cd todo-express
-   npm install
-   npm start
-   ```
+```zsh
+pnpm cli.qwik
+```
 
-1. Change to generated location
-   ```
-   cd todo-express
-   npm install
-   npm start
-   ```
+> If you want to test the cli on consumer repository, you can `pnpm link.dist` on the qwik monorepo, then `pnpm link --global @builder.io/qwik` on the consumer project, and finally run the cli from there.
 
-## Publishing `create-qwik` CLI Package
+## Publishing `create-qwik` cli Package
path: starters/README.md
user: login: maiieul
body: Hmmm, I prefer lowercase feels more modern to me. I think it's not a big deal as this is an internal readme anyways. I'll merge as I'm too lazy to bring it back 👅 
created_at: 2025-03-11T19:31:16Z
author_association: MEMBER

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-08T15:22:25Z
body: ###  🦋  Changeset detected

Latest commit: 407e7076676cba12d7e734e4d9d3e51aacdf05e9

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 4 packages</summary>

  | Name                  | Type  |
| --------------------- | ----- |
| @builder.io/qwik      | Patch |
| eslint-plugin-qwik    | Patch |
| @builder.io/qwik-city | Patch |
| create-qwik           | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/maiieul/qwik/new/tailwind-v3-support?filename=.changeset/sweet-jokes-film.md&value=---%0A%22qwik-docs%22%3A%20patch%0A---%0A%0Afeat(cli)%3A%20add%20ability%20to%20keep%20using%20tailwind%20v3%0A)


author_association: NONE
user: login: pkg-pr-new[bot]
created_at: 2025-03-08T15:34:32Z
body: 
[Open in Stackblitz](https://pkg.pr.new/template/67da56c2-8d22-473b-8eb2-757324675956)


```
npm i https://pkg.pr.new/@builder.io/qwik@7403
```


```
npm i https://pkg.pr.new/@builder.io/qwik-city@7403
```


```
npm i https://pkg.pr.new/eslint-plugin-qwik@7403
```


```
npm i https://pkg.pr.new/create-qwik@7403
```


_commit: <a href="https://github.com/QwikDev/qwik/runs/38427249157"><code>ac5c36e</code></a>_

author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-08T16:01:59Z
body: <!-- refined-cf-pages-action:deployment-summary:qwik -->

###### built with [Refined Cloudflare Pages Action](https://github.com/AdrianGonz97/refined-cf-pages-action)
## ⚡ Cloudflare Pages Deployment
| Name | Status | Preview | Last Commit |
| :--- | :----- | :------ | :---------- |
| **qwik-docs** | ✅ Ready ([View Log](https://github.com/QwikDev/qwik/actions/runs/13739506932)) | [Visit Preview](https://maiieul-tailwind-v3-support.qwik-8nx.pages.dev) | ac5c36ee5d3ac10b385148a307b8e3e1f6da9c50 |

author_association: CONTRIBUTOR