@undp/create-app 0.2.21 β†’ 0.3.0

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 (62) hide show
  1. package/README.md +8 -8
  2. package/bin/generateFiles/generateGitIgnore.js +0 -1
  3. package/bin/generateFiles/generatePackageJson.js +62 -61
  4. package/bin/generateFiles/generatePageForNext.js +3 -3
  5. package/bin/generateFiles/generateViteConfig.js +12 -4
  6. package/bin/templates/next/auth/README.md +6 -6
  7. package/bin/templates/next/auth/app/about/page.tsx +1 -1
  8. package/bin/templates/next/auth/app/login/page.tsx +1 -1
  9. package/bin/templates/next/auth/app/page.tsx +2 -2
  10. package/bin/templates/next/auth/app/user/page.tsx +1 -1
  11. package/bin/templates/next/auth/biome.json +3 -0
  12. package/bin/templates/next/basic/README.md +6 -6
  13. package/bin/templates/next/basic/app/about/page.tsx +1 -1
  14. package/bin/templates/next/basic/app/page.tsx +2 -2
  15. package/bin/templates/next/basic/biome.json +3 -0
  16. package/bin/templates/vite/basic/README.md +6 -6
  17. package/bin/templates/vite/basic/biome.json +3 -0
  18. package/bin/templates/vite/basic/src/App.tsx +3 -3
  19. package/bin/templates/vite/basic/tsconfig.json +1 -1
  20. package/bin/templates/vite/basic/vite.config.ts +1 -7
  21. package/bin/templates/vite/query/README.md +6 -6
  22. package/bin/templates/vite/query/biome.json +3 -0
  23. package/bin/templates/vite/query/src/App.tsx +4 -4
  24. package/bin/templates/vite/query/tsconfig.json +1 -1
  25. package/bin/templates/vite/query/vite.config.ts +1 -7
  26. package/bin/templates/vite/query+router/README.md +6 -6
  27. package/bin/templates/vite/query+router/biome.json +3 -0
  28. package/bin/templates/vite/query+router/src/App.tsx +2 -2
  29. package/bin/templates/vite/query+router/src/routes/queryDemo.tsx +2 -2
  30. package/bin/templates/vite/query+router/tsconfig.json +1 -1
  31. package/bin/templates/vite/query+router/vite.config.ts +1 -7
  32. package/bin/templates/vite/router/README.md +6 -6
  33. package/bin/templates/vite/router/biome.json +3 -0
  34. package/bin/templates/vite/router/src/App.tsx +2 -2
  35. package/bin/templates/vite/router/src/routes/about.tsx +1 -1
  36. package/bin/templates/vite/router/tsconfig.json +1 -1
  37. package/bin/templates/vite/router/vite.config.ts +1 -7
  38. package/bin/templates/viteWithLanguage/basic/README.md +18 -6
  39. package/bin/templates/viteWithLanguage/basic/biome.json +3 -0
  40. package/bin/templates/viteWithLanguage/basic/src/App.tsx +3 -3
  41. package/bin/templates/viteWithLanguage/basic/tsconfig.json +1 -1
  42. package/bin/templates/viteWithLanguage/basic/vite.config.ts +1 -7
  43. package/bin/templates/viteWithLanguage/query/README.md +18 -6
  44. package/bin/templates/viteWithLanguage/query/biome.json +3 -0
  45. package/bin/templates/viteWithLanguage/query/src/App.tsx +4 -4
  46. package/bin/templates/viteWithLanguage/query/tsconfig.json +1 -1
  47. package/bin/templates/viteWithLanguage/query/vite.config.ts +1 -7
  48. package/bin/templates/viteWithLanguage/query+router/README.md +20 -6
  49. package/bin/templates/viteWithLanguage/query+router/biome.json +3 -0
  50. package/bin/templates/viteWithLanguage/query+router/src/App.tsx +2 -2
  51. package/bin/templates/viteWithLanguage/query+router/src/components/Header.tsx +1 -1
  52. package/bin/templates/viteWithLanguage/query+router/src/routes/queryDemo.tsx +2 -2
  53. package/bin/templates/viteWithLanguage/query+router/tsconfig.json +1 -1
  54. package/bin/templates/viteWithLanguage/query+router/vite.config.ts +1 -7
  55. package/bin/templates/viteWithLanguage/router/README.md +20 -6
  56. package/bin/templates/viteWithLanguage/router/biome.json +3 -0
  57. package/bin/templates/viteWithLanguage/router/src/App.tsx +2 -2
  58. package/bin/templates/viteWithLanguage/router/src/components/Header.tsx +1 -1
  59. package/bin/templates/viteWithLanguage/router/src/routes/about.tsx +1 -1
  60. package/bin/templates/viteWithLanguage/router/tsconfig.json +1 -1
  61. package/bin/templates/viteWithLanguage/router/vite.config.ts +1 -7
  62. package/package.json +1 -1
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],
@@ -6,7 +6,7 @@ It includes:
6
6
  * Routing with [TanStack Router](https://tanstack.com/router)
7
7
  * Data fetching with [TanStack Query](https://tanstack.com/query)
8
8
  * TailwindCSS
9
- * Code linting and formatting via ESLint and Prettier
9
+ * Code linting and formatting via Biome
10
10
 
11
11
  ## 🧩 Installation
12
12
 
@@ -34,19 +34,19 @@ The page will reload if you make edits. You will also see any lint errors in the
34
34
  - `npm run build`: Executes `tsc && vite build` and builds the app for production and deployment.
35
35
  - `npm run preview`: Executes `vite preview` and serves the static build output (from vite build) locally.
36
36
  - `npm run clean`: Executes `rimraf node_modules && rimraf dist && rimraf package-lock.json` and remove node_modules folder, dist folder and package-lock.json.
37
- - `npm run lint`: Executes `npx eslint --fix && npx prettier . --write` and resolve all the linting and prettier errors.
37
+ - `npm run check`: Executes `biome check .` and lists all the linting and prettier errors.
38
+ - `npm run check:fix`: Executes `biome check --write .` and resolve all the linting and prettier errors.
38
39
 
39
40
  ## 🧰 Tooling Setup
40
41
 
41
- This project uses ESLint integrated with Prettier to automatically format and lint your code.
42
+ This project uses Biome integrated to automatically format and lint your code.
42
43
 
43
44
  If you’re using Visual Studio Code, install:
44
- * [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
45
- * [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
45
+ * [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)
46
46
 
47
47
  Your editor should now show linting errors and automatically fix issues where possible.
48
48
 
49
- More info: [ESLint Integrations](http://eslint.org/docs/user-guide/integrations)
49
+ More info: [Biome Docs](https://biomejs.dev/guides/getting-started/)
50
50
 
51
51
  ## 🎨 Styling
52
52
 
@@ -45,6 +45,9 @@
45
45
  "correctness": {
46
46
  "noUnusedVariables": "error",
47
47
  "noUndeclaredVariables": "error"
48
+ },
49
+ "nursery": {
50
+ "useSortedClasses": "error"
48
51
  }
49
52
  }
50
53
  },
@@ -8,7 +8,7 @@ function App() {
8
8
  const { increment, decrement } = useCounterActions();
9
9
  return (
10
10
  <>
11
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
11
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
12
12
  <img
13
13
  src='./imgs/Vitejs-logo.svg'
14
14
  alt='vite logo'
@@ -48,7 +48,7 @@ function App() {
48
48
  To get started, edit the App.tsx file.{' '}
49
49
  <span className='font-bold'>Count: {count}</span>
50
50
  </P>
51
- <div className='flex gap-4 justify-center mb-8'>
51
+ <div className='mb-8 flex justify-center gap-4'>
52
52
  <Button
53
53
  variant='tertiary'
54
54
  onClick={() => {
@@ -19,12 +19,12 @@ function useTodoData() {
19
19
  export function TanStackQueryDemo() {
20
20
  const { data, isLoading, isError } = useTodoData();
21
21
 
22
- if (isLoading) return <Spinner size='lg' className='my-20 m-auto' />;
22
+ if (isLoading) return <Spinner size='lg' className='mx-auto my-20' />;
23
23
 
24
24
  if (isError) return <>Error</>;
25
25
  return (
26
26
  <>
27
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
27
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
28
28
  <img
29
29
  src='/imgs/Vitejs-logo.svg'
30
30
  alt='vite logo'
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "files": [],
27
- "include": ["eslint.config.mjs", "src", "tailwind.config.js"],
27
+ "include": ["src", "tailwind.config.js"],
28
28
  "references": [{ "path": "./tsconfig.node.json" }]
29
29
  }
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],
@@ -5,7 +5,7 @@ It includes:
5
5
  * UNDP Design System
6
6
  * Routing with [TanStack Router](https://tanstack.com/router)
7
7
  * TailwindCSS
8
- * Code linting and formatting via ESLint and Prettier
8
+ * Code linting and formatting via Biome
9
9
 
10
10
  ## 🧩 Installation
11
11
 
@@ -33,19 +33,19 @@ The page will reload if you make edits. You will also see any lint errors in the
33
33
  - `npm run build`: Executes `tsc && vite build` and builds the app for production and deployment.
34
34
  - `npm run preview`: Executes `vite preview` and serves the static build output (from vite build) locally.
35
35
  - `npm run clean`: Executes `rimraf node_modules && rimraf dist && rimraf package-lock.json` and remove node_modules folder, dist folder and package-lock.json.
36
- - `npm run lint`: Executes `npx eslint --fix && npx prettier . --write` and resolve all the linting and prettier errors.
36
+ - `npm run check`: Executes `biome check .` and lists all the linting and prettier errors.
37
+ - `npm run check:fix`: Executes `biome check --write .` and resolve all the linting and prettier errors.
37
38
 
38
39
  ## 🧰 Tooling Setup
39
40
 
40
- This project uses ESLint integrated with Prettier to automatically format and lint your code.
41
+ This project uses Biome integrated to automatically format and lint your code.
41
42
 
42
43
  If you’re using Visual Studio Code, install:
43
- * [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
44
- * [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
44
+ * [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)
45
45
 
46
46
  Your editor should now show linting errors and automatically fix issues where possible.
47
47
 
48
- More info: [ESLint Integrations](http://eslint.org/docs/user-guide/integrations)
48
+ More info: [Biome Docs](https://biomejs.dev/guides/getting-started/)
49
49
 
50
50
  ## 🎨 Styling
51
51
 
@@ -45,6 +45,9 @@
45
45
  "correctness": {
46
46
  "noUnusedVariables": "error",
47
47
  "noUndeclaredVariables": "error"
48
+ },
49
+ "nursery": {
50
+ "useSortedClasses": "error"
48
51
  }
49
52
  }
50
53
  },
@@ -8,7 +8,7 @@ export function App() {
8
8
  const { increment, decrement } = useCounterActions();
9
9
  return (
10
10
  <>
11
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
11
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
12
12
  <img
13
13
  src='./imgs/Vitejs-logo.svg'
14
14
  alt='vite logo'
@@ -48,7 +48,7 @@ export function App() {
48
48
  To get started, edit the App.tsx file.{' '}
49
49
  <span className='font-bold'>Count: {count}</span>
50
50
  </P>
51
- <div className='flex gap-4 justify-center mb-8'>
51
+ <div className='mb-8 flex justify-center gap-4'>
52
52
  <Button
53
53
  variant='tertiary'
54
54
  onClick={() => {
@@ -5,7 +5,7 @@ import { P } from '@undp/design-system-react/Typography';
5
5
  export function About() {
6
6
  return (
7
7
  <>
8
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
8
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
9
9
  <img
10
10
  src='/imgs/Vitejs-logo.svg'
11
11
  alt='vite logo'
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "files": [],
27
- "include": ["eslint.config.mjs", "src", "tailwind.config.js"],
27
+ "include": ["src", "tailwind.config.js"],
28
28
  "references": [{ "path": "./tsconfig.node.json" }]
29
29
  }
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],
@@ -4,7 +4,7 @@ It includes:
4
4
  * React 19.x with React compiler
5
5
  * UNDP Design System
6
6
  * TailwindCSS
7
- * Code linting and formatting via ESLint and Prettier
7
+ * Code linting and formatting via Biome
8
8
 
9
9
  ## 🧩 Installation
10
10
 
@@ -32,24 +32,36 @@ The page will reload if you make edits. You will also see any lint errors in the
32
32
  - `npm run build`: Executes `tsc && vite build` and builds the app for production and deployment.
33
33
  - `npm run preview`: Executes `vite preview` and serves the static build output (from vite build) locally.
34
34
  - `npm run clean`: Executes `rimraf node_modules && rimraf dist && rimraf package-lock.json` and remove node_modules folder, dist folder and package-lock.json.
35
- - `npm run lint`: Executes `npx eslint --fix && npx prettier . --write` and resolve all the linting and prettier errors.
35
+ - `npm run check`: Executes `biome check .` and lists all the linting and prettier errors.
36
+ - `npm run check:fix`: Executes `biome check --write .` and resolve all the linting and prettier errors.
36
37
 
37
38
  ## 🧰 Tooling Setup
38
39
 
39
- This project uses ESLint integrated with Prettier to automatically format and lint your code.
40
+ This project uses Biome integrated to automatically format and lint your code.
40
41
 
41
42
  If you’re using Visual Studio Code, install:
42
- * [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
43
- * [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
43
+ * [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)
44
44
 
45
45
  Your editor should now show linting errors and automatically fix issues where possible.
46
46
 
47
- More info: [ESLint Integrations](http://eslint.org/docs/user-guide/integrations)
47
+ More info: [Biome Docs](https://biomejs.dev/guides/getting-started/)
48
+
49
+ __Recommendation__
50
+
51
+ On Visual Studio Code, you can also use the [i18n Ally](https://github.com/lokalise/i18n-ally/wiki) extension for a better translation workflow. It provides features such as translation key autocomplete, inline translation previews, missing key detection, and quick navigation between translation files.
48
52
 
49
53
  ## 🎨 Styling
50
54
 
51
55
  This project uses [Tailwind CSS](https://tailwindcss.com/) for styling and and includes pre-configured design tokens from the UNDP Design System.
52
56
 
57
+ ## πŸ”£ Adding a new language
58
+
59
+ 1. Create a new translation file (e.g. `src/locales/<language code>/common.json`) containing all translated keys.
60
+ 2. Import and register the language in your i18next `src/i18n.ts`.
61
+ 3. Add the new language in `LANGUAGE` variable in `src/constants.ts`.
62
+ 4. Add the language code to your language selector or supported languages list.
63
+ 5. Switch languages using `i18n.changeLanguage('fr')` and i18next will load the corresponding translations.
64
+
53
65
  ## 🌐 Embedding the Visualization
54
66
 
55
67
  To embed the visualization on an external page, include:
@@ -45,6 +45,9 @@
45
45
  "correctness": {
46
46
  "noUnusedVariables": "error",
47
47
  "noUndeclaredVariables": "error"
48
+ },
49
+ "nursery": {
50
+ "useSortedClasses": "error"
48
51
  }
49
52
  }
50
53
  },
@@ -14,8 +14,8 @@ function App() {
14
14
  const { increment, decrement } = useCounterActions();
15
15
  const { i18n, t } = useTranslation();
16
16
  return (
17
- <div className=' min-h-screen flex flex-col justify-center'>
18
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
17
+ <div className='flex min-h-screen flex-col justify-center'>
18
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
19
19
  <img
20
20
  src='./imgs/Vitejs-logo.svg'
21
21
  alt='vite logo'
@@ -70,7 +70,7 @@ function App() {
70
70
  {t('started', { fileName: 'app.tsx' })}{' '}
71
71
  <span className='font-bold'>{t('count', { count: count })}</span>
72
72
  </P>
73
- <div className='flex gap-4 justify-center'>
73
+ <div className='flex justify-center gap-4'>
74
74
  <Button
75
75
  variant='tertiary'
76
76
  onClick={() => {
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "files": [],
27
- "include": ["eslint.config.mjs", "src", "tailwind.config.js"],
27
+ "include": ["src", "tailwind.config.js"],
28
28
  "references": [{ "path": "./tsconfig.node.json" }]
29
29
  }
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],
@@ -5,7 +5,7 @@ It includes:
5
5
  * UNDP Design System
6
6
  * Data fetching with [TanStack Query](https://tanstack.com/query)
7
7
  * TailwindCSS
8
- * Code linting and formatting via ESLint and Prettier
8
+ * Code linting and formatting via Biome
9
9
 
10
10
  ## 🧩 Installation
11
11
 
@@ -33,24 +33,36 @@ The page will reload if you make edits. You will also see any lint errors in the
33
33
  - `npm run build`: Executes `tsc && vite build` and builds the app for production and deployment.
34
34
  - `npm run preview`: Executes `vite preview` and serves the static build output (from vite build) locally.
35
35
  - `npm run clean`: Executes `rimraf node_modules && rimraf dist && rimraf package-lock.json` and remove node_modules folder, dist folder and package-lock.json.
36
- - `npm run lint`: Executes `npx eslint --fix && npx prettier . --write` and resolve all the linting and prettier errors.
36
+ - `npm run check`: Executes `biome check .` and lists all the linting and prettier errors.
37
+ - `npm run check:fix`: Executes `biome check --write .` and resolve all the linting and prettier errors.
37
38
 
38
39
  ## 🧰 Tooling Setup
39
40
 
40
- This project uses ESLint integrated with Prettier to automatically format and lint your code.
41
+ This project uses Biome integrated to automatically format and lint your code.
41
42
 
42
43
  If you’re using Visual Studio Code, install:
43
- * [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
44
- * [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
44
+ * [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)
45
45
 
46
46
  Your editor should now show linting errors and automatically fix issues where possible.
47
47
 
48
- More info: [ESLint Integrations](http://eslint.org/docs/user-guide/integrations)
48
+ More info: [Biome Docs](https://biomejs.dev/guides/getting-started/)
49
+
50
+ __Recommendation__
51
+
52
+ On Visual Studio Code, you can also use the [i18n Ally](https://github.com/lokalise/i18n-ally/wiki) extension for a better translation workflow. It provides features such as translation key autocomplete, inline translation previews, missing key detection, and quick navigation between translation files.
49
53
 
50
54
  ## 🎨 Styling
51
55
 
52
56
  This project uses [Tailwind CSS](https://tailwindcss.com/) for styling and and includes pre-configured design tokens from the UNDP Design System.
53
57
 
58
+ ## πŸ”£ Adding a new language
59
+
60
+ 1. Create a new translation file (e.g. `src/locales/<language code>/common.json`) containing all translated keys.
61
+ 2. Import and register the language in your i18next `src/i18n.ts`.
62
+ 3. Add the new language in `LANGUAGE` variable in `src/constants.ts`.
63
+ 4. Add the language code to your language selector or supported languages list.
64
+ 5. Switch languages using `i18n.changeLanguage('fr')` and i18next will load the corresponding translations.
65
+
54
66
  ## πŸ” Data Fetching
55
67
 
56
68
  Data fetching is powered by [TanStack Query](https://tanstack.com/query) for efficient, declarative data fetching and caching.
@@ -45,6 +45,9 @@
45
45
  "correctness": {
46
46
  "noUnusedVariables": "error",
47
47
  "noUndeclaredVariables": "error"
48
+ },
49
+ "nursery": {
50
+ "useSortedClasses": "error"
48
51
  }
49
52
  }
50
53
  },
@@ -30,12 +30,12 @@ function App() {
30
30
  const count = useCounter();
31
31
  const { increment, decrement } = useCounterActions();
32
32
 
33
- if (isLoading) return <Spinner size='lg' className='my-20 m-auto' />;
33
+ if (isLoading) return <Spinner size='lg' className='mx-auto my-20' />;
34
34
 
35
35
  if (isError) return <>Error</>;
36
36
  return (
37
- <div className=' min-h-screen flex flex-col justify-center'>
38
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
37
+ <div className='flex min-h-screen flex-col justify-center'>
38
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
39
39
  <img
40
40
  src='./imgs/Vitejs-logo.svg'
41
41
  alt='vite logo'
@@ -97,7 +97,7 @@ function App() {
97
97
  {t('started', { fileName: 'app.tsx' })}{' '}
98
98
  <span className='font-bold'>{t('count', { count: count })}</span>
99
99
  </P>
100
- <div className='flex gap-4 justify-center mb-8'>
100
+ <div className='mb-8 flex justify-center gap-4'>
101
101
  <Button
102
102
  variant='tertiary'
103
103
  onClick={() => {
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "files": [],
27
- "include": ["eslint.config.mjs", "src", "tailwind.config.js"],
27
+ "include": ["src", "tailwind.config.js"],
28
28
  "references": [{ "path": "./tsconfig.node.json" }]
29
29
  }
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],
@@ -6,7 +6,7 @@ It includes:
6
6
  * Routing with [TanStack Router](https://tanstack.com/router)
7
7
  * Data fetching with [TanStack Query](https://tanstack.com/query)
8
8
  * TailwindCSS
9
- * Code linting and formatting via ESLint and Prettier
9
+ * Code linting and formatting via Biome
10
10
 
11
11
  ## 🧩 Installation
12
12
 
@@ -34,24 +34,36 @@ The page will reload if you make edits. You will also see any lint errors in the
34
34
  - `npm run build`: Executes `tsc && vite build` and builds the app for production and deployment.
35
35
  - `npm run preview`: Executes `vite preview` and serves the static build output (from vite build) locally.
36
36
  - `npm run clean`: Executes `rimraf node_modules && rimraf dist && rimraf package-lock.json` and remove node_modules folder, dist folder and package-lock.json.
37
- - `npm run lint`: Executes `npx eslint --fix && npx prettier . --write` and resolve all the linting and prettier errors.
37
+ - `npm run check`: Executes `biome check .` and lists all the linting and prettier errors.
38
+ - `npm run check:fix`: Executes `biome check --write .` and resolve all the linting and prettier errors.
38
39
 
39
40
  ## 🧰 Tooling Setup
40
41
 
41
- This project uses ESLint integrated with Prettier to automatically format and lint your code.
42
+ This project uses Biome integrated to automatically format and lint your code.
42
43
 
43
44
  If you’re using Visual Studio Code, install:
44
- * [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
45
- * [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
45
+ * [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)
46
46
 
47
47
  Your editor should now show linting errors and automatically fix issues where possible.
48
48
 
49
- More info: [ESLint Integrations](http://eslint.org/docs/user-guide/integrations)
49
+ More info: [Biome Docs](https://biomejs.dev/guides/getting-started/)
50
+
51
+ __Recommendation__
52
+
53
+ On Visual Studio Code, you can also use the [i18n Ally](https://github.com/lokalise/i18n-ally/wiki) extension for a better translation workflow. It provides features such as translation key autocomplete, inline translation previews, missing key detection, and quick navigation between translation files.
50
54
 
51
55
  ## 🎨 Styling
52
56
 
53
57
  This project uses [Tailwind CSS](https://tailwindcss.com/) for styling and and includes pre-configured design tokens from the UNDP Design System.
54
58
 
59
+ ## πŸ”£ Adding a new language
60
+
61
+ 1. Create a new translation file (e.g. `src/locales/<language code>/common.json`) containing all translated keys.
62
+ 2. Import and register the language in your i18next `src/i18n.ts`.
63
+ 3. Add the new language in `LANGUAGE` variable in `src/constants.ts`.
64
+ 4. Add the language code to your language selector or supported languages list.
65
+ 5. Switch languages using `i18n.changeLanguage('fr')` and i18next will load the corresponding translations.
66
+
55
67
  ## 🧭 Routing
56
68
 
57
69
  Routing is powered by [TanStack Router](https://tanstack.com/router) and uses a code-based configuration (in the `./src/main.tsx`).
@@ -102,6 +114,8 @@ import { Link } from "@tanstack/react-router";
102
114
 
103
115
  More info: [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).
104
116
 
117
+ __Please note: Language routing is done at in `src/main.tsx`__
118
+
105
119
  ## πŸ” Data Fetching
106
120
 
107
121
  Data fetching is powered by [TanStack Query](https://tanstack.com/query) for efficient, declarative data fetching and caching.
@@ -45,6 +45,9 @@
45
45
  "correctness": {
46
46
  "noUnusedVariables": "error",
47
47
  "noUndeclaredVariables": "error"
48
+ },
49
+ "nursery": {
50
+ "useSortedClasses": "error"
48
51
  }
49
52
  }
50
53
  },
@@ -10,7 +10,7 @@ function App() {
10
10
  const { increment, decrement } = useCounterActions();
11
11
  return (
12
12
  <>
13
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
13
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
14
14
  <img
15
15
  src='/imgs/Vitejs-logo.svg'
16
16
  alt='vite logo'
@@ -50,7 +50,7 @@ function App() {
50
50
  {t('started', { fileName: 'app.tsx' })}{' '}
51
51
  <span className='font-bold'>{t('count', { count: count })}</span>
52
52
  </P>
53
- <div className='flex gap-4 justify-center mb-8'>
53
+ <div className='mb-8 flex justify-center gap-4'>
54
54
  <Button
55
55
  variant='tertiary'
56
56
  onClick={() => {
@@ -39,7 +39,7 @@ export default function HeaderEl() {
39
39
  <HeaderActions>
40
40
  <DropdownMenu>
41
41
  <DropdownMenuTrigger asChild>
42
- <div className='cursor-pointer flex h-9 flex gap-2 rtl:[direction:rtl] items-center text-primary-blue-600 hover:text-primary-blue-400 dark:text-primary-white dark:hover:text-primary-white uppercase font-semibold text-sm justify-between whitespace-nowrap bg-transparent p-0 data-[placeholder]:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 [&[data-state=open]>.chevron-down]:rotate-180'>
42
+ <div className='flex h-9 cursor-pointer items-center justify-between gap-2 whitespace-nowrap bg-transparent p-0 font-semibold text-primary-blue-600 text-sm uppercase hover:text-primary-blue-400 disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground dark:text-primary-white dark:hover:text-primary-white rtl:[direction:rtl] [&>span]:line-clamp-1 [&[data-state=open]>.chevron-down]:rotate-180'>
43
43
  <LanguageSwitcherIcon />
44
44
  {LANGUAGES.find(d => d.id === locale)?.label}
45
45
  <ChevronDown />
@@ -21,12 +21,12 @@ export function TanStackQueryDemo() {
21
21
  const { data, isLoading, isError } = useTodoData();
22
22
  const { t } = useTranslation();
23
23
 
24
- if (isLoading) return <Spinner size='lg' className='my-20 m-auto' />;
24
+ if (isLoading) return <Spinner size='lg' className='mx-auto my-20' />;
25
25
 
26
26
  if (isError) return <>Error</>;
27
27
  return (
28
28
  <>
29
- <div className='flex gap-4 items-center justify-center my-8 mx-auto'>
29
+ <div className='mx-auto my-8 flex items-center justify-center gap-4'>
30
30
  <img
31
31
  src='/imgs/Vitejs-logo.svg'
32
32
  alt='vite logo'
@@ -24,6 +24,6 @@
24
24
  }
25
25
  },
26
26
  "files": [],
27
- "include": ["eslint.config.mjs", "src", "tailwind.config.js"],
27
+ "include": ["src", "tailwind.config.js"],
28
28
  "references": [{ "path": "./tsconfig.node.json" }]
29
29
  }
@@ -2,7 +2,6 @@ import path from 'path';
2
2
 
3
3
  import { defineConfig } from 'vite';
4
4
  import react from '@vitejs/plugin-react';
5
- import eslint from '@nabla/vite-plugin-eslint';
6
5
  import { visualizer } from 'rollup-plugin-visualizer';
7
6
  import postcssNested from 'postcss-nested';
8
7
  import tailwindcss from '@tailwindcss/postcss';
@@ -10,12 +9,7 @@ import { viteStaticCopy } from 'vite-plugin-static-copy';
10
9
 
11
10
  export default defineConfig({
12
11
  plugins: [
13
- react({
14
- babel: {
15
- plugins: ['babel-plugin-react-compiler'],
16
- },
17
- }),
18
- eslint(),
12
+ react(),
19
13
  visualizer({ filename: 'stats.html', open: true }),
20
14
  viteStaticCopy({
21
15
  targets: [{ src: 'staticwebapp.config.json', dest: '' }],