A step-by-step guide on how to create a React project from scratch with TypeScript and . Vite You can find the full source code here: https://github.com/alexadam/project-templates/tree/master/projects/react-app-vite Setup Prerequisites: node ( ) https://nodejs.org/en/download/ yarn ( ) https://yarnpkg.com/getting-started/install Create the project's folder: mkdir react-app cd react-app Generate a default file with yarn: package.json yarn init -y Install React, TypeScript, and Vite: yarn add react react-dom yarn add --dev @types/react \ @types/react-dom \ sass \ typescript \ @vitejs/plugin-react \ vite Add build, dev, & clean scripts in the file: package.json .... }, "scripts": { "clean": "rm -rf dist/*", "build": "vite --config vite.config.js build", "dev": "vite --config vite.config.js serve", "preview": "vite --config vite.config.js preview" } Configure TypeScript by creating the file with: tsconfig.json { "compilerOptions": { "incremental": true, "target": "es6", "module": "commonjs", "lib": ["dom", "dom.iterable", "es6"], "allowJs": true, "jsx": "react", "sourceMap": true, "outDir": "./dist/", "rootDir": ".", "removeComments": true, "strict": true, "moduleResolution": "node", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "experimentalDecorators": true }, "include": [ "./src" ], "exclude": [ "./node_modules", "./build", "./dist" ] } To configure Vite, make a file containing: vite.config.js import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react( { include: '**/*.{ts,js,tsx}', } )], base: '', root: 'src', build: { outDir: '../dist', }, server: { port: 8080 }, preview: { port: 8080 } }) Example App Create a folder named (in the project's folder): src mkdir src cd src Make a simple React component in the file : numbers.tsx import React, {useState} from 'react'; interface INumberProps { initValue: number } const Numbers = (props: INumberProps) => { const [value, setValue] = useState(props.initValue) const onIncrement = () => { setValue(value + 1) } const onDecrement = () => { setValue(value - 1) } return ( <div> Number is {value} <div> <button onClick={onIncrement}>+</button> <button onClick={onDecrement}>-</button> </div> </div> ) } export default Numbers Create the main React component (the entry point) in the file : app.tsx import * as React from 'react'; import ReactDOM from "react-dom/client"; import Numbers from './numbers'; import './app.scss' const App = () => { return ( <Numbers initValue={42} /> ) } const root = ReactDOM.createRoot(document.getElementById("app") as HTMLElement); root.render(<App />); Next, add the : index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>React TypeScript</title> </head> <body> <div id="app"></div> <script type="module" src="./app.tsx"></script> </body> </html> Add some style in app.scss html, body { width: 100%; height: 100%; margin: 0; padding: 0; } * { box-sizing: border-box; } #app { width: 100%; height: 100%; margin: 0; padding: 0; } Then, run and open in a browser. yarn dev http://localhost:8080/ Use This Project as a Template You can save the steps as a shell script: Setup #!/bin/sh rm -rf node_modules rm -rf dist rm -rf build rm package.json rm yarn.lock yarn init --yes yarn add react react-dom yarn add --dev @types/react \ @types/react-dom \ sass \ typescript \ @vitejs/plugin-react \ vite # Remove the last line sed -i.bak '$ d' package.json && rm package.json.bak # append the scripts commads cat <<EOT >> package.json ,"scripts": { "clean": "rm -rf dist/*", "build": "vite --config vite.config.js build", "dev": "vite --config vite.config.js serve", "preview": "vite --config vite.config.js preview" } } Delete the folder, and, when you want to start a new project, you can copy the contents of to the new location: node-modules react-app mkdir new-project cd new-project # copy the react-app folder content to the new project rsync -rtv /path/to/../react-app/ . ./init.sh