How to Install Node.js Using NVM on Windows (Managing Multiple Versions)
NVM for Windows lets you run multiple Node.js versions on one machine and switch between them in seconds. This guide covers the full install, every command you need, and fixes for the errors that trip people up.
TL;DR
Uninstall existing Node.js first. Install nvm-setup.exe from GitHub. Run terminal as Administrator. Use nvm install lts to add a version and nvm use to switch. Each version keeps its own npm and global packages, so reinstall CLI tools after switching.
Step-by-step.
Every Node.js developer hits the same wall eventually. One project needs Node 18. Another needs Node 24. Your machine can only run one at a time.
NVM for Windows solves this. It lets you install several Node.js versions side by side and switch between them with a single command. No uninstalling. No reinstalling. No broken projects.
This guide walks through the full setup. Every command is included so you can follow along in your terminal.
What NVM for Windows Actually Does
NVM stands for Node Version Manager. The Windows build is a separate project from the Unix version. It was written by Corey Butler and it works differently under the hood.
Here is the short version. NVM installs each Node.js version into its own folder. It then creates a symlink at C:\Program Files\nodejs that points to whichever version you selected. Your PATH never changes. Only the symlink target does.
That is why switching versions is instant. Windows is simply following a different shortcut.
Each Node.js version also carries its own npm and its own global packages. This matters more than most tutorials mention, and we cover it below.
Before You Install: Remove Existing Node.js
This step is not optional. Skip it and you will get strange PATH conflicts later.
Open Settings, then Apps, then Installed apps. Search for Node.js. Uninstall it.
Then delete these folders if they still exist:
C:\Program Files\nodejs
C:\Users\YourName\AppData\Roaming\npm
C:\Users\YourName\AppData\Roaming\npm-cache
Restart your machine. A stale PATH entry is the single most common cause of NVM failing quietly.
Step 1: Download and Install NVM for Windows
Go to the official releases page on GitHub. Download nvm-setup.exe from the latest release. Avoid third-party mirrors.
Run the installer. It asks for two paths:
Symlink location: C:\Program Files\nodejs
NVM install root: C:\Users\YourName\AppData\Roaming\nvm
Accept both defaults unless you have a reason not to. Paths with spaces or non-English characters cause problems.
Finish the install. Then close every open terminal window. The installer edits environment variables, and open terminals will not pick up the change.
Step 2: Verify the Installation
Open a new terminal as Administrator. This part matters — NVM needs admin rights to create symlinks.
Run:
nvm version
You should see a version number. If you see "nvm is not recognized," your PATH did not update. Restart the machine and try again.
Step 3: Install a Node.js Version
First, see what is available:
nvm list available
This prints a table of current, LTS, and older releases.
To install the latest long-term support release:
nvm install lts
To install a specific version:
nvm install 22.14.0
To install the newest release:
nvm install latest
Install as many as your projects need. Each one downloads into its own folder.
Step 4: Switch Between Versions
List what you have installed:
nvm list
An asterisk marks the version currently in use.
Switch with:
nvm use 22.14.0
Confirm it worked:
node -v
That is the whole workflow. Two commands and you are on a different runtime.
You can also turn NVM's version management off temporarily:
nvm off
And back on:
nvm on
Step 5: npm and Global Packages Per Version
This is where developers get caught out.
Each Node.js version installs with its own bundled npm. It also keeps its own global packages folder.
So if you install a CLI tool globally on Node 22:
npm install -g pnpm
Then switch to Node 24, that tool is gone. You have to reinstall it on the new version.
Plan for this. Keep global installs to a minimum and prefer project-local dependencies. Your package.json should be the source of truth, not your machine.
Common NVM Windows Errors and How to Fix Them
"exit status 1: Access is denied." You are not running as Administrator. Close the terminal and reopen it with elevated rights.
"node is not recognized" after nvm use. The symlink folder is missing from PATH. Add C:\Program Files\nodejs to your system PATH manually, then restart.
Install hangs or fails to download. Corporate proxies block the download. Set the proxy with nvm proxy followed by your proxy URL. Antivirus software can also block the symlink creation.
Version switches but node -v shows the old number. You are in a terminal that was open before the switch. Open a fresh one.
Wrong architecture installed. Run nvm arch to check whether you are on 32-bit or 64-bit. You can force it with nvm install 22.14.0 64.
How NVM for Windows Differs from Unix NVM
If you have used NVM on macOS or Linux, expect some gaps.
NVM for Windows does not read .nvmrc files natively. There is no aliasing system. There is no automatic version switching when you cd into a project folder.
You can work around the .nvmrc gap in PowerShell:
nvm use (Get-Content .nvmrc)
It is not automatic, but it respects the file your team already uses.
Which Node.js Version Should You Install in 2026?
As of August 2026, Node 24 is the active LTS line and the right default for new projects. Node 22 is in maintenance LTS and supported into April 2027, which makes it fine for existing production apps you have not migrated yet. Node 26 is the current release and becomes LTS in October 2026.
Node 20 and everything before it has reached end of life. Do not ship on it.
One practical setup: install the active LTS as your daily driver, then add whatever older version your legacy projects still require. Two or three versions is usually enough.
Where This Fits in a Real Project
Version management is one small piece of a working development environment. Getting the rest right matters just as much.
Our team works across Node.js, React, Next.js, and TypeScript on production client software. You can see the full stack we build on across our technologies page, and browse shipped work in our projects portfolio.
If you are setting up a backend environment from scratch, the SSL certificate setup tutorial covers securing it once it is deployed. For data safety on AWS, the S3 backup guide walks through the same ground.
More step-by-step guides are on the tutorials hub, and longer technical writing lives on the blog.
Frequently asked.
Do I need to uninstall Node.js before installing NVM on Windows?+
Yes. An existing Node.js install leaves entries in your system PATH that conflict with the symlink NVM creates. Uninstall Node.js, delete the leftover nodejs and npm folders, then restart before running the NVM installer.
Why does nvm use fail with "Access is denied"?+
NVM needs administrator rights to create the symlink at C:\Program Files\nodejs. Close your terminal and reopen it as Administrator, then run the command again.
Does NVM for Windows support .nvmrc files?+
Not natively. The Windows build is a separate project from Unix NVM and does not read .nvmrc automatically. In PowerShell you can run nvm use (Get-Content .nvmrc) to read the file manually.
Do my global npm packages carry over when I switch Node versions?+
No. Each Node.js version installed through NVM keeps its own npm and its own global packages folder. Any globally installed CLI tool has to be reinstalled after switching versions.
Which Node.js version should I install in 2026?+
Node 24 is the active LTS line and the safest default for new projects. Node 22 is in maintenance LTS and supported until April 2027. Node 20 and earlier have reached end of life.
Can I run two Node.js versions at the same time on Windows?+
Not in the same terminal session. NVM switches which version is active rather than running them in parallel. For true parallel runtimes, use separate machines, containers, or WSL.
Have a project in mind?
Our team has shipped production software for client apps — from initial integration to scaling, caching and cost optimisation. We’d love to help.
Continue with Tutorials.
View all tutorials
TwilioHow to Send Twilio SMS Using Your Brand Name (Sender ID Setup)
Getting an SMS from "CRAXINNO" instead of a random number looks more legitimate and gets opened more often. Twilio calls this an Alphanumeric Sender ID, and in supported countries it takes about ten minutes to set up. The catch is the phrase "in supported countries." Where you are sending decides almost everything about how this works, and one very large market does not support it at all. Read This First: Where Alphanumeric Sender IDs Do Not Work Alphanumeric Sender IDs are not available for the United States or Canada. Not with an application, not with a business account, not with a workaround. The carriers do not accept them. For US traffic, you register a phone number through A2P 10DLC, or use a toll-free number or short code. Your brand identity comes from carrier-level brand registration rather than from the sender string. This catches out a lot of teams who build the integration first and discover the restriction when messages start failing. If your primary market is North America, stop here and read Twilio's A2P 10DLC documentation instead. Where it does work: most of Europe, the UK, Australia, India, much of Asia, Africa, and the Middle East. Country support and requirements change regularly, so check Twilio's country guidelines for your specific destinations before you build. Three Levels of Country Requirement Supported countries fall into three groups, and knowing which one you are sending to determines your timeline. No registration needed. Set the sender string and send. The UK, Australia, and most of Western Europe work this way. This is what the video demonstrates. Pre-registration required. You submit the sender ID to Twilio, who registers it with local carriers. Approval takes days to weeks. India, Vietnam, the Philippines, Saudi Arabia, the UAE, and Qatar all sit here. Sending an unregistered ID to these countries means silent failure or substitution with a random number. Not supported. The US and Canada, as covered above. India deserves a specific mention because it is the strictest. You need DLT registration with an Indian telecom operator, covering your entity, your sender ID header, and every message template you intend to send. Unregistered templates are blocked. Budget two to three weeks. The Limitation Nobody Mentions Until It Bites Alphanumeric Sender IDs are one-way only. Recipients cannot reply. There is no inbound path. If someone tries, the message goes nowhere and they get no error. This makes them right for one-time passcodes, delivery notifications, appointment reminders, and transactional alerts. It makes them wrong for anything conversational — support threads, two-way confirmations, or any flow where a customer might reasonably respond. If you need replies, use a phone number. Some teams run both: a sender ID for outbound notifications and a number for conversations. Sender ID Format Rules Between 1 and 11 characters. Letters A-Z and a-z, digits 0-9, and spaces. At least one letter is required — an all-numeric string is not valid. No leading or trailing spaces. Two practical notes. Casing is not guaranteed to survive; some carriers normalise everything to uppercase. And avoid characters that look alike across fonts, since a sender ID exists to be recognised at a glance. Pick something short and obviously yours. "CRAXINNO" reads better than "CraxinnoTech" truncated to eleven characters. Step 1: Get Your Credentials Sign in to the Twilio Console. Your Account SID and Auth Token are on the dashboard. The Auth Token is a password. Do not commit it, do not paste it into a client-side file, and do not put it in a support ticket. Store both in environment variables. For anything beyond a test, use an API Key and Secret instead of the Auth Token directly. API keys can be revoked individually without rotating your account credentials, which matters when someone leaves or a laptop goes missing. Step 2: Install the SDK npm install twilio Then create a .env file: 1 2 3 TWILIO_ACCOUNT_SID = your_account_sid TWILIO_AUTH_TOKEN = your_auth_token TWILIO_SENDER_ID = CRAXINNO Add .env to .gitignore before you write anything into it. Step 3: Send the Message 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 require ( 'dotenv' ) . config ( ) ; const twilio = require ( 'twilio' ) ; const client = twilio ( process . env . TWILIO_ACCOUNT_SID , process . env . TWILIO_AUTH_TOKEN ) ; async function sendSMS ( to , body ) { try { const message = await client . messages . create ( { body , from : process . env . TWILIO_SENDER_ID , to } ) ; console . log ( 'Sent:' , message . sid ) ; return message ; } catch ( error ) { console . error ( 'Failed:' , error . code , error . message ) ; throw error ; } } sendSMS ( '+447700900000' , 'Your verification code is 482913' ) ; The only difference from sending via a phone number is the from value. Instead of a number in E.164 format, you pass your sender string. The to number must be in E.164 format — a plus sign, country code, then the number, with no spaces or dashes. Step 4: Verify Delivery A successful API call means Twilio accepted the message, not that it arrived. Check the actual status: 1 2 const sent = await client . messages ( message . sid ) . fetch ( ) ; console . log ( sent . status , sent . errorCode ) ; Status moves through queued , sent , and ideally delivered . A status of undelivered or failed comes with an error code that tells you why. For anything in production, configure a status callback webhook rather than polling. Twilio posts delivery updates to your endpoint as they happen. Using a Messaging Service Instead For production traffic, create a Messaging Service in the Twilio Console rather than hardcoding the sender. Add both your alphanumeric sender ID and a phone number to the sender pool. Twilio then picks the right sender for each destination automatically — the sender ID where it is supported, the number where it is not. In code you pass messagingServiceSid instead of from . That one change means a message to a US number does not simply fail; it falls back to your registered number. This is the difference between a demo and something you can run a business on. Common Errors 21612 — cannot route to this number. Usually an unsupported destination country for alphanumeric senders. This is what a US number returns. 21606 — the From number is not a valid, SMS-capable inbound number. Your sender string breaks a format rule, or the destination country requires pre-registration you have not completed. Message shows as delivered but the sender is a random number. The carrier substituted it. Common where registration is required and has not been done. 30007 — message filtered. The carrier blocked it, typically for content resembling spam or, in India, an unregistered template. Works in testing, fails in one country. Almost always a country-specific registration requirement. Check Twilio's country guidelines for that destination. 21608 — unverified number on a trial account. Trial accounts can only send to numbers you have verified in the console. Upgrade or verify the recipient. Before You Go Live Test with a real handset in each destination country. Emulators and virtual numbers do not reflect carrier behaviour. Keep a fallback sender configured. A Messaging Service handles this; hardcoded from values do not. Log the message SID for every send. When a customer says they never received a code, the SID is the only way to find out what actually happened. Respect local rules on timing and consent. Several jurisdictions restrict marketing SMS to certain hours and require documented opt-in. The penalties are real. Monitor your delivery rate per country. A drop in one market usually means a carrier policy change rather than a bug in your code. Where This Fits in a Real Project SMS is rarely the whole feature. It sits inside authentication, order flows, or a notification system, alongside retry logic, rate limiting, and a record of what was sent to whom. Our team builds and ships production integrations like this for client software — messaging, payments, and third-party APIs, with the operational layer around them. You can see the stack we work across on our technologies page and browse shipped work in our projects portfolio. If you are setting up the environment around this, the NVM on Windows tutorial covers Node version management, and the SSL certificate guide handles securing the server your webhook endpoint runs on. More walkthroughs are on the tutorials hub, and longer technical writing lives on the blog .
HTMLHow to Deploy HTML and CSS Projects on Netlify (Manual Upload)
You built something with HTML and CSS. Now you want a link you can send to someone. Netlify's drag-and-drop deploy gets you a live URL in under a minute. No Git, no terminal, no build tools. Drag a folder onto a page and the site is online. This guide covers the upload, plus the three things that go wrong immediately afterward: broken image paths, subpages returning 404, and a custom domain that will not connect. What You Need A folder containing your project files. HTML, CSS, images, whatever else the site uses. A file named index.html at the top level of that folder. Not home.html . Not Index.html . Netlify looks for exactly index.html , lowercase, and serves it as your homepage. Getting this wrong is the most common reason a fresh deploy shows a blank page or a directory listing. A Netlify account. The free tier is generous and no card is required. This works for vanilla CSS, Bootstrap, and Tailwind — as long as Tailwind is loaded via CDN or you have already compiled your CSS to a plain file. If you are running a Tailwind build step, compile first and upload the output. Step 1: Check Your Folder Structure Before uploading, open the folder and confirm the layout looks like this: 1 2 3 4 5 6 7 8 my - project / ├── index . html ├── css / │ └── style . css ├── js / │ └── script . js └── images / └── logo . png The critical detail is that index.html sits at the root of the folder you drag, not inside a subfolder. If your files are nested one level deeper, drag the inner folder instead. Step 2: Deploy Sign in at app.netlify.com. On your team dashboard, find the drag-and-drop area — it usually reads "Drag and drop your site output folder here" or sits under Add new site, then Deploy manually. Drag your project folder onto it. Upload takes a few seconds. Netlify assigns a random subdomain such as spontaneous-halva-4f2a91.netlify.app . Your site is live at that URL. That is the whole deploy. Step 3: Rename the Site The random name is fine for a quick share and terrible for a portfolio. Go to Site configuration, then Site details, then Change site name. Pick something readable — yourname-portfolio.netlify.app . Do this before you share the link anywhere, because the old URL stops working once you change it. Fixing Broken Images and Missing CSS Your site loads but the styling is gone and images are missing. This happens to almost everyone on their first deploy, and there are two causes. Case sensitivity. Windows and macOS treat Logo.png and logo.png as the same file. Netlify's servers do not. If your HTML references images/Logo.png and the actual file is logo.png , it worked locally and it will 404 in production. Fix: make every filename lowercase, and make every reference in your HTML match exactly. Absolute local paths. If your HTML contains something like C:/Users/You/Desktop/project/css/style.css , or a leading slash pointing somewhere that does not exist on the server, the browser cannot find the file. Fix: use relative paths. css/style.css and images/logo.png , referenced from where index.html sits. Open your browser's developer console on the live site. Every failed file shows up there as a 404 with the exact path it tried, which usually tells you the answer immediately. Fixing 404s on Subpages Your homepage works, but yoursite.netlify.app/about returns a 404. For a static HTML site, Netlify serves files by path. /about only works if a file named about.html exists — Netlify will match the clean URL to it. If you have pages/about.html , then the URL is /pages/about . If your site is a single-page app using client-side routing, you need a _redirects file at the root of the folder you upload, containing: 1 /* /index.html 200 That tells Netlify to serve index.html for every path and let your JavaScript handle routing. For a plain HTML and CSS site, you do not need this. Adding a Custom Domain Go to Domain management, then Add a domain, and enter your domain. You have two paths. Netlify DNS. Netlify gives you four nameservers to enter at your domain registrar. This is the simpler option and it handles the SSL certificate automatically. External DNS. Keep your current DNS provider and add records manually. Point the apex domain at Netlify's load balancer IP, and add a CNAME for www pointing to your Netlify subdomain. Netlify shows you the exact values. Either way, DNS propagation takes anywhere from a few minutes to 48 hours. Netlify provisions a free Let's Encrypt certificate automatically once the domain resolves, so leave it a while before assuming something is broken. If HTTPS does not appear after a day, check Domain management for a certificate error. It is nearly always a DNS record that has not propagated or a conflicting record left over from a previous host. Updating a Manually Deployed Site Here is the tradeoff nobody mentions in the drag-and-drop tutorials. Every change means dragging the entire folder again. There is no version history you can meaningfully work with, no rollback to a specific commit, and no record of what changed between deploys. For a one-off share or a class assignment, that is fine. For anything you will update more than a handful of times, connect a Git repository instead. Push to your branch and Netlify rebuilds automatically. You get deploy previews on pull requests, a full history, and one-click rollback to any previous deploy. The manual upload is the right way to start. It is the wrong way to maintain something. When to Move Beyond Manual Deploys Move to a Git-connected deploy when any of these become true. You are updating the site regularly. Dragging a folder gets old fast. You need a build step. Tailwind compilation, Sass, a bundler, any framework — Netlify runs the build for you on a Git deploy. More than one person touches the site. Manual uploads have no merge story at all. You need environment variables or serverless functions. Connecting a repo takes about two minutes: Add new site, then Import an existing project, then authorise GitHub and pick the repository. Netlify's Free Tier Limits Worth knowing before you build something that outgrows it. The free tier covers a substantial amount of bandwidth and build minutes per month, and supports custom domains with free SSL. Concurrent builds are limited to one, and some team features are paid. The specific numbers change. Check Netlify's current pricing page rather than trusting any figure in a tutorial, including this one. Where This Fits in a Real Project Static hosting handles the frontend. The moment you need authentication, a database, payments, or an API, the architecture question changes — and that decision is easier to make early than to retrofit. Our team builds and ships production frontends in React and Next.js, along with the backend infrastructure that supports them. You can see the stack we work across on our technologies page and browse shipped work in our projects portfolio . If you are setting up a local environment, the NVM on Windows tutorial covers Node version management. For self-hosted deployments, the SSL certificate guide handles TLS on Nginx. More walkthroughs are on the tutorials hub, and longer technical writing lives on the blog .
ReactHow to Create and Run a React Project with TypeScript
Setting up a React project with TypeScript takes about two minutes with the right tool. The hard part is knowing which tool to use, because the answer changed. Create React App was the default for years. It was deprecated in February 2025 and is no longer recommended for new projects. If a tutorial tells you to run npx create-react-app , it is out of date. This guide uses Vite, which is what the React team now points people toward for single-page apps. What You Need First Node.js version 20 or higher. Check with: node -v If that command is not recognised or the number is below 20, install Node first. On Windows, the NVM tutorial covers installing it in a way that lets you switch versions per project. You also need npm, which ships with Node. Confirm with npm -v . A code editor. VS Code has the strongest TypeScript support out of the box. Why Vite Instead of Create React App Three reasons, briefly. Speed. Vite starts a dev server in under a second because it serves native ES modules rather than bundling everything upfront. CRA's Webpack setup takes tens of seconds on a large project. Maintenance. CRA has not received meaningful updates in years and its dependency tree carries known vulnerabilities that cannot be resolved without ejecting. Direction. The React documentation now recommends either a framework such as Next.js, or Vite for a plain single-page app. If you are building something with routing, data fetching, and SEO requirements, consider Next.js instead. Vite is the right answer for a client-side app, a dashboard behind a login, or anything you are learning on. Step 1: Create the Project Run this in the folder where you keep your projects: npm create vite@latest my-app -- --template react-ts The react-ts template is the important part. It scaffolds React with TypeScript already configured — no separate setup step. If you prefer the interactive prompts, run npm create vite@latest on its own and select React, then TypeScript, when asked. Step 2: Install Dependencies cd my-app npm install This pulls down React, TypeScript, Vite, and the type definitions. It takes a few seconds. Step 3: Run It npm run dev Vite prints a local URL, usually http://localhost:5173 . Open it and you have a working React app with hot module replacement — save a file and the browser updates without a full reload, preserving component state. Note the command. Vite uses npm run dev , not npm start . That difference catches out everyone coming from CRA. Understanding the Project Structure 1 2 3 4 5 6 7 8 9 10 11 my - app / ├── public / ├── src / │ ├── App . tsx │ ├── main . tsx │ ├── index . css │ └── vite - env . d . ts ├── index . html ├── package . json ├── tsconfig . json └── vite . config . ts A few things differ from what you may expect. index.html sits at the project root, not inside public/ . Vite treats it as the entry point and processes it directly. main.tsx is where React mounts to the DOM. App.tsx is your root component. .tsx is the extension for files containing JSX. Plain TypeScript files without JSX use .ts . vite-env.d.ts gives TypeScript the type definitions for Vite's environment variables. Leave it alone. Writing Your First Typed Component Delete the contents of App.tsx and replace with: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type GreetingProps = { name : string ; count ? : number ; } ; function Greeting ( { name , count = 0 } : GreetingProps ) { return ( < div > < h1 > Hello , { name } < / h1 > < p > Clicked { count } times < / p > < / div > ) ; } export default function App ( ) { return < Greeting name = "Nimish" / > ; } Two things worth understanding here. The type block defines the shape of the props. TypeScript now checks every use of Greeting against it. Pass a number where a string is expected and your editor flags it before you run anything. The ? on count marks it optional. Without the ? , TypeScript requires it on every usage. Try removing name="Nimish" and watch the error appear in your editor. That immediate feedback is the entire value proposition of TypeScript. Typing State and Events Two patterns you will use constantly. State usually infers its own type: 1 const [ count , setCount ] = useState ( 0 ) ; TypeScript works out that count is a number from the initial value. You only need an explicit type when the initial value does not tell the full story: 1 const [ user , setUser ] = useState < User | null > ( null ) ; Event handlers need their event typed: 1 2 3 function handleChange ( e : React . ChangeEvent < HTMLInputElement > ) { setName ( e . target . value ) ; } The element type inside the angle brackets matters. HTMLInputElement for inputs, HTMLTextAreaElement for textareas, HTMLSelectElement for selects. Getting it wrong means e.target.value will not be typed correctly. Building for Production npm run build This type-checks the whole project, then compiles and bundles into a dist folder. The build fails on type errors. That is intentional and it is the point — a type error caught at build time is a bug that never reaches a user. Preview the production build locally before deploying: npm run preview The dist folder is what you deploy. It is static output, so it works on Netlify, Vercel, S3, or any static host. The Netlify deployment guide covers that process, though for a Vite app you would normally connect Git rather than dragging the folder. Common Errors and Fixes Cannot find module './App' or its corresponding type declarations — usually a case mismatch in the filename, or a missing .tsx extension on the file itself. JSX element implicitly has type 'any' — the React type definitions are missing. Run npm install -D @types/react @types/react-dom . Property does not exist on type — you are accessing a field that is not in your type definition. Add it to the type rather than reaching for any . Port 5173 already in use — another Vite server is running. Either stop it, or start this one with npm run dev -- --port 3000 . Blank page after building and deploying — the base path is wrong. If you are deploying to a subdirectory, set base: '/subdirectory/' in vite.config.ts . Environment variables are undefined — Vite only exposes variables prefixed with VITE_ . Rename API_URL to VITE_API_URL and access it via import.meta.env.VITE_API_URL , not process.env . Migrating an Existing CRA Project If you have a Create React App project you want to move over, the outline is: Install Vite and the React plugin, remove react-scripts , move index.html from public/ to the root and add a script tag pointing at src/main.tsx , rename any .js files containing JSX to .jsx or .tsx , swap process.env.REACT_APP_* for import.meta.env.VITE_* , and update your package scripts to dev , build , and preview . Budget an afternoon for a mid-sized app. Most of the time goes on environment variables and any Webpack-specific configuration you had customised. Where This Fits in a Real Project A scaffolded project is the starting point. What follows is routing, state management, a testing setup, and a CI pipeline — and those decisions are cheaper to make now than to retrofit later. Our team builds production React and Next.js applications in TypeScript for client software. You can see the stack we work across on our technologies page and browse shipped work in our projects portfolio . If you are still setting up locally, the NVM on Windows tutorial handles Node version management. For deployment, the Netlify guide covers static hosting and the SSL certificate guide covers self-hosted TLS. More walkthroughs are on the tutorials hub, and longer technical writing lives on the blog .



