diff --git a/.gitignore b/.gitignore index a547bf3..105a9cf 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ node_modules dist dist-ssr *.local - +server/.env # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/README.md b/README.md index a36934d..ad437cf 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,207 @@ -# React + Vite +# Brew Application -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +Welcome to the **Brew** application! This project features a React + Vite frontend and a Node.js Express + PostgreSQL backend. -Currently, two official plugins are available: +## Architecture Overview -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) +The codebase is split into two main sections: +- **Frontend**: A React application located in the root directory, built with [Vite](https://vite.dev/). Key files include: + - [package.json](file:///home/sortedcord/Projects/brew/package.json) (dependencies and scripts) + - [src/App.jsx](file:///home/sortedcord/Projects/brew/src/App.jsx) (routing and layout) + - [src/AuthContext.jsx](file:///home/sortedcord/Projects/brew/src/AuthContext.jsx) (authentication state and backend communication) +- **Backend**: An Express application located in the [server/](file:///home/sortedcord/Projects/brew/server/) directory. Key files include: + - [server/package.json](file:///home/sortedcord/Projects/brew/server/package.json) (backend dependencies and scripts) + - [server/index.js](file:///home/sortedcord/Projects/brew/server/index.js) (Express application setup, routes, and authentication middleware) + - [server/db.js](file:///home/sortedcord/Projects/brew/server/db.js) (PostgreSQL connection and table initialization) -## React Compiler +--- -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). +## Prerequisites -## Expanding the ESLint configuration +Make sure you have the following installed on your system: +- **Node.js** (v18.x or higher recommended) +- **npm** (v9.x or higher) +- **PostgreSQL** (v14 or higher) -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. +--- + +## 1. Database Setup (PostgreSQL) + +You need a running PostgreSQL database instance. Follow the steps below based on your operating system: + +### Installing PostgreSQL + +#### Linux (Debian/Ubuntu) +```bash +sudo apt update +sudo apt install postgresql postgresql-contrib +``` +The PostgreSQL service should start automatically. If not, start it with: +```bash +sudo systemctl start postgresql +sudo systemctl enable postgresql +``` + +#### macOS (using Homebrew) +```bash +brew install postgresql +brew services start postgresql +``` + +#### Windows +Download and run the interactive installer from the [Official PostgreSQL Downloads page](https://www.postgresql.org/download/windows/). + +--- + +### Creating the Database and User + +1. Log into the PostgreSQL interactive terminal as the superuser `postgres`: + ```bash + sudo -i -u postgres psql + ``` + *(On macOS/Windows, open your terminal/command prompt and run `psql postgres` or use a graphical tool like PgAdmin).* + +2. Create a new database named `brew`: + ```sql + CREATE DATABASE brew; + ``` + +3. Create a database user with a secure password: + ```sql + CREATE USER brew_user WITH PASSWORD 'your_secure_password'; + ``` + +4. Grant all privileges on the database to your new user: + ```sql + GRANT ALL PRIVILEGES ON DATABASE brew TO brew_user; + ``` + +5. (For PostgreSQL 15+) Connect to the database and grant schema permissions: + ```sql + \c brew + GRANT ALL ON SCHEMA public TO brew_user; + ``` + +6. Exit the PostgreSQL shell: + ```sql + \q + ``` + +> [!NOTE] +> Database tables (such as `users`) are initialized automatically when you start the backend server, as defined in [server/db.js](file:///home/sortedcord/Projects/brew/server/db.js). + +--- + +## 2. Backend Setup + +1. Navigate to the backend directory: + ```bash + cd server + ``` + +2. Create a [server/.env](file:///home/sortedcord/Projects/brew/server/.env) file by copying the template [server/.env.example](file:///home/sortedcord/Projects/brew/server/.env.example): + ```bash + cp .env.example .env + ``` + +3. Open [server/.env](file:///home/sortedcord/Projects/brew/server/.env) and configure the environment variables: + ```env + PORT=5000 + DATABASE_URL=postgresql://brew_user:your_secure_password@localhost:5432/brew + JWT_SECRET=your_jwt_secret_here + ``` + *Replace `your_secure_password` with the password you set during the database setup.* + +4. Install dependencies and start the backend server: + ```bash + npm install + npm start + ``` + The backend should start and display: + ```text + Database initialized + Server running on port 5000 + ``` + +--- + +## 3. Frontend Setup + +1. Open a new terminal window/tab and navigate to the project root directory: + ```bash + cd /home/sortedcord/Projects/brew + ``` + +2. Install frontend dependencies: + ```bash + npm install + ``` + +3. Start the Vite development server: + ```bash + npm run dev + ``` + +4. Open your browser and navigate to the local URL printed in the console (usually `http://localhost:5173`). + +--- + +## Production Deployment + +When deploying the Brew application to a production environment, follow these guidelines for security, reliability, and performance: + +### 1. Database (PostgreSQL) +- **Restricted Access**: Do not use superuser accounts (such as `postgres`) for backend application connections. Instead, use a restricted role with standard read/write permissions. +- **Managed Databases**: Use a managed database service (e.g., Supabase, Neon, AWS RDS, GCP Cloud SQL) to leverage automated backups, scaling, and high-availability. +- **SSL Connection**: Enforce encrypted database connections by appending SSL options to the connection string (e.g., `?sslmode=require`). + +### 2. Backend Server Setup +- **Environment Variables**: In your production environment, set the following environment variables: + - `NODE_ENV=production` + - `PORT=8080` (or whichever port is provided by your host) + - `DATABASE_URL=postgresql://:@:/?sslmode=require` + - `JWT_SECRET=your_long_random_production_secret` (generate a secure 32-byte key using `openssl rand -base64 32`) +- **Process Management**: Use a process manager like **PM2** to run the backend node process, keep it alive, and handle automatic clustering or restarts: + ```bash + # Install PM2 globally + npm install -g pm2 + + # Start the backend server + pm2 start server/index.js --name "brew-backend" + ``` +- **Restrict CORS**: In [server/index.js](file:///home/sortedcord/Projects/brew/server/index.js), configure the `cors` middleware to only accept requests from your frontend production domain: + ```javascript + app.use(cors({ origin: 'https://yourfrontenddomain.com' })); + ``` + +### 3. Frontend Build & Hosting +- **Build the static bundle**: Run the build script in the root directory to generate optimized production assets: + ```bash + npm run build + ``` + This generates static HTML, CSS, and JS files in the `dist/` directory. +- **Hosting**: + - Deploy the static files from the `dist/` directory to static hosting platforms like **Vercel**, **Netlify**, **Cloudflare Pages**, or **AWS S3/CloudFront**. + - Alternatively, if using a VPS, serve the `dist/` directory using **Nginx** and proxy API traffic: + ```nginx + server { + listen 80; + server_name yourfrontenddomain.com; + + # Serve static frontend + location / { + root /var/www/brew/dist; + try_files $uri $uri/ /index.html; + } + + # Proxy API requests to backend server + location /api/ { + proxy_pass http://localhost:5000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + } + ``` diff --git a/server/index.js b/server/index.js index df10aa8..e463e87 100644 --- a/server/index.js +++ b/server/index.js @@ -1,3 +1,10 @@ +if (process.stdout._handle && typeof process.stdout._handle.setBlocking === 'function') { + process.stdout._handle.setBlocking(true); +} +if (process.stderr._handle && typeof process.stderr._handle.setBlocking === 'function') { + process.stderr._handle.setBlocking(true); +} + const express = require('express'); const cors = require('cors'); const bcrypt = require('bcrypt'); @@ -11,6 +18,17 @@ const PORT = process.env.PORT || 5000; app.use(cors()); app.use(express.json()); +// Request logger middleware +app.use((req, res, next) => { + console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`); + if (req.body && Object.keys(req.body).length > 0) { + const logBody = { ...req.body }; + if (logBody.password) logBody.password = '[REDACTED]'; + console.log(' Body:', JSON.stringify(logBody)); + } + next(); +}); + // Middleware to verify JWT token const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization'];