{"id":29018,"date":"2026-08-20T18:26:27","date_gmt":"2026-08-20T18:26:27","guid":{"rendered":"https:\/\/www.tftus.com\/blog\/?p=29018"},"modified":"2026-08-20T18:26:30","modified_gmt":"2026-08-20T18:26:30","slug":"how-to-deploy-reactjs-app","status":"publish","type":"post","link":"https:\/\/www.tftus.com\/blog\/how-to-deploy-reactjs-app","title":{"rendered":"How to Deploy ReactJS App: Step-by-Step Guide for Beginners (2026)"},"content":{"rendered":"\n<p>To deploy a ReactJS app, run <code>npm run build<\/code> to generate a production bundle, push the project to a git repository, then connect that repo to a static site host such as Vercel, Netlify, GitHub Pages, or AWS Amplify. The host runs your build command, publishes the output folder, and redeploys automatically on every git push. Most first deployments finish in under ten minutes.<\/p>\n\n\n\n<p>Creating a React app is fun, but at some point you must deploy it \u2014 where most beginners stall. The stall is rarely the platform. It is that the tool most tutorials still open with, Create React App, was deprecated in February 2025, and its output folder (<code>build<\/code>) differs from Vite&#8217;s (<code>dist<\/code>) \u2014 mismatch that folder and you ship a blank white page. This guide covers the hosting services for deploying React apps, the steps for each, the routing and environment variables traps, and a validation checklist to run before you share the URL.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Is React App Deployment?<\/h2>\n\n\n\n<p>React app deployment is the process of publishing your app online. A React application compiles to static files \u2014 HTML, CSS, and JavaScript \u2014 served from a web host or a content delivery network. Unlike server side applications, a standard React app needs no runtime on the server, only a place to serve static assets.<\/p>\n\n\n\n<p>The build command (<code>npm run build<\/code>) creates a production bundle in a build folder. With Create React App that folder is <code>build<\/code>; with Vite it is <code>dist<\/code>. Getting this wrong is the most common cause of a blank page after a first deployment: the host publishes an empty directory.<\/p>\n\n\n\n<p>Knowing how the deployment process works helps you select a cloud platform. Some offer static site hosting only; others add server side rendering and serverless functions. According to a <a href=\"https:\/\/blog.logrocket.com\/9-ways-deploy-react-app-free\/\" rel=\"nofollow noopener\" target=\"_blank\">2024 LogRocket analysis of React deployment options<\/a>, developers increasingly rely on Vercel, Netlify, Firebase, and GitHub Pages because they automate updates through Git-based integrations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Deployment Matters<\/h2>\n\n\n\n<p>Deploying makes your work usable, and React&#8217;s US reach makes that a commercial question. As Jyothish R, CTO at <a href=\"https:\/\/www.forbes.com\/councils\/forbestechcouncil\/2025\/02\/06\/how-to-hire-top-react-developers-in-2025-a-recruiting-guide\/\" rel=\"nofollow noopener\" target=\"_blank\">AIMLEAP<\/a>, noted in Forbes: over 2.9 million U.S. websites use React, including Meta, Netflix, and The New York Times.<\/p>\n\n\n\n<p>How you deploy affects performance directly. In <a href=\"https:\/\/medium.com\/walmartglobaltech\/introducing-electrode-an-open-source-release-from-walmartlabs-14b836135319\" rel=\"nofollow noopener\" target=\"_blank\">Walmart&#8217;s Electrode migration<\/a>, moving Walmart.com to React with server side rendering made the home page 20% faster and cut JavaScript bundle size by 20%. Rendering strategy is a deployment decision, not an afterthought.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create React App Is Deprecated: What That Means for Deployment<\/h2>\n\n\n\n<p>On February 14, 2025, the React team <a href=\"https:\/\/react.dev\/blog\/2025\/02\/14\/sunsetting-create-react-app\" rel=\"nofollow noopener\" target=\"_blank\">officially deprecated Create React App<\/a> for new apps and recommended migrating to a framework or to a build tool such as Vite, Parcel, or Rsbuild. Create React App still works in maintenance mode but receives no new features \u2014 tutorials teaching <code>npx create-react-app<\/code> are teaching a deprecated default.<\/p>\n\n\n\n<p>This changes three things when you deploy your React app:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><\/th><th>Create React App<\/th><th>Vite<\/th><\/tr><\/thead><tbody><tr><td>Scaffold command<\/td><td><code>npx create-react-app my-app<\/code><\/td><td><code>npm create vite@latest my-app<\/code><\/td><\/tr><tr><td>Build command<\/td><td><code>npm run build<\/code> (react scripts)<\/td><td><code>npm run build<\/code><\/td><\/tr><tr><td>Build folder<\/td><td><code>build<\/code><\/td><td><code>dist<\/code><\/td><\/tr><tr><td>Environment variables prefix<\/td><td><code>REACT_APP_<\/code><\/td><td><code>VITE_<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Following an older tutorial on a new react project? Check which column you are in before configuring any build settings. Everything else here applies to both.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3 Prerequisites Before You Deploy<\/h2>\n\n\n\n<p>Three things must be in place before your first deployment: a supported Node runtime, an app whose production build runs clean locally, and a github repository the host can watch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set Up Your Tools<\/h3>\n\n\n\n<p>Install a supported Node.js LTS release on your local machine \u2014 <strong>Node 22 or Node 24 as of 2026<\/strong>. Node 18 and Node 20 are both <a href=\"https:\/\/nodejs.org\/en\/blog\/announcements\/node-18-eol-support\" rel=\"nofollow noopener\" target=\"_blank\">end-of-life<\/a> and receive no security patches, and <a href=\"https:\/\/vite.dev\/blog\/announcing-vite7\" rel=\"nofollow noopener\" target=\"_blank\">Vite 7 refuses to build<\/a> on anything below Node 20.19 or 22.12. Use <code>nvm<\/code> if you juggle versions. Then install Git and create a GitHub account, and verify all three:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node -v    # v22.x.x or v24.x.x\nnpm -v\ngit --version\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Prepare Your React Project<\/h3>\n\n\n\n<p>Run the app locally and fix bugs before building. Then build and serve the bundle locally with the following command: <code>npx serve -s build<\/code> (or <code>dist<\/code>). Production builds fail differently from dev mode, and this catches the two classic beginner failures: an import whose casing works on macOS but breaks on the host&#8217;s Linux filesystem, and <code>process.env.REACT_APP_API_KEY<\/code> returning <code>undefined<\/code> in a Vite project because Vite reads <code>import.meta.env.VITE_*<\/code> instead.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Repository Setup<\/h3>\n\n\n\n<p>Before the first commit, confirm <code>.gitignore<\/code> excludes <code>node_modules<\/code> and your build output (<code>build\/<\/code> or <code>dist\/<\/code>) \u2014 committing them bloats version control and slows every build. Then initialise Git in your project directory to put the app under version control, then create a new github repository and push to it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git init\ngit add .\ngit commit -m \"Initial commit\"\ngit remote add origin &lt;YOUR_GITHUB_REPO_URL&gt;\ngit branch -M main\ngit push -u origin main\n<\/code><\/pre>\n\n\n\n<p>If Git answers <code>remote origin already exists<\/code>, you have run this before \u2014 use <code>git remote set-url origin &lt;URL&gt;<\/code> instead.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Managing Environment Variables<\/h2>\n\n\n\n<p>Set these before your first deployment, not after. Environment variables keep sensitive data such as API keys out of your code. In Create React App they must be prefixed <code>REACT_APP_<\/code>; in Vite, <code>VITE_<\/code>. Add them to a <code>.env<\/code> file in the root of your project directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>REACT_APP_API_KEY=your_key_here\n<\/code><\/pre>\n\n\n\n<p>Set them in the host&#8217;s dashboard, not just locally: on Vercel, <strong>Project \u2192 Settings \u2192 Environment Variables<\/strong>; on Netlify, <strong>Project configuration \u2192 Environment variables<\/strong>; in the AWS Amplify console, <strong>App settings \u2192 Environment variables<\/strong>. Firebase Hosting is the exception \u2014 it serves static files with no build-time variable UI of its own, so values usually ride in your CI step or in Cloud Functions config instead. Never commit a <code>.env<\/code> file to your github repo.<\/p>\n\n\n\n<p>One detail catches almost everyone: React bakes environment variables into the bundle at build time, not runtime. A team that shipped with <code>REACT_APP_API_URL=localhost:8000<\/code> still in <code>.env<\/code> watched production call localhost and fail silently for hours \u2014 the fix was a separate production env file and a rebuild. Set variables before the build, then test your API calls.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Which Deployment Platform Should You Choose?<\/h2>\n\n\n\n<p>Most guides on deploying React apps push one platform. The answer depends on traffic, budget, and whether the project earns money \u2014 free hosting carries a licence, not just a bandwidth cap.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Platform<\/th><th>Best for<\/th><th>Build folder<\/th><th>Free tier (2026)<\/th><th>Client side routing<\/th><\/tr><\/thead><tbody><tr><td>Vercel<\/td><td>Fastest path for most React apps<\/td><td><code>dist<\/code> \/ <code>build<\/code><\/td><td>100 GB transfer, <strong>non-commercial only<\/strong><\/td><td>Automatic<\/td><\/tr><tr><td>Netlify<\/td><td>Commercial projects on a free tier<\/td><td><code>dist<\/code> \/ <code>build<\/code><\/td><td>300 credits\/month, commercial allowed<\/td><td><code>_redirects<\/code> file<\/td><\/tr><tr><td>GitHub Pages<\/td><td>Portfolios, docs, free static site hosting<\/td><td><code>build<\/code><\/td><td>Free; private repos need GitHub Pro<\/td><td>Manual 404.html workaround<\/td><\/tr><tr><td>AWS Amplify<\/td><td>Teams already inside AWS<\/td><td>Auto-detected<\/td><td>1,000 build min, 5 GB stored, 15 GB served<\/td><td>Configurable rewrite<\/td><\/tr><tr><td>Firebase<\/td><td>Apps using Firebase backend services<\/td><td><code>build<\/code><\/td><td>10 GB Hosting storage (Spark)<\/td><td>Set during <code>firebase init<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Vercel&#8217;s Hobby plan includes 100 GB of monthly data transfer and is licensed for personal, non-commercial use only \u2014 once a project takes payments, runs ads, or is built for a paying client, <a href=\"https:\/\/vercel.com\/docs\/limits\/fair-use-guidelines\" rel=\"nofollow noopener\" target=\"_blank\">Vercel&#8217;s fair use guidelines require the Pro plan<\/a> at $20 per seat per month. Netlify permits commercial use on its free plan, but accounts opened since September 2025 get 300 credits per month rather than the legacy 100 GB \u2014 deploys cost 15 credits each and bandwidth 20 credits per GB, so a media-heavy site burns the allowance fast.<\/p>\n\n\n\n<p><strong>Quick decision guide:<\/strong> personal project, no revenue, low traffic \u2014 Vercel&#8217;s Hobby tier is the fastest path. Client work, a startup, or anything with payments or ads \u2014 Netlify&#8217;s commercially-permitted free tier, or Vercel Pro if you want to stay on Vercel. Portfolio, docs, or a site that rarely changes \u2014 GitHub Pages costs nothing and needs no compliance review. A team already running infrastructure on AWS, or expecting to scale past a few thousand monthly users \u2014 AWS Amplify. Already using Firestore, Authentication, or Cloud Functions \u2014 Firebase Hosting keeps everything in one console.<\/p>\n\n\n\n<p><strong>A compliance note for US readers:<\/strong> free-tier hosting is rarely certified for regulated data. If your app handles PII, payments, or health information, check the provider&#8217;s own compliance page before deploying anything that touches user data \u2014 <a href=\"https:\/\/vercel.com\/docs\/security\/compliance\" rel=\"nofollow noopener\" target=\"_blank\">Vercel<\/a>, <a href=\"https:\/\/www.netlify.com\/security\/\" rel=\"nofollow noopener\" target=\"_blank\">Netlify<\/a>, <a href=\"https:\/\/aws.amazon.com\/compliance\/programs\/\" rel=\"nofollow noopener\" target=\"_blank\">AWS<\/a>, and <a href=\"https:\/\/firebase.google.com\/support\/privacy\" rel=\"nofollow noopener\" target=\"_blank\">Firebase<\/a> each publish which SOC 2, HIPAA, and PCI-DSS certifications apply, and none of them extend automatically to a free or entry-level plan \u2014 talk to your legal team before committing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Deploy a React App on Vercel<\/h2>\n\n\n\n<p>Vercel is a cloud platform for Jamstack web apps and web services that deploy instantly with zero configuration. Of all the ways of deploying React apps, this is the fastest route to deploy a React application \u2014 three steps, typically under five minutes from import to live URL, because Vercel auto-detects both Create React App and Vite and sets the build command and output directory for you.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Import Your Project<\/h3>\n\n\n\n<p>Sign in to Vercel with GitHub, GitLab, or Bitbucket, click <strong>New Project<\/strong>, and select the react repository to deploy. <a href=\"https:\/\/vercel.com\/kb\/guide\/deploying-react-with-vercel\" rel=\"nofollow noopener\" target=\"_blank\">Vercel detects the framework<\/a> and preconfigures the recommended build settings automatically. If detection picks the wrong preset, set the framework to <strong>Other<\/strong> and enter <code>npm run build<\/code> with the correct output directory by hand. Deploying from a monorepo? Set <strong>Root Directory<\/strong> to the app&#8217;s subfolder before your first build.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Deploy and Preview<\/h3>\n\n\n\n<p>Click <strong>Deploy<\/strong> to deploy your app. Vercel installs dependencies, creates an optimized production build, and publishes to a live URL within minutes. Every code commit generates a new deployment, and every pull request gets a preview URL for review before going live.<\/p>\n\n\n\n<p>When a build fails, open the deployment in the dashboard and read the <strong>Build Logs<\/strong> tab \u2014 the top failure for beginners is <code>Module not found<\/code>, which almost always means a dependency sits in <code>devDependencies<\/code> (or was never committed) rather than a genuine code error.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Configure and Scale<\/h3>\n\n\n\n<p>From the project console, add environment variables, connect custom domains, and create multiple project aliases so staging and production point at different builds. Vercel&#8217;s edge network absorbs traffic spikes without manual server management.<\/p>\n\n\n\n<p>After migrating to Vercel, <a href=\"https:\/\/vercel.com\/customers\/runway-enables-next-generation-content-creation-with-ai-and-vercel\" rel=\"nofollow noopener\" target=\"_blank\">Runway cut build times from 5\u20138 minutes to 40 seconds<\/a>; <a href=\"https:\/\/vercel.com\/blog\/leonardo-ai-performantly-generates-4-5-million-images-daily-with-next-js-and-vercel\" rel=\"nofollow noopener\" target=\"_blank\">Leonardo.Ai went from over 10 minutes to about 2<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Deploy the React App on Netlify<\/h2>\n\n\n\n<p>Netlify offers a modern workflow for building and deploying web applications, with continuous deployment from a git repository, and the same deployment process on every push. Budget for two things upfront: the free plan&#8217;s 300 monthly credits, and the <code>_redirects<\/code> file your routes will need.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create a New Static Site<\/h3>\n\n\n\n<p>Sign in and click <strong>Add New Site<\/strong> to create a new static site, then choose <strong>Import an Existing Project<\/strong>. Connect your GitHub, GitLab, or Bitbucket account, authorise access, and pick your react project repository. Netlify then asks for two fields that decide whether the deploy works: build command (<code>npm run build<\/code>) and publish directory (<code>build<\/code> for Create React App, <code>dist<\/code> for Vite).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Confirm Build Settings<\/h3>\n\n\n\n<p>Netlify detects your framework and suggests a build command and publish directory. <a href=\"https:\/\/docs.netlify.com\/build\/frameworks\/framework-setup-guides\/react\/\" rel=\"nofollow noopener\" target=\"_blank\">For a Create React App project it suggests<\/a> <code>react-scripts build<\/code> and <code>build<\/code>. For Vite, change the publish directory to <code>dist<\/code>. Wrong directory, blank page \u2014 check this before you deploy your app. If that folder is right and the page is still blank, check for a stale <code>homepage<\/code> field in <code>package.json<\/code>: a value meant for GitHub Pages makes every asset load from the wrong path.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Manage and Update<\/h3>\n\n\n\n<p>Netlify gives you a unique URL immediately, and every git push triggers a new build. Netlify supports custom domains on every plan: open <strong>Domain settings &gt; Add a domain<\/strong>, then point an <code>ALIAS<\/code>\/<code>ANAME<\/code> record at your Netlify subdomain for the apex and a <code>CNAME<\/code> for <code>www<\/code>; SSL provisions automatically once DNS resolves, usually within the hour. Watch the credit meter as you go \u2014 every production deploy costs 15 credits whether the build takes 30 seconds or 10 minutes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Deploy the ReactJS App on GitHub Pages<\/h2>\n\n\n\n<p>GitHub Pages is a static site hosting service built into GitHub, ideal for portfolios, documentation, and small business landing pages. It is free for public repos but designed for static websites, and static websites alone, with no native support for client side routing. Publishing from a <strong>private<\/strong> repo requires a paid GitHub plan, which catches students and client work most often.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install the gh-pages Package<\/h3>\n\n\n\n<p>In your terminal, run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install gh-pages --save-dev\n<\/code><\/pre>\n\n\n\n<p>Then add a homepage key to <code>package.json<\/code> pointing at your GitHub Pages URL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"homepage\": \"https:\/\/yourusername.github.io\/repo-name\"\n<\/code><\/pre>\n\n\n\n<p>Omit this key and the deploy still succeeds, but the site loads blank: React requests <code>\/static\/js\/main.js<\/code> from the domain root instead of <code>\/repo-name\/<\/code>, and every asset 404s.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Add the predeploy and deploy Scripts<\/h3>\n\n\n\n<p>Add these to the scripts section of <code>package.json<\/code> so the build runs before publishing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"predeploy\": \"npm run build\",\n\"deploy\": \"gh-pages -d build\"\n<\/code><\/pre>\n\n\n\n<p><code>gh-pages -d build<\/code> pushes only the contents of that folder to an orphan <code>gh-pages<\/code> branch, leaving your source history untouched. Vite users: change it to <code>gh-pages -d dist<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Push to the GitHub Pages Branch<\/h3>\n\n\n\n<p>Run the following command to deploy your app: <code>npm run deploy<\/code>. This builds and pushes the static files to the <code>gh-pages<\/code> branch. In your github repository settings, open the Pages section and set the source to that branch.<\/p>\n\n\n\n<p>Expect one surprise. Developers deploy, see the homepage work, then find every route except <code>\/<\/code> returns 404 \u2014 GitHub Pages looks for a physical file at <code>\/about<\/code> and there isn&#8217;t one. The fix is a <code>404.html<\/code> fallback, invisible until after your first deployment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Deploy the React App on AWS Amplify<\/h2>\n\n\n\n<p>AWS Amplify offers a Git-based CI\/CD workflow for building, deploying, and hosting single page web apps and static sites with serverless backends, deploying updates on every git commit. Teams needing more control than git push use GitHub Actions: a GitHub Actions workflow in <code>.github\/workflows<\/code> runs tests and linting before deploying \u2014 continuous deployment with explicit stages. <a href=\"https:\/\/aws.amazon.com\/amplify\/pricing\/\" rel=\"nofollow noopener\" target=\"_blank\">Amplify&#8217;s free tier<\/a> covers 1,000 build minutes, 5 GB stored, and 15 GB served per month for the first 12 months.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create App in the Amplify Console<\/h3>\n\n\n\n<p>Sign in to AWS and open the AWS Amplify console. Choose <strong>Create new app<\/strong>, select GitHub (or GitLab, Bitbucket, CodeCommit), authenticate, and <a href=\"https:\/\/docs.aws.amazon.com\/hands-on\/latest\/build-react-app-amplify-graphql\/module-one.html\" rel=\"nofollow noopener\" target=\"_blank\">select the repository and branch<\/a> to deploy. If the repo belongs to a GitHub organisation rather than your personal account, an org owner must approve the Amplify GitHub app first \u2014 otherwise your repo simply won&#8217;t appear in the list.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Build and Deploy<\/h3>\n\n\n\n<p>Amplify detects the React framework and generates build settings for you. Review them, then choose <strong>Save and deploy<\/strong>. Amplify installs dependencies, runs the build process, and hosts the result on a global CDN at an <code>amplifyapp.com<\/code> domain, usually within five minutes.<\/p>\n\n\n\n<p>The most common build failure here is a Node version mismatch between your machine and Amplify&#8217;s image. Pin it in <code>amplify.yml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>frontend:\n  phases:\n    preBuild:\n      commands:\n        - nvm use 22\n        - npm ci\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Manage and Scale<\/h3>\n\n\n\n<p>The amplify console monitors your branch and triggers a fresh build on every git commit. From there you manage custom domains, SSL, environment variables, and build logs. Costs start once you pass the free tier: $0.01 per build minute, $0.023 per GB stored, and $0.15 per GB served \u2014 so a busy CI pipeline, not traffic, is usually the first line on the bill.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Firebase Hosting and Other Deployment Options<\/h2>\n\n\n\n<p>Firebase Hosting suits any React application already using Firestore, Authentication, or Cloud Functions. Install the CLI, then run the following command: <code>firebase init<\/code>, choose Hosting, set <code>build<\/code> as the public directory, then run firebase deploy to deploy your app. <a href=\"https:\/\/firebase.google.com\/docs\/hosting\/usage-quotas-pricing\" rel=\"nofollow noopener\" target=\"_blank\">Firebase gives 10 GB of Hosting storage<\/a> at no cost on the Spark plan, with HTTPS and CDN delivery by default.<\/p>\n\n\n\n<p>Also worth knowing: Render for a React frontend plus a web service backend, Cloudflare Pages, and S3 with CloudFront on AWS. Static site generators and frameworks such as Next.js add static site generation and SSR when SEO demands pre-rendered HTML.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Deploying to Your Own Server<\/h3>\n\n\n\n<p>Deploying to a company&#8217;s existing infrastructure? Cloud platform tutorials are the wrong guide. You need nginx or Apache with an SPA fallback (<code>try_files $uri \/index.html<\/code>), otherwise every deep link 404s.<\/p>\n\n\n\n<p><strong>Watch:<\/strong> <em>How to Organize Your Application Environment Without Using Docker<\/em> \u2014 an NGINX Unit walkthrough proxying traffic to a ReactJS frontend and Python APIs from one control plane, if containers feel like overkill.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- wp:embed {\"url\":\"https:\/\/www.devnetwork.com\/online-learning\/nginx-unit-for-developers-how-to-organize-your-application-environment-without-using-docker\/\",\"type\":\"video\"} --&gt;\n&lt;figure class=\"wp-block-embed\"&gt;&lt;div class=\"wp-block-embed__wrapper\"&gt;\nhttps:&#47;&#47;www.devnetwork.com\/online-learning\/nginx-unit-for-developers-how-to-organize-your-application-environment-without-using-docker\/\n&lt;\/div&gt;&lt;\/figure&gt;\n&lt;!-- \/wp:embed --&gt;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Client Side Routing and React Router 404 Errors<\/h2>\n\n\n\n<p>React Router navigates between pages without reloading, which works locally and breaks on a static site host. When a user refreshes <code>\/dashboard<\/code>, the server looks for a file at that path, finds nothing, and returns 404. Routing configuration is what makes single page apps survive a refresh.<\/p>\n\n\n\n<p>Fix it per platform:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vercel:<\/strong> handled automatically for SPAs.<\/li>\n\n\n\n<li><strong>Netlify:<\/strong> create a new <code>_redirects<\/code> file in <code>public<\/code> containing <code>\/* \/index.html 200<\/code>.<\/li>\n\n\n\n<li><strong>GitHub Pages:<\/strong> create a new <code>404.html<\/code> copy of <code>index.html<\/code> so React Router handles the path.<\/li>\n\n\n\n<li><strong>Firebase:<\/strong> answer &#8220;yes&#8221; to the single-page app rewrite prompt during <code>firebase init<\/code>.<\/li>\n\n\n\n<li><strong>nginx:<\/strong> add <code>try_files $uri \/index.html;<\/code> to your location block.<\/li>\n<\/ul>\n\n\n\n<p>Never deploy your react app without testing React Router routes directly and on refresh. Broken deep links read as a broken site.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Post-Deployment Validation Checklist<\/h2>\n\n\n\n<p>A successful build is not a working app. Platforms return a green tick when the build compiles, while the live app can still show a blank screen from a runtime error or wrong base path. Run this before sharing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Open the deployed URL in incognito and check the console for errors.<\/li>\n\n\n\n<li>Visit at least three routes directly, then refresh each one.<\/li>\n\n\n\n<li>Confirm API calls succeed and CORS headers are correct.<\/li>\n\n\n\n<li>Verify environment variables resolved to production values, not localhost.<\/li>\n\n\n\n<li>Check that images and static assets load, not just the HTML shell.<\/li>\n\n\n\n<li>Run Lighthouse for Core Web Vitals before traffic arrives.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;The Core Web Vitals established by Google serve as direct ranking factors. The performance metrics of Largest Contentful Paint (LCP) and Interaction To Next Paint (INP) suffer degradation when bundles become too large, negatively affecting organic traffic.&#8221;<\/p>\n\n\n\n<p>\u2014 Raju Dandigam, Engineering Manager, <a href=\"https:\/\/www.forbes.com\/councils\/forbestechcouncil\/2025\/08\/25\/beyond-the-bundle-strategic-javascript-optimization-for-high-performance-react-apps\/\" rel=\"nofollow noopener\" target=\"_blank\">Navan<\/a> (Forbes Technology Council, 2025)<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">3 Common Mistakes to Avoid<\/h2>\n\n\n\n<p>Three mistakes account for most failed first deployments, and each has a distinct symptom:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Symptom<\/th><th>Cause<\/th><th>Fix<\/th><\/tr><\/thead><tbody><tr><td><code>sh: react-scripts: command not found<\/code><\/td><td>Dependency missing from <code>package.json<\/code> or <code>node_modules<\/code> committed<\/td><td><code>npm ci<\/code> locally, verify the dependency, redeploy<\/td><\/tr><tr><td>Blank white page, no console errors<\/td><td>Wrong publish directory or stale <code>homepage<\/code> field<\/td><td>Match <code>build<\/code> vs <code>dist<\/code>; clear <code>homepage<\/code><\/td><\/tr><tr><td>Works on <code>\/<\/code>, 404s everywhere else<\/td><td>No SPA routing fallback<\/td><td>Add <code>_redirects<\/code>, <code>404.html<\/code>, or <code>try_files<\/code><\/td><\/tr><tr><td>API calls hit <code>localhost<\/code> in production<\/td><td>Env vars baked in at build time<\/td><td>Set vars in the host dashboard, rebuild<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">1. Skipping the Local Production Build Test<\/h3>\n\n\n\n<p>Developers test with <code>npm start<\/code> in dev mode, deploy, then discover production behaves differently. The dev server proxies API calls and tolerates loose import casing; the production bundle does neither. Always run the following command locally first: <code>npm run build &amp;&amp; npx serve -s build<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Hardcoding Secrets<\/h3>\n\n\n\n<p>Don&#8217;t commit API keys, even in <code>.env.production<\/code>. Once a key is in git history, rotating it becomes a security incident, not a settings change. Store keys in the hosting dashboard.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Ignoring Bundle Size<\/h3>\n\n\n\n<p>A 5 MB bundle that feels fine on office fibre bounces mobile users on 3G. Measure before guessing: run <code>npx source-map-explorer 'build\/static\/js\/*.js'<\/code> (or <code>npx vite-bundle-visualizer<\/code> on Vite), then apply code splitting, lazy loading, and a CDN for static assets.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;The optimization of bundle size functions as a vital key performance indicator (KPI), affecting three essential business areas: User Retention: Extended loading times result in higher user abandonment rates. If a delay is longer than three seconds, user engagement (and therefore revenue generation) is more likely to decrease.&#8221;<\/p>\n\n\n\n<p>\u2014 Raju Dandigam, Engineering Manager, <a href=\"https:\/\/www.forbes.com\/councils\/forbestechcouncil\/2025\/08\/25\/beyond-the-bundle-strategic-javascript-optimization-for-high-performance-react-apps\/\" rel=\"nofollow noopener\" target=\"_blank\">Navan<\/a> (Forbes Technology Council, 2025)<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Deploying React apps shouldn&#8217;t be hard or costly. Pick the platform matching your traffic, licence, and infrastructure, get the output folder right, configure client side routing and environment variables before you deploy your React application, and validate the live URL rather than trusting a green build. A clean React project on Vercel goes from import to live URL in about the time a single Create React App build used to take \u2014 Runway&#8217;s whole pipeline dropped to 40 seconds. Keep the checklist above open on your second monitor for the first deploy; by the third it will be muscle memory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQs<\/h2>\n\n\n\n<p><strong>Q1.<\/strong> What is the easiest way to deploy a React app?<\/p>\n\n\n\n<p>Vercel or Netlify. Connect your github repository, confirm the build command and publish directory, and click deploy. Both handle SSL, custom domains, and client side routing with no configuration, and redeploy on every git push.<\/p>\n\n\n\n<p><strong>Q2.<\/strong> Can I deploy a React app for free?<\/p>\n\n\n\n<p>Yes. GitHub Pages, Netlify, Vercel, Firebase, and Cloudflare Pages all have free tiers covering most small to medium projects. Read the licence, not just the limit: Vercel&#8217;s Hobby plan is restricted to non-commercial personal projects, while Netlify&#8217;s free tier permits commercial use.<\/p>\n\n\n\n<p><strong>Q3.<\/strong> How can I deploy a React app in 5 minutes?<\/p>\n\n\n\n<p>Push your react project to GitHub, import it into Vercel, and click Deploy to deploy your app. Framework detection sets the build command for you, so the whole first deployment is typically three clicks and a two-minute build.<\/p>\n\n\n\n<p><strong>Q4.<\/strong> How do I deploy a React app on GitHub Pages?<\/p>\n\n\n\n<p>Install <code>gh-pages<\/code>, add a <code>homepage<\/code> field to <code>package.json<\/code>, add predeploy and deploy scripts, then run <code>npm run deploy<\/code>. Set the repository&#8217;s Pages source to that branch and add a <code>404.html<\/code> fallback so deep links don&#8217;t break.<\/p>\n\n\n\n<p><strong>Q5.<\/strong> What common errors happen during React deployment?<\/p>\n\n\n\n<p>Blank screens from a wrong publish directory or base path, 404s on refresh from missing SPA routing rules, API calls failing because environment variables were baked in at build time, and CORS errors when frontend and backend sit on different domains.<\/p>\n\n\n\n<p><strong>Q6.<\/strong> What are environment variables, and why do I need them?<\/p>\n\n\n\n<p>They store configuration and secrets outside your code \u2014 API keys, endpoints, feature flags. They&#8217;re read at build time, must be prefixed (<code>REACT_APP_<\/code> or <code>VITE_<\/code>), and belong in your hosting platform&#8217;s dashboard, never in a git repository.<\/p>\n\n\n\n<p><strong>Q7.<\/strong> What is the difference between Netlify and AWS Amplify?<\/p>\n\n\n\n<p>Netlify is simpler and ideal for small deployments and a frontend-only React application. AWS Amplify supports serverless backends, databases, and enterprise-scale applications, with a steeper learning curve and deeper AWS integration.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>To deploy a ReactJS app, run npm run build to generate a production bundle, push the project to a git repository, then connect that repo to a static site host such as Vercel, Netlify, GitHub Pages, or AWS Amplify. The host runs your build command, publishes the output folder, and redeploys automatically on every git [&hellip;]<\/p>\n","protected":false},"author":10,"featured_media":29457,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[8,21],"tags":[],"class_list":["post-29018","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-react-js"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/posts\/29018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/comments?post=29018"}],"version-history":[{"count":13,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/posts\/29018\/revisions"}],"predecessor-version":[{"id":30763,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/posts\/29018\/revisions\/30763"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/media\/29457"}],"wp:attachment":[{"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/media?parent=29018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/categories?post=29018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tftus.com\/blog\/wp-json\/wp\/v2\/tags?post=29018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}