Installation Guide
This guide provides detailed instructions for installing and configuring PaparcApp in both development and production environments.
Prerequisites
Before installing PaparcApp, ensure your system meets these requirements:
Required Software
npm Version : 9.x or higherIncluded with Node.js
System Requirements
Component Minimum Recommended RAM 2 GB 4 GB Storage 500 MB 1 GB CPU 1 core 2 cores OS Linux, macOS, Windows Linux (Ubuntu 20.04+)
Verify Prerequisites
Check that all required software is installed:
Node.js Version
npm Version
PostgreSQL Version
node --version
# Expected: v18.0.0 or higher
If any version is below the minimum requirement, please upgrade before proceeding.
Installation Steps
1. Clone the Repository
Clone the PaparcApp repository from GitHub:
git clone https://github.com/rafakata/PaparcApp.git
cd PaparcApp
The project structure:
PaparcApp/
├── proyecto/ # Main application directory
│ ├── app.js # Express configuration
│ ├── package.json # Dependencies and scripts
│ ├── .env.example # Environment template
│ ├── bin/www # HTTP server entry point
│ ├── config/
│ │ └── database.js # PostgreSQL connection pool
│ ├── controllers/ # Business logic
│ ├── database/ # SQL schema files
│ ├── middlewares/ # Authentication guards
│ ├── models/ # Data access objects (DAOs)
│ ├── routes/ # Express routers
│ ├── services/ # Pricing engine, notifications
│ ├── public/ # Static assets
│ ├── views/ # EJS templates
│ └── tests/ # Jest test suites
└── README.md
2. Install Dependencies
Navigate to the proyecto directory and install npm packages:
This installs all production and development dependencies:
View complete dependency list
Production Dependencies: Development Dependencies:
Create .env File
Copy the example template and customize it:
Environment Configuration Options
Local Development
Production (Neon.tech)
All Variables
# Server Configuration
PORT = 3000
NODE_ENV = development
# Session Secret (generate a secure random string)
SESSION_SECRET = your_32_character_random_string_here
# PostgreSQL Local Connection
DB_USER = postgres
DB_PASSWORD = your_postgres_password
DB_HOST = localhost
DB_PORT = 5432
DB_NAME = paparcapp_db
For local development, use the individual DB_* variables. The connection pool in config/database.js will use these.
# Server Configuration
PORT = 3000
NODE_ENV = production
# Session Secret (use a strong random string)
SESSION_SECRET = prod_32_character_random_string_here
# PostgreSQL Connection (Neon.tech)
DATABASE_URL = postgresql://user:[email protected] /database? sslmode = require
In production, the app uses DATABASE_URL with SSL enabled. The connection string includes all connection details.
Complete list of all environment variables: # Server
PORT = 3000 # HTTP port (default: 3000)
NODE_ENV = development # Environment: development | production
# Session
SESSION_SECRET = secret_key # Secure random string (min 32 chars)
# Database (Local)
DB_USER = postgres # PostgreSQL username
DB_PASSWORD = password # PostgreSQL password
DB_HOST = localhost # Database host
DB_PORT = 5432 # PostgreSQL port
DB_NAME = paparcapp_db # Database name
# Database (Production - Neon.tech)
DATABASE_URL = postgresql://... # Full connection string with SSL
# Optional: Email Notifications (n8n webhook)
N8N_WEBHOOK_URL = https://... # n8n webhook endpoint
Generate Secure SESSION_SECRET
Using Node.js crypto
Using OpenSSL
Using pwgen
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Security Best Practices:
Never commit .env to version control
Use different secrets for development and production
Rotate secrets periodically
Use at least 32 characters for SESSION_SECRET
4. Database Setup
Option A: Local PostgreSQL
Create Database
Connect to PostgreSQL and create the database: # Connect as postgres superuser
sudo -u postgres psql
-- Create database
CREATE DATABASE paparcapp_db ;
-- Create dedicated user (optional but recommended)
CREATE USER paparcapp_user WITH PASSWORD 'secure_password' ;
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE paparcapp_db TO paparcapp_user;
-- Exit
\q
Load Database Schema
Execute the SQL files in the correct order: # From the proyecto directory
psql -U postgres -d paparcapp_db -f database/01_tables.sql
psql -U postgres -d paparcapp_db -f database/02_constraints.sql
psql -U postgres -d paparcapp_db -f database/03_indexes.sql
psql -U postgres -d paparcapp_db -f database/04_initial_data.sql
Or combine into a single command: cat database/ * .sql | psql -U postgres -d paparcapp_db
Verify Setup
Check that all tables were created: psql -U postgres -d paparcapp_db -c "\dt"
Expected output (13 tables): Schema | Name | Type | Owner
--------+----------------------------------+-------+----------
public | additional_service | table | postgres
public | contract | table | postgres
public | contract_plan | table | postgres
public | customer | table | postgres
public | customer_vehicle | table | postgres
public | main_service | table | postgres
public | notification | table | postgres
public | photo_evidence | table | postgres
public | reservation | table | postgres
public | reservation_additional_service | table | postgres
public | service_rate | table | postgres
public | vehicle | table | postgres
public | vehicle_coefficient | table | postgres
Option B: Neon.tech (Cloud PostgreSQL)
Create Neon Account
Go to neon.tech
Sign up for a free account
Create a new project
Get Connection String
Copy the connection string from the Neon dashboard: Add this to your .env file as DATABASE_URL.
Load Schema via psql
# Set connection string
export DATABASE_URL = "postgresql://..."
# Load schema
psql $DATABASE_URL -f database/01_tables.sql
psql $DATABASE_URL -f database/02_constraints.sql
psql $DATABASE_URL -f database/03_indexes.sql
psql $DATABASE_URL -f database/04_initial_data.sql
Database Schema Files
Understanding what each SQL file does:
01_tables.sql - Table Creation
Creates all 13 tables with primary keys:
customer - System users (ADMIN, REGISTRADO, NO-REGISTRADO)
vehicle - Vehicle registry with unique license plates
customer_vehicle - N:M relationship (virtual garage)
vehicle_coefficient - Pricing multipliers by vehicle type
main_service - Three service tiers (ECO, TRANSFER, MEET)
service_rate - Pricing by day ranges for each service
additional_service - Extra services catalog (washes, ITV, etc.)
reservation - Booking records with lifecycle states
reservation_additional_service - N:M for extras per booking
photo_evidence - Vehicle condition photos
notification - Email log
contract_plan - Subscription plans
contract - Active subscriptions
CREATE TABLE vehicle (
id_vehicle SERIAL PRIMARY KEY ,
license_plate VARCHAR ( 15 ) NOT NULL UNIQUE ,
brand VARCHAR ( 50 ) NOT NULL ,
model VARCHAR ( 50 ) NOT NULL ,
color VARCHAR ( 30 ) NOT NULL ,
type VARCHAR ( 30 ) NOT NULL ,
registration_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
02_constraints.sql - Business Rules
Adds foreign keys and CHECK constraints to enforce business logic:
Reservation status: only PENDIENTE, EN CURSO, FINALIZADA, CANCELADA
Payment method: only TARJETA, EFECTIVO, or NULL
Parking spot required for IN PROGRESS and COMPLETED states
Exit date must be after entry date
Price must be non-negative
Email and phone validation patterns
Vehicle multiplier must be positive
Example: reservation constraints
ALTER TABLE reservation ADD CONSTRAINT check_status
CHECK ( status IN ( 'PENDIENTE' , 'EN CURSO' , 'FINALIZADA' , 'CANCELADA' ));
ALTER TABLE reservation ADD CONSTRAINT check_exit_after_entry
CHECK (exit_date > entry_date);
ALTER TABLE reservation ADD CONSTRAINT check_price_non_negative
CHECK (total_price >= 0 );
03_indexes.sql - Performance Optimization
04_initial_data.sql - Seed Data
Loads essential configuration and test data: Master Configuration:
5 vehicle coefficients (TURISMO ×1.0, MOTOCICLETA ×0.5, etc.)
3 main services (ECO, TRANSFER, MEET) with descriptions
12 service rate tiers (4 day ranges × 3 services)
3 subscription plans (Quarterly, Semiannual, Annual)
Additional services catalog (washes, ITV, charging, etc.)
Test Data:
Sample customers (including admin users)
Test vehicles
Sample reservations in different states
Photo evidence examples
Notification logs
Example: pricing configuration
INSERT INTO vehicle_coefficient (vehicle_type, multiplier) VALUES
( 'TURISMO' , 1 . 00 ),
( 'MOTOCICLETA' , 0 . 50 ),
( 'FURGONETA' , 1 . 25 ),
( 'CARAVANA' , 2 . 00 ),
( 'ESPECIAL' , 1 . 50 );
INSERT INTO service_rate (id_main_service, min_days, max_days, daily_price) VALUES
( 1 , 1 , 3 , 12 . 00 ), -- ECO: 1-3 days = €12/day
( 1 , 4 , 10 , 8 . 00 ), -- ECO: 4-10 days = €8/day
( 1 , 11 , 15 , 6 . 00 ), -- ECO: 11-15 days = €6/day
( 1 , 16 , 9999 , 5 . 00 ); -- ECO: 16+ days = €5/day
5. Start the Application
Development Mode
Production Mode
Testing
Start with Nodemon for auto-restart on file changes: Expected output: [nodemon] 3.1.11
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,ejs
[nodemon] starting `node ./bin/www`
✓ Database connection pool initialized
✓ Pricing cache initialized successfully
Server listening on http://localhost:3000
Nodemon watches for file changes and automatically restarts the server. Perfect for development.
Start with standard Node.js (no auto-restart): For production deployment with process management: # Using PM2
npm install -g pm2
pm2 start bin/www --name paparcapp
pm2 save
pm2 startup
In production:
Set NODE_ENV=production in .env
Use HTTPS (cookies have secure flag)
Enable trust proxy in Express (already configured)
Use a process manager like PM2
Run the Jest test suite: Expected output: PASS tests/pricingService.test.js
Pricing Service
✓ calculates price for same-day booking (1 day minimum) (5ms)
✓ applies correct tier for multi-day stay (3ms)
✓ multiplies by vehicle coefficient (caravana ×2) (2ms)
✓ adds additional services to total (3ms)
✓ throws error for invalid vehicle type (2ms)
✓ respects 2-hour courtesy period (no extra day) (3ms)
✓ charges extra day after courtesy period (2ms)
Test Suites: 1 passed, 1 total
Tests: 7 passed, 7 total
Time: 1.234s
Post-Installation
Create Admin User
If the initial data script didn’t create an admin user, create one manually:
-- Generate password hash first
-- In Node.js console: require('bcrypt').hash('your_password', 10, console.log)
INSERT INTO customer (
full_name,
email,
phone,
password_hash,
type ,
is_active
) VALUES (
'Admin User' ,
'[email protected] ' ,
'+34600000001' ,
'$2b$10$YourBcryptHashHere' , -- Replace with actual hash
'ADMIN' ,
true
);
Generate bcrypt hash for password
// Create a script: hash-password.js
const bcrypt = require ( 'bcrypt' );
const password = process . argv [ 2 ] || 'admin123' ;
bcrypt . hash ( password , 10 , ( err , hash ) => {
if ( err ) throw err ;
console . log ( 'Password:' , password );
console . log ( 'Hash:' , hash );
});
// Run it:
// node hash-password.js your_password
For social login (Google/Facebook), set up Firebase:
Enable Providers
In Authentication > Sign-in method:
Enable Google
Enable Facebook (requires Facebook App ID)
Get Config
From Project Settings > General, copy the Firebase config: const firebaseConfig = {
apiKey: "AIza..." ,
authDomain: "paparcapp.firebaseapp.com" ,
projectId: "paparcapp" ,
storageBucket: "paparcapp.appspot.com" ,
messagingSenderId: "123456789" ,
appId: "1:123456789:web:abc123"
};
Update Client Config
Add the config to public/javascripts/firebase-config.js
For automated emails via n8n:
Create Workflow
Import the notification workflow (check services/templates/ for email templates)
Get Webhook URL
Copy the webhook URL from n8n
Update .env
N8N_WEBHOOK_URL = https://your-n8n-instance.com/webhook/...
Deployment Options
Deploy to Render
Create Web Service
Connect your GitHub repository
Select the proyecto directory
Set build command: npm install
Set start command: npm start
Configure Environment
Add environment variables in Render dashboard:
NODE_ENV=production
DATABASE_URL (from Neon.tech)
SESSION_SECRET
PORT=3000
Deploy
Render will automatically build and deploy
Deploy to Heroku
# Install Heroku CLI
curl https://cli-assets.heroku.com/install.sh | sh
# Login
heroku login
# Create app
cd proyecto
heroku create paparcapp
# Add PostgreSQL
heroku addons:create heroku-postgresql:mini
# Set environment variables
heroku config:set NODE_ENV=production
heroku config:set SESSION_SECRET=your_secret
# Deploy
git push heroku main
# Open app
heroku open
Deploy with Docker
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application
COPY . .
# Expose port
EXPOSE 3000
# Start server
CMD [ "npm" , "start" ]
version : '3.8'
services :
app :
build : .
ports :
- "3000:3000"
environment :
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/paparcapp
- SESSION_SECRET=your_secret
depends_on :
- db
db :
image : postgres:16-alpine
environment :
- POSTGRES_DB=paparcapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes :
- pgdata:/var/lib/postgresql/data
- ./database:/docker-entrypoint-initdb.d
volumes :
pgdata :
# Build and run
docker-compose up -d
Troubleshooting
Cannot connect to database
Symptoms: Error: connect ECONNREFUSED 127.0.0.1:5432
Solutions:
Check PostgreSQL is running:
# Linux
sudo systemctl status postgresql
# macOS
brew services list
# Windows
sc query postgresql
Verify connection settings in .env
Test direct connection:
psql -U postgres -d paparcapp_db -c "SELECT 1;"
Check PostgreSQL logs:
# Linux
sudo tail -f /var/log/postgresql/postgresql- * .log
# macOS
tail -f /usr/local/var/log/postgres.log
Pricing cache initialization failed
Symptoms: Error initializing pricing cache
Process exited with code 1
Solutions:
Ensure initial data was loaded:
psql -U postgres -d paparcapp_db -c "SELECT COUNT(*) FROM vehicle_coefficient;"
# Should return 5
Check service rates exist:
psql -U postgres -d paparcapp_db -c "SELECT COUNT(*) FROM service_rate;"
# Should return 12
Re-run initial data script:
psql -U postgres -d paparcapp_db -f database/04_initial_data.sql
Check database connection works before starting app
Session not working / Can't login
Symptoms:
Login succeeds but immediately logs out
Session data not persisting
“Unauthorized” errors
Solutions:
Check SESSION_SECRET is set in .env
Clear browser cookies and cache
Verify express-session is installed:
In production, ensure HTTPS is enabled (session cookies require secure flag)
Check trust proxy setting in app.js (required for Render/Heroku)
Symptoms: Error: listen EADDRINUSE: address already in use :::3000
Solutions:
Change port in .env:
Kill the process using port 3000:
# Linux/macOS
lsof -ti:3000 | xargs kill -9
# Windows
netstat -ano | findstr :3000
taskkill /PID < PI D > /F
Or run with custom port temporarily:
bcrypt compilation errors
Symptoms: Error: node-pre-gyp install --fallback-to-build
Solutions:
Install build tools:
# Linux
sudo apt-get install build-essential
# macOS
xcode-select --install
# Windows
npm install --global windows-build-tools
Rebuild bcrypt:
Or use pre-built binaries:
npm uninstall bcrypt
npm install bcrypt --build-from-source
Security Checklist
Before deploying to production:
Next Steps
Architecture Guide Learn about the MVC pattern, service layers, and data flow
API Reference Explore REST endpoints for pricing and reservations
Database Schema Detailed documentation of all 13 tables and relationships
Quickstart Get started quickly with PaparcApp