487 lines
15 KiB
Markdown
487 lines
15 KiB
Markdown
# ⚡️ Fusero App Boilerplate
|
||
|
||
A full-stack application boilerplate with a React frontend and Node.js backend — powered by Fastify, Vite, PostgreSQL, Docker, and optional Kubernetes & Helm support. Built for modern dev workflows and AI-powered backend endpoint generation.
|
||
|
||
---
|
||
|
||
## 📚 Table of Contents
|
||
|
||
- [⚡️ Fusero App Boilerplate](#️-fusero-app-boilerplate)
|
||
- [📚 Table of Contents](#-table-of-contents)
|
||
- [📁 Project Structure](#-project-structure)
|
||
- [⚙️ Prerequisites](#️-prerequisites)
|
||
- [💻 Development Setup](#-development-setup)
|
||
- [Alternate: Running Services in Separate Terminals](#alternate-running-services-in-separate-terminals)
|
||
- [🛠️ Environment Setup](#️-environment-setup)
|
||
- [For Kubernetes, these are set in chart/values.yaml:](#for-kubernetes-these-are-set-in-chartvaluesyaml)
|
||
- [POSTGRES\_NAME=fusero-boilerplate-db](#postgres_namefusero-boilerplate-db)
|
||
- [POSTGRES\_HOSTNAME=postgres-service](#postgres_hostnamepostgres-service)
|
||
- [POSTGRES\_PORT=19095](#postgres_port19095)
|
||
- [POSTGRES\_USER=root](#postgres_userroot)
|
||
- [POSTGRES\_PASSWORD=root123](#postgres_passwordroot123)
|
||
- [🚀 Production Deployment](#-production-deployment)
|
||
- [🌐 Frontend Routing in Production](#-frontend-routing-in-production)
|
||
- [🔐 HTTPS with Self-Signed Certificates](#-https-with-self-signed-certificates)
|
||
- [🧠 Development Best Practices](#-development-best-practices)
|
||
- [📘 API Documentation](#-api-documentation)
|
||
- [🧩 ChatGPT-Powered Endpoint Creation](#-chatgpt-powered-endpoint-creation)
|
||
- [🧪 Troubleshooting](#-troubleshooting)
|
||
- [🤝 Contributing](#-contributing)
|
||
- [📄 License](#-license)
|
||
- [Kubernetes Troubleshooting \& Redeployment Commands](#kubernetes-troubleshooting--redeployment-commands)
|
||
- [1. Rebuild the backend Docker image (after code/config changes)](#1-rebuild-the-backend-docker-image-after-codeconfig-changes)
|
||
- [2. (If using a remote registry) Push the image](#2-if-using-a-remote-registry-push-the-image)
|
||
- [3. Upgrade the Helm release with the latest values](#3-upgrade-the-helm-release-with-the-latest-values)
|
||
- [4. Restart the backend deployment to pick up new images and env vars](#4-restart-the-backend-deployment-to-pick-up-new-images-and-env-vars)
|
||
- [5. Check backend pod environment variables](#5-check-backend-pod-environment-variables)
|
||
- [6. Check backend pod logs for errors](#6-check-backend-pod-logs-for-errors)
|
||
- [7. If you change DB env vars or code, repeat steps 1-6](#7-if-you-change-db-env-vars-or-code-repeat-steps-1-6)
|
||
- [Frontend Rebuild \& Redeploy (Kubernetes)](#frontend-rebuild--redeploy-kubernetes)
|
||
- [1. Rebuild the frontend Docker image](#1-rebuild-the-frontend-docker-image)
|
||
- [2. (If using a remote registry) Push the image](#2-if-using-a-remote-registry-push-the-image-1)
|
||
- [3. Upgrade the Helm release](#3-upgrade-the-helm-release)
|
||
- [4. Restart the frontend deployment](#4-restart-the-frontend-deployment)
|
||
- [Port-Forwarding for Local Access](#port-forwarding-for-local-access)
|
||
- [Frontend (React app)](#frontend-react-app)
|
||
- [Backend (API)](#backend-api)
|
||
- [NGINX Backend Service Name: Docker Compose vs Kubernetes](#nginx-backend-service-name-docker-compose-vs-kubernetes)
|
||
- [How to update the NGINX config for Kubernetes](#how-to-update-the-nginx-config-for-kubernetes)
|
||
- [Cleaning Up Duplicate or Crashing Deployments and Pods in Kubernetes](#cleaning-up-duplicate-or-crashing-deployments-and-pods-in-kubernetes)
|
||
- [1. List deployments and pods](#1-list-deployments-and-pods)
|
||
- [2. Delete old or crashing deployments (example IDs from your cluster)](#2-delete-old-or-crashing-deployments-example-ids-from-your-cluster)
|
||
- [3. Delete old or crashing pods (example IDs from your cluster)](#3-delete-old-or-crashing-pods-example-ids-from-your-cluster)
|
||
- [Debugging Frontend Pod Crashes: NGINX SSL Certificate Errors](#debugging-frontend-pod-crashes-nginx-ssl-certificate-errors)
|
||
- [How to fix for Kubernetes (Recommended)](#how-to-fix-for-kubernetes-recommended)
|
||
- [Connecting to the Database from Your Host (DBeaver, etc.)](#connecting-to-the-database-from-your-host-dbeaver-etc)
|
||
|
||
---
|
||
|
||
## 📁 Project Structure
|
||
|
||
fusero-app-boilerplate/
|
||
├── frontend/ # React frontend application
|
||
├── backend/ # Node.js backend application
|
||
├── docker-compose.yml # Production Docker configuration
|
||
├── docker-compose.dev.yml # Development Docker configuration
|
||
└── chart/ # Helm chart for Kubernetes deployment
|
||
|
||
---
|
||
|
||
## ⚙️ Prerequisites
|
||
|
||
- Node.js (v20 or higher)
|
||
- npm (v9 or higher)
|
||
- Docker & Docker Compose
|
||
- Git
|
||
|
||
---
|
||
|
||
## 💻 Development Setup
|
||
|
||
🗃️ PostgreSQL must run in Docker for consistent behavior.
|
||
|
||
Create volume and start the database:
|
||
docker volume create fusero-db-data
|
||
docker-compose up -d db
|
||
|
||
Backend setup:
|
||
cd backend
|
||
cp .env.example .env
|
||
npm install
|
||
npm run migrate
|
||
npm run seed
|
||
npm run dev &
|
||
cd ..
|
||
|
||
Frontend setup:
|
||
cd frontend
|
||
cp .env.example .env
|
||
npm install
|
||
npm run dev &
|
||
cd ..
|
||
|
||
App is running:
|
||
Frontend → http://localhost:3000
|
||
Backend → http://localhost:14000
|
||
|
||
---
|
||
|
||
### Alternate: Running Services in Separate Terminals
|
||
|
||
Terminal 1 (backend):
|
||
cd backend
|
||
npm install
|
||
npm run dev
|
||
|
||
Terminal 2 (frontend):
|
||
cd frontend
|
||
npm install
|
||
npm run dev
|
||
|
||
---
|
||
|
||
## 🛠️ Environment Setup
|
||
|
||
backend/.env:
|
||
POSTGRES_NAME=fusero-boilerplate-db
|
||
POSTGRES_HOSTNAME=localhost
|
||
POSTGRES_PORT=19095
|
||
POSTGRES_USER=root
|
||
POSTGRES_PASSWORD=root123
|
||
JWT_SECRET=your_jwt_secret_key_here
|
||
|
||
# For Kubernetes, these are set in chart/values.yaml:
|
||
# POSTGRES_NAME=fusero-boilerplate-db
|
||
# POSTGRES_HOSTNAME=postgres-service
|
||
# POSTGRES_PORT=19095
|
||
# POSTGRES_USER=root
|
||
# POSTGRES_PASSWORD=root123
|
||
|
||
frontend/.env:
|
||
VITE_API_BASE_URL=http://localhost:14000/api/v1
|
||
|
||
---
|
||
|
||
## 🚀 Production Deployment
|
||
|
||
1. Build and run with Docker:
|
||
docker-compose up --build
|
||
|
||
2. Apply migrations and seed inside backend container:
|
||
docker exec -it fusero-app-backend npx mikro-orm migration:up
|
||
docker exec -it fusero-app-backend npm run seed
|
||
|
||
3. Ensure all required environment variables are configured.
|
||
Never commit `.env` files.
|
||
|
||
---
|
||
|
||
## 🌐 Frontend Routing in Production
|
||
|
||
In production, the frontend is served through NGINX.
|
||
|
||
NGINX configuration (important for React routing):
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
React Router Configuration:
|
||
Use `basename="/"` in dev, and `basename="/dashboard"` in production.
|
||
|
||
Use relative paths in links:
|
||
Correct: to="canvas/canvas-endpoints"
|
||
Wrong: to="/dashboard/canvas/canvas-endpoints"
|
||
|
||
---
|
||
|
||
## 🔐 HTTPS with Self-Signed Certificates
|
||
|
||
Generate a self-signed cert:
|
||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./nginx/ssl/nginx.key -out ./nginx/ssl/nginx.crt
|
||
|
||
Ensure `docker-compose.yml` mounts the certs:
|
||
volumes:
|
||
- ./nginx/ssl:/etc/nginx/ssl
|
||
|
||
Configure NGINX to use the cert in production.
|
||
|
||
---
|
||
|
||
## 🧠 Development Best Practices
|
||
|
||
- Always run the DB via Docker
|
||
- Use `docker-compose.dev.yml` for development
|
||
- Never run PostgreSQL directly on host
|
||
- Run frontend and backend separately for hot reload
|
||
- Use `.env.example` as a template
|
||
- Never commit `.env`
|
||
- Commit `package-lock.json`
|
||
- Use meaningful commit messages
|
||
|
||
---
|
||
|
||
## 📘 API Documentation
|
||
|
||
After running the backend:
|
||
|
||
Development → http://localhost:14000/api-docs
|
||
Production → https://your-domain/api-docs
|
||
|
||
---
|
||
|
||
## 🧩 ChatGPT-Powered Endpoint Creation
|
||
|
||
Prompts like "Create a course endpoint for Canvas" auto-generate API endpoints.
|
||
|
||
How it works:
|
||
1. The frontend sends your prompt to `/api/v1/canvas-api/chatgpt/completions`
|
||
2. If ChatGPT returns a valid endpoint JSON, it's POSTed to `/api/v1/canvas-api/endpoints`
|
||
3. The UI auto-refreshes the endpoint list and shows a toast
|
||
|
||
Example Prompt:
|
||
Create a course endpoint for Canvas.
|
||
|
||
Expected JSON:
|
||
{
|
||
"name": "Create Course",
|
||
"method": "POST",
|
||
"path": "/courses",
|
||
"description": "Creates a new course in Canvas."
|
||
}
|
||
|
||
Developer Notes:
|
||
- Frontend logic: frontend/src/components/CanvasEndpoints.tsx
|
||
- Backend API: /api/v1/canvas-api/endpoints
|
||
|
||
---
|
||
|
||
## 🧪 Troubleshooting
|
||
|
||
Port Conflicts:
|
||
docker ps
|
||
lsof -i :3000
|
||
lsof -i :14000
|
||
|
||
Database Issues:
|
||
Ensure DB is in Docker and configured correctly
|
||
Try restarting:
|
||
docker-compose -f docker-compose.dev.yml down
|
||
docker-compose -f docker-compose.dev.yml up db
|
||
|
||
CORS Issues:
|
||
Check API base URL in frontend `.env`
|
||
Check backend CORS settings
|
||
Verify ports match and services are running
|
||
|
||
---
|
||
|
||
## 🤝 Contributing
|
||
|
||
1. Create a branch
|
||
2. Make your changes
|
||
3. Pass all tests
|
||
4. Open a pull request
|
||
5. Update docs if needed
|
||
|
||
---
|
||
|
||
## 📄 License
|
||
|
||
This project is licensed under the MIT License.
|
||
See the LICENSE file for full details.
|
||
|
||
---
|
||
|
||
## Kubernetes Troubleshooting & Redeployment Commands
|
||
|
||
If your backend is not picking up environment variables or is failing to connect to the database, follow these steps:
|
||
|
||
### 1. Rebuild the backend Docker image (after code/config changes)
|
||
```bash
|
||
docker build -t fusero-backend-dev:local .
|
||
```
|
||
|
||
### 2. (If using a remote registry) Push the image
|
||
```bash
|
||
docker push <your-registry>/fusero-backend-dev:local
|
||
```
|
||
|
||
### 3. Upgrade the Helm release with the latest values
|
||
```bash
|
||
helm upgrade fusero ./chart -n fusero -f chart/values.dev.yaml
|
||
```
|
||
|
||
### 4. Restart the backend deployment to pick up new images and env vars
|
||
```bash
|
||
kubectl rollout restart deployment/fusero-backend -n fusero
|
||
```
|
||
|
||
### 5. Check backend pod environment variables
|
||
```bash
|
||
kubectl get pods -n fusero
|
||
# Replace <backend-pod-name> with the actual pod name from above
|
||
kubectl exec -n fusero <backend-pod-name> -- printenv | grep POSTGRES
|
||
```
|
||
|
||
### 6. Check backend pod logs for errors
|
||
```bash
|
||
kubectl logs <backend-pod-name> -n fusero --tail=50
|
||
```
|
||
|
||
### 7. If you change DB env vars or code, repeat steps 1-6
|
||
|
||
---
|
||
|
||
**Note:**
|
||
- Make sure your backend code does NOT load `.env` at runtime in Kubernetes. It should use the environment variables provided by the pod.
|
||
- If you see connection errors to the DB, always check the pod's environment and logs as above.
|
||
|
||
---
|
||
|
||
## Frontend Rebuild & Redeploy (Kubernetes)
|
||
|
||
If you change the VITE_API_BASE_URL or any frontend environment variable, rebuild and redeploy the frontend:
|
||
|
||
### 1. Rebuild the frontend Docker image
|
||
```bash
|
||
docker build -t fusero-frontend-dev:local ./frontend
|
||
```
|
||
|
||
### 2. (If using a remote registry) Push the image
|
||
```bash
|
||
docker push <your-registry>/fusero-frontend-dev:local
|
||
```
|
||
|
||
### 3. Upgrade the Helm release
|
||
```bash
|
||
helm upgrade fusero ./chart -n fusero -f chart/values.dev.yaml
|
||
```
|
||
|
||
### 4. Restart the frontend deployment
|
||
```bash
|
||
kubectl rollout restart deployment/fusero-frontend -n fusero
|
||
```
|
||
|
||
---
|
||
|
||
## Port-Forwarding for Local Access
|
||
|
||
To access your services running in Kubernetes from your local machine, use these commands:
|
||
|
||
### Frontend (React app)
|
||
```bash
|
||
kubectl port-forward -n fusero svc/fusero-frontend-service 3000:80
|
||
```
|
||
- Access at: http://localhost:3000
|
||
|
||
### Backend (API)
|
||
```bash
|
||
kubectl port-forward -n fusero svc/fusero-backend-service 14000:14000
|
||
```
|
||
- Access at: http://localhost:14000
|
||
|
||
---
|
||
|
||
## NGINX Backend Service Name: Docker Compose vs Kubernetes
|
||
|
||
**If your frontend uses NGINX to proxy API requests, you must update the backend service name depending on your environment:**
|
||
|
||
- **Docker Compose/local:** The backend may be named `fusero-app-backend`.
|
||
- **Kubernetes:** The backend service is named `fusero-backend-service`.
|
||
|
||
### How to update the NGINX config for Kubernetes
|
||
|
||
Edit `frontend/nginx.conf`:
|
||
|
||
**Change this:**
|
||
```nginx
|
||
proxy_pass http://fusero-app-backend:14000/;
|
||
```
|
||
**To this:**
|
||
```nginx
|
||
proxy_pass http://fusero-backend-service:14000/;
|
||
```
|
||
|
||
Then rebuild and redeploy the frontend:
|
||
```bash
|
||
docker build -t fusero-frontend-dev:local ./frontend
|
||
# (push if needed)
|
||
helm upgrade fusero ./chart -n fusero -f chart/values.dev.yaml
|
||
kubectl rollout restart deployment/fusero-frontend -n fusero
|
||
```
|
||
|
||
**If you see an NGINX error like `host not found in upstream`, this is the cause!**
|
||
|
||
---
|
||
|
||
## Cleaning Up Duplicate or Crashing Deployments and Pods in Kubernetes
|
||
|
||
If you see multiple frontend or backend pods (or CrashLoopBackOff errors), clean up your namespace with these steps:
|
||
|
||
### 1. List deployments and pods
|
||
```bash
|
||
kubectl get deployments -n fusero
|
||
kubectl get pods -n fusero
|
||
```
|
||
|
||
### 2. Delete old or crashing deployments (example IDs from your cluster)
|
||
```bash
|
||
kubectl delete deployment fusero-frontend-65cb8db99d -n fusero
|
||
kubectl delete deployment fusero-frontend-74fcbb778 -n fusero
|
||
```
|
||
|
||
### 3. Delete old or crashing pods (example IDs from your cluster)
|
||
```bash
|
||
kubectl delete pod fusero-frontend-65cb8db99d-f2lhr -n fusero
|
||
kubectl delete pod fusero-frontend-74fcbb778-v89gm -n fusero
|
||
```
|
||
|
||
**Tip:** Only keep the latest, healthy pods and deployments. If in doubt, check with `kubectl get deployments -n fusero` and `kubectl get pods -n fusero` before deleting.
|
||
|
||
---
|
||
|
||
## Debugging Frontend Pod Crashes: NGINX SSL Certificate Errors
|
||
|
||
If your frontend pod crashes with an error like:
|
||
|
||
```
|
||
nginx: [emerg] cannot load certificate "/etc/nginx/certs/fusero-selfsigned.crt": BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory)
|
||
```
|
||
|
||
This means NGINX is trying to load an SSL certificate that does not exist in the pod.
|
||
|
||
### How to fix for Kubernetes (Recommended)
|
||
1. Edit `frontend/nginx.conf`:
|
||
- Change:
|
||
```nginx
|
||
listen 14443 ssl;
|
||
ssl_certificate /etc/nginx/certs/fusero-selfsigned.crt;
|
||
ssl_certificate_key /etc/nginx/certs/fusero-selfsigned.key;
|
||
```
|
||
- To:
|
||
```nginx
|
||
listen 8080;
|
||
# (remove the ssl_certificate and ssl_certificate_key lines)
|
||
```
|
||
2. Rebuild the frontend Docker image:
|
||
```bash
|
||
docker build --no-cache -t fusero-frontend-dev:local ./frontend
|
||
```
|
||
3. (If using a remote registry) Push the image.
|
||
4. Redeploy with Helm:
|
||
```bash
|
||
helm upgrade fusero ./chart -n fusero -f chart/values.dev.yaml
|
||
```
|
||
5. Check pod status:
|
||
```bash
|
||
kubectl get pods -n fusero
|
||
```
|
||
|
||
**This will make NGINX listen on port 8080 without SSL, which is standard for in-cluster Kubernetes services.**
|
||
|
||
---
|
||
|
||
## Connecting to the Database from Your Host (DBeaver, etc.)
|
||
|
||
To connect to the Postgres database running in Kubernetes from your local machine (for example, using DBeaver or another SQL client):
|
||
|
||
1. **Port-forward the Postgres service:**
|
||
```bash
|
||
kubectl port-forward svc/postgres-service 5432:5432
|
||
```
|
||
- Keep this terminal open while you use your database client.
|
||
- If port 5432 is in use on your machine, you can use another local port (e.g., `15432:5432`) and connect to port 15432 in your client.
|
||
|
||
2. **Database connection settings:**
|
||
- **Host:** `localhost`
|
||
- **Port:** `5432` (or your chosen local port)
|
||
- **Database:** `fusero-boilerplate-db`
|
||
- **Username:** `root`
|
||
- **Password:** `root123`
|
||
|
||
3. **Open DBeaver (or your preferred client) and create a new Postgres connection using the above settings.**
|
||
|
||
4. **Test the connection.**
|
||
|
||
---
|