React SPA for the RecipeNest platform — browse chef profiles, discover recipes, and manage your own culinary portfolio.
Built with React 18, Vite 5, and React Router v6. Deployed on Vercel.
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- Pages & Routes
- Component Overview
- API Service Layer
- Deployment
| Concern | Library / Version |
|---|---|
| Framework | React 18.2 |
| Build tool | Vite 5.1 |
| Routing | React Router DOM 6.22 |
| HTTP | Native Fetch API |
| Styling | Plain CSS with custom properties |
| Hosting | Vercel |
recipenest-frontend/
├── public/ # Static assets (food/chef images)
├── src/
│ ├── pages/
│ │ ├── HomePage.jsx # Landing page — hero, recipes, chefs
│ │ ├── LoginPage.jsx # Split-panel login form
│ │ ├── RegisterPage.jsx # Split-panel register + avatar picker
│ │ ├── ChefsPage.jsx # Chef directory with search/filter
│ │ ├── ChefDetailPage.jsx # Chef profile + recipe grid
│ │ ├── RecipesPage.jsx # Recipe directory with search/sort
│ │ ├── DashboardPage.jsx # Authenticated chef dashboard
│ │ ├── AddRecipePage.jsx # Create recipe form + image picker
│ │ ├── EditRecipePage.jsx # Edit existing recipe
│ │ └── ProfileEditPage.jsx # Update chef profile
│ ├── components/
│ │ ├── Navbar.jsx # Responsive nav with mobile hamburger
│ │ ├── Footer.jsx # 3-column footer (hidden on auth pages)
│ │ ├── ChefCard.jsx # Chef card with image overlay
│ │ ├── RecipeCard.jsx # Recipe card with image + chef badge
│ │ └── ProtectedRoute.jsx # Redirects unauthenticated users to /login
│ ├── context/
│ │ └── AuthContext.jsx # Global auth state + localStorage sync
│ ├── services/
│ │ └── api.js # Typed fetch wrappers for every endpoint
│ ├── App.jsx # Route definitions
│ ├── main.jsx # React entry point
│ └── index.css # Design system (tokens, utilities, animations)
├── .env # Local dev environment variables (git-ignored)
├── .env.example # Template for production variables
├── vercel.json # SPA rewrite rule for client-side routing
└── vite.config.js
cd recipenest-frontend
npm install
npm run devApp runs at http://localhost:5173.
Make sure the backend API is running at http://localhost:5000 (or update .env).
npm run build # Production build → dist/
npm run preview # Serve the production build locallyCreate a .env file in this directory (copy from .env.example):
VITE_API_URL=http://localhost:5000/apiIn Vercel, add this as an environment variable:
| Key | Value |
|---|---|
VITE_API_URL |
https://your-api.onrender.com/api |
All Vite environment variables must be prefixed with
VITE_to be accessible in client code viaimport.meta.env.VITE_*.
| Route | Component | Auth required |
|---|---|---|
/ |
HomePage |
No |
/login |
LoginPage |
No |
/register |
RegisterPage |
No |
/chefs |
ChefsPage |
No |
/chefs/:id |
ChefDetailPage |
No |
/recipes |
RecipesPage |
No |
/dashboard |
DashboardPage |
Yes |
/profile/edit |
ProfileEditPage |
Yes |
/recipes/add |
AddRecipePage |
Yes |
/recipes/edit/:id |
EditRecipePage |
Yes |
Protected routes are wrapped in <ProtectedRoute> — unauthenticated users are redirected to /login.
Provides user, login(data), and logout() to the whole tree via React Context.
Auth state is persisted in localStorage using the token, chefId, name, email, and avatarUrl keys.
- Responsive: collapses to a hamburger menu on mobile
- Active link highlighting via
useLocation - Shows Dashboard / Logout when logged in, Login / Register when not
- Three-column layout: brand, explore links, account links
- Automatically hidden on
/loginand/registerviauseLocation
- Image overlay with gradient
- Falls back to a pool of bundled food/chef images when no custom image is set
- Skeleton loading state during data fetch
src/services/api.js exports four namespaced objects:
import { authAPI, chefsAPI, recipesAPI, profileAPI } from './services/api';
// Examples
await authAPI.login({ email, password });
await recipesAPI.create({ title, description, ingredients, instructions, imageUrl });
await profileAPI.update({ name, bio, avatarUrl });The BASE_URL is read from import.meta.env.VITE_API_URL with a fallback to http://localhost:5000/api.
All authenticated calls automatically attach Authorization: Bearer <token> from localStorage.
The frontend is deployed to Vercel as a static SPA.
- Push the repo to GitHub
- Create a New Project on Vercel and import the repo
- Set Root Directory to
recipenest-frontend - Add the
VITE_API_URLenvironment variable pointing to your Render API URL - Deploy
vercel.json includes a catch-all rewrite rule so that client-side routes (e.g. /chefs/3) return index.html instead of a 404:
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}