Skip to content

Commit 0f42575

Browse files
authored
fix: duplicate tailwindcss dependency (#76)
closes #75 <details> <summary>diff from main</summary> ![v6NZTR9c 2025-03-30 at 12 34 AM@2x](https://github.com/user-attachments/assets/32ce64f8-801d-4e1e-9437-2ac94442668d) </details>
1 parent b3e1801 commit 0f42575

File tree

7 files changed

+133
-14
lines changed

7 files changed

+133
-14
lines changed

templates/react/add-on/start/assets/postcss.config.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

templates/react/add-on/start/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
},
77
"dependencies": {
88
"@tanstack/react-router-with-query": "^1.114.3",
9-
"@tailwindcss/postcss": "^4.0.7",
109
"@tanstack/react-start": "^1.114.3",
11-
"postcss": "^8.5.2",
1210
"vinxi": "^0.5.3",
1311
"vite-tsconfig-paths": "^5.1.4"
1412
}

templates/solid/add-on/start/assets/postcss.config.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

templates/solid/add-on/start/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
"start": "vinxi start"
66
},
77
"dependencies": {
8-
"@tailwindcss/postcss": "^4.0.7",
98
"@tanstack/solid-start": "^1.114.3",
10-
"postcss": "^8.5.2",
119
"vinxi": "^0.5.3",
1210
"vite-tsconfig-paths": "^5.1.4"
1311
}

tests/cra.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, expect, test } from 'vitest'
22

33
import { createApp } from '../src/create-app.js'
4+
import { finalizeAddOns } from '../src/add-ons.js';
45
import { cleanupOutput, createTestEnvironment } from './test-utilities.js'
56

67
describe('React Templates', () => {
@@ -115,6 +116,36 @@ describe('React Templates', () => {
115116
'./snapshots/cra/fr-ts-tw-npm.json',
116117
)
117118
})
119+
120+
test('file router with add-on start on npm', async () => {
121+
const projectName = 'TEST';
122+
const framework = 'react'
123+
const template = 'file-router'
124+
const { environment, output } = createTestEnvironment(projectName);
125+
await createApp(
126+
{
127+
addOns: true,
128+
framework,
129+
chosenAddOns: await finalizeAddOns(framework, template, ['start']),
130+
git: true,
131+
mode: template,
132+
packageManager: 'npm',
133+
projectName,
134+
tailwind: true,
135+
toolchain: 'none',
136+
typescript: true,
137+
variableValues: {},
138+
},
139+
{
140+
silent: true,
141+
environment,
142+
},
143+
);
144+
cleanupOutput(output);
145+
await expect(JSON.stringify(output, null, 2)).toMatchFileSnapshot(
146+
'./snapshots/cra/cr-ts-start-npm.json',
147+
);
148+
});
118149
})
119150

120151
describe('Solid Templates', () => {
@@ -229,4 +260,34 @@ describe('Solid Templates', () => {
229260
'./snapshots/cra/solid-fr-ts-tw-npm.json',
230261
)
231262
})
263+
264+
test('file router with add-on start on npm', async () => {
265+
const projectName = 'TEST';
266+
const framework = 'solid';
267+
const template = 'file-router';
268+
const { environment, output } = createTestEnvironment(projectName);
269+
await createApp(
270+
{
271+
addOns: true,
272+
framework,
273+
chosenAddOns: await finalizeAddOns(framework, template, ['start']),
274+
git: true,
275+
mode: template,
276+
packageManager: 'npm',
277+
projectName,
278+
tailwind: true,
279+
toolchain: 'none',
280+
typescript: true,
281+
variableValues: {},
282+
},
283+
{
284+
silent: true,
285+
environment,
286+
},
287+
);
288+
cleanupOutput(output);
289+
await expect(JSON.stringify(output, null, 2)).toMatchFileSnapshot(
290+
'./snapshots/cra/solid-cr-ts-start-npm.json',
291+
);
292+
});
232293
})

tests/snapshots/cra/cr-ts-start-npm.json

Lines changed: 37 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"files": {
3+
".gitignore": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n",
4+
"/.vscode/settings.json": "{\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n",
5+
"/public/manifest.json": "{\n \"short_name\": \"TanStack App\",\n \"name\": \"Create TanStack App Sample\",\n \"icons\": [\n {\n \"src\": \"favicon.ico\",\n \"sizes\": \"64x64 32x32 24x24 16x16\",\n \"type\": \"image/x-icon\"\n },\n {\n \"src\": \"logo192.png\",\n \"type\": \"image/png\",\n \"sizes\": \"192x192\"\n },\n {\n \"src\": \"logo512.png\",\n \"type\": \"image/png\",\n \"sizes\": \"512x512\"\n }\n ],\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"theme_color\": \"#000000\",\n \"background_color\": \"#ffffff\"\n}\n",
6+
"/public/robots.txt": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n",
7+
"/src/api.ts": "import {\n createStartAPIHandler,\n defaultAPIFileRouteHandler,\n} from '@tanstack/solid-start/api'\n\nexport default createStartAPIHandler(defaultAPIFileRouteHandler)\n",
8+
"/src/client.tsx": "import { hydrate } from 'solid-js/web'\nimport { StartClient } from '@tanstack/solid-start'\nimport { createRouter } from './router'\n\nconst router = createRouter()\n\nhydrate(() => <StartClient router={router} />, document.body)\n",
9+
"/src/components/Header.tsx": "import { Link } from '@tanstack/solid-router'\n\nexport default function Header() {\n return (\n <header class=\"p-2 flex gap-2 bg-white text-black justify-between\">\n <nav class=\"flex flex-row\">\n <div class=\"px-2 font-bold\">\n <Link to=\"/\">Home</Link>\n </div>\n\n <div class=\"px-2 font-bold\">\n <Link to=\"/demo/start/server-funcs\">Start - Server Functions</Link>\n </div>\n </nav>\n\n <div></div>\n </header>\n )\n}\n",
10+
"/src/router.tsx": "import { createRouter as createTanstackRouter } from '@tanstack/solid-router'\n\n// Import the generated route tree\nimport { routeTree } from './routeTree.gen'\n\nimport './styles.css'\n\n// Create a new router instance\nexport const createRouter = () => {\n const router = createTanstackRouter({\n routeTree,\n scrollRestoration: true,\n })\n return router\n}\n\nconst router = createRouter()\n\n// Register the router instance for type safety\ndeclare module '@tanstack/solid-router' {\n interface Register {\n router: typeof router\n }\n}\n",
11+
"/src/routes/__root.tsx": "import { Outlet, createRootRouteWithContext } from '@tanstack/solid-router'\nimport { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'\n\nimport Header from '../components/Header'\n\nexport const Route = createRootRouteWithContext()({\n component: RootComponent,\n})\n\nfunction RootComponent() {\n return (\n <>\n <Header />\n\n <Outlet />\n {/* <TanStackRouterDevtools /> */}\n </>\n )\n}\n",
12+
"/src/routes/demo.start.server-funcs.tsx": "import * as fs from 'fs'\nimport { createFileRoute, useRouter } from '@tanstack/solid-router'\nimport { createServerFn } from '@tanstack/solid-start'\n\nconst filePath = 'count.txt'\n\nasync function readCount() {\n return parseInt(\n await fs.promises.readFile(filePath, 'utf-8').catch(() => '0'),\n )\n}\n\nconst getCount = createServerFn({\n method: 'GET',\n}).handler(() => {\n return readCount()\n})\n\nconst updateCount = createServerFn({ method: 'POST' })\n .validator((d: number) => d)\n .handler(async ({ data }) => {\n const count = await readCount()\n await fs.promises.writeFile(filePath, `${count + data}`)\n })\n\nexport const Route = createFileRoute('/demo/start/server-funcs')({\n component: Home,\n loader: async () => await getCount(),\n})\n\nfunction Home() {\n const router = useRouter()\n const state = Route.useLoaderData()\n\n return (\n <div class=\"p-4\">\n <button\n onClick={() => {\n updateCount({ data: 1 }).then(() => {\n router.invalidate()\n })\n }}\n claclassssName=\"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded\"\n >\n Add 1 to {state}?\n </button>\n </div>\n )\n}\n",
13+
"/src/routes/index.tsx": "import { createFileRoute } from '@tanstack/solid-router'\nimport logo from '../logo.svg'\n\nexport const Route = createFileRoute('/')({\n component: App,\n})\n\nfunction App() {\n return (\n <main class=\"min-h-screen flex flex-col items-center justify-center bg-[#282c34] text-white text-[calc(10px+2vmin)] text-center\">\n <img\n src={logo}\n class=\"h-[40vmin] pointer-events-none animate-[spin_20s_linear_infinite]\"\n alt=\"logo\"\n />\n <p>\n Edit <code>src/routes/index.tsx</code> and save to reload.\n </p>\n <a\n class=\"text-[#61dafb] hover:underline\"\n href=\"https://solidjs.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn Solid\n </a>\n <a\n class=\"text-[#61dafb] hover:underline\"\n href=\"https://tanstack.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn TanStack\n </a>\n </main>\n )\n}\n",
14+
"/src/ssr.tsx": "import {\n createStartHandler,\n defaultStreamHandler,\n} from '@tanstack/solid-start/server'\nimport { getRouterManifest } from '@tanstack/solid-start/router-manifest'\n\nimport { createRouter } from './router'\n\nexport default createStartHandler({\n createRouter,\n getRouterManifest,\n})(defaultStreamHandler)\n",
15+
"/src/styles.css": "@import \"tailwindcss\";\n\nbody {\n @apply m-0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n",
16+
"README.md": "Welcome to your new TanStack app! \n\n# Getting Started\n\nTo run this application:\n\n```bash\nnpm install\nnpm run start\n```\n\n# Building For Production\n\nTo build this application for production:\n\n```bash\nnpm run build\n```\n\n## Styling\n\nThis project uses [Tailwind CSS](https://tailwindcss.com/) for styling.\n\n\n\n## Routing\nThis project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as fiels in `src/routes`.\n\n### Adding A Route\n\nTo add a new route to your application just add another a new file in the `./src/routes` directory.\n\nTanStack will automatically generate the content of the route file for you.\n\nNow that you have two routes you can use a `Link` component to navigate between them.\n\n### Adding Links\n\nTo use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/solid-router`.\n\n```tsx\nimport { Link } from \"@tanstack/solid-router\";\n```\n\nThen anywhere in your JSX you can use it like so:\n\n```tsx\n<Link to=\"/about\">About</Link>\n```\n\nThis will create a link that will navigate to the `/about` route.\n\nMore information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/solid/api/router/linkComponent).\n\n### Using A Layout\n\nIn the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.\n\nHere is an example layout that includes a header:\n\n```tsx\nimport { Outlet, createRootRoute } from '@tanstack/solid-router'\nimport { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'\n\nimport { Link } from \"@tanstack/solid-router\";\n\nexport const Route = createRootRoute({\n component: () => (\n <>\n <header>\n <nav>\n <Link to=\"/\">Home</Link>\n <Link to=\"/about\">About</Link>\n </nav>\n </header>\n <Outlet />\n <TanStackRouterDevtools />\n </>\n ),\n})\n```\n\nThe `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.\n\nMore information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/solid/guide/routing-concepts#layouts).\n\n## Data Fetching\n\nThere are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.\n\nFor example:\n\n```tsx\nconst peopleRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: \"/people\",\n loader: async () => {\n const response = await fetch(\"https://swapi.dev/api/people\");\n return response.json() as Promise<{\n results: {\n name: string;\n }[];\n }>;\n },\n component: () => {\n const data = peopleRoute.useLoaderData();\n return (\n <ul>\n {data.results.map((person) => (\n <li key={person.name}>{person.name}</li>\n ))}\n </ul>\n );\n },\n});\n```\n\nLoaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/solid/guide/data-loading#loader-parameters).\n\n# Demo files\n\nFiles prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.\n\n\n\n# Learn More\n\nYou can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).\n",
17+
"app.config.ts": "import { defineConfig } from '@tanstack/solid-start/config'\nimport viteTsConfigPaths from 'vite-tsconfig-paths'\n\nexport default defineConfig({\n tsr: {\n appDirectory: 'src',\n },\n vite: {\n plugins: [\n // this is the plugin that enables path aliases\n viteTsConfigPaths({\n projects: ['./tsconfig.json'],\n }),\n ],\n },\n})\n",
18+
"package.json": "{\n \"name\": \"TEST\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"start\": \"vinxi start\",\n \"build\": \"vinxi build\",\n \"serve\": \"vite preview\",\n \"test\": \"vitest run\",\n \"dev\": \"vinxi dev\"\n },\n \"dependencies\": {\n \"@tailwindcss/vite\": \"^4.0.6\",\n \"@tanstack/router-plugin\": \"^1.109.2\",\n \"@tanstack/solid-router\": \"^1.110.0\",\n \"@tanstack/solid-router-devtools\": \"^1.109.2\",\n \"@tanstack/solid-start\": \"^1.114.3\",\n \"solid-js\": \"^1.9.4\",\n \"tailwindcss\": \"^4.0.6\",\n \"vinxi\": \"^0.5.3\",\n \"vite-tsconfig-paths\": \"^5.1.4\"\n },\n \"devDependencies\": {\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^6.0.11\",\n \"vite-plugin-solid\": \"^2.11.2\"\n }\n}",
19+
"tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"preserve\",\n \"jsxImportSource\": \"solid-js\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true\n }\n}\n"
20+
},
21+
"commands": [
22+
{
23+
"command": "npm",
24+
"args": [
25+
"install"
26+
]
27+
},
28+
{
29+
"command": "git",
30+
"args": [
31+
"init"
32+
]
33+
}
34+
]
35+
}

0 commit comments

Comments
 (0)