create-tsrouter-app 0.0.4 → 0.1.1

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 (32) hide show
  1. package/CONTRIBUTING.md +8 -6
  2. package/README.md +7 -3
  3. package/dist/index.js +105 -46
  4. package/package.json +1 -1
  5. package/src/index.ts +132 -45
  6. package/{project-template → templates/base}/README.md.ejs +36 -4
  7. package/{project-template → templates/base}/package.json +1 -1
  8. package/{project-template → templates/base}/src/App.tsx.ejs +15 -5
  9. package/templates/base/src/logo.svg +43 -0
  10. package/templates/base/vite.config.js.ejs +15 -0
  11. package/templates/file-router/package.fr.json +5 -0
  12. package/templates/file-router/src/main.tsx.ejs +35 -0
  13. package/templates/file-router/src/routes/__root.tsx +11 -0
  14. package/project-template/src/logo.svg +0 -44
  15. package/project-template/vite.config.js.ejs +0 -14
  16. /package/{project-template → templates/base}/.vscode/settings.json +0 -0
  17. /package/{project-template → templates/base}/gitignore +0 -0
  18. /package/{project-template → templates/base}/index.html.ejs +0 -0
  19. /package/{project-template → templates/base}/package.ts.json +0 -0
  20. /package/{project-template → templates/base}/package.tw.json +0 -0
  21. /package/{project-template → templates/base}/public/favicon.ico +0 -0
  22. /package/{project-template → templates/base}/public/logo192.png +0 -0
  23. /package/{project-template → templates/base}/public/logo512.png +0 -0
  24. /package/{project-template → templates/base}/public/manifest.json +0 -0
  25. /package/{project-template → templates/base}/public/robots.txt +0 -0
  26. /package/{project-template → templates/base}/src/App.css +0 -0
  27. /package/{project-template → templates/base}/src/App.test.tsx.ejs +0 -0
  28. /package/{project-template → templates/base}/src/reportWebVitals.ts.ejs +0 -0
  29. /package/{project-template → templates/base}/src/styles.css.ejs +0 -0
  30. /package/{project-template → templates/base}/tsconfig.dev.json +0 -0
  31. /package/{project-template → templates/base}/tsconfig.json +0 -0
  32. /package/{project-template → templates/code-router}/src/main.tsx.ejs +0 -0
package/CONTRIBUTING.md CHANGED
@@ -24,9 +24,11 @@
24
24
 
25
25
  These must all product running applications that can be built (`pnpm build`) and tested (`pnpm test`).
26
26
 
27
- | Command | Description |
28
- | ------------------------------------------------------- | ------------------------------------------ |
29
- | `pnpm start app-js` | Creates a JavaScript app |
30
- | `pnpm start app-ts --template typescript` | Creates a TypeScript app |
31
- | `pnpm start app-js-tw --tailwind` | Creates a JavaScript app with Tailwind CSS |
32
- | `pnpm start app-ts-tw --template typescript --tailwind` | Creates a TypeScript app with Tailwind CSS |
27
+ | Command | Description |
28
+ | -------------------------------------------------------- | ------------------------------------------------------------------ |
29
+ | `pnpm start app-js` | Creates a JavaScript app |
30
+ | `pnpm start app-ts --template typescript` | Creates a TypeScript app |
31
+ | `pnpm start app-js-tw --tailwind` | Creates a JavaScript app with Tailwind CSS |
32
+ | `pnpm start app-ts-tw --template typescript --tailwind` | Creates a TypeScript app with Tailwind CSS |
33
+ | `pnpm start app-fr --template file-router` | Creates a TypeScript app with File Based Routing |
34
+ | `pnpm start app-fr-tw --template file-router --tailwind` | Creates a TypeScript app with File Based Routing with Tailwind CSS |
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This CLI applications builds Tanstack Start applications that are the functional equivalent of [Create React App](https://create-react-app.dev/).
4
4
 
5
- To help accelerate the migration away from create-react-app we created the create-tsrouter-app CLI which is a plug-n-play replacement for CRA.
5
+ To help accelerate the migration away from `create-react-app` we created the `create-tsrouter-app` CLI which is a plug-n-play replacement for CRA.
6
6
 
7
7
  Instead of:
8
8
 
@@ -13,7 +13,7 @@ npx create-react-app my-app
13
13
  You can now run:
14
14
 
15
15
  ```bash
16
- npx create-tsrouter-app my-app
16
+ npx create-tsrouter-app@latest my-app
17
17
  ```
18
18
 
19
19
  Instead of using:
@@ -25,7 +25,7 @@ npx create-react-app my-app --template typescript
25
25
  To create a SPA application using TypeScript. You can now run:
26
26
 
27
27
  ```bash
28
- npx create-tsrouter-app my-app --template typescript
28
+ npx create-tsrouter-app@latest my-app --template typescript
29
29
  ```
30
30
 
31
31
  What you'll get is a Vite application that uses TanStack Router. All the files will still be in the same place as in CRA, but you'll get a fully functional Router setup under in `app/main.tsx`.
@@ -38,6 +38,10 @@ You can also specify your preferred package manager with `--package-manager` suc
38
38
 
39
39
  Extensive documentation on using the TanStack Router, migrating to a File Base Routing approach, as well as integrating [@tanstack/react-query](https://tanstack.com/query/latest) and [@tanstack/store](https://tanstack.com/store/latest) be found in the generated `README.md` for your project.
40
40
 
41
+ ## File Based Routing
42
+
43
+ By default `create-tsrouter-app` will create a Code Based Routing application. If you want to use File Based Routing then you can specify `--template file-router`. The location of the home page will be `app/routes/index.tsx`.
44
+
41
45
  # Contributing
42
46
 
43
47
  Check out the [Contributing](CONTRIBUTING.md) guide.
package/dist/index.js CHANGED
@@ -1,34 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
3
4
  import { resolve } from 'node:path';
4
5
  import { fileURLToPath } from 'node:url';
5
6
  import { Command, InvalidArgumentError } from 'commander';
6
- import { intro, outro, spinner } from '@clack/prompts';
7
+ import { intro, outro, spinner, log } from '@clack/prompts';
7
8
  import { execa } from 'execa';
8
9
  import { render } from 'ejs';
9
10
  import { SUPPORTED_PACKAGE_MANAGERS, getPackageManager, } from './utils/getPackageManager.js';
10
11
  const program = new Command();
11
- const createCopyFile = (templateDir, targetDir) => async function copyFiles(files) {
12
- for (const file of files) {
13
- const targetFileName = file.replace('.tw', '');
14
- await copyFile(resolve(templateDir, file), resolve(targetDir, targetFileName));
15
- }
16
- };
17
- const createTemplateFile = (projectName, options, templateDir, targetDir) => async function templateFile(file, targetFileName) {
18
- const templateValues = {
19
- packageManager: options.packageManager,
20
- projectName: projectName,
21
- typescript: options.typescript,
22
- tailwind: options.tailwind,
23
- js: options.typescript ? 'ts' : 'js',
24
- jsx: options.typescript ? 'tsx' : 'jsx',
12
+ const CODE_ROUTER = 'code-router';
13
+ const FILE_ROUTER = 'file-router';
14
+ function sortObject(obj) {
15
+ return Object.keys(obj)
16
+ .sort()
17
+ .reduce((acc, key) => {
18
+ acc[key] = obj[key];
19
+ return acc;
20
+ }, {});
21
+ }
22
+ function createCopyFile(targetDir) {
23
+ return async function copyFiles(templateDir, files) {
24
+ for (const file of files) {
25
+ const targetFileName = file.replace('.tw', '');
26
+ await copyFile(resolve(templateDir, file), resolve(targetDir, targetFileName));
27
+ }
28
+ };
29
+ }
30
+ function createTemplateFile(projectName, options, targetDir) {
31
+ return async function templateFile(templateDir, file, targetFileName) {
32
+ const templateValues = {
33
+ packageManager: options.packageManager,
34
+ projectName: projectName,
35
+ typescript: options.typescript,
36
+ tailwind: options.tailwind,
37
+ js: options.typescript ? 'ts' : 'js',
38
+ jsx: options.typescript ? 'tsx' : 'jsx',
39
+ fileRouter: options.mode === FILE_ROUTER,
40
+ codeRouter: options.mode === CODE_ROUTER,
41
+ };
42
+ const template = await readFile(resolve(templateDir, file), 'utf-8');
43
+ const content = render(template, templateValues);
44
+ const target = targetFileName ?? file.replace('.ejs', '');
45
+ await writeFile(resolve(targetDir, target), content);
25
46
  };
26
- const template = await readFile(resolve(templateDir, file), 'utf-8');
27
- const content = render(template, templateValues);
28
- const target = targetFileName ?? file.replace('.ejs', '');
29
- await writeFile(resolve(targetDir, target), content);
30
- };
31
- async function createPackageJSON(projectName, options, templateDir, targetDir) {
47
+ }
48
+ async function createPackageJSON(projectName, options, templateDir, routerDir, targetDir) {
32
49
  let packageJSON = JSON.parse(await readFile(resolve(templateDir, 'package.json'), 'utf8'));
33
50
  packageJSON.name = projectName;
34
51
  if (options.typescript) {
@@ -51,22 +68,39 @@ async function createPackageJSON(projectName, options, templateDir, targetDir) {
51
68
  },
52
69
  };
53
70
  }
71
+ if (options.mode === FILE_ROUTER) {
72
+ const frPackageJSON = JSON.parse(await readFile(resolve(routerDir, 'package.fr.json'), 'utf8'));
73
+ packageJSON = {
74
+ ...packageJSON,
75
+ dependencies: {
76
+ ...packageJSON.dependencies,
77
+ ...frPackageJSON.dependencies,
78
+ },
79
+ };
80
+ }
81
+ packageJSON.dependencies = sortObject(packageJSON.dependencies);
82
+ packageJSON.devDependencies = sortObject(packageJSON.devDependencies);
54
83
  await writeFile(resolve(targetDir, 'package.json'), JSON.stringify(packageJSON, null, 2));
55
84
  }
56
85
  async function createApp(projectName, options) {
57
- const templateDir = fileURLToPath(new URL('../project-template', import.meta.url));
86
+ const templateDirBase = fileURLToPath(new URL('../templates/base', import.meta.url));
87
+ const templateDirRouter = fileURLToPath(new URL(`../templates/${options.mode}`, import.meta.url));
58
88
  const targetDir = resolve(process.cwd(), projectName);
59
- const copyFiles = createCopyFile(templateDir, targetDir);
60
- const templateFile = createTemplateFile(projectName, options, templateDir, targetDir);
89
+ if (existsSync(targetDir)) {
90
+ log.error(`Directory "${projectName}" already exists`);
91
+ return;
92
+ }
93
+ const copyFiles = createCopyFile(targetDir);
94
+ const templateFile = createTemplateFile(projectName, options, targetDir);
61
95
  intro(`Creating a new TanStack app in ${targetDir}...`);
62
96
  // Make the root directory
63
97
  await mkdir(targetDir, { recursive: true });
64
98
  // Setup the .vscode directory
65
99
  await mkdir(resolve(targetDir, '.vscode'), { recursive: true });
66
- await copyFile(resolve(templateDir, '.vscode/settings.json'), resolve(targetDir, '.vscode/settings.json'));
100
+ await copyFile(resolve(templateDirBase, '.vscode/settings.json'), resolve(targetDir, '.vscode/settings.json'));
67
101
  // Fill the public directory
68
102
  await mkdir(resolve(targetDir, 'public'), { recursive: true });
69
- copyFiles([
103
+ copyFiles(templateDirBase, [
70
104
  './public/robots.txt',
71
105
  './public/favicon.ico',
72
106
  './public/manifest.json',
@@ -75,50 +109,74 @@ async function createApp(projectName, options) {
75
109
  ]);
76
110
  // Make the src directory
77
111
  await mkdir(resolve(targetDir, 'src'), { recursive: true });
112
+ if (options.mode === FILE_ROUTER) {
113
+ await mkdir(resolve(targetDir, 'src/routes'), { recursive: true });
114
+ }
78
115
  // Copy in Vite and Tailwind config and CSS
79
116
  if (!options.tailwind) {
80
- await copyFiles(['./src/App.css']);
117
+ await copyFiles(templateDirBase, ['./src/App.css']);
81
118
  }
82
- await templateFile('./vite.config.js.ejs');
83
- await templateFile('./src/styles.css.ejs');
84
- copyFiles(['./src/logo.svg']);
119
+ await templateFile(templateDirBase, './vite.config.js.ejs');
120
+ await templateFile(templateDirBase, './src/styles.css.ejs');
121
+ copyFiles(templateDirBase, ['./src/logo.svg']);
85
122
  // Setup the app component. There are four variations, typescript/javascript and tailwind/non-tailwind.
86
- await templateFile('./src/App.tsx.ejs', options.typescript ? undefined : './src/App.jsx');
87
- await templateFile('./src/App.test.tsx.ejs', options.typescript ? undefined : './src/App.test.jsx');
123
+ if (options.mode === FILE_ROUTER) {
124
+ copyFiles(templateDirRouter, ['./src/routes/__root.tsx']);
125
+ await templateFile(templateDirBase, './src/App.tsx.ejs', './src/routes/index.tsx');
126
+ }
127
+ else {
128
+ await templateFile(templateDirBase, './src/App.tsx.ejs', options.typescript ? undefined : './src/App.jsx');
129
+ await templateFile(templateDirBase, './src/App.test.tsx.ejs', options.typescript ? undefined : './src/App.test.jsx');
130
+ }
131
+ // Create the main entry point
132
+ if (options.typescript) {
133
+ await templateFile(templateDirRouter, './src/main.tsx.ejs');
134
+ }
135
+ else {
136
+ await templateFile(templateDirRouter, './src/main.tsx.ejs', './src/main.jsx');
137
+ }
88
138
  // Setup the main, reportWebVitals and index.html files
89
139
  if (options.typescript) {
90
- await templateFile('./src/main.tsx.ejs');
91
- await templateFile('./src/reportWebVitals.ts.ejs');
140
+ await templateFile(templateDirBase, './src/reportWebVitals.ts.ejs');
92
141
  }
93
142
  else {
94
- await templateFile('./src/main.tsx.ejs', './src/main.jsx');
95
- await templateFile('./src/reportWebVitals.ts.ejs', './src/reportWebVitals.js');
143
+ await templateFile(templateDirBase, './src/reportWebVitals.ts.ejs', './src/reportWebVitals.js');
96
144
  }
97
- await templateFile('./index.html.ejs');
145
+ await templateFile(templateDirBase, './index.html.ejs');
98
146
  // Setup tsconfig
99
147
  if (options.typescript) {
100
- await copyFiles(['./tsconfig.json', './tsconfig.dev.json']);
148
+ await copyFiles(templateDirBase, ['./tsconfig.json', './tsconfig.dev.json']);
101
149
  }
102
150
  // Setup the package.json file, optionally with typescript and tailwind
103
- await createPackageJSON(projectName, options, templateDir, targetDir);
151
+ await createPackageJSON(projectName, options, templateDirBase, templateDirRouter, targetDir);
104
152
  // Add .gitignore
105
- await copyFile(resolve(templateDir, 'gitignore'), resolve(targetDir, '.gitignore'));
153
+ await copyFile(resolve(templateDirBase, 'gitignore'), resolve(targetDir, '.gitignore'));
106
154
  // Create the README.md
107
- await templateFile('README.md.ejs');
155
+ await templateFile(templateDirBase, 'README.md.ejs');
108
156
  // Install dependencies
109
157
  const s = spinner();
110
158
  s.start(`Installing dependencies via ${options.packageManager}...`);
111
159
  await execa(options.packageManager, ['install'], { cwd: targetDir });
112
160
  s.stop(`Installed dependencies`);
113
- outro(`Created your new TanStack app in ${targetDir}.`);
161
+ outro(`Created your new TanStack app in ${targetDir}.
162
+
163
+ Use the following commands to start your app:
164
+
165
+ % cd ${projectName}
166
+ % ${options.packageManager} start
167
+
168
+ Please read README.md for more information on testing, styling, adding routes, react-query, etc.
169
+ `);
114
170
  }
115
171
  program
116
172
  .name('create-tsrouter-app')
117
173
  .description('CLI to create a new TanStack application')
118
174
  .argument('<project-name>', 'name of the project')
119
- .option('--template <type>', 'project template (typescript/javascript)', (value) => {
120
- if (value !== 'typescript' && value !== 'javascript') {
121
- throw new InvalidArgumentError(`Invalid template: ${value}. Only the following are allowed: typescript, javascript`);
175
+ .option('--template <type>', 'project template (typescript, javascript, file-router)', (value) => {
176
+ if (value !== 'typescript' &&
177
+ value !== 'javascript' &&
178
+ value !== 'file-router') {
179
+ throw new InvalidArgumentError(`Invalid template: ${value}. Only the following are allowed: typescript, javascript, file-router`);
122
180
  }
123
181
  return value;
124
182
  }, 'javascript')
@@ -130,11 +188,12 @@ program
130
188
  }, getPackageManager())
131
189
  .option('--tailwind', 'add Tailwind CSS', false)
132
190
  .action((projectName, options) => {
133
- const typescript = options.template === 'typescript';
191
+ const typescript = options.template === 'typescript' || options.template === 'file-router';
134
192
  createApp(projectName, {
135
193
  typescript,
136
194
  tailwind: options.tailwind,
137
195
  packageManager: options.packageManager,
196
+ mode: options.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER,
138
197
  });
139
198
  });
140
199
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tsrouter-app",
3
- "version": "0.0.4",
3
+ "version": "0.1.1",
4
4
  "description": "Tanstack Application Builder",
5
5
  "bin": "./dist/index.js",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises'
4
+ import { existsSync } from 'node:fs'
4
5
  import { resolve } from 'node:path'
5
6
  import { fileURLToPath } from 'node:url'
6
7
  import { Command, InvalidArgumentError } from 'commander'
7
- import { intro, outro, spinner } from '@clack/prompts'
8
+ import { intro, outro, spinner, log } from '@clack/prompts'
8
9
  import { execa } from 'execa'
9
10
  import { render } from 'ejs'
10
11
 
@@ -17,14 +18,27 @@ import type { PackageManager } from './utils/getPackageManager.js'
17
18
 
18
19
  const program = new Command()
19
20
 
21
+ const CODE_ROUTER = 'code-router'
22
+ const FILE_ROUTER = 'file-router'
23
+
20
24
  interface Options {
21
25
  typescript: boolean
22
26
  tailwind: boolean
23
27
  packageManager: PackageManager
28
+ mode: typeof CODE_ROUTER | typeof FILE_ROUTER
29
+ }
30
+
31
+ function sortObject(obj: Record<string, string>): Record<string, string> {
32
+ return Object.keys(obj)
33
+ .sort()
34
+ .reduce<Record<string, string>>((acc, key) => {
35
+ acc[key] = obj[key]
36
+ return acc
37
+ }, {})
24
38
  }
25
39
 
26
- const createCopyFile = (templateDir: string, targetDir: string) =>
27
- async function copyFiles(files: Array<string>) {
40
+ function createCopyFile(targetDir: string) {
41
+ return async function copyFiles(templateDir: string, files: Array<string>) {
28
42
  for (const file of files) {
29
43
  const targetFileName = file.replace('.tw', '')
30
44
  await copyFile(
@@ -33,14 +47,18 @@ const createCopyFile = (templateDir: string, targetDir: string) =>
33
47
  )
34
48
  }
35
49
  }
50
+ }
36
51
 
37
- const createTemplateFile = (
52
+ function createTemplateFile(
38
53
  projectName: string,
39
54
  options: Required<Options>,
40
- templateDir: string,
41
55
  targetDir: string,
42
- ) =>
43
- async function templateFile(file: string, targetFileName?: string) {
56
+ ) {
57
+ return async function templateFile(
58
+ templateDir: string,
59
+ file: string,
60
+ targetFileName?: string,
61
+ ) {
44
62
  const templateValues = {
45
63
  packageManager: options.packageManager,
46
64
  projectName: projectName,
@@ -48,6 +66,8 @@ const createTemplateFile = (
48
66
  tailwind: options.tailwind,
49
67
  js: options.typescript ? 'ts' : 'js',
50
68
  jsx: options.typescript ? 'tsx' : 'jsx',
69
+ fileRouter: options.mode === FILE_ROUTER,
70
+ codeRouter: options.mode === CODE_ROUTER,
51
71
  }
52
72
 
53
73
  const template = await readFile(resolve(templateDir, file), 'utf-8')
@@ -55,11 +75,13 @@ const createTemplateFile = (
55
75
  const target = targetFileName ?? file.replace('.ejs', '')
56
76
  await writeFile(resolve(targetDir, target), content)
57
77
  }
78
+ }
58
79
 
59
80
  async function createPackageJSON(
60
81
  projectName: string,
61
82
  options: Required<Options>,
62
83
  templateDir: string,
84
+ routerDir: string,
63
85
  targetDir: string,
64
86
  ) {
65
87
  let packageJSON = JSON.parse(
@@ -90,6 +112,24 @@ async function createPackageJSON(
90
112
  },
91
113
  }
92
114
  }
115
+ if (options.mode === FILE_ROUTER) {
116
+ const frPackageJSON = JSON.parse(
117
+ await readFile(resolve(routerDir, 'package.fr.json'), 'utf8'),
118
+ )
119
+ packageJSON = {
120
+ ...packageJSON,
121
+ dependencies: {
122
+ ...packageJSON.dependencies,
123
+ ...frPackageJSON.dependencies,
124
+ },
125
+ }
126
+ }
127
+ packageJSON.dependencies = sortObject(
128
+ packageJSON.dependencies as Record<string, string>,
129
+ )
130
+ packageJSON.devDependencies = sortObject(
131
+ packageJSON.devDependencies as Record<string, string>,
132
+ )
93
133
  await writeFile(
94
134
  resolve(targetDir, 'package.json'),
95
135
  JSON.stringify(packageJSON, null, 2),
@@ -97,18 +137,21 @@ async function createPackageJSON(
97
137
  }
98
138
 
99
139
  async function createApp(projectName: string, options: Required<Options>) {
100
- const templateDir = fileURLToPath(
101
- new URL('../project-template', import.meta.url),
140
+ const templateDirBase = fileURLToPath(
141
+ new URL('../templates/base', import.meta.url),
142
+ )
143
+ const templateDirRouter = fileURLToPath(
144
+ new URL(`../templates/${options.mode}`, import.meta.url),
102
145
  )
103
146
  const targetDir = resolve(process.cwd(), projectName)
104
147
 
105
- const copyFiles = createCopyFile(templateDir, targetDir)
106
- const templateFile = createTemplateFile(
107
- projectName,
108
- options,
109
- templateDir,
110
- targetDir,
111
- )
148
+ if (existsSync(targetDir)) {
149
+ log.error(`Directory "${projectName}" already exists`)
150
+ return
151
+ }
152
+
153
+ const copyFiles = createCopyFile(targetDir)
154
+ const templateFile = createTemplateFile(projectName, options, targetDir)
112
155
 
113
156
  intro(`Creating a new TanStack app in ${targetDir}...`)
114
157
 
@@ -118,13 +161,13 @@ async function createApp(projectName: string, options: Required<Options>) {
118
161
  // Setup the .vscode directory
119
162
  await mkdir(resolve(targetDir, '.vscode'), { recursive: true })
120
163
  await copyFile(
121
- resolve(templateDir, '.vscode/settings.json'),
164
+ resolve(templateDirBase, '.vscode/settings.json'),
122
165
  resolve(targetDir, '.vscode/settings.json'),
123
166
  )
124
167
 
125
168
  // Fill the public directory
126
169
  await mkdir(resolve(targetDir, 'public'), { recursive: true })
127
- copyFiles([
170
+ copyFiles(templateDirBase, [
128
171
  './public/robots.txt',
129
172
  './public/favicon.ico',
130
173
  './public/manifest.json',
@@ -134,55 +177,85 @@ async function createApp(projectName: string, options: Required<Options>) {
134
177
 
135
178
  // Make the src directory
136
179
  await mkdir(resolve(targetDir, 'src'), { recursive: true })
180
+ if (options.mode === FILE_ROUTER) {
181
+ await mkdir(resolve(targetDir, 'src/routes'), { recursive: true })
182
+ }
137
183
 
138
184
  // Copy in Vite and Tailwind config and CSS
139
185
  if (!options.tailwind) {
140
- await copyFiles(['./src/App.css'])
186
+ await copyFiles(templateDirBase, ['./src/App.css'])
141
187
  }
142
- await templateFile('./vite.config.js.ejs')
143
- await templateFile('./src/styles.css.ejs')
188
+ await templateFile(templateDirBase, './vite.config.js.ejs')
189
+ await templateFile(templateDirBase, './src/styles.css.ejs')
144
190
 
145
- copyFiles(['./src/logo.svg'])
191
+ copyFiles(templateDirBase, ['./src/logo.svg'])
146
192
 
147
193
  // Setup the app component. There are four variations, typescript/javascript and tailwind/non-tailwind.
148
- await templateFile(
149
- './src/App.tsx.ejs',
150
- options.typescript ? undefined : './src/App.jsx',
151
- )
152
- await templateFile(
153
- './src/App.test.tsx.ejs',
154
- options.typescript ? undefined : './src/App.test.jsx',
155
- )
194
+ if (options.mode === FILE_ROUTER) {
195
+ copyFiles(templateDirRouter, ['./src/routes/__root.tsx'])
196
+ await templateFile(
197
+ templateDirBase,
198
+ './src/App.tsx.ejs',
199
+ './src/routes/index.tsx',
200
+ )
201
+ } else {
202
+ await templateFile(
203
+ templateDirBase,
204
+ './src/App.tsx.ejs',
205
+ options.typescript ? undefined : './src/App.jsx',
206
+ )
207
+ await templateFile(
208
+ templateDirBase,
209
+ './src/App.test.tsx.ejs',
210
+ options.typescript ? undefined : './src/App.test.jsx',
211
+ )
212
+ }
213
+
214
+ // Create the main entry point
215
+ if (options.typescript) {
216
+ await templateFile(templateDirRouter, './src/main.tsx.ejs')
217
+ } else {
218
+ await templateFile(
219
+ templateDirRouter,
220
+ './src/main.tsx.ejs',
221
+ './src/main.jsx',
222
+ )
223
+ }
156
224
 
157
225
  // Setup the main, reportWebVitals and index.html files
158
226
  if (options.typescript) {
159
- await templateFile('./src/main.tsx.ejs')
160
- await templateFile('./src/reportWebVitals.ts.ejs')
227
+ await templateFile(templateDirBase, './src/reportWebVitals.ts.ejs')
161
228
  } else {
162
- await templateFile('./src/main.tsx.ejs', './src/main.jsx')
163
229
  await templateFile(
230
+ templateDirBase,
164
231
  './src/reportWebVitals.ts.ejs',
165
232
  './src/reportWebVitals.js',
166
233
  )
167
234
  }
168
- await templateFile('./index.html.ejs')
235
+ await templateFile(templateDirBase, './index.html.ejs')
169
236
 
170
237
  // Setup tsconfig
171
238
  if (options.typescript) {
172
- await copyFiles(['./tsconfig.json', './tsconfig.dev.json'])
239
+ await copyFiles(templateDirBase, ['./tsconfig.json', './tsconfig.dev.json'])
173
240
  }
174
241
 
175
242
  // Setup the package.json file, optionally with typescript and tailwind
176
- await createPackageJSON(projectName, options, templateDir, targetDir)
243
+ await createPackageJSON(
244
+ projectName,
245
+ options,
246
+ templateDirBase,
247
+ templateDirRouter,
248
+ targetDir,
249
+ )
177
250
 
178
251
  // Add .gitignore
179
252
  await copyFile(
180
- resolve(templateDir, 'gitignore'),
253
+ resolve(templateDirBase, 'gitignore'),
181
254
  resolve(targetDir, '.gitignore'),
182
255
  )
183
256
 
184
257
  // Create the README.md
185
- await templateFile('README.md.ejs')
258
+ await templateFile(templateDirBase, 'README.md.ejs')
186
259
 
187
260
  // Install dependencies
188
261
  const s = spinner()
@@ -190,20 +263,32 @@ async function createApp(projectName: string, options: Required<Options>) {
190
263
  await execa(options.packageManager, ['install'], { cwd: targetDir })
191
264
  s.stop(`Installed dependencies`)
192
265
 
193
- outro(`Created your new TanStack app in ${targetDir}.`)
266
+ outro(`Created your new TanStack app in ${targetDir}.
267
+
268
+ Use the following commands to start your app:
269
+
270
+ % cd ${projectName}
271
+ % ${options.packageManager} start
272
+
273
+ Please read README.md for more information on testing, styling, adding routes, react-query, etc.
274
+ `)
194
275
  }
195
276
 
196
277
  program
197
278
  .name('create-tsrouter-app')
198
279
  .description('CLI to create a new TanStack application')
199
280
  .argument('<project-name>', 'name of the project')
200
- .option<'typescript' | 'javascript'>(
281
+ .option<'typescript' | 'javascript' | 'file-router'>(
201
282
  '--template <type>',
202
- 'project template (typescript/javascript)',
283
+ 'project template (typescript, javascript, file-router)',
203
284
  (value) => {
204
- if (value !== 'typescript' && value !== 'javascript') {
285
+ if (
286
+ value !== 'typescript' &&
287
+ value !== 'javascript' &&
288
+ value !== 'file-router'
289
+ ) {
205
290
  throw new InvalidArgumentError(
206
- `Invalid template: ${value}. Only the following are allowed: typescript, javascript`,
291
+ `Invalid template: ${value}. Only the following are allowed: typescript, javascript, file-router`,
207
292
  )
208
293
  }
209
294
  return value
@@ -230,17 +315,19 @@ program
230
315
  (
231
316
  projectName: string,
232
317
  options: {
233
- template: string
318
+ template: 'typescript' | 'javascript' | 'file-router'
234
319
  tailwind: boolean
235
320
  packageManager: PackageManager
236
321
  },
237
322
  ) => {
238
- const typescript = options.template === 'typescript'
323
+ const typescript =
324
+ options.template === 'typescript' || options.template === 'file-router'
239
325
 
240
326
  createApp(projectName, {
241
327
  typescript,
242
328
  tailwind: options.tailwind,
243
329
  packageManager: options.packageManager,
330
+ mode: options.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER,
244
331
  })
245
332
  },
246
333
  )
@@ -32,11 +32,14 @@ This project uses [Tailwind CSS](https://tailwindcss.com/) for styling.
32
32
  This project uses CSS for styling.
33
33
  <% } %>
34
34
  ## Routing
35
-
36
- This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a code based router. Which means that the routes are defined in code (in the `./src/main.<%= jsx %>` file). If you like you can also use a file based routing setup by following the [File Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing) guide.
35
+ <% if (fileRouter) { %>This 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`.<% } else { %>This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a code based router. Which means that the routes are defined in code (in the `./src/main.<%= jsx %>` file). If you like you can also use a file based routing setup by following the [File Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing) guide.<% } %>
37
36
 
38
37
  ### Adding A Route
38
+ <% if (fileRouter) { %>
39
+ To add a new route to your application just add another a new file in the `./src/routes` directory.
39
40
 
41
+ TanStack will automatically generate the content of the route file for you.
42
+ <% } else { %>
40
43
  To add a new route to your application just add another `createRoute` call to the `./src/main.<%= jsx %>` file. The example below adds a new `/about`route to the root route.
41
44
 
42
45
  ```tsx
@@ -70,7 +73,7 @@ const aboutRoute = createRoute({
70
73
  That is how we have the `App` component set up with the home page.
71
74
 
72
75
  For more information on the options you have when you are creating code based routes check out the [Code Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/code-based-routing) documentation.
73
-
76
+ <% } %>
74
77
  Now that you have two routes you can use a `Link` component to navigate between them.
75
78
 
76
79
  ### Adding Links
@@ -93,6 +96,7 @@ More information on the `Link` component can be found in the [Link documentation
93
96
 
94
97
  ### Using A Layout
95
98
 
99
+ <% if (codeRouter) { %>
96
100
  Layouts can be used to wrap the contents of the routes in menus, headers, footers, etc.
97
101
 
98
102
  There is already a layout in the `src/main.<%= jsx %>` file:
@@ -111,6 +115,8 @@ const rootRoute = createRootRoute({
111
115
  You can use the React component specified in the `component` property of the `rootRoute` to wrap the contents of the routes. The `<Outlet />` component is used to render the current route within the body of the layout. For example you could add a header to the layout like so:
112
116
 
113
117
  ```tsx
118
+ import { Link } from "@tanstack/react-router";
119
+
114
120
  const rootRoute = createRootRoute({
115
121
  component: () => (
116
122
  <>
@@ -126,11 +132,37 @@ const rootRoute = createRootRoute({
126
132
  ),
127
133
  });
128
134
  ```
135
+ <% } else { %>In 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.
136
+
137
+ Here is an example layout that includes a header:
129
138
 
139
+ ```tsx
140
+ import { createRootRoute, Outlet } from '@tanstack/react-router'
141
+ import { TanStackRouterDevtools } from '@tanstack/router-devtools'
142
+
143
+ import { Link } from "@tanstack/react-router";
144
+
145
+ export const Route = createRootRoute({
146
+ component: () => (
147
+ <>
148
+ <header>
149
+ <nav>
150
+ <Link to="/">Home</Link>
151
+ <Link to="/about">About</Link>
152
+ </nav>
153
+ </header>
154
+ <Outlet />
155
+ <TanStackRouterDevtools />
156
+ </>
157
+ ),
158
+ })
159
+ ```
160
+ <% } %>
130
161
  The `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.
131
162
 
132
163
  More information on layouts can be found in the [Layouts documentation](hthttps://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).
133
164
 
165
+ <% if (codeRouter) { %>
134
166
  ### Migrating To File Base Routing
135
167
 
136
168
  First you need to add the Vite plugin for Tanstack Router:
@@ -301,7 +333,7 @@ reportWebVitals();
301
333
  Now you've got a file based routing setup in your project! Let's have some fun with it! Just create a file in `about.<%= jsx %>` in `src/routes` and it if the application is running TanStack will automatically add contents to the file and you'll have the start of your `/about` route ready to go with no additional work. You can see why folks find File Based Routing so easy to use.
302
334
 
303
335
  You can find out everything you need to know on how to use file based routing in the [File Based Routing](https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing) documentation.
304
-
336
+ <% } %>
305
337
  ## Data Fetching
306
338
 
307
339
  There 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.
@@ -6,7 +6,7 @@
6
6
  "start": "vite --port 3000",
7
7
  "build": "vite build && tsc --noEmit",
8
8
  "serve": "vite preview",
9
- "test": "vitest"
9
+ "test": "vitest run"
10
10
  },
11
11
  "dependencies": {
12
12
  "@tanstack/react-router": "^1.104.1",
@@ -1,7 +1,15 @@
1
- import logo from "./logo.svg";
2
- <% if (!tailwind) { %>
3
- import "./App.css";
1
+ <% if (fileRouter) { %>
2
+ import { createFileRoute } from "@tanstack/react-router";
3
+ import logo from "../logo.svg";<% if (!tailwind) { %>
4
+ import "../App.css";
4
5
  <% } %>
6
+ <% } else { %>import logo from "./logo.svg";<% if (!tailwind) { %>
7
+ import "./App.css";
8
+ <% } %><% } %><% if (fileRouter) { %>
9
+
10
+ export const Route = createFileRoute("/")({
11
+ component: App,
12
+ });<% } %>
5
13
 
6
14
  function App() {
7
15
  return (<% if (tailwind) { %>
@@ -13,7 +21,7 @@ function App() {
13
21
  alt="logo"
14
22
  />
15
23
  <p>
16
- Edit <code>src/App.<%= jsx %></code> and save to reload.
24
+ Edit <code><% if (fileRouter) { %>src/routes/index.tsx<% } else {%>src/App.<%= jsx %><% } %></code> and save to reload.
17
25
  </p>
18
26
  <a
19
27
  className="text-[#61dafb] hover:underline"
@@ -38,7 +46,7 @@ function App() {
38
46
  <header className="App-header">
39
47
  <img src={logo} className="App-logo" alt="logo" />
40
48
  <p>
41
- Edit <code>src/App.<%= jsx %></code> and save to reload.
49
+ Edit <code><% if (fileRouter) { %>src/routes/index.tsx<% } else {%>src/App.<%= jsx %><% } %></code> and save to reload.
42
50
  </p>
43
51
  <a
44
52
  className="App-link"
@@ -61,4 +69,6 @@ function App() {
61
69
  <% } %> );
62
70
  }
63
71
 
72
+ <% if (!fileRouter) { %>
64
73
  export default App;
74
+ <% } %>
@@ -0,0 +1,43 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 841.9 595.3">
3
+ <!-- Generator: Adobe Illustrator 29.3.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 146) -->
4
+ <defs>
5
+ <style>
6
+ .st0 {
7
+ fill: #9ae7fc;
8
+ }
9
+
10
+ .st1 {
11
+ fill: #61dafb;
12
+ }
13
+ </style>
14
+ </defs>
15
+ <g>
16
+ <path class="st1" d="M666.3,296.5c0-32.5-40.7-63.3-103.1-82.4,14.4-63.6,8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6,0,8.3.9,11.4,2.6,13.6,7.8,19.5,37.5,14.9,75.7-1.1,9.4-2.9,19.3-5.1,29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50,32.6-30.3,63.2-46.9,84-46.9v-22.3c-27.5,0-63.5,19.6-99.9,53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7,0,51.4,16.5,84,46.6-14,14.7-28,31.4-41.3,49.9-22.6,2.4-44,6.1-63.6,11-2.3-10-4-19.7-5.2-29-4.7-38.2,1.1-67.9,14.6-75.8,3-1.8,6.9-2.6,11.5-2.6v-22.3c-8.4,0-16,1.8-22.6,5.6-28.1,16.2-34.4,66.7-19.9,130.1-62.2,19.2-102.7,49.9-102.7,82.3s40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4,6.5,3.8,14.1,5.6,22.5,5.6,27.5,0,63.5-19.6,99.9-53.6,36.4,33.8,72.4,53.2,99.9,53.2s16-1.8,22.6-5.6c28.1-16.2,34.4-66.7,19.9-130.1,62-19.1,102.5-49.9,102.5-82.3h0ZM536.1,229.8c-3.7,12.9-8.3,26.2-13.5,39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4,14.2,2.1,27.9,4.7,41,7.9h0ZM490.3,336.3c-7.8,13.5-15.8,26.3-24.1,38.2-14.9,1.3-30,2-45.2,2s-30.2-.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8,6.2-13.4,13.2-26.8,20.7-39.9,7.8-13.5,15.8-26.3,24.1-38.2,14.9-1.3,30-2,45.2-2s30.2.7,45,1.9c8.3,11.9,16.4,24.6,24.2,38,7.6,13.1,14.5,26.4,20.8,39.8-6.3,13.4-13.2,26.8-20.7,39.9h0ZM522.6,323.3c5.4,13.4,10,26.8,13.8,39.8-13.1,3.2-26.9,5.9-41.2,8,4.9-7.7,9.8-15.6,14.4-23.7,4.6-8,8.9-16.1,13-24.1h0ZM421.2,430c-9.3-9.6-18.6-20.3-27.8-32,9,.4,18.2.7,27.5.7s18.7-.2,27.8-.7c-9,11.7-18.3,22.4-27.5,32ZM346.8,371.1c-14.2-2.1-27.9-4.7-41-7.9,3.7-12.9,8.3-26.2,13.5-39.5,4.1,8,8.4,16,13.1,24s9.5,15.8,14.4,23.4ZM420.7,163c9.3,9.6,18.6,20.3,27.8,32-9-.4-18.2-.7-27.5-.7s-18.7.2-27.8.7c9-11.7,18.3-22.4,27.5-32ZM346.7,221.9c-4.9,7.7-9.8,15.6-14.4,23.7-4.6,8-8.9,16-13,24-5.4-13.4-10-26.8-13.8-39.8,13.1-3.1,26.9-5.8,41.2-7.9h0ZM256.2,347.1c-35.4-15.1-58.3-34.9-58.3-50.6s22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1,5.7,19.6,13.2,40,22.5,60.9-9.2,20.8-16.6,41.1-22.2,60.6-9.9-3.1-19.3-6.5-28-10.2h0ZM310,490c-13.6-7.8-19.5-37.5-14.9-75.7,1.1-9.4,2.9-19.3,5.1-29.4,19.6,4.8,41,8.5,63.5,10.9,13.5,18.5,27.5,35.3,41.6,50-32.6,30.3-63.2,46.9-84,46.9-4.5-.1-8.3-1-11.3-2.7h0ZM547.2,413.8c4.7,38.2-1.1,67.9-14.6,75.8-3,1.8-6.9,2.6-11.5,2.6-20.7,0-51.4-16.5-84-46.6,14-14.7,28-31.4,41.3-49.9,22.6-2.4,44-6.1,63.6-11,2.3,10.1,4.1,19.8,5.2,29.1ZM585.7,347.1c-8.6,3.7-18,7-27.7,10.1-5.7-19.6-13.2-40-22.5-60.9,9.2-20.8,16.6-41.1,22.2-60.6,9.9,3.1,19.3,6.5,28.1,10.2,35.4,15.1,58.3,34.9,58.3,50.6,0,15.7-23,35.6-58.4,50.6h0Z"/>
17
+ <circle class="st1" cx="420.9" cy="296.5" r="45.7"/>
18
+ <path class="st1" d="M520.5,78.1"/>
19
+ </g>
20
+ <circle class="st0" cx="420.8" cy="296.6" r="43"/>
21
+ <path class="st1" d="M466.1,296.6c0,25-20.2,45.2-45.2,45.2s-45.2-20.2-45.2-45.2,20.2-45.2,45.2-45.2,45.2,20.2,45.2,45.2ZM386,295.6v-6.3c0-1.1,1.2-5.1,1.8-6.2,1-1.9,2.9-3.5,4.6-4.7l-3.4-3.4c4-3.6,9.4-3.7,13.7-.7,1.9-4.7,6.6-7.1,11.6-6.7l-.8,4.2c5.9.2,13.1,4.1,13.1,10.8s0,.5-.7.7c-1.7.3-3.4-.4-5-.6s-1.2-.4-1.2.3,2.5,4.1,3,5.5,1,3.5.8,5.3c-5.6-.8-10.5-3.2-14.8-6.7.3,2.6,4.1,21.7,5.3,21.9s.8-.6,1-1.1,1.3-6.3,1.3-6.7c0-1-1.7-1.8-2.2-2.8-1.2-2.7,1.3-4.7,3.7-3.3s5.2,6.2,7.5,7.3,13,1.4,14.8,3.3-2.9,4.6-1.5,7.6c6.7-2.6,13.5-3.3,20.6-2.5,3.1-9.7,3.1-20.3-.9-29.8-7.3,0-14.7-3.6-17.2-10.8-2.5-7.2-.7-8.6-1.3-9.3-.8-1-6.3.6-7.4-1.5s.3-1.1-.2-1.4-1.9-.6-2.6-.8c-26-6.4-51.3,15.7-49.7,42.1,0,1.6,1.6,10.3,2.4,11.1s4.8,0,6.3,0,3.7.3,5,.5c2.9.4,7.2,2.4,9.4,2.5s2.4-.8,2.7-2.4c.4-2.6.5-7.4.5-10.1s-1-7.8-1.3-11.6c-.9-.2-.7,0-.9.5-.7,1.3-1.1,3.2-1.9,4.8s-5.2,8.7-5.7,9-.7-.5-.8-.8c-1.6-3.5-2-7.9-1.9-11.8-.9-1-5.4,4.9-6.7,5.3l-.8-.4v-.3h-.2ZM455.6,276.4c1.1-1.2-6-8.9-7.2-10-3-2.7-5.4-4.5-3.5,1.4s5.7,7.8,10.6,8.5h.1ZM410.9,270.1c-.4-.5-6.1,2.9-5.5,4.6,1.9-1.3,5.9-1.7,5.5-4.6ZM400.4,276.4c-.3-2.4-6.3-2.7-7.2-1s1.6,1.4,1.9,1.4c1.8.3,3.5-.6,5.2-.4h.1ZM411.3,276.8c3.8,1.3,6.6,3.6,10.9,3.7s0-3-1.2-3.9c-2.2-1.7-5.1-2.4-7.8-2.4s-1.6-.3-1.4.4c2.8.6,7.3.7,8.4,3.8-2.3-.3-3.9-1.6-6.2-2s-2.5-.5-2.6.3h0ZM420.6,290.3c-.8-5.1-5.7-10.8-10.9-11.6s-1.3-.4-.8.5,4.7,3.2,5.7,4,4.5,4.2,2.1,3.8-8.4-7.8-9.4-6.7c.2.9,1.1,1.9,1.7,2.7,3,3.8,6.9,6.8,11.8,7.4h-.2ZM395.3,279.8c-5,1.1-6.9,6.3-6.7,11,.7.8,5-3.8,5.4-4.5s2.7-4.6,1.1-4-2.9,4.4-4.2,4.6.2-2.1.4-2.5c1.1-1.6,2.9-3.1,4-4.6h0ZM400.4,281.5c-.4-.5-2,1.3-2.3,1.7-2.9,3.9-2.6,10.2-1.5,14.8.8.2.8-.3,1.2-.7,3-3.8,5.5-10.5,4.5-15.4-2.1,3.1-3.1,7.3-3.6,11h-1.3c0-4,1.9-7.7,3-11.4h0ZM426.9,305.9c0-1.7-1.7-1.4-2.5-1.9s-1.3-1.9-3-1.4c1.3,2.1,3,3.2,5.5,3.4h0ZM417.2,308.5c7.6.7,5.5-1.9,1.4-5.5-1.3-.3-1.5,4.5-1.4,5.5ZM437,309.7c-3.5-.3-7.8-2-11.2-2.1s-1.3,0-1.9.7c4,1.3,8.4,1.7,12.1,4l1-2.5h0ZM420.5,312.8c-7.3,0-15.1,3.7-20.4,8.8s-4.8,5.3-4.8,6.2c0,1.8,8.6,6.2,10.5,6.8,12.1,4.8,27.5,3.5,38.2-4.2s3.1-2.7,0-6.2c-5.7-6.6-14.7-11.4-23.4-11.3h-.1ZM398.7,316.9c-1.4-1.4-5-1.9-7-2.1s-5.3-.3-6.9.6l13.9,1.4h0ZM456.9,314.8h-7.4c-.9,0-4.9,1.1-6,1.6s-.8.6,0,.5c2.4,0,5.1-1,7.6-1.3s3.5.2,5.1,0,1.3-.3.6-.8h0Z"/>
22
+ <path class="st0" d="M386,295.6l.8.4c1.3-.3,5.8-6.2,6.7-5.3,0,3.9.3,8.3,1.9,11.8s0,1.2.8.8,5.1-7.8,5.7-9,1.3-3.5,1.9-4.8,0-.7.9-.5c.3,3.8,1.2,7.8,1.3,11.6s0,7.5-.5,10.1-1.1,2.4-2.7,2.4-6.5-2.1-9.4-2.5-3.7-.5-5-.5-5.4,1.1-6.3,0-2.2-9.5-2.4-11.1c-1.5-26.4,23.7-48.5,49.7-42.1s2.2.4,2.6.8,0,1,.2,1.4c1.1,2,6.5.5,7.4,1.5s.4,6.9,1.3,9.3c2.5,7.2,10,10.9,17.2,10.8,4,9.4,4,20.1.9,29.8-7.2-.7-13.9,0-20.6,2.5-1.3-3.1,4.1-5.1,1.5-7.6s-11.8-1.9-14.8-3.3-5.4-6.1-7.5-7.3-4.9.6-3.7,3.3,2.1,1.8,2.2,2.8-1,6.2-1.3,6.7-.3,1.3-1,1.1c-1.1-.3-5-19.3-5.3-21.9,4.3,3.5,9.2,5.9,14.8,6.7.2-1.9-.3-3.5-.8-5.3s-3-5.1-3-5.5c0-.8.9-.3,1.2-.3,1.6,0,3.3.8,5,.6s.7.3.7-.7c0-6.6-7.2-10.6-13.1-10.8l.8-4.2c-5.1-.3-9.6,2-11.6,6.7-4.3-3-9.8-3-13.7.7l3.4,3.4c-1.8,1.3-3.5,2.8-4.6,4.7s-1.8,5.1-1.8,6.2v6.6h.2ZM431.6,265c7.8,2.1,8.7-3.5.2-1.3l-.2,1.3ZM432.4,270.9c.3.6,6.4-.4,5.8-2.3s-4.6.6-5.7.6l-.2,1.7h.1ZM434.5,276c.8,1.2,5.7-1.8,5.5-2.7-.4-1.9-6.6,1.2-5.5,2.7ZM442.9,276.4c-.9-.9-5,2.8-4.6,4,.6,2.4,5.7-3,4.6-4ZM445.1,279.9c-.3.2-3.1,4.6-1.5,5s3.5-3.4,3.5-4-1.3-1.3-2-.9h0ZM448.9,287.4c2.1.8,3.8-5.1,2.3-5.5-1.9-.6-2.6,5.1-2.3,5.5ZM457.3,288.6c.5-1.7,1.1-4.7-1-5.5-1,.3-.6,3.9-.6,4.8l.3.5,1.3.2h0Z"/>
23
+ <path class="st0" d="M455.6,276.4c-5-.8-9.1-3.6-10.6-8.5s.5-4,3.5-1.4,8.3,8.7,7.2,10h-.1Z"/>
24
+ <path class="st0" d="M420.6,290.3c-4.9-.6-8.9-3.6-11.8-7.4s-1.5-1.8-1.7-2.7c1-1,8.5,6.6,9.4,6.7,2.4.4-1.8-3.5-2.1-3.8-1-.8-5.4-3.5-5.7-4-.4-.8.5-.5.8-.5,5.2.8,10.1,6.6,10.9,11.6h.2Z"/>
25
+ <path class="st0" d="M400.4,281.5c-1.1,3.7-3,7.3-3,11.4h1.3c.5-3.7,1.5-7.8,3.6-11,1,4.8-1.5,11.6-4.5,15.4s-.4.8-1.2.7c-1.1-4.5-1.3-10.8,1.5-14.8s1.9-2.2,2.3-1.7h0Z"/>
26
+ <path class="st0" d="M411.3,276.8c0-.8,2.1-.4,2.6-.3,2.4.4,4,1.7,6.2,2-1.2-3.1-5.7-3.2-8.4-3.8,0-.8.9-.4,1.4-.4,2.8,0,5.6.7,7.8,2.4,2.2,1.7,4,4,1.2,3.9-4.3,0-7.1-2.4-10.9-3.7h0Z"/>
27
+ <path class="st0" d="M395.3,279.8c-1.1,1.6-3,3-4,4.6s-1.9,2.8-.4,2.5,2.8-4,4.2-4.6-.9,3.6-1.1,4c-.4.7-4.7,5.2-5.4,4.5-.2-4.6,1.8-9.9,6.7-11h0Z"/>
28
+ <path class="st0" d="M437,309.7l-1,2.5c-3.6-2.3-8-2.8-12.1-4,.5-.7,1.1-.7,1.9-.7,3.4,0,7.8,1.8,11.2,2.1h0Z"/>
29
+ <path class="st0" d="M417.2,308.5c0-1,0-5.8,1.4-5.5,4,3.5,6.1,6.2-1.4,5.5Z"/>
30
+ <path class="st0" d="M400.4,276.4c-1.8-.3-3.5.7-5.2.4s-2.3-.8-1.9-1.4c.8-1.6,6.9-1.4,7.2,1h-.1Z"/>
31
+ <path class="st0" d="M410.9,270.1c.4,3-3.6,3.3-5.5,4.6-.6-1.8,5-5.1,5.5-4.6Z"/>
32
+ <path class="st0" d="M426.9,305.9c-2.5-.2-4.1-1.3-5.5-3.4,1.7-.4,2,.8,3,1.4s2.6.3,2.5,1.9h0Z"/>
33
+ <path class="st1" d="M432.4,270.9l.2-1.7c1.1,0,5.1-2.2,5.7-.6s-5.5,2.9-5.8,2.3h-.1Z"/>
34
+ <path class="st1" d="M431.6,265l.2-1.3c8.4-2.1,7.7,3.4-.2,1.3Z"/>
35
+ <path class="st1" d="M434.5,276c-1.1-1.5,5.1-4.6,5.5-2.7s-4.6,4-5.5,2.7Z"/>
36
+ <path class="st1" d="M442.9,276.4c1.1,1.1-4,6.4-4.6,4s3.7-4.9,4.6-4Z"/>
37
+ <path class="st1" d="M445.1,279.9c.7-.4,2.1,0,2,.9s-2.4,4.4-3.5,4,1.3-4.8,1.5-5h0Z"/>
38
+ <path class="st1" d="M448.9,287.4c-.3-.3.4-6.1,2.3-5.5,1.4.4-.2,6.2-2.3,5.5Z"/>
39
+ <path class="st1" d="M457.3,288.6l-1.3-.2-.3-.5c0-.9-.4-4.6.6-4.8,2.1.8,1.5,3.8,1,5.5h0Z"/>
40
+ <path class="st0" d="M420.5,312.8c8.9,0,17.9,4.7,23.4,11.3,5.6,6.6,3.8,3.5,0,6.2-10.7,7.7-26.1,9-38.2,4.2-1.9-.8-10.5-5.1-10.5-6.8s4-5.3,4.8-6.2c5.3-5,13.1-8.6,20.4-8.8h.1Z"/>
41
+ <path class="st0" d="M398.7,316.9l-13.9-1.4c1.7-1,5-.8,6.9-.6s5.6.7,7,2.1h0Z"/>
42
+ <path class="st0" d="M456.9,314.8c.7.5,0,.8-.6.8-1.6.2-3.5-.2-5.1,0-2.4.3-5.2,1.2-7.6,1.3s-1.1,0,0-.5,5.1-1.6,6-1.6h7.4,0Z"/>
43
+ </svg>
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "vite";
2
+ import viteReact from "@vitejs/plugin-react";<% if (tailwind) { %>
3
+ import tailwindcss from "@tailwindcss/vite";
4
+ <% } %><%if (fileRouter) { %>
5
+ import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
6
+ <% } %>
7
+
8
+ // https://vitejs.dev/config/
9
+ export default defineConfig({
10
+ plugins: [<% if(fileRouter) { %>TanStackRouterVite(), <% } %>viteReact()<% if (tailwind) { %>, tailwindcss()<% } %>],
11
+ test: {
12
+ globals: true,
13
+ environment: "jsdom",
14
+ },
15
+ });
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "@tanstack/router-plugin": "^1.105.0"
4
+ }
5
+ }
@@ -0,0 +1,35 @@
1
+ import { StrictMode } from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import { RouterProvider, createRouter } from "@tanstack/react-router";
4
+
5
+ // Import the generated route tree
6
+ import { routeTree } from "./routeTree.gen";
7
+
8
+ import "./styles.css";
9
+ import reportWebVitals from "./reportWebVitals";
10
+
11
+ // Create a new router instance
12
+ const router = createRouter({ routeTree });
13
+
14
+ // Register the router instance for type safety
15
+ declare module "@tanstack/react-router" {
16
+ interface Register {
17
+ router: typeof router;
18
+ }
19
+ }
20
+
21
+ // Render the app
22
+ const rootElement = document.getElementById("app")!;
23
+ if (!rootElement.innerHTML) {
24
+ const root = ReactDOM.createRoot(rootElement);
25
+ root.render(
26
+ <StrictMode>
27
+ <RouterProvider router={router} />
28
+ </StrictMode>
29
+ );
30
+ }
31
+
32
+ // If you want to start measuring performance in your app, pass a function
33
+ // to log results (for example: reportWebVitals(console.log))
34
+ // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
35
+ reportWebVitals();
@@ -0,0 +1,11 @@
1
+ import { createRootRoute, Outlet } from '@tanstack/react-router'
2
+ import { TanStackRouterDevtools } from '@tanstack/router-devtools'
3
+
4
+ export const Route = createRootRoute({
5
+ component: () => (
6
+ <>
7
+ <Outlet />
8
+ <TanStackRouterDevtools />
9
+ </>
10
+ ),
11
+ })
@@ -1,44 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 841.9 595.3">
3
- <!-- Generator: Adobe Illustrator 29.3.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 146) -->
4
- <defs>
5
- <style>
6
- .st0 {
7
- fill: #9ae7fc;
8
- }
9
-
10
- .st1 {
11
- fill: #61dafb;
12
- }
13
-
14
- .st2 {
15
- fill: #61dafb;
16
- }
17
- </style>
18
- </defs>
19
- <circle class="st0" cx="420.7" cy="297.3" r="51"/>
20
- <path class="st2" d="M474.4,297.3c0,29.6-24,53.6-53.6,53.6s-53.6-24-53.6-53.6,24-53.6,53.6-53.6,53.6,24,53.6,53.6ZM379.5,296.1v-7.5c0-1.3,1.4-6.1,2.1-7.4,1.2-2.3,3.4-4.1,5.4-5.6l-4-4c4.7-4.3,11.1-4.4,16.2-.8,2.3-5.6,7.8-8.4,13.8-8l-1,5c7,.2,15.5,4.9,15.5,12.8s0,.6-.8.8c-2,.3-4-.5-5.9-.7s-1.4-.5-1.4.4,3,4.9,3.5,6.5,1.2,4.1,1,6.3c-6.6-1-12.4-3.8-17.5-8,.3,3.1,4.9,25.7,6.3,26s1-.7,1.2-1.3,1.5-7.5,1.5-8c0-1.2-2-2.1-2.6-3.3-1.4-3.2,1.5-5.6,4.4-3.9s6.2,7.4,8.9,8.6,15.4,1.7,17.6,3.9-3.4,5.4-1.8,9c8-3.1,16-3.9,24.4-3,3.7-11.5,3.7-24.1-1.1-35.3-8.6,0-17.4-4.3-20.4-12.8s-.8-10.2-1.5-11c-1-1.2-7.5.7-8.8-1.8s.3-1.3-.2-1.7-2.3-.7-3.1-.9c-30.8-7.6-60.8,18.6-58.9,49.9.1,1.9,1.9,12.2,2.8,13.2s5.7,0,7.5,0,4.4.4,5.9.6c3.4.5,8.5,2.9,11.1,3s2.9-1,3.2-2.8c.5-3.1.6-8.8.6-12s-1.2-9.3-1.5-13.7c-1.1-.2-.8,0-1.1.6-.8,1.6-1.3,3.8-2.3,5.7s-6.2,10.3-6.8,10.7-.8-.6-1-1c-1.9-4.2-2.4-9.4-2.3-14-1.1-1.2-6.4,5.8-8,6.3l-1-.5ZM462,273.3c1.3-1.4-7.1-10.5-8.5-11.8-3.6-3.2-6.4-5.3-4.2,1.7s6.8,9.2,12.6,10.1ZM409,265.8c-.5-.6-7.2,3.4-6.5,5.5,2.2-1.6,7-2,6.5-5.5ZM396.5,273.3c-.3-2.9-7.5-3.2-8.5-1.2s1.9,1.7,2.3,1.7c2.1.4,4.1-.7,6.2-.5ZM409.5,273.8c4.5,1.6,7.8,4.3,12.9,4.4s-.1-3.6-1.4-4.6c-2.6-2-6-2.9-9.2-2.8s-1.9-.4-1.7.5c3.3.7,8.6.8,10,4.5-2.7-.3-4.6-1.9-7.4-2.4s-3-.6-3.1.4ZM420.5,289.8c-1-6-6.8-12.8-12.9-13.8s-1.6-.5-1,.6,5.6,3.8,6.7,4.8,5.3,5,2.5,4.5-10-9.2-11.2-8c.2,1.1,1.3,2.3,2,3.2,3.5,4.5,8.2,8.1,14,8.8ZM390.5,277.3c-5.9,1.3-8.2,7.5-8,13,.8.9,5.9-4.5,6.4-5.3s3.2-5.4,1.3-4.7-3.4,5.2-5,5.5.2-2.5.5-3c1.3-1.9,3.4-3.7,4.7-5.5ZM396.5,279.3c-.5-.6-2.4,1.6-2.7,2-3.4,4.6-3.1,12.1-1.8,17.5.9.2,1-.3,1.4-.8,3.5-4.5,6.5-12.5,5.3-18.2-2.5,3.7-3.7,8.6-4.3,13h-1.5c0-4.8,2.2-9.1,3.5-13.5ZM428,308.3c.1-2-2-1.7-3-2.3s-1.6-2.2-3.5-1.7c1.6,2.5,3.5,3.8,6.5,4ZM416.5,311.3c9,.8,6.5-2.3,1.7-6.5-1.6-.4-1.8,5.3-1.7,6.5ZM440,312.8c-4.1-.4-9.3-2.4-13.3-2.5s-1.6,0-2.2.8c4.8,1.5,9.9,2,14.3,4.7l1.2-3ZM420.4,316.4c-8.7.1-17.9,4.4-24.2,10.4s-5.7,6.3-5.7,7.3c0,2.1,10.2,7.3,12.4,8.1,14.3,5.7,32.6,4.1,45.3-5s3.7-3.2.1-7.4c-6.7-7.8-17.4-13.5-27.8-13.4ZM394.5,321.3c-1.7-1.7-5.9-2.3-8.3-2.5s-6.3-.4-8.2.7l16.5,1.7ZM463.5,318.8h-8.8c-1.1,0-5.8,1.3-7.1,1.9s-1,.7.1.6c2.8-.1,6.1-1.2,9-1.5s4.1.2,6,0,1.6-.4.7-1Z"/>
21
- <path class="st0" d="M379.5,296.1l1,.5c1.6-.4,6.9-7.4,8-6.3-.1,4.6.4,9.8,2.3,14s.1,1.4,1,1,6.1-9.3,6.8-10.7,1.5-4.1,2.3-5.7,0-.8,1.1-.6c.3,4.5,1.4,9.3,1.5,13.7s0,8.9-.6,12-1.3,2.9-3.2,2.8-7.7-2.5-11.1-3-4.4-.6-5.9-.6-6.4,1.3-7.5,0-2.6-11.3-2.8-13.2c-1.8-31.3,28.1-57.5,58.9-49.9s2.6.5,3.1.9,0,1.2.2,1.7c1.3,2.4,7.7.6,8.8,1.8s.5,8.2,1.5,11c3,8.5,11.8,12.9,20.4,12.8,4.7,11.2,4.8,23.8,1.1,35.3-8.5-.8-16.5,0-24.4,3-1.6-3.7,4.9-6,1.8-9s-14-2.2-17.6-3.9-6.4-7.2-8.9-8.6-5.8.7-4.4,3.9,2.5,2.1,2.6,3.3-1.2,7.3-1.5,8-.3,1.5-1.2,1.3c-1.3-.3-5.9-22.9-6.3-26,5.1,4.2,10.9,7,17.5,8,.2-2.2-.3-4.2-1-6.3s-3.5-6.1-3.5-6.5c0-.9,1.1-.4,1.4-.4,1.9.1,3.9,1,5.9.7s.8.3.8-.8c0-7.8-8.5-12.6-15.5-12.8l1-5c-6-.4-11.4,2.4-13.8,8-5.1-3.6-11.6-3.5-16.2.8l4,4c-2.1,1.5-4.2,3.3-5.4,5.6s-2.1,6.1-2.1,7.4v7.5ZM433.5,259.8c9.3,2.5,10.3-4.1.2-1.5l-.2,1.5ZM434.5,266.8c.4.7,7.6-.5,6.9-2.7s-5.4.7-6.7.7l-.2,2ZM437,272.8c1,1.4,6.7-2.1,6.5-3.2-.5-2.2-7.8,1.4-6.5,3.2ZM447,273.3c-1.1-1.1-5.9,3.3-5.5,4.7.7,2.8,6.8-3.5,5.5-4.7ZM449.6,277.4c-.3.2-3.7,5.4-1.8,5.9s4.1-4,4.2-4.8-1.6-1.5-2.4-1.1ZM454,286.3c2.5.9,4.5-6,2.7-6.5-2.2-.7-3.1,6.1-2.7,6.5ZM464,287.8c.6-2,1.3-5.6-1.2-6.5-1.2.3-.7,4.6-.7,5.7l.4.6,1.5.2Z"/>
22
- <path class="st0" d="M462,273.3c-5.9-.9-10.8-4.3-12.6-10.1s.6-4.8,4.2-1.7,9.8,10.3,8.5,11.8Z"/>
23
- <path class="st0" d="M420.5,289.8c-5.8-.7-10.5-4.3-14-8.8s-1.8-2.1-2-3.2c1.2-1.2,10.1,7.8,11.2,8,2.8.5-2.1-4.2-2.5-4.5-1.2-1-6.4-4.2-6.7-4.8-.5-1,.6-.6,1-.6,6.2,1,12,7.8,12.9,13.8Z"/>
24
- <path class="st0" d="M396.5,279.3c-1.3,4.4-3.6,8.7-3.5,13.5h1.5c.6-4.4,1.8-9.3,4.3-13,1.2,5.7-1.8,13.7-5.3,18.2s-.5,1-1.4.8c-1.3-5.3-1.6-12.8,1.8-17.5s2.2-2.6,2.7-2Z"/>
25
- <path class="st0" d="M409.5,273.8c.1-1,2.5-.5,3.1-.4,2.8.5,4.7,2,7.4,2.4-1.4-3.7-6.7-3.8-10-4.5-.1-.9,1.1-.5,1.7-.5,3.3,0,6.6.8,9.2,2.8s4.8,4.7,1.4,4.6c-5.1-.1-8.4-2.8-12.9-4.4Z"/>
26
- <path class="st0" d="M390.5,277.3c-1.3,1.9-3.5,3.6-4.7,5.5s-2.3,3.3-.5,3,3.3-4.8,5-5.5-1.1,4.3-1.3,4.7c-.5.8-5.6,6.2-6.4,5.3-.2-5.5,2.1-11.7,8-13Z"/>
27
- <path class="st0" d="M440,312.8l-1.2,3c-4.3-2.7-9.5-3.3-14.3-4.7.6-.8,1.3-.8,2.2-.8,4,.1,9.2,2.1,13.3,2.5Z"/>
28
- <path class="st0" d="M416.5,311.3c0-1.2.1-6.9,1.7-6.5,4.7,4.2,7.2,7.3-1.7,6.5Z"/>
29
- <path class="st0" d="M396.5,273.3c-2.1-.3-4.1.8-6.2.5s-2.7-1-2.3-1.7c1-1.9,8.2-1.7,8.5,1.2Z"/>
30
- <path class="st0" d="M409,265.8c.5,3.5-4.3,3.9-6.5,5.5-.7-2.1,5.9-6.1,6.5-5.5Z"/>
31
- <path class="st0" d="M428,308.3c-3-.2-4.9-1.5-6.5-4,2-.5,2.4,1,3.5,1.7s3.1.3,3,2.3Z"/>
32
- <path class="st2" d="M434.5,266.8l.2-2c1.3,0,6.1-2.6,6.7-.7s-6.5,3.4-6.9,2.7Z"/>
33
- <path class="st2" d="M433.5,259.8l.2-1.5c10-2.5,9.1,4-.2,1.5Z"/>
34
- <path class="st2" d="M437,272.8c-1.3-1.8,6-5.5,6.5-3.2s-5.5,4.7-6.5,3.2Z"/>
35
- <path class="st2" d="M447,273.3c1.3,1.3-4.7,7.6-5.5,4.7s4.4-5.8,5.5-4.7Z"/>
36
- <path class="st2" d="M449.6,277.4c.8-.5,2.5,0,2.4,1.1s-2.8,5.2-4.2,4.8,1.5-5.7,1.8-5.9Z"/>
37
- <path class="st2" d="M454,286.3c-.4-.4.5-7.2,2.7-6.5,1.7.5-.2,7.4-2.7,6.5Z"/>
38
- <path class="st2" d="M464,287.8l-1.5-.2-.4-.6c0-1.1-.5-5.4.7-5.7,2.5.9,1.8,4.5,1.2,6.5Z"/>
39
- <path class="st0" d="M420.4,316.4c10.5-.1,21.2,5.6,27.8,13.4s4.5,4.1-.1,7.4c-12.7,9.1-30.9,10.7-45.3,5-2.2-.9-12.4-6-12.4-8.1s4.7-6.3,5.7-7.3c6.3-5.9,15.5-10.2,24.2-10.4Z"/>
40
- <path class="st0" d="M394.5,321.3l-16.5-1.7c2-1.2,5.9-.9,8.2-.7s6.6.8,8.3,2.5Z"/>
41
- <path class="st0" d="M463.5,318.8c.8.6,0,.9-.7,1-1.9.2-4.1-.2-6,0-2.9.3-6.2,1.4-9,1.5s-1.3-.1-.1-.6,6-1.9,7.1-1.9h8.8Z"/>
42
- <path class="st2" d="M666.3,296.5c0-32.5-40.7-63.3-103.1-82.4,14.4-63.6,8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6,0,8.3.9,11.4,2.6,13.6,7.8,19.5,37.5,14.9,75.7-1.1,9.4-2.9,19.3-5.1,29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50,32.6-30.3,63.2-46.9,84-46.9v-22.3c-27.5,0-63.5,19.6-99.9,53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7,0,51.4,16.5,84,46.6-14,14.7-28,31.4-41.3,49.9-22.6,2.4-44,6.1-63.6,11-2.3-10-4-19.7-5.2-29-4.7-38.2,1.1-67.9,14.6-75.8,3-1.8,6.9-2.6,11.5-2.6v-22.3c-8.4,0-16,1.8-22.6,5.6-28.1,16.2-34.4,66.7-19.9,130.1-62.2,19.2-102.7,49.9-102.7,82.3s40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4,6.5,3.8,14.1,5.6,22.5,5.6,27.5,0,63.5-19.6,99.9-53.6,36.4,33.8,72.4,53.2,99.9,53.2s16-1.8,22.6-5.6c28.1-16.2,34.4-66.7,19.9-130.1,62-19.1,102.5-49.9,102.5-82.3h0ZM536.1,229.8c-3.7,12.9-8.3,26.2-13.5,39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4,14.2,2.1,27.9,4.7,41,7.9h0ZM490.3,336.3c-7.8,13.5-15.8,26.3-24.1,38.2-14.9,1.3-30,2-45.2,2s-30.2-.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8,6.2-13.4,13.2-26.8,20.7-39.9,7.8-13.5,15.8-26.3,24.1-38.2,14.9-1.3,30-2,45.2-2s30.2.7,45,1.9c8.3,11.9,16.4,24.6,24.2,38,7.6,13.1,14.5,26.4,20.8,39.8-6.3,13.4-13.2,26.8-20.7,39.9h0ZM522.6,323.3c5.4,13.4,10,26.8,13.8,39.8-13.1,3.2-26.9,5.9-41.2,8,4.9-7.7,9.8-15.6,14.4-23.7,4.6-8,8.9-16.1,13-24.1h0ZM421.2,430c-9.3-9.6-18.6-20.3-27.8-32,9,.4,18.2.7,27.5.7s18.7-.2,27.8-.7c-9,11.7-18.3,22.4-27.5,32ZM346.8,371.1c-14.2-2.1-27.9-4.7-41-7.9,3.7-12.9,8.3-26.2,13.5-39.5,4.1,8,8.4,16,13.1,24s9.5,15.8,14.4,23.4ZM420.7,163c9.3,9.6,18.6,20.3,27.8,32-9-.4-18.2-.7-27.5-.7s-18.7.2-27.8.7c9-11.7,18.3-22.4,27.5-32ZM346.7,221.9c-4.9,7.7-9.8,15.6-14.4,23.7-4.6,8-8.9,16-13,24-5.4-13.4-10-26.8-13.8-39.8,13.1-3.1,26.9-5.8,41.2-7.9h0ZM256.2,347.1c-35.4-15.1-58.3-34.9-58.3-50.6s22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1,5.7,19.6,13.2,40,22.5,60.9-9.2,20.8-16.6,41.1-22.2,60.6-9.9-3.1-19.3-6.5-28-10.2h0ZM310,490c-13.6-7.8-19.5-37.5-14.9-75.7,1.1-9.4,2.9-19.3,5.1-29.4,19.6,4.8,41,8.5,63.5,10.9,13.5,18.5,27.5,35.3,41.6,50-32.6,30.3-63.2,46.9-84,46.9-4.5-.1-8.3-1-11.3-2.7h0ZM547.2,413.8c4.7,38.2-1.1,67.9-14.6,75.8-3,1.8-6.9,2.6-11.5,2.6-20.7,0-51.4-16.5-84-46.6,14-14.7,28-31.4,41.3-49.9,22.6-2.4,44-6.1,63.6-11,2.3,10.1,4.1,19.8,5.2,29.1ZM585.7,347.1c-8.6,3.7-18,7-27.7,10.1-5.7-19.6-13.2-40-22.5-60.9,9.2-20.8,16.6-41.1,22.2-60.6,9.9,3.1,19.3,6.5,28.1,10.2,35.4,15.1,58.3,34.9,58.3,50.6,0,15.7-23,35.6-58.4,50.6h0Z"/>
43
- <path class="st1" d="M520.5,78.1"/>
44
- </svg>
@@ -1,14 +0,0 @@
1
- import { defineConfig } from "vite";
2
- import viteReact from "@vitejs/plugin-react";
3
- <% if (tailwind) { %>
4
- import tailwindcss from "@tailwindcss/vite";
5
- <% } %>
6
-
7
- // https://vitejs.dev/config/
8
- export default defineConfig({
9
- plugins: [viteReact()<% if (tailwind) { %>, tailwindcss()<% } %>],
10
- test: {
11
- globals: true,
12
- environment: "jsdom",
13
- },
14
- });
File without changes