├── .env.example ├── .nvmrc ├── .husky └── pre-commit ├── src ├── styles │ ├── global.pcss │ └── tailwind.css ├── App.module.pcss ├── static │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── mstile-150x150.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── .htaccess │ ├── browserconfig.xml │ ├── site.webmanifest │ ├── safari-pinned-tab.svg │ └── webpack.svg ├── ts-node.register.mjs ├── index.tsx ├── App.tsx ├── ErrorFallbackExample.tsx └── types │ └── shims.d.ts ├── .browserslistrc ├── .prettierignore ├── pnpm-workspace.yaml ├── .lintstagedrc ├── prettier.config.mjs ├── tailwind.config.ts ├── .stylelintignore ├── .vscode ├── extensions.json └── settings.json ├── svgo.config.mjs ├── postcss.config.mjs ├── tsconfig.json ├── LICENSE ├── public └── index.html ├── eslint.config.js ├── stylelint.config.mjs ├── .gitignore ├── package.json ├── CODE_OF_CONDUCT.md ├── webpack.config.ts ├── .gitattributes └── README.md /.env.example: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 24.9.0 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm lint-staged 2 | -------------------------------------------------------------------------------- /src/styles/global.pcss: -------------------------------------------------------------------------------- 1 | @import '#tailwind.css'; 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 versions 2 | > 1% 3 | not dead 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Build 2 | build 3 | 4 | node_modules 5 | __generated__ 6 | pnpm-lock.yaml 7 | -------------------------------------------------------------------------------- /src/App.module.pcss: -------------------------------------------------------------------------------- 1 | @reference '#global.pcss'; 2 | 3 | .test { 4 | @apply text-primary-500; 5 | } 6 | -------------------------------------------------------------------------------- /src/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/favicon.ico -------------------------------------------------------------------------------- /src/styles/tailwind.css: -------------------------------------------------------------------------------- 1 | @import 'tailwindcss'; 2 | 3 | @theme { 4 | --color-primary-500: gray; 5 | } 6 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | onlyBuiltDependencies: 2 | - '@tailwindcss/oxide' 3 | - 'esbuild' 4 | - 'unrs-resolver' 5 | -------------------------------------------------------------------------------- /src/static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/favicon-16x16.png -------------------------------------------------------------------------------- /src/static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/favicon-32x32.png -------------------------------------------------------------------------------- /src/static/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/mstile-150x150.png -------------------------------------------------------------------------------- /src/static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/apple-touch-icon.png -------------------------------------------------------------------------------- /src/static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/static/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexey-koran/react-template/HEAD/src/static/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/static/.htaccess: -------------------------------------------------------------------------------- 1 | Options -MultiViews 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^ index.html [QSA,L] 5 | -------------------------------------------------------------------------------- /src/ts-node.register.mjs: -------------------------------------------------------------------------------- 1 | import { register } from 'node:module'; 2 | import { pathToFileURL } from 'node:url'; 3 | 4 | register('ts-node/esm', pathToFileURL('./')); 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx}": [ 3 | "prettier --write", 4 | "pnpm lint:fix-staged" 5 | ], 6 | "*.{css,pcss}": ["pnpm lint:css:fix-staged"] 7 | } 8 | -------------------------------------------------------------------------------- /prettier.config.mjs: -------------------------------------------------------------------------------- 1 | import { config } from '@alexey-koran/prettier-config'; 2 | 3 | /** @type {import('prettier').Config} */ 4 | 5 | export default { 6 | ...config, 7 | plugins: ['prettier-plugin-tailwindcss'], 8 | tailwindConfig: './tailwind.config.ts', 9 | }; 10 | -------------------------------------------------------------------------------- /src/static/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #b91d47 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss'; 2 | 3 | const tailwindCssConfig = { 4 | content: { 5 | relative: true, 6 | files: ['./src/**/*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx}'], 7 | }, 8 | plugins: [], 9 | } satisfies Config; 10 | 11 | export default tailwindCssConfig; 12 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | *.js 2 | *.cjs 3 | *.mjs 4 | *.jsx 5 | *.cjsx 6 | *.mjsx 7 | *.ts 8 | *.cts 9 | *.mts 10 | *.tsx 11 | *.ctsx 12 | *.mtsx 13 | *.svg 14 | *.png 15 | *.jpg 16 | *.jpeg 17 | *.ico 18 | *.webp 19 | *.xml 20 | *.html 21 | *.otf 22 | *.ttf 23 | *.woff 24 | *.woff2 25 | *.eot 26 | *.md 27 | *.webmanifest 28 | node_modules 29 | build 30 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "formulahendry.auto-rename-tag", 4 | "cpylua.language-postcss", 5 | "SonarSource.sonarlint-vscode", 6 | "dannyconnell.split-html-attributes", 7 | "bradlc.vscode-tailwindcss", 8 | "streetsidesoftware.code-spell-checker", 9 | "streetsidesoftware.code-spell-checker-russian", 10 | "dbaeumer.vscode-eslint", 11 | "esbenp.prettier-vscode" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react'; 2 | 3 | import { createRoot } from 'react-dom/client'; 4 | 5 | import { App } from '@/App'; 6 | 7 | import '@/styles/global.pcss'; 8 | 9 | const container = document.getElementById('app'); 10 | 11 | if (container === null) { 12 | throw new Error('Root not found'); 13 | } 14 | 15 | const root = createRoot(container); 16 | 17 | root.render( 18 | 19 | 20 | , 21 | ); 22 | -------------------------------------------------------------------------------- /src/static/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /svgo.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('svgo').Config} */ 2 | 3 | export default { 4 | js2svg: { 5 | indent: 2, 6 | pretty: true, 7 | }, 8 | plugins: [ 9 | { 10 | name: 'preset-default', 11 | params: { 12 | overrides: { 13 | inlineStyles: { 14 | onlyMatchedOnce: false, 15 | }, 16 | mergePaths: false, 17 | }, 18 | }, 19 | }, 20 | 'removeDeprecatedAttrs', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | import tailwindcss from '@tailwindcss/postcss'; 2 | import postcssAssets from 'postcss-assets'; 3 | import postcssPresetEnv from 'postcss-preset-env'; 4 | import stylelint from 'stylelint'; 5 | 6 | export default () => ({ 7 | plugins: [ 8 | stylelint(), 9 | tailwindcss(), 10 | postcssPresetEnv({ 11 | features: { 'nesting-rules': false }, 12 | }), 13 | postcssAssets({ 14 | loadPaths: ['**'], 15 | }), 16 | ], 17 | }); 18 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | 3 | import { ErrorBoundary } from 'react-error-boundary'; 4 | 5 | import { ErrorFallbackExample } from '@/ErrorFallbackExample'; 6 | 7 | import styles from './App.module.pcss'; 8 | 9 | export const App: FC = () => ( 10 | // This is just an example, replace ErrorFallbackExample by your implementation! 11 | 12 |
Test PCSS Modules
13 |
Test Tailwind utility classes
14 |
15 | ); 16 | -------------------------------------------------------------------------------- /src/static/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@alexey-koran/tsconfig", 3 | "include": [ 4 | "./**/*.js", 5 | "./**/*.cjs", 6 | "./**/*.mjs", 7 | "./**/*.jsx", 8 | "./**/*.cjsx", 9 | "./**/*.mjsx", 10 | "./**/*.ts", 11 | "./**/*.cts", 12 | "./**/*.mts", 13 | "./**/*.tsx", 14 | "./**/*.ctsx", 15 | "./**/*.mtsx" 16 | ], 17 | "exclude": ["node_modules"], 18 | "compilerOptions": { 19 | "jsx": "react-jsx", 20 | "baseUrl": ".", 21 | "outDir": "./build/", 22 | "rootDir": "./", 23 | "typeRoots": ["./node_modules/@types", "./src/types"], 24 | "paths": { 25 | "@/*": ["src/*"] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ErrorFallbackExample.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | 3 | import type { FallbackProps } from 'react-error-boundary'; 4 | 5 | // This is just an example, replace it by your implementation! 6 | 7 | interface ErrorFallbackProps extends Omit { 8 | error: Error; 9 | } 10 | 11 | export const ErrorFallbackExample: FC = ({ error, resetErrorBoundary }) => ( 12 |
13 |

Something went wrong:

14 | 15 |
{error.message}
16 | 17 | 23 |
24 | ); 25 | -------------------------------------------------------------------------------- /src/static/webpack.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /src/types/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import type { FC, JSX } from 'react'; 3 | 4 | const content: FC; 5 | 6 | export = content; 7 | } 8 | 9 | declare module '*.svg?url' { 10 | const content: string; 11 | 12 | export = content; 13 | } 14 | 15 | declare module '*.png' { 16 | const content: string; 17 | 18 | export = content; 19 | } 20 | 21 | declare module '*.jpg' { 22 | const content: string; 23 | 24 | export = content; 25 | } 26 | 27 | declare module '*.jpeg' { 28 | const content: string; 29 | 30 | export = content; 31 | } 32 | 33 | declare module '*.webp' { 34 | const content: string; 35 | 36 | export = content; 37 | } 38 | 39 | declare module '*.module.css' { 40 | const classes: Readonly>; 41 | 42 | export = classes; 43 | } 44 | 45 | declare module '*.module.pcss' { 46 | const classes: Readonly>; 47 | 48 | export = classes; 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Alexey Koran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | MIT License 24 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 18 | 24 | 30 | 34 | 39 | 43 | 47 | <%= htmlWebpackPlugin.options.title %> 48 | 49 | 50 | 51 | 52 | 53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { 2 | shareableConfig, 3 | supportedFileTypes, 4 | supportedExtensions, 5 | } from '@alexey-koran/eslint-config'; 6 | 7 | const config = [ 8 | ...shareableConfig, 9 | { 10 | name: 'local/all', 11 | files: [supportedFileTypes.all], 12 | languageOptions: { 13 | parserOptions: { 14 | tsconfigRootDir: import.meta.dirname, 15 | projectService: { 16 | defaultProject: './tsconfig.json', 17 | }, 18 | }, 19 | }, 20 | settings: { 21 | 'import/extensions': supportedExtensions.all, 22 | // start eslint-import-resolver-typescript 23 | 'import/parsers': { 24 | '@typescript-eslint/parser': [...supportedExtensions.ts, ...supportedExtensions.tsx], 25 | }, 26 | // eslint-import-resolver-webpack 27 | 'import/resolver': { 28 | typescript: { 29 | alwaysTryTypes: true, 30 | project: './tsconfig.json', 31 | }, 32 | webpack: { 33 | config: './webpack.config.ts', 34 | }, 35 | node: { 36 | paths: ['src'], 37 | extensions: supportedExtensions.all, 38 | }, 39 | }, 40 | // end eslint-import-resolver-typescript 41 | }, 42 | }, 43 | { 44 | name: 'global/ignores', 45 | // The new config system no longer supports .eslintignore files 46 | // https://eslint.org/blog/2022/10/eslint-v8.25.0-released/#highlights 47 | ignores: ['build'], 48 | }, 49 | ]; 50 | 51 | export default config; 52 | -------------------------------------------------------------------------------- /stylelint.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('stylelint').Config} */ 2 | 3 | export default { 4 | extends: ['stylelint-config-standard', 'stylelint-config-clean-order'], 5 | plugins: ['stylelint-prettier'], 6 | rules: { 7 | 'prettier/prettier': true, 8 | 'import-notation': null, 9 | 'at-rule-no-unknown': [ 10 | true, 11 | { 12 | ignoreAtRules: [ 13 | 'tailwind', 14 | 'apply', 15 | 'layer', 16 | 'config', 17 | 'variants', 18 | 'responsive', 19 | 'screen', 20 | 'reference', 21 | 'custom-variant', 22 | 'theme', 23 | ], 24 | }, 25 | ], 26 | 'function-no-unknown': [ 27 | true, 28 | { 29 | ignoreFunctions: ['theme'], 30 | }, 31 | ], 32 | 'color-no-invalid-hex': true, 33 | 'value-keyword-case': [ 34 | 'lower', 35 | { 36 | camelCaseSvgKeywords: true, 37 | }, 38 | ], 39 | 'annotation-no-unknown': true, 40 | 'block-no-empty': true, 41 | 'custom-property-no-missing-var-function': true, 42 | 'declaration-block-no-duplicate-custom-properties': true, 43 | 'declaration-block-no-duplicate-properties': true, 44 | 'declaration-block-no-shorthand-property-overrides': true, 45 | 'function-calc-no-unspaced-operator': true, 46 | 'function-linear-gradient-no-nonstandard-direction': true, 47 | 'keyframe-declaration-no-important': true, 48 | 'named-grid-areas-no-invalid': true, 49 | 'no-descending-specificity': true, 50 | 'no-duplicate-at-import-rules': true, 51 | 'no-duplicate-selectors': true, 52 | 'no-empty-source': true, 53 | 'no-unknown-animations': true, 54 | 'no-invalid-double-slash-comments': true, 55 | 'no-invalid-position-at-import-rule': true, 56 | 'no-irregular-whitespace': true, 57 | 'property-no-unknown': true, 58 | 'string-no-newline': true, 59 | 'selector-class-pattern': [ 60 | '^[a-z][a-zA-Z0-9]+$', 61 | { 62 | message: (selector) => `Expected class selector "${selector}" to be lowerCamelCase`, 63 | }, 64 | ], 65 | 'selector-type-no-unknown': true, 66 | 'selector-pseudo-class-no-unknown': true, 67 | 'selector-pseudo-element-no-unknown': true, 68 | 'unit-no-unknown': true, 69 | }, 70 | }; 71 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "[javascript]": { 4 | "editor.defaultFormatter": "esbenp.prettier-vscode" 5 | }, 6 | "[javascriptreact]": { 7 | "editor.defaultFormatter": "esbenp.prettier-vscode" 8 | }, 9 | "[typescript]": { 10 | "editor.defaultFormatter": "esbenp.prettier-vscode" 11 | }, 12 | "[typescriptreact]": { 13 | "editor.defaultFormatter": "esbenp.prettier-vscode" 14 | }, 15 | "[css][postcss][scss][less]": { 16 | "editor.defaultFormatter": "esbenp.prettier-vscode" 17 | }, 18 | "editor.codeActionsOnSave": { 19 | "source.fixAll.eslint": "explicit" 20 | }, 21 | "editor.formatOnSave": true, 22 | "editor.quickSuggestions": { 23 | "strings": "on" 24 | }, 25 | "eslint.workingDirectories": [ 26 | { 27 | "mode": "auto" 28 | } 29 | ], 30 | "cSpell.language": "en,ru", 31 | "cSpell.enabledFileTypes": { 32 | "typescript": true, 33 | "javascript": true, 34 | "javascriptreact": true, 35 | "typescriptreact": true, 36 | "html": true, 37 | "css": true, 38 | "json": false, 39 | "jsonc": false, 40 | "yaml": false 41 | }, 42 | "typescript.preferences.importModuleSpecifier": "non-relative", 43 | "typescript.preferences.importModuleSpecifierEnding": "minimal", 44 | "splitHTMLAttributes.closingBracketOnNewLine": true, 45 | "stylelint.packageManager": "pnpm", 46 | "stylelint.validate": ["postcss"], 47 | "css.validate": false, 48 | "less.validate": false, 49 | "scss.validate": false, 50 | "eslint.useFlatConfig": true, 51 | "explorer.fileNesting.enabled": true, 52 | "explorer.fileNesting.expand": false, 53 | "explorer.fileNesting.patterns": { 54 | "*.ts": "${capture}.ts", 55 | "*.tsx": "${capture}.module.pcss, ${capture}.ts, index.ts", 56 | ".env": "*.env, .env.*, .envrc, env.d.ts", 57 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*", 58 | "webpack.config.*": "*.env, .env.*, .envrc, eslint.*, env.d.ts, postcss.config.*, prettier.*, svgo.config.*, stylelint.config.*, tailwind.config.*", 59 | "package.json": ".browserslist*, .commitlint*, .editorconfig, .eslint*, .github*, .lintstagedrc*, .npm*, .nvmrc, .pnpm*, package-lock.json, .prettier*, .stylelint*, .vscode*, commitlint*, lint-staged*, pnpm*, tsconfig.*", 60 | "README*": "AUTHORS, BACKERS*, CHANGELOG*, CITATION*, CODE_OF_CONDUCT*, CODEOWNERS, CONTRIBUTING*, CONTRIBUTORS, COPYING, CREDITS, GOVERNANCE.MD, HISTORY.MD, LICENSE*, MAINTAINERS, SECURITY.MD, SPONSORS*", 61 | "readme*": "authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, security.md, sponsors*" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Build 14 | build 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # Snowpack dependency directory (https://snowpack.dev/) 49 | web_modules/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional stylelint cache 61 | .stylelintcache 62 | 63 | # Microbundle cache 64 | .rpt2_cache/ 65 | .rts2_cache_cjs/ 66 | .rts2_cache_es/ 67 | .rts2_cache_umd/ 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # Output of 'npm pack' 73 | *.tgz 74 | 75 | # Yarn Integrity file 76 | .yarn-integrity 77 | 78 | # dotenv environment variable files 79 | .env 80 | .env.development.local 81 | .env.test.local 82 | .env.production.local 83 | .env.local 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | .parcel-cache 88 | 89 | # Next.js build output 90 | .next 91 | out 92 | 93 | # Nuxt.js build / generate output 94 | .nuxt 95 | dist 96 | 97 | # Gatsby files 98 | .cache/ 99 | # Comment in the public line in if your project uses Gatsby and not Next.js 100 | # https://nextjs.org/blog/next-9-1#public-directory-support 101 | # public 102 | 103 | # vuepress build output 104 | .vuepress/dist 105 | 106 | # vuepress v2.x temp and cache directory 107 | .temp 108 | .cache 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | 135 | # GraphQL generated types 136 | __generated__ 137 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-template", 3 | "version": "0.4.2", 4 | "description": "React and typescript template", 5 | "main": "src/index.tsx", 6 | "type": "module", 7 | "author": "Alexey-Koran ", 8 | "license": "MIT", 9 | "bugs": { 10 | "url": "https://github.com/alexey-koran/react-template/issues" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/alexey-koran/react-template.git" 15 | }, 16 | "keywords": [ 17 | "react", 18 | "typescript", 19 | "react template", 20 | "react boilerplate" 21 | ], 22 | "homepage": "https://github.com/alexey-koran/react-template#readme", 23 | "packageManager": "pnpm@10.18.3", 24 | "engines": { 25 | "node": ">=22.20.0" 26 | }, 27 | "imports": { 28 | "#tailwind.css": "./src/styles/tailwind.css", 29 | "#global.pcss": "./src/styles/global.pcss" 30 | }, 31 | "scripts": { 32 | "dev": "node --import ./src/ts-node.register.mjs node_modules/webpack/bin/webpack serve --color --hot --mode=development", 33 | "prod": "node --import ./src/ts-node.register.mjs node_modules/webpack/bin/webpack serve --color --hot --mode=production", 34 | "buildapp": "node --import ./src/ts-node.register.mjs node_modules/webpack/bin/webpack --mode=production", 35 | "clean": "rm -f -r build", 36 | "build": "pnpm clean && pnpm buildapp", 37 | "analyze": "node --import ./src/ts-node.register.mjs node_modules/webpack/bin/webpack --analyze --mode=production", 38 | "prepare": "husky && echo 'pnpm lint-staged' > .husky/pre-commit", 39 | "prettier": "prettier --check \"**/*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx,pcss}\"", 40 | "prettier:fix": "prettier --write \"**/*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx,pcss}\"", 41 | "lint": "eslint --concurrency=auto **/*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx}", 42 | "lint:fix": "eslint --concurrency=auto **/*.{js,cjs,mjs,jsx,cjsx,mjsx,ts,cts,mts,tsx,ctsx,mtsx} --fix", 43 | "lint:fix-staged": "eslint --concurrency=auto --fix", 44 | "lint:css": "stylelint src", 45 | "lint:css:fix": "pnpm lint:css -- --fix", 46 | "lint:css:fix-staged": "pnpm stylelint -- --fix", 47 | "lint-all": "pnpm prettier && pnpm lint && pnpm lint:css", 48 | "fix-all": "pnpm prettier:fix && pnpm lint:fix && pnpm lint:css:fix", 49 | "fix-staged": "lint-staged", 50 | "type-check": "tsc --noEmit", 51 | "test:eslint-config": "eslint-config-inspector", 52 | "test:webpack-config": "node --import ./src/ts-node.register.mjs node_modules/webpack/bin/webpack configtest", 53 | "svgo": "cross-env svgo $FILE", 54 | "svgo-all": "svgo -r -f src" 55 | }, 56 | "dependencies": { 57 | "react": "^19.2.0", 58 | "react-dom": "^19.2.0" 59 | }, 60 | "devDependencies": { 61 | "@alexey-koran/eslint-config": "^0.4.3", 62 | "@alexey-koran/prettier-config": "^0.1.5", 63 | "@alexey-koran/tsconfig": "^0.1.0", 64 | "@eslint/config-inspector": "^1.3.0", 65 | "@eslint/js": "^9.37.0", 66 | "@svgr/webpack": "^8.1.0", 67 | "@tailwindcss/postcss": "^4.1.14", 68 | "@types/dotenv-webpack": "^7.0.8", 69 | "@types/html-webpack-plugin": "^3.2.9", 70 | "@types/node": "^24.8.0", 71 | "@types/react": "^19.2.2", 72 | "@types/react-dom": "^19.2.2", 73 | "@types/webpack": "^5.28.5", 74 | "@types/webpack-bundle-analyzer": "^4.7.0", 75 | "clsx": "^2.1.1", 76 | "copy-webpack-plugin": "^13.0.1", 77 | "cross-env": "^10.1.0", 78 | "css-loader": "^7.1.2", 79 | "dotenv-webpack": "^8.1.1", 80 | "esbuild-loader": "^4.4.0", 81 | "eslint": "^9.37.0", 82 | "fork-ts-checker-webpack-plugin": "^9.1.0", 83 | "html-webpack-plugin": "^5.6.4", 84 | "husky": "^9.1.7", 85 | "lint-staged": "^16.2.4", 86 | "mini-css-extract-plugin": "^2.9.4", 87 | "postcss": "^8.5.6", 88 | "postcss-assets": "^6.0.0", 89 | "postcss-loader": "^8.2.0", 90 | "postcss-preset-env": "^10.4.0", 91 | "prettier": "^3.6.2", 92 | "prettier-plugin-tailwindcss": "^0.7.0", 93 | "react-error-boundary": "^6.0.0", 94 | "style-loader": "^4.0.0", 95 | "stylelint": "^16.25.0", 96 | "stylelint-config-clean-order": "^7.0.0", 97 | "stylelint-config-standard": "^39.0.1", 98 | "stylelint-prettier": "^5.0.3", 99 | "svgo": "^4.0.0", 100 | "tailwindcss": "^4.1.14", 101 | "ts-node": "^10.9.2", 102 | "typescript": "^5.9.3", 103 | "webpack": "^5.102.1", 104 | "webpack-bundle-analyzer": "^4.10.2", 105 | "webpack-cli": "^6.0.1", 106 | "webpack-dev-server": "^5.2.2" 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][mozilla coc]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][faq]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [mozilla coc]: https://github.com/mozilla/diversity 131 | [faq]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | -------------------------------------------------------------------------------- /webpack.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve, dirname } from 'path'; 2 | import { fileURLToPath } from 'url'; 3 | 4 | import type { Configuration as WebpackConfiguration, WebpackOptionsNormalized } from 'webpack'; 5 | 6 | import CopyWebpackPlugin from 'copy-webpack-plugin'; 7 | import Dotenv from 'dotenv-webpack'; 8 | import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; 9 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 10 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; 11 | import type { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server'; 12 | 13 | import { EsbuildPlugin } from 'esbuild-loader'; 14 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 15 | 16 | interface AdditionalOptions { 17 | hot?: boolean; 18 | analyze?: boolean; 19 | } 20 | 21 | type Env = Record | undefined; 22 | 23 | type Options = Pick & AdditionalOptions; 24 | 25 | type Configuration = WebpackConfiguration & WebpackDevServerConfiguration; 26 | 27 | const projectDirname = dirname(fileURLToPath(import.meta.url)); 28 | 29 | const configOutput: Configuration['output'] = { 30 | path: resolve(projectDirname, 'build'), 31 | filename: 'js/[name].[contenthash].js', 32 | assetModuleFilename: 'assets/[hash][ext][query]', 33 | }; 34 | 35 | const configOptimization: Configuration['optimization'] = { 36 | runtimeChunk: 'single', 37 | minimizer: [ 38 | new EsbuildPlugin({ 39 | format: 'esm', 40 | jsx: 'automatic', 41 | css: true, 42 | }), 43 | ], 44 | splitChunks: { 45 | chunks: 'all', 46 | cacheGroups: { 47 | defaultVendors: { 48 | test: /[\\/]node_modules[\\/]/, 49 | priority: -10, 50 | reuseExistingChunk: true, 51 | }, 52 | default: { 53 | minChunks: 1, 54 | priority: -20, 55 | reuseExistingChunk: true, 56 | }, 57 | }, 58 | }, 59 | }; 60 | 61 | const configModules = (isProduction: boolean): Required['module'] => ({ 62 | rules: [ 63 | { 64 | test: /\.(js|cjs|mjs|jsx|cjsx|mjsx|ts|cts|mts|tsx|ctsx|mtsx)$/, 65 | loader: 'esbuild-loader', 66 | exclude: /node_modules/, 67 | options: { 68 | target: 'esnext', 69 | }, 70 | }, 71 | { 72 | test: /\.(png|jpg|jpeg|gif|webp)$/i, 73 | type: 'asset/resource', 74 | generator: { 75 | filename: 'images/[hash][ext][query]', 76 | }, 77 | }, 78 | { 79 | test: /\.(woff|woff2|eot|ttf|otf)$/i, 80 | type: 'asset/resource', 81 | generator: { 82 | filename: 'fonts/[hash][ext][query]', 83 | }, 84 | }, 85 | { 86 | test: /\.(css|pcss)$/, 87 | exclude: /node_modules/, 88 | use: [ 89 | isProduction ? MiniCssExtractPlugin.loader : 'style-loader', 90 | { 91 | loader: 'css-loader', 92 | options: { 93 | importLoaders: 1, 94 | modules: { 95 | auto: true, 96 | namedExport: false, 97 | localIdentName: isProduction ? '[hash:base64]' : '[name]-[local]-[hash:base64:8]', 98 | }, 99 | }, 100 | }, 101 | { 102 | loader: 'postcss-loader', 103 | }, 104 | ], 105 | }, 106 | { 107 | test: /\.svg$/i, 108 | type: 'asset/resource', 109 | resourceQuery: /url/, 110 | generator: { 111 | filename: 'svg/[hash][ext][query]', 112 | }, 113 | }, 114 | { 115 | test: /\.svg$/, 116 | issuer: /\.tsx?$/, 117 | resourceQuery: { not: [/url/] }, 118 | use: [ 119 | { 120 | loader: '@svgr/webpack', 121 | options: { 122 | svgoConfig: './svgo.config.mjs', 123 | prettierConfig: './prettier.config.mjs', 124 | }, 125 | }, 126 | ], 127 | }, 128 | ], 129 | }); 130 | 131 | interface GetConfigPluginsProps { 132 | isAnalyze: boolean; 133 | isDevelopment: boolean; 134 | isProduction: boolean; 135 | } 136 | 137 | const getConfigPlugins = ({ 138 | isAnalyze, 139 | isDevelopment, 140 | isProduction, 141 | }: GetConfigPluginsProps): Required['plugins'] => [ 142 | new Dotenv(), 143 | new HtmlWebpackPlugin({ 144 | title: 'React and typescript template', 145 | template: './public/index.html', 146 | }), 147 | new MiniCssExtractPlugin({ 148 | filename: isProduction ? 'css/[name].[contenthash].css' : 'css/[name].css', 149 | chunkFilename: isProduction ? 'css/[id].[contenthash].css' : 'css/[id].css', 150 | }), 151 | ...(isDevelopment ? [new ForkTsCheckerWebpackPlugin()] : []), 152 | ...(isAnalyze ? [new BundleAnalyzerPlugin({ analyzerPort: 8081 })] : []), 153 | ...(isProduction 154 | ? [new CopyWebpackPlugin({ patterns: [{ from: './src/static', to: '.' }] })] 155 | : []), 156 | ]; 157 | 158 | const config = (_env: Env, { analyze = false, hot = false, mode }: Options): Configuration => { 159 | const isProduction = mode === 'production'; 160 | const isDevelopment = mode === 'development'; 161 | const isDevServer = isDevelopment && hot; 162 | const isAnalyze = isDevelopment && analyze; 163 | 164 | const appConfig: Configuration = { 165 | mode: isProduction ? 'production' : 'development', 166 | devtool: isProduction ? false : 'eval-source-map', 167 | 168 | entry: './src/index.tsx', 169 | 170 | output: configOutput, 171 | 172 | optimization: configOptimization, 173 | 174 | module: configModules(isProduction), 175 | 176 | resolve: { 177 | extensions: [ 178 | '.wasm', 179 | '.json', 180 | '.js', 181 | '.cjs', 182 | '.mjs', 183 | '.jsx', 184 | '.cjsx', 185 | '.mjsx', 186 | '.ts', 187 | '.cts', 188 | '.mts', 189 | '.tsx', 190 | '.ctsx', 191 | '.mtsx', 192 | '.d.ts', 193 | ], 194 | alias: { 195 | '@': resolve(projectDirname, 'src'), 196 | }, 197 | }, 198 | 199 | plugins: getConfigPlugins({ isAnalyze, isDevelopment, isProduction }), 200 | }; 201 | 202 | const devServer: WebpackDevServerConfiguration = { 203 | static: { 204 | directory: resolve(projectDirname, 'src/static'), 205 | }, 206 | historyApiFallback: true, 207 | compress: true, 208 | port: 8080, 209 | }; 210 | 211 | return isDevServer 212 | ? { 213 | ...appConfig, 214 | devServer, 215 | } 216 | : appConfig; 217 | }; 218 | 219 | export default config; 220 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ## GITATTRIBUTES FOR WEB PROJECTS 2 | # 3 | # These settings are for any web project. 4 | # 5 | # Details per file setting: 6 | # text These files should be normalized (i.e. convert CRLF to LF). 7 | # binary These files are binary and should be left untouched. 8 | # 9 | # Note that binary is a macro for -text -diff. 10 | ###################################################################### 11 | 12 | # Auto detect 13 | ## Handle line endings automatically for files detected as 14 | ## text and leave all files detected as binary untouched. 15 | ## This will handle all files NOT defined below. 16 | 17 | # Fix end-of-lines in Git versions older than 2.10 18 | # https://github.com/git/git/blob/master/Documentation/RelNotes/2.10.0.txt#L248 19 | * text=auto eol=lf 20 | 21 | # === 22 | # Binary Files (don't diff, don't fix line endings) 23 | # === 24 | 25 | # Graphics 26 | *.ai binary 27 | *.bmp binary 28 | *.eps binary 29 | *.gif binary 30 | *.gifv binary 31 | *.ico binary 32 | *.jng binary 33 | *.jp2 binary 34 | *.jpg binary 35 | *.jpeg binary 36 | *.jpx binary 37 | *.jxr binary 38 | *.pdf binary 39 | *.png binary 40 | *.psb binary 41 | *.psd binary 42 | # SVG treated as an asset (binary) by default. 43 | *.svg text 44 | # If you want to treat it as binary, 45 | # use the following line instead. 46 | # *.svg binary 47 | *.svgz binary 48 | *.tif binary 49 | *.tiff binary 50 | *.wbmp binary 51 | *.webp binary 52 | 53 | # Audio 54 | *.flac binary 55 | *.kar binary 56 | *.m4a binary 57 | *.mid binary 58 | *.midi binary 59 | *.mp3 binary 60 | *.ogg binary 61 | *.ra binary 62 | *.wav binary 63 | 64 | # Video 65 | *.3gpp binary 66 | *.3gp binary 67 | *.as binary 68 | *.asf binary 69 | *.asx binary 70 | *.avi binary 71 | *.fla binary 72 | *.flv binary 73 | *.m4v binary 74 | *.mng binary 75 | *.mov binary 76 | *.mp4 binary 77 | *.mpeg binary 78 | *.mpg binary 79 | *.ogv binary 80 | *.swc binary 81 | *.swf binary 82 | *.webm binary 83 | *.wmv binary 84 | 85 | # Archives 86 | *.7z binary 87 | *.gz binary 88 | *.jar binary 89 | *.rar binary 90 | *.tar binary 91 | *.zip binary 92 | 93 | # Fonts 94 | *.ttf binary 95 | *.eot binary 96 | *.otf binary 97 | *.oft binary 98 | *.woff binary 99 | *.woff2 binary 100 | 101 | # Executables 102 | *.exe binary 103 | *.pyc binary 104 | 105 | # Source code 106 | *.bash text eol=lf 107 | *.bat text eol=crlf 108 | *.cmd text eol=crlf 109 | *.coffee text 110 | *.css text diff=css 111 | *.htm text diff=html 112 | *.html text diff=html 113 | *.inc text 114 | *.ini text 115 | *.js text 116 | *.cjs text 117 | *.mjs text 118 | *.json text 119 | *.jsx text 120 | *.cjsx text 121 | *.mjsx text 122 | *.less text 123 | *.ls text 124 | *.map text -diff 125 | *.od text 126 | *.onlydata text 127 | *.pcss text diff=css 128 | *.php text diff=php 129 | *.pl text 130 | *.ps1 text eol=crlf 131 | *.py text diff=python 132 | *.rb text diff=ruby 133 | *.sass text 134 | *.scm text 135 | *.scss text diff=css 136 | *.sh text eol=lf 137 | .husky/* text eol=lf 138 | *.sql text 139 | *.styl text 140 | *.tag text 141 | *.ts text 142 | *.cts text 143 | *.mts text 144 | *.tsx text 145 | *.ctsx text 146 | *.mtsx text 147 | *.xml text 148 | *.xhtml text diff=html 149 | 150 | # Docker 151 | Dockerfile text 152 | 153 | # Documentation 154 | *.ipynb text eol=lf 155 | *.markdown text diff=markdown 156 | *.md text diff=markdown 157 | *.mdwn text diff=markdown 158 | *.mdown text diff=markdown 159 | *.mkd text diff=markdown 160 | *.mkdn text diff=markdown 161 | *.mdtxt text 162 | *.mdtext text 163 | *.txt text 164 | AUTHORS text 165 | CHANGELOG text 166 | CHANGES text 167 | CONTRIBUTING text 168 | COPYING text 169 | copyright text 170 | *COPYRIGHT* text 171 | INSTALL text 172 | license text 173 | LICENSE text 174 | NEWS text 175 | readme text 176 | *README* text 177 | TODO text 178 | 179 | # Templates 180 | *.dot text 181 | *.ejs text 182 | *.erb text 183 | *.haml text 184 | *.handlebars text 185 | *.hbs text 186 | *.hbt text 187 | *.jade text 188 | *.latte text 189 | *.mustache text 190 | *.njk text 191 | *.phtml text 192 | *.svelte text 193 | *.tmpl text 194 | *.tpl text 195 | *.twig text 196 | *.vue text 197 | 198 | # Configs 199 | *.cnf text 200 | *.conf text 201 | *.config text 202 | .editorconfig text 203 | .env text 204 | .gitattributes text 205 | .gitconfig text 206 | .htaccess text 207 | *.lock text -diff 208 | package.json text eol=lf 209 | package-lock.json text eol=lf -diff 210 | pnpm-lock.yaml text eol=lf -diff 211 | .prettierrc text 212 | yarn.lock text -diff 213 | *.toml text 214 | *.yaml text 215 | *.yml text 216 | browserslist text 217 | Makefile text 218 | makefile text 219 | 220 | # Heroku 221 | Procfile text 222 | 223 | # RC files (like .babelrc or .eslintrc) 224 | *.*rc text 225 | 226 | # Ignore files (like .npmignore or .gitignore) 227 | *.*ignore text 228 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React template 2 | 3 | This repository provides a modern React + TypeScript template for building Single Page Applications 4 | 5 | It was created during my time working at a company as a replacement for Create React App in 2021 6 | 7 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiI+CiAgPHVzZSB4bGluazpocmVmPSIjYSIvPgogIDx1c2UgeGxpbms6aHJlZj0iI2IiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuNjI1IDEuNSkiLz4KICA8ZGVmcz4KICAgIDxwYXRoIGlkPSJhIiBmaWxsPSIjZmZmZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS40MjQuNzY4YTcgNyAwIDEgMCAzLjY1OCAxMC45NTdBOCA4IDAgMSAxIDExLjQyNC43NjhaIi8+CiAgICA8cGF0aCBpZD0iYiIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOC41NjguNTc2YTUuMjUgNS4yNSAwIDEgMCAyLjc0MyA4LjIxOEE2IDYgMCAxIDEgOC41NjguNTc2WiIvPgogIDwvZGVmcz4KPC9zdmc+Cg==)](CODE_OF_CONDUCT.md) 8 | 9 | | Node | Package manager | 10 | | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 11 | | [![Minimum node version](https://img.shields.io/badge/min%20node-22.20.0-orange?style=for-the-badge&logo=node.js)](https://nodejs.org/en/) | [![Minimum npm version](https://img.shields.io/badge/min%20npm-10.9.3-orange?style=for-the-badge&logo=npm)](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) | 12 | | [![Recommended node version](https://img.shields.io/badge/rec%20node-24.9.0-blue?style=for-the-badge&logo=node.js)](https://nodejs.org/en/) | [![Recommended pnpm](https://img.shields.io/badge/rec%20pnpm-10.17.0-blue?style=for-the-badge&logo=pnpm)](https://pnpm.io/) | 13 | 14 | # Installation 15 | 16 | > [!TIP] 17 | > Highly recommend 18 | > 19 | > [PNPM](https://pnpm.io/) as a **package manager** 20 | > 21 | > [NVM](https://github.com/nvm-sh/nvm) as a **Node.js version manager** 22 | 23 | ```bash 24 | git clone repo_url 25 | cd project_location 26 | pnpm i 27 | ``` 28 | 29 | # Scripts 30 | 31 | > [!IMPORTANT] 32 | > Development server use the **8080** port 33 | 34 | ```bash 35 | http://localhost:8080/ 36 | ``` 37 | 38 | > [!NOTE] 39 | > 40 | > `allJsTsExtensions` = js, cjs, mjs, jsx, cjsx, mjsx, ts, cts, mts, tsx, ctsx, mtsx 41 | > 42 | > For the more details check [scripts section in package.json](./package.json#L17) 43 | 44 |
45 | 46 |

Scripts table

47 | 48 | | Command | Description | Path | 49 | | -------------------------- | -------------------------------------------------------- | ------------------------------- | 50 | | | | | 51 | | | `Dev server` | | 52 | | `pnpm dev` | dev-server in **developer** mode (hot reload) | | 53 | | `pnpm prod` | dev-server in **production** mode (build optimizations) | | 54 | | | | | 55 | | | `Build application` | | 56 | | `pnpm clean` | clean build folder | `./build` | 57 | | `pnpm buildapp` | build application for deploy | `./build` | 58 | | `pnpm build` | clean build folder & build application for deploy | `./build` | 59 | | | | | 60 | | | `Code linting & formatting` | | 61 | | `pnpm prettier` | code format check | `**/*.{allJsTsExtensions,pcss}` | 62 | | `pnpm prettier:fix` | code format autofix | `**/*.{allJsTsExtensions,pcss}` | 63 | | `pnpm lint` | eslint check | `**/*.{allJsTsExtensions}` | 64 | | `pnpm lint:fix` | eslint autofix | `**/*.{allJsTsExtensions}` | 65 | | `pnpm lint:fix-staged` | eslint autofix | only on git staged files | 66 | | `pnpm lint:css` | stylelint check | `./src` | 67 | | `pnpm lint:css:fix` | stylelint autofix | `./src` | 68 | | `pnpm lint:css:fix-staged` | stylelint autofix | only on git staged files | 69 | | `pnpm lint-all` | prettier, eslint & stylelint check processes in order | see above | 70 | | `pnpm fix-all` | prettier, eslint & stylelint autofix processes in order | see above | 71 | | `pnpm fix-staged` | scripts from `.lintstagedrc` in autofix mode | only on git staged files | 72 | | | | | 73 | | | `Analyzation & config check` | | 74 | | `pnpm analyze` | analyze webpack bundle | | 75 | | `pnpm test:eslint-config` | eslint config inspector, displays flat configs & rules | | 76 | | `pnpm test:webpack-config` | webpack config test | | 77 | | | | | 78 | | | `Optimization` | | 79 | | `pnpm svgo $FILE_PATH` | svgo on passed `.svg` file for optimization | `$FILE_PATH` | 80 | | `pnpm svgo-all` | svgo on all `.svg` files in the project for optimization | `./src` | 81 | | | | | 82 | | | `Utility` | | 83 | | `pnpm prepare` | runs automatically after installation, setup husky | | 84 | 85 |
86 | 87 | # Dependencies 88 | 89 | > [!NOTE] 90 | > 91 | > For the more details check [dev & prod dependencies in package.json](./package.json#L41) 92 | 93 |
94 | 95 |

Dependencies table

96 | 97 | | Package name | Description | Version | 98 | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | 99 | | | | | 100 | | | `Webpack` | | 101 | | webpack | Application bundler | [v5.102.\*](https://webpack.js.org/) | 102 | | webpack-cli | CLI for webpack | [v5.1.\*](https://webpack.js.org/api/cli/) | 103 | | webpack-dev-server | Development server | [v6.0.\*](https://webpack.js.org/configuration/dev-server/) | 104 | | webpack-bundle-analyzer | Application bundle analysis | [v4.10.\*](https://github.com/webpack-contrib/webpack-bundle-analyzer) | 105 | | | `Plugins` | | 106 | | fork-ts-checker-webpack-plugin | Runs [TypeScript](https://www.typescriptlang.org/) type checker on a separate process | [v9.1.\*](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) | 107 | | html-webpack-plugin | Generate HTML5 output file entry path: `./public/index.html` | [v5.6.\*](https://github.com/jantimon/html-webpack-plugin) | 108 | | mini-css-extract-plugin | Create a CSS file per JS file which contains CSS | [v2.9.\*](https://github.com/webpack-contrib/mini-css-extract-plugin) | 109 | | copy-webpack-plugin | Copy files to the build directory entry path `./src/static` | [v13.0.\*](https://www.npmjs.com/package/copy-webpack-plugin) | 110 | | dotenv-webpack | Support `.env` and other environment variables | [v8.1.\*](https://github.com/mrsteele/dotenv-webpack) | 111 | | | `Loaders ` | | 112 | | esbuild-loader | Faster alternatives for transpilation and minification with [esbuild](https://github.com/evanw/esbuild) | [v4.4.\*](https://github.com/privatenumber/esbuild-loader) | 113 | | @svgr/webpack | Transform SVG's into React components | [v8.1.\*](https://react-svgr.com/) | 114 | | style-loader | Inject CSS into the DOM | [v4.0.\*](https://github.com/webpack-contrib/style-loader/) | 115 | | css-loader | Interprets `@import` and `url()` like `import/require()` and will resolve them | [v7.1.\*](https://github.com/webpack-contrib/css-loader) | 116 | | postcss-loader | Loader to process CSS with [PostCSS](https://github.com/postcss/postcss) | [v8.2.\*](https://github.com/webpack-contrib/postcss-loader) | 117 | | | | | 118 | | | `Typescript` | | 119 | | typescript | [TypeScript](https://www.typescriptlang.org/) is JavaScript with syntax for types | [v5.9.\*](https://github.com/microsoft/TypeScript/releases) | 120 | | ts-node | [TypeScript](https://www.typescriptlang.org/) execution and REPL for [node.js](https://nodejs.org/) | [v10.9.\*](https://typestrong.org/ts-node/) | 121 | | | | | 122 | | | `React` | | 123 | | react | Library for web and native user interfaces | [v19.2.\*](https://react.dev/versions) | 124 | | react-dom | React package for working with the [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) | [v19.2.\*](https://github.com/facebook/react) | 125 | | react-error-boundary | Reusable React [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) component | [v6.0.\*](https://github.com/bvaughn/react-error-boundary) | 126 | | | | | 127 | | | `CSS` | | 128 | | tailwindcss | A utility-first CSS framework for rapidly building custom user interfaces | [v4.1.\*](https://tailwindcss.com/) | 129 | | postcss | Tool for transforming styles with JS plugins | [v8.5.\*](https://postcss.org/) | 130 | | postcss-preset-env | Polyfills modern CSS based on `.browserslistrc` | [v10.4.\*](https://www.npmjs.com/package/postcss-preset-env) | 131 | | postcss-assets | Asset manager for CSS (archived) | [v6.0.0](https://www.npmjs.com/package/postcss-assets) | 132 | | clsx | Utility for constructing className strings conditionally | [v2.1.\*](https://github.com/lukeed/clsx) | 133 | | | | | 134 | | | `Git hooks` | | 135 | | husky | Automatically lint commit messages, code run tests upon committing or pushing, works with git hooks | [v9.1.\*](https://typicode.github.io/husky/) | 136 | | lint-staged | Run linters & formatters scripts on git staged files | [v16.2.\*](https://github.com/lint-staged/lint-staged) | 137 | | | | | 138 | | | `Code linting & formatting` | | 139 | | | `Tools` | | 140 | | eslint | Configurable JavaScript linter | [v9.37.\*](https://eslint.org/) | 141 | | prettier | Opinionated code formatter | [v3.6.\*](https://prettier.io/) | 142 | | stylelint | Mighty CSS linter that helps you avoid errors and enforce conventions | [v16.25.\*](https://github.com/stylelint/stylelint) | 143 | | | `Configs` | | 144 | | @alexey-koran/prettier-config | Prettier [sharing configuration](https://prettier.io/docs/en/configuration.html#sharing-configurations) | [v0.1\*](https://npmjs.com/@alexey-koran/prettier-config) | 145 | | @alexey-koran/eslint-config | ESLint [shareable config](https://eslint.org/docs/latest/extend/shareable-configs) | [v0.4\*](https://npmjs.com/@alexey-koran/eslint-config) | 146 | | stylelint-config-clean-order | Order your styles with [stylelint-order](https://github.com/hudochenkov/stylelint-order) | [v7.0.\*](https://github.com/kutsan/stylelint-config-clean-order) | 147 | | stylelint-config-standard | Standard shareable config for [Stylelint](https://stylelint.io/) | [v39.0.\*](https://github.com/stylelint/stylelint-config-standard) | 148 | | | `Plugins` | | 149 | | @eslint/js | ESLint JavaScript plugin. Separating out JavaScript-specific functionality from ESLint | [v9.37.\*](https://www.npmjs.com/package/@eslint/js) | 150 | | @tailwindcss/postcss | [PostCSS](https://postcss.org/) plugin for [Tailwind CSS](https://tailwindcss.com/) | [v4.1.\*](https://github.com/tailwindlabs/tailwindcss-postcss) | 151 | | prettier-plugin-tailwindcss | Prettier plugin for Tailwind CSS that automatically sorts classes | [v0.7.\*](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) | 152 | | stylelint-prettier | Runs [Prettier](https://github.com/prettier/prettier) as a Stylelint rule and reports differences as individual Stylelint issues | [v5.0.\*](https://github.com/prettier/stylelint-prettier) | 153 | | | | | 154 | | | `Other` | | 155 | | svgo | [Node.js](https://nodejs.org/) library and command-line application for optimizing SVG files | [v4.0.\*](https://github.com/svg/svgo) | 156 | | cross-env | Run scripts that set and use environment variables across platforms | [v10.1.0](https://github.com/kentcdodds/cross-env) | 157 | | @eslint/config-inspector | ESLint config inspector | [v1.3.\*](https://github.com/eslint/config-inspector) | 158 | | @alexey-koran/tsconfig | TSConfig [sharing configuration](https://www.typescriptlang.org/tsconfig/#extends) | [v0.1.\*](https://www.npmjs.com/package/@alexey-koran/tsconfig) | 159 | | | | | 160 | | | `@types` | | 161 | | @types/dotenv-webpack | type definitions for [dotenv-webpack](https://github.com/mrsteele/dotenv-webpack) | [v7.0.\*](https://www.npmjs.com/package/@types/dotenv-webpack) | 162 | | @types/html-webpack-plugin | type definitions for [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) | [v3.2.\*](https://www.npmjs.com/package/@types/html-webpack-plugin) | 163 | | @types/node | type definitions for [node.js](https://nodejs.org/) | [v24.8.\*](https://www.npmjs.com/package/@types/node) | 164 | | @types/react | type definitions for [react](https://react.dev/) | [v19.2.\*](https://www.npmjs.com/package/@types/react) | 165 | | @types/react-dom | type definitions for [react-dom](https://react.dev/) | [v19.2.\*](https://www.npmjs.com/package/@types/react-dom) | 166 | | @types/webpack | type definitions for [webpack](https://webpack.js.org/) | [v5.28.\*](https://www.npmjs.com/package/@types/webpack) | 167 | | @types/webpack-bundle-analyzer | type definitions for [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) | [v4.7.\*](https://www.npmjs.com/package/@types/webpack-bundle-analyzer) | 168 | 169 |
170 | --------------------------------------------------------------------------------