# πŸ—ΊοΈ Ora Map - Family Location Mapping Application A full-stack web application for mapping and searching family locations in Yemen using interactive maps. ## πŸ“‹ Table of Contents - [Features](#features) - [Tech Stack](#tech-stack) - [Project Structure](#project-structure) - [Getting Started](#getting-started) - [Docker Deployment](#docker-deployment) - [Development](#development) - [API Endpoints](#api-endpoints) ## ✨ Features - πŸ” **Family Search**: Search for families by name with autocomplete suggestions - πŸ—ΊοΈ **Interactive Map**: Leaflet-based map with multiple tile layer options - πŸ“ **Location Markers**: View family locations with city information - βž• **Add Families**: Admin UI to add new family locations to the database - πŸ’Ύ **MongoDB Database**: Real database persistence with full CRUD operations - 🎨 **Modern UI**: Clean and responsive design with modal forms - 🐳 **Docker Ready**: Containerized for easy deployment - ☸️ **Kubernetes Ready**: Helm chart for production deployment - πŸ’š **Health Checks**: Built-in health monitoring ## πŸ› οΈ Tech Stack **Backend:** - Node.js 20 Alpine - Express.js 4.18 - MongoDB 7.0 - Mongoose ODM - CORS enabled **Frontend:** - HTML5/CSS3 - Vanilla JavaScript (ES6+) - Leaflet.js (interactive maps) - Fuse.js (fuzzy search) - Nginx (production server) **DevOps:** - Docker & Docker Compose - Kubernetes & Helm Charts - Woodpecker CI/CD - Harbor Registry ## πŸ“ Project Structure with MongoDB β”‚ β”œβ”€β”€ package.json # Backend dependencies β”‚ β”œβ”€β”€ Dockerfile # Backend container image β”‚ β”œβ”€β”€ config/ β”‚ β”‚ └── database.js # MongoDB connection β”‚ β”œβ”€β”€ models/ β”‚ β”‚ └── Family.js # Mongoose schema β”‚ └── scripts/ β”‚ └── seed.js # Database seeding script β”œβ”€β”€ frontend/ β”‚ β”œβ”€β”€ Dockerfile # Frontend Nginx container β”‚ β”œβ”€β”€ nginx.conf # Nginx configuration β”‚ └── public/ β”‚ β”œβ”€β”€ index.html # Frontend HTML with modal form β”‚ β”œβ”€β”€ script.js # Frontend JavaScript with CRUD β”‚ └── style.css # Styles including modal β”œβ”€β”€ oramap/ # Helm Chart β”‚ β”œβ”€β”€ Chart.yaml # Chart metadata (v0.3.0) β”‚ β”œβ”€β”€ values.yaml # Configuration values β”‚ β”œβ”€β”€ README.md # Helm documentation β”‚ └── templates/ β”‚ β”œβ”€β”€ deployment.yaml # Backend & Frontend deployments β”‚ β”œβ”€β”€ service.yaml # Services β”‚ β”œβ”€β”€ ingress.yaml # Ingress rules β”‚ β”œβ”€β”€ configmap.yaml # Nginx config β”‚ β”œβ”€β”€ mongodb-statefulset.yaml # MongoDB StatefulSet β”‚ └── mongodb-service.yaml # MongoDB service β”œβ”€β”€ old/ # Legacy files β”‚ β”œβ”€β”€ server.js β”‚ β”œβ”€β”€ package.json β”‚ └── data/families.json β”œβ”€β”€ Dockerfile # Monolith Docker build β”œβ”€β”€ docker-compose.yml # Monolith deployment β”œβ”€β”€ docker-compose.microservices.yml # Microservices with MongoDB β”‚ β”œβ”€β”€ script.js β”‚ └── style.css β”œβ”€β”€ Dockerfile # Monolith Docker build β”œβ”€β”€ docker-compose.yml # Monolith deployment β”œβ”€β”€ MongoDB**: Database for family locations (Port 27017) - **Backend**: Express API server with MongoDB integration (Internal Port 3000) - **Frontend**: Nginx serving static files with API proxy (Port 80) - Nginx proxies `/api/*` requests to backend - Best for: Production, scalability, CI/CD pipelines - Use: `docker-compose -f docker-compose.microservices.yml up` ### 3. **Kubernetes Mode** (Enterprise) - Helm chart deployment with StatefulSet for MongoDB - Persistent storage for database - Horizontal scaling for backend/frontend - Ingress with TLS support - See: `oramap/README.md` for Helm chart documentation ## πŸ—οΈ Architecture The application supports two deployment modes: ### 1. **Monolith Mode** (Simple) - Single container with Express serving both API and static files - Best for: Development, simple deployments - Use: `docker-compose up` ### 2. **Microservices Mode** (Production) - **Frontend**: Nginx serving static files (Port 80) - **Backend**: Express API server (Internal Port 3000) - Nginx proxies `/api/*` requests to backend - Best for: Production, scalability, CI/CD pipelines - Use: `docker-compose -f docker-compose.microservices.yml up` ## πŸš€ Getting Started ### Prerequisites - Node.js (v18 or higher) - Docker & Docker Compose (optional, for containerized deployment) ### Local Development 1. **Start MongoDB (optional - uses local instance if not running):** ```bash # Using Docker docker run -d -p 27017:27017 --name mongodb mongo:7.0 # Or install MongoDB locally ``` 2. **Install backend dependencies:** ```bash cd backend npm install ``` 3. **Seed initial data:** ```bash npm run seed ``` 4. **Start the server:** ```bash npm start # Or for development with auto-reload: npm run dev ``` 5. **Open your browser:** Navigate to `http://localhost:3000` ## 🐳 Docker Deployment ### Monolith Mode (Recommended for Development) 1. **Build and start:** ```bash docker-compose up -d ``` 2. **Access:** http://localhost:3000 3. **Stop:** ```bash docker-compose down ``` ### Microservices Mode (Recommended for Production) 1. **Build and start all services (Backend + Frontend + MongoDB):** ```bash docker-compose -f docker-compose.microservices.yml up -d ``` 2. **Seed the database:** ```bash docker exec -it oramap-backend npm run seed ``` 3. **Access:** http://localhost (Port 80) 4. **View logs:** ```bash docker logs oramap-frontend docker logs oramap-backend docker logs oramap-mongo ``` 5. **Stop:** ```bash docker-compose -f docker-compose.microservices.yml down # To remove volumes: docker-compose -f docker-compose.microservices.yml down -v ``` ### Using Docker directly **Monolith:** ```bash docker build -t oramap:latest . docker run -d -p 3000:3000 --name oramap-app oramap:latest ``` **Microservices:** ```bash # Build images docker build -t oramap-backend -f backend/Dockerfile backend/ docker build -t oramap-frontend -f frontend/Dockerfile frontend/ # Run with network docker network create oramap-network docker run -d --name oramap-backend --network oramap-network oramap-backend docker run -d --name oramap-frontend --network oramap-network -p 80:80 oramap-frontend ``` ## πŸ”„ CI/CD Pipeline The project includes a Woodpecker CI configuration (`.woodpecker.yaml`) that automatically: 1. **Builds** separate frontend and backend Docker images on push 2. **Tags** images with branch name and commit SHA 3. **Pushes** to Harbor registry (`harbor.dvirlabs.com`) 4. **Updates** Kubernetes manifests with new image tags 5. **Triggers** on changes to `frontend/**` or `backend/**` paths ### Pipeline Steps: - `build-frontend`: Build and push frontend Nginx image - `build-backend`: Build and push backend API image - `update-values-frontend`: Update frontend image tag in values.yaml - `update-values-backend`: Update backend image tag in values.yaml ## πŸ’» Development ### Running in Development Mode ```bash cd backend npm run dev ``` ### Database Management **Seed initial data:** ```bash npm run seed ``` **Force re-seed (clears existing data):** ```bash npm run seed:force ``` ### Adding New Families Use the web UI "Add Family" button, or make API calls: ```bash curl -X POST http://localhost:3000/api/families \ -H "Content-Type: application/json" \ -d '{ "family": "Family Name", "city": "City Name", "lat": 15.3545, "lng": 44.2064 }' ``` ## πŸ“‘ API Endpoints ### Get All Families ``` GET /api/families ``` Returns all families sorted by name. **Example:** ```bash curl http://localhost:3000/api/families ``` **Response:** ```json [ { "_id": "507f1f77bcf86cd799439011", "family": "ΧžΧ©Χ€Χ—Χͺ Χ›Χ€Χ”", "city": "צנגא", "lat": 15.3545, "lng": 44.2064, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z" } ] ``` ### Search Families ``` GET /api/search?family={familyName} ``` Returns matching family records using MongoDB text search. **Example:** ```bash curl "http://localhost:3000/api/search?family=Kafe" ``` ### Create Family ``` POST /api/families Content-Type: application/json ``` Creates a new family location. **Request Body:** ```json { "family": "ΧžΧ©Χ€Χ—Χͺ Χ“Χ•Χ“", "city": "Χ’Χ“ΧŸ", "lat": 12.7855, "lng": 45.0187 } ``` **Response:** ```json { "_id": "507f1f77bcf86cd799439011", "family": "ΧžΧ©Χ€Χ—Χͺ Χ“Χ•Χ“", "city": "Χ’Χ“ΧŸ", "lat": 12.7855, "lng": 45.0187, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z" } ``` ### Update Family ``` PUT /api/families/:id Content-Type: application/json ``` Updates an existing family. **Request Body:** ```json { "family": "ΧžΧ©Χ€Χ—Χͺ Χ›Χ”ΧŸ", "city": "צנגא", "lat": 15.3695, "lng": 44.1910 } ``` ### Delete Family ``` DELETE /api/families/:id ``` Deletes a family by ID. **Example:** ```bash curl -X DELETE http://localhost:3000/api/families/507f1f77bcf86cd799439011 ``` ### Health Check ``` GET /api/health ``` Returns server and database health status. **Response:** ```json { "status": "ok", "timestamp": "2024-01-01T00:00:00.000Z", "database": "connected" } ``` Returns server health status. **Example Response:** ```json { "status": "ok", "timestamp": "2026-03-24T10:30:00.000Z" } ``` ## πŸ—ΊοΈ Available Family Names - Kafe (קא׀ח) - Shiheb (Χ©Χ—Χ‘-Χ©Χ‘Χ—) - Uzeyri (Χ’Χ–Χ™Χ¨Χ™-Χ’Χ•Χ–Χ¨Χ™) - Salumi (Χ‘ΧœΧ•ΧžΧ™-Χ©ΧœΧ•ΧžΧ™) - Afgin (Χ’Χ€Χ’'Χ™ΧŸ) - Eraki (גראקי) ## πŸ“ License ISC ## 🀝 Contributing Contributions, issues, and feature requests are welcome!