Overview
This guide covers deploying Q-Sopa to production. The application is built with Vite and can be deployed to any static hosting platform.
Building for Production
Before deploying, you need to create an optimized production build.
Build Command
This command:
Bundles your React application
Optimizes assets (minification, tree-shaking)
Creates a dist/ directory with production-ready files
Build Configuration
The build is configured in vite.config.js:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig ({
plugins: [ react ()] ,
})
Preview your production build locally before deploying: npm run build
npm run preview
This serves the dist/ folder at http://localhost:4173
Environment Variables
Setting Up Environment Variables
Create environment files for different stages:
.env.development (local development):
VITE_API_BASE_URL = http://localhost:3000
.env.production (production):
VITE_API_BASE_URL = https://apiqsp-production.up.railway.app
Using Environment Variables
Update src/services/api.js to use environment variables:
const BASE_URL = import . meta . env . VITE_API_BASE_URL || "https://apiqsp-production.up.railway.app" ;
export const getCategorias = async () => {
const res = await fetch ( ` ${ BASE_URL } /categories` );
if ( ! res . ok ) throw new Error ( "Error al cargar categorías" );
return res . json ();
};
export const getComidas = async () => {
const res = await fetch ( ` ${ BASE_URL } /products` );
if ( ! res . ok ) throw new Error ( "Error al cargar comidas" );
return res . json ();
};
export const getProductsByCategory = async ( categoryId ) => {
const res = await fetch ( ` ${ BASE_URL } /products/category/ ${ categoryId } ` );
if ( ! res . ok ) throw new Error ( "Error al cargar productos de la categoría" );
return res . json ();
};
Vite only exposes environment variables prefixed with VITE_ to your client-side code. Never store sensitive keys in client-side environment variables.
Vercel (Recommended)
Vercel offers seamless deployment with automatic builds and previews.
Deploy
Follow the prompts to configure your project.
Set Environment Variables
In the Vercel dashboard:
Go to Project Settings → Environment Variables
Add VITE_API_BASE_URL with your production API URL
Redeploy to apply changes
Vercel Configuration
Create vercel.json in your project root:
{
"buildCommand" : "npm run build" ,
"outputDirectory" : "dist" ,
"framework" : "vite" ,
"rewrites" : [
{
"source" : "/(.*)" ,
"destination" : "/index.html"
}
]
}
GitHub Integration
For automatic deployments:
Push your code to GitHub
Import your repository in Vercel Dashboard
Configure build settings:
Framework Preset : Vite
Build Command : npm run build
Output Directory : dist
Add environment variables
Deploy
Every push to your main branch will trigger an automatic deployment. Pull requests get preview deployments.
Netlify
Netlify is another excellent option for static sites.
Install Netlify CLI
npm install -g netlify-cli
Netlify Configuration
Create netlify.toml in your project root:
[ build ]
command = "npm run build"
publish = "dist"
[[ redirects ]]
from = "/*"
to = "/index.html"
status = 200
[ build . environment ]
NODE_VERSION = "18"
Setting Environment Variables
In Netlify Dashboard:
Go to Site Settings → Build & Deploy → Environment
Add VITE_API_BASE_URL
Trigger a new deploy
Railway
Deploy alongside your backend API on Railway.
Install Railway CLI
npm install -g @railway/cli
Add Build Configuration
Create railway.json: {
"$schema" : "https://railway.app/railway.schema.json" ,
"build" : {
"builder" : "NIXPACKS" ,
"buildCommand" : "npm run build"
},
"deploy" : {
"startCommand" : "npm run preview" ,
"restartPolicyType" : "ON_FAILURE"
}
}
Railway is particularly useful if your API is already hosted there, as both frontend and backend can be in the same project.
GitHub Pages
Deploy to GitHub Pages for free static hosting.
Update vite.config.js
Add base path for GitHub Pages: import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig ({
plugins: [ react ()] ,
base: '/your-repo-name/' , // Replace with your repository name
})
Install gh-pages
npm install --save-dev gh-pages
Add Deploy Scripts
Update package.json: {
"scripts" : {
"dev" : "vite" ,
"build" : "vite build" ,
"preview" : "vite preview" ,
"predeploy" : "npm run build" ,
"deploy" : "gh-pages -d dist"
}
}
Deploy
This builds your app and pushes it to the gh-pages branch.
Enable GitHub Pages
Go to your repository settings
Navigate to Pages section
Set source to gh-pages branch
Save
Cloudflare Pages
Deploy with Cloudflare’s global CDN.
Configure Build
Framework preset : Vite
Build command : npm run build
Build output directory : dist
Set Environment Variables
Add VITE_API_BASE_URL in the environment variables section
Deploy
Click “Save and Deploy”
CORS Configuration
If your API and frontend are on different domains, you may encounter CORS issues.
Backend CORS Setup
Your API must allow requests from your frontend domain. Example Express.js configuration:
const express = require ( 'express' );
const cors = require ( 'cors' );
const app = express ();
// Allow your production domain
app . use ( cors ({
origin: [ 'https://your-frontend-domain.com' , 'http://localhost:5173' ],
credentials: true
}));
// Your API routes...
Never use cors({origin: '*'}) in production. Always specify allowed origins explicitly.
Image Optimization
Use WebP format for better compression
Implement lazy loading :
// In ProductCard.jsx
< img
src = { image }
alt = { title }
loading = "lazy"
/>
Use CDN for images : Host product images on a CDN like Cloudinary or Imgix
Code Splitting
Vite automatically handles code splitting, but you can optimize further:
import { lazy , Suspense } from 'react' ;
const Menu = lazy (() => import ( './pages/Menu' ));
function App () {
return (
< Suspense fallback = { < div > Loading... </ div > } >
< Menu />
</ Suspense >
);
}
Caching Strategy
Implement API response caching:
// src/services/api.js
const cache = new Map ();
const CACHE_DURATION = 5 * 60 * 1000 ; // 5 minutes
export const getCategorias = async () => {
const cacheKey = 'categories' ;
const cached = cache . get ( cacheKey );
if ( cached && Date . now () - cached . timestamp < CACHE_DURATION ) {
return cached . data ;
}
const res = await fetch ( ` ${ BASE_URL } /categories` );
if ( ! res . ok ) throw new Error ( "Error al cargar categorías" );
const data = await res . json ();
cache . set ( cacheKey , { data , timestamp: Date . now () });
return data ;
};
Monitoring and Analytics
Adding Google Analytics
Install the package :
Initialize in your app :
// src/main.jsx
import ReactGA from 'react-ga4' ;
ReactGA . initialize ( 'G-XXXXXXXXXX' );
// Track page views
ReactGA . send ({ hitType: "pageview" , page: window . location . pathname });
Error Tracking with Sentry
Install Sentry :
npm install @sentry/react
Configure :
// src/main.jsx
import * as Sentry from "@sentry/react" ;
Sentry . init ({
dsn: "your-sentry-dsn" ,
environment: import . meta . env . MODE ,
tracesSampleRate: 1.0 ,
});
Deployment Checklist
Continuous Deployment
Set up automatic deployments with GitHub Actions:
# .github/workflows/deploy.yml
name : Deploy to Production
on :
push :
branches :
- main
jobs :
deploy :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- name : Setup Node
uses : actions/setup-node@v3
with :
node-version : '18'
- name : Install dependencies
run : npm ci
- name : Build
run : npm run build
env :
VITE_API_BASE_URL : ${{ secrets.VITE_API_BASE_URL }}
- name : Deploy to Vercel
uses : amondnet/vercel-action@v20
with :
vercel-token : ${{ secrets.VERCEL_TOKEN }}
vercel-org-id : ${{ secrets.ORG_ID }}
vercel-project-id : ${{ secrets.PROJECT_ID }}
vercel-args : '--prod'
Troubleshooting Deployment
Build fails with 'MODULE_NOT_FOUND'
Ensure all dependencies are in package.json: rm -rf node_modules package-lock.json
npm install
npm run build
Blank page after deployment
Check the browser console for errors. Common causes:
Incorrect base path in vite.config.js
Missing environment variables
CORS issues with API
Environment variables not working
Remember:
Variables must be prefixed with VITE_
Rebuild after changing environment variables
Access with import.meta.env.VITE_VARIABLE_NAME
Next Steps
Troubleshooting Fix common issues and errors
Customization Customize the application