A full-stack web application with a React frontend and Node.js backend.
Predix is a modern web application built with:
- Frontend: React with TypeScript, built with Vite
- Backend: Node.js with Express
- Database: (Add your database technology here)
The frontend provides an interactive user interface, while the backend handles API requests, business logic, and data management.
predix/
├── frontend/ # React + TypeScript frontend
│ ├── src/ # Source code
│ ├── package.json # Frontend dependencies
│ └── vite.config.ts # Vite configuration
├── backend/ # Node.js backend
│ ├── index.js # Main server file
│ ├── db.js # Database configuration
│ └── package.json # Backend dependencies
└── README.md # This file
This guide will help you deploy your application to production.
Vercel is perfect for deploying React applications. Follow these steps:
- Make sure your code is pushed to GitHub
- Ensure your frontend code is in the
frontend/directory
- Go to vercel.com and sign up or log in
- Click "New Project"
- Import your GitHub repository (e.g.,
your-username/predix) - Configure the project settings:
- Framework Preset: Vite
- Root Directory:
frontend - Build Command:
npm run build(or leave default) - Output Directory:
dist(or leave default)
- Click "Deploy"
-
In your Vercel project dashboard, go to Settings → Environment Variables
-
Add the following environment variables:
Variable Name Description Example Value VITE_API_URLYour backend API URL https://your-app.onrender.comVITE_APP_NAMEApplication name (optional) Predix -
Click "Save"
-
Redeploy your application to apply the changes
Render makes it easy to deploy Node.js applications. Follow these steps:
- Make sure your code is pushed to GitHub
- Ensure your backend has a
package.jsonwith a start script
- Go to render.com and sign up or log in
- Click "New" → "Web Service"
- Connect your GitHub repository (e.g.,
your-username/predix) - Configure the service:
- Name:
predix-backend(or your preferred name) - Root Directory:
backend - Environment:
Node - Build Command:
npm install - Start Command:
node index.js(ornpm start) - Instance Type: Free (or your preferred tier)
- Name:
- Click "Create Web Service"
-
In your Render service dashboard, go to Environment section
-
Add the following environment variables:
Variable Name Description Example Value NODE_ENVEnvironment mode productionDATABASE_URLYour database connection string mongodb://...orpostgresql://...CORS_ORIGINFrontend URL for CORS https://your-app.vercel.appJWT_SECRETSecret key for authentication (if using JWT) your-secret-key-hereNote: Render automatically sets the
PORTenvironment variable for your service. Your server should listen onprocess.env.PORT, and you typically do not need to configurePORTmanually in the Render dashboard. -
Click "Save Changes"
-
Your service will automatically redeploy
Create a .env file in the frontend/ directory for local development:
# Backend API URL
VITE_API_URL=http://localhost:3000
# Optional: Application name
VITE_APP_NAME=PredixImportant Notes:
- In Vite, environment variables must be prefixed with
VITE_to be accessible in your code - Access them in your code using
import.meta.env.VITE_API_URL - Never commit
.envfiles to version control (they're in.gitignore)
Create a .env file in the backend/ directory for local development:
# Server port
PORT=3000
# Environment
NODE_ENV=development
# Database connection (update with your actual database)
DATABASE_URL=mongodb://localhost:27017/predix
# OR for PostgreSQL:
# DATABASE_URL=postgresql://user:password@localhost:5432/predix
# CORS - Frontend URL
CORS_ORIGIN=http://localhost:5173
# Authentication (if using JWT)
JWT_SECRET=your-local-secret-key-change-in-production
# Other API keys or secrets
# API_KEY=your-api-keyImportant Notes:
- Never commit
.envfiles to version control - Use different values for development and production
- Keep sensitive data like API keys and secrets secure
The frontend and backend communicate using HTTP requests. Here's how it works:
In your React components, you make requests to the backend:
// Example: Fetching data from the backend
async function fetchData() {
try {
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/data`);
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch data:', error);
throw error;
}
}
// Example: Sending data to the backend
async function createItem(item: unknown) {
try {
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/items`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(item),
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const result = await response.json();
return result;
} catch (error) {
console.error('Failed to create item:', error);
throw error;
}
}Your backend listens for these requests and sends responses:
// Middleware to parse JSON request bodies
app.use(express.json());
// Example: Backend API endpoint
app.get('/api/data', (req, res) => {
// Get data from database
const data = { message: 'Hello from backend!' };
res.json(data);
});
// Always validate and sanitize input on the backend before using it.
app.post('/api/items', (req, res) => {
const { name, price } = req.body || {};
// Basic validation example (adjust fields to match your real model)
if (typeof name !== 'string' || name.trim() === '' || typeof price !== 'number') {
return res.status(400).json({ success: false, error: 'Invalid item data.' });
}
const newItem = { name: name.trim(), price };
// Save to database...
res.json({ success: true, item: newItem });
});For the frontend and backend to communicate across different domains, CORS must be enabled:
// Backend: Enable CORS
const cors = require('cors');
app.use(cors({
origin: process.env.CORS_ORIGIN, // Your frontend URL
credentials: true, // Allow cookies/auth headers; frontend must use credentials: 'include' in fetch when needed
}));┌─────────────┐ HTTP Request ┌─────────────┐
│ │ ──────────────────────────> │ │
│ Frontend │ │ Backend │
│ (Vercel) │ <────────────────────────── │ (Render) │
│ │ JSON Response │ │
└─────────────┘ └─────────────┘
│ │
│ │
└──────────────────────────────────────────────┘
Uses VITE_API_URL environment variable
- Node.js (v16 or higher)
- npm or yarn
- Git
# Navigate to backend directory
cd backend
# Install dependencies
npm install
# Create .env file with your environment variables
# (see Backend Environment Variables section above)
# Start the server
npm start
# Backend will run on http://localhost:3000# Open a new terminal
# Navigate to frontend directory
cd frontend
# Install dependencies
npm install
# Create .env file with your environment variables
# (see Frontend Environment Variables section above)
# Start the development server
npm run dev
# Frontend will run on http://localhost:5173Now you can access your application at http://localhost:5173 and it will communicate with the backend at http://localhost:3000.
- Solution: Check that
VITE_API_URLis correctly set in your frontend environment variables - Verify the backend URL is correct and the backend is running
- Check CORS configuration in the backend
- Solution: Make sure you restart your development server after changing
.envfiles - In Vite, ensure variables start with
VITE_ - In production, verify environment variables are set in Vercel/Render dashboards
- Solution: Check the build logs in Vercel/Render
- Ensure all dependencies are listed in
package.json - Verify the build and start commands are correct
- Vite Documentation
- React Documentation
- Vercel Documentation
- Render Documentation
- Express.js Documentation
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
Made with ❤️ by the Predix team