A full-featured hotel booking web application built with Flask, PostgreSQL, and Tailwind CSS. QuickStay allows users to browse rooms, make bookings, manage profiles, and provides an admin dashboard for hotel management.
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Getting Started
- Environment Variables
- Database Setup
- CI/CD Pipeline
- Deployment
- Screenshots
- Contributing
- License
- 🔐 Authentication — Register, Login, Logout with session management
- 🔑 Password Recovery — OTP-based password reset via email (Flask-Mail)
- 👤 Profile Management — View, edit profile, change password, delete account
- 📥 Data Export — Download personal data as JSON (privacy compliance)
- 🌙 Dark/Light Mode — Toggle between themes
- 📱 Fully Responsive — Works on desktop, tablet, and mobile
- 🛡️ CSRF Protection — All forms protected with Flask-WTF
- 🔒 Password Hashing — Werkzeug security with salted hashes
- 🚫 Account Deactivation — Soft delete with password confirmation
- ⏱️ OTP Expiry — Time-limited OTP codes (10 minutes)
- 📊 Admin Dashboard — Manage users, rooms, and bookings
- 👥 User Management — View, block/unblock users
- 🐳 Docker — Multi-stage Dockerfile with Docker Compose
- 🔄 Jenkins Pipeline — Automated CI/CD with auto-deploy
- 🔍 SonarQube — Code quality analysis
- 🛡️ Trivy — Container security scanning
- 🔎 OWASP — Dependency vulnerability check
- 🗄️ Auto Migrations — Database migrations on container startup
| Layer | Technology |
|---|---|
| Backend | Flask 3.1 (Python 3.11) |
| Database | PostgreSQL 15 |
| ORM | SQLAlchemy + Flask-Migrate (Alembic) |
| Frontend | Tailwind CSS + Jinja2 Templates |
| Icons | Lucide Icons |
| Auth | Flask-Login + Flask-WTF (CSRF) |
| Flask-Mail (SMTP/Gmail) | |
| Containerization | Docker + Docker Compose |
| CI/CD | Jenkins Pipeline |
| Security Scanning | SonarQube, Trivy, OWASP Dependency-Check |
QuickStay/
│
├── app/
│ ├── init.py # App factory
│ ├── config.py # Configuration (dev/prod/test)
│ ├── utils.py # Helper functions
│ ├── extensions.py # Flask extensions initialization
│ │
│ ├── models/ # Database models
│ │ ├── init.py
│ │ ├── user.py # User model
│ │ ├── room.py # Room model
│ │ ├── booking.py # Booking model
│ │ └── review.py # Review model
│ │
│ ├── controllers/ # Route handlers (Blueprints)
│ │ ├── init.py
│ │ ├── auth_controller.py # Auth routes (login, register, etc.)
│ │ ├── main_controller.py # Public pages (home, about, etc.)
│ │ ├── booking_controller.py # Booking routes
│ │ ├── profile_controller.py # Profile management routes
│ │ └── admin/
│ │ ├── init.py
│ │ └── dashboard_controller.py # Admin dashboard
│ │
│ ├── templates/ # Jinja2 HTML templates
│ │ ├── base.html # Base layout
│ │ ├── auth/ # Auth pages
│ │ │ ├── login.html
│ │ │ ├── register.html
│ │ │ └── forgot-password.html
│ │ ├── main/ # Public pages
│ │ │ ├── home.html
│ │ │ ├── rooms.html
│ │ │ ├── about.html
│ │ │ ├── contact.html
│ │ │ └── faq.html
│ │ ├── profile/ # Profile pages
│ │ │ ├── view.html
│ │ │ ├── edit.html
│ │ │ └── change_password.html
│ │ ├── admin/ # Admin pages
│ │ └── extra/ # Error & legal pages
│ │ │ ├── 404.html
│ │ │ ├── 500.html
│ │ │ ├── privacy.html
│ │ │ └── terms.html
│ │
│ └── static/ # Static assets
│ ├── css/
│ ├── js/
│ └── images/
│
├── migrations/ # Database migrations (Alembic)
├── .env # Environment variables (dev)
├── .env.production # Environment variables (prod)
├── .dockerignore
├── .gitignore
├── deploy.sh # Deployment script
├── docker-compose.yml # Docker services
├── Dockerfile # Multi-stage Docker build
├── entrypoint.sh # Container startup script
├── Jenkinsfile # CI/CD pipeline
├── requirements.txt # Python dependencies
└── run.py # Application entry point
- Docker (v20+)
- Docker Compose (v2+)
- Git
- Python 3.11+
- PostgreSQL 15+
- Git
- pip (Python package manager)
- Jenkins (with Docker)
- SonarQube Server
- Trivy (installed on Jenkins server)
- OWASP Dependency-Check (Jenkins plugin)
Step 1: Clone the repository
git clone https://github.com/mananurrehman/quickstay.git
cd quickstayStep 2: Create environment file
cp .env.example .env.production
Edit .env.production with your values:
# Flask
SECRET_KEY=your-super-secret-key-change-this
FLASK_ENV=production
# Database
DATABASE_URL=postgresql://quickstay_user:quickstay123@db:5432/quickstay
# Email (Gmail SMTP)
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-gmail-app-password
MAIL_DEFAULT_SENDER=your-email@gmail.com
Step 3: Create required directories
sudo mkdir -p /home/ubuntu/quickstay-data/postgres
sudo mkdir -p /home/ubuntu/quickstay-data/uploads
Step 4: Build and run
docker compose up -d --build
Step 5: Verify
# Check containers are running
docker compose ps
# Check logs
docker compose logs -f web
Step 6: Access the application
http://localhost:5000
Step 1: Clone the repository
git clone https://github.com/mananurrehman/quickstay.git
cd quickstay
Step 2: Create Virtual Environment
# Create virtual environment
python -m venv venv
# Activate it
# On Linux/Mac:
source venv/bin/activate
# On Windows:
venv\Scripts\activate
Step 3: Install dependencies
pip install -r requirements.txt
Step 4: Create environment file
cp .env.example .env
Edit .env with your values:
# Flask
SECRET_KEY=your-secret-key
FLASK_ENV=development
FLASK_DEBUG=True
# Database
DATABASE_URL=postgresql://username:password@localhost:5432/quickstay
# Email (Gmail SMTP)
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-gmail-app-password
MAIL_DEFAULT_SENDER=your-email@gmail.com
Step 5: Setup PostgreSQL database
# Login to PostgreSQL
psql -U postgres
# Create database and user
CREATE DATABASE quickstay;
CREATE USER quickstay_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE quickstay TO quickstay_user;
\q
Step 6: Run database migrations
# Initialize migrations (first time only)
flask db init
# Generate migration files
flask db migrate -m "Initial migration"
# Apply migrations
flask db upgrade
Step 7: Run the application
python run.py
Step 8: Access the application
http://localhost:5000
| Variable | Description | Required | Default |
|---|---|---|---|
| SECRET_KEY | Flask secret key for sessions | ✅ | None |
| FLASK_ENV | Environment (development/production) | ✅ | development |
| FLASK_DEBUG | Debug mode (True/False) | ❌ | False |
| DATABASE_URL | PostgreSQL connection string | ✅ | None |
| MAIL_SERVER | SMTP server address | ✅ | smtp.gmail.com |
| MAIL_PORT | SMTP port | ✅ | 587 |
| MAIL_USE_TLS | Enable TLS | ✅ | True |
| MAIL_USERNAME | SMTP email address | ✅ | None |
| MAIL_PASSWORD | SMTP password/app password | ✅ | None |
| MAIL_DEFAULT_SENDER | Default sender email | ✅ | None |
- Go to Google Account Security
- Enable 2-Step Verification
- Go to App Passwords
- Select app: Mail, device: Other (enter "QuickStay")
- Copy the 16-character password
- Use this as MAIL_PASSWORD in your
.env
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Users │────→│ Bookings │←────│ Rooms │
│ │ │ │ │ │
│ id │ │ id │ │ id │
│ username │ │ user_id │ │ name │
│ email │ │ room_id │ │ type │
│ password │ │ check_in │ │ price │
│ role │ │ check_out│ │ status │
└──────────┘ └──────────┘ └──────────┘
│ │
│ ┌──────────┐ │
└─────────→│ Reviews │←──────────┘
│ │
│ id │
│ user_id │
│ room_id │
│ rating │
│ comment │
└──────────┘
# Generate new migration after model changes
flask db migrate -m "Description of changes"
# Apply migrations
flask db upgrade
# Rollback last migration
flask db downgrade
# View migration history
flask db history
GitHub Push
↓
Jenkins (Poll SCM - every 5 mins)
↓
┌─────────────────────────────────────┐
│ Stage 1: Clone Repository │
│ Stage 2: SonarQube Analysis │
│ Stage 3: Trivy Security Scan │
│ Stage 4: OWASP Dependency Check │
│ Stage 5: Deploy to Staging │
│ Stage 6: Verify Deployment │
└─────────────────────────────────────┘
↓
✅ App Live on Staging Server
| Tool | Purpose |
|---|---|
| SSH Agent Plugin | SSH into staging server |
| SonarQube Scanner | Code quality analysis |
| OWASP Dependency-Check | Vulnerability scanning |
| GitHub Integration | Repository integration |
| Credential ID | Type | Purpose |
|---|---|---|
| oracle-vm-ssh-testuser | SSH Key | Access to staging server |
| SonarQube Token | Secret Text | SonarQube authentication |
The pipeline uses Poll SCM to check for new commits:
Schedule: H/5 * * * * (every 5 minutes)
docker compose up -d --build
↓
┌─────────────────────────────┐
│ PostgreSQL Container │
│ - Health check passes │
│ - Database ready │
└──────────────┬──────────────┘
↓
┌─────────────────────────────┐
│ Flask App Container │
│ 1. Wait for database │
│ 2. Run migrations │
│ 3. Start Flask server │
└─────────────────────────────┘
↓
App live on port 5000
# Start all services
docker compose up -d --build
# Stop all services
docker compose down
# View running containers
docker compose ps
# View logs (live)
docker compose logs -f web
# View database logs
docker compose logs -f db
# Restart app only
docker compose restart web
# Rebuild app only
docker compose up -d --build web
# Enter app container
docker exec -it quickstay-web bash
# Enter database container
docker exec -it quickstay-db psql -U quickstay_user -d quickstay
☐ Set strong SECRET_KEY (use: python -c "import secrets; print(secrets.token_hex(32))")
☐ Set FLASK_ENV=production
☐ Set FLASK_DEBUG=False
☐ Configure real SMTP credentials
☐ Use strong database password
☐ Create data directories for volumes
☐ Setup firewall (allow only ports 5000, 22)
☐ Configure SSL/HTTPS (recommended)
☐ Setup regular database backups
- Fork the repository
- Create your feature branch
git checkout -b feature/amazing-feature
- Commit your changes
git commit -m "Add amazing feature"
- Push to the branch
git push origin feature/amazing-feature
- Open a Pull Request
- Follow MVC architecture with Flask Blueprints
- Use Tailwind CSS for styling (match existing design patterns)
- Support dark mode in all templates
- Add CSRF protection on all forms
- Write responsive templates (mobile-first)
- Use Lucide icons consistently
- GitHub: @mananurrehman
- LinkedIn: @mananurrehman







