17 KiB
Looking - PfosiLooking Monorepo
An art project exploring modern gay dating culture through interactive storytelling
"Looking" is a documentary photography and art project by Nick Pfosi that examines the cultural landscape of gay dating apps like Grindr and modern LGBTQ+ meeting spaces. The project captures user stories, experiences, and narratives about contemporary gay dating culture through an interactive mobile application.
📋 Table of Contents
- Project Overview
- Tech Stack
- Prerequisites
- Quick Start
- Project Structure
- Available Scripts
- Data Management
- Documentation Links
- Troubleshooting
- Technical Debt & Security
- Future Modernization Path
🎨 Project Overview
This monorepo contains the full-stack "Looking" application:
- Frontend: Ionic 3 / Angular 5 mobile application for browsing profiles and stories
- Backend: Express.js REST API with MongoDB for data management
- DevContainer: Complete Docker-based development environment
The name "Urnings" (seen in code) references a historical term for homosexual men, adding a scholarly dimension to the project's exploration of queer identity and dating culture.
🛠 Tech Stack
Frontend (app/)
- Framework: Ionic 3.9.2 with Angular 5.0.3
- Language: TypeScript 2.4.2
- Build Tool:
@ionic/app-scripts3.2.4 - UI Components: Ionic Angular, Ionicons
- HTTP: Angular HTTP module with RxJS 5.5.2
- Dev Server: Port 8100
Backend (backend/)
- Framework: Express 4.14.0
- Runtime: Node.js 14.x
- Database: MongoDB 4.4
- ODM: Mongoose 4.7.4
- Authentication: JWT (jsonwebtoken 7.3.0)
- Security: PBKDF2 password hashing (233,335 iterations)
- Image Processing: Multer 1.2.0
- Logging: Winston 2.4.0, Morgan 1.7.0
- Email: Nodemailer 4.0.1
- API Server: Port 3069
DevOps
- DevContainer: Node 14 (Debian Bullseye)
- Database: MongoDB 4.4
- Database Admin: Mongo Express (port 8081)
- Production: Docker Compose + Traefik + Let's Encrypt SSL
✅ Prerequisites
Before you begin, ensure you have:
- Docker Desktop (latest version) - Download here
- Visual Studio Code (latest version) - Download here
- VS Code Remote - Containers extension - Install from marketplace
- Git (for cloning the repository)
Note
: You do NOT need Node.js, npm, or MongoDB installed locally. The DevContainer provides everything.
🚀 Quick Start
Using DevContainer (Recommended)
-
Clone the repository:
git clone <repository-url> cd PfosiLooking-monorepo -
Open in VS Code:
code . -
Reopen in Container:
- VS Code should prompt: "Reopen in Container"
- Or manually: Press
F1→ "Dev Containers: Reopen in Container"
-
Wait for setup (first time only - 5-10 minutes):
- Container builds with Node 14 + Python 2.7
- Dependencies install automatically via
postCreateCommand.sh - MongoDB starts and initializes
-
Start development servers:
npm run dev:all -
Access the application:
- Frontend: http://localhost:8100
- Backend API: http://localhost:3069
- MongoDB: localhost:27017
- Mongo Express: http://localhost:8081 (admin/password)
📁 Project Structure
PfosiLooking-monorepo/
├── app/ # Ionic 3 / Angular 5 frontend
│ ├── src/
│ │ ├── app/ # App module and root component
│ │ ├── pages/ # Page components (grid, chat, profile, etc.)
│ │ ├── services/ # Data services (ProfileService)
│ │ └── assets/ # Static assets, images, data
│ └── package.json # Frontend dependencies
│
├── backend/ # Express.js API
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ ├── models/ # Mongoose schemas
│ │ ├── modules/ # Utilities (auth, images, mailer, etc.)
│ │ └── bin/www # Server startup script
│ ├── data/ # Seed data (profiles.json)
│ └── package.json # Backend dependencies
│
├── .devcontainer/ # Development container configuration
│ ├── devcontainer.json # VS Code DevContainer config
│ ├── docker-compose.yml # Dev services (app, mongo, mongo-express)
│ ├── Dockerfile # Custom dev image (Node 14 + Python 2.7)
│ └── postCreateCommand.sh # Auto-install dependencies
│
├── docker-compose.yml # Production deployment configuration
├── package.json # Root workspace configuration
└── README.md # This file
📜 Available Scripts
Development
# Start both frontend and backend concurrently
npm run dev:all
# Start only backend (port 3069)
npm run dev:backend
# Start only frontend (port 8100)
npm run dev:app
Installation
# Install all dependencies (root + workspaces)
npm run install:all
# Install workspace dependencies only
npm run install:workspaces
Database
# Seed MongoDB with initial data from backend/data/profiles.json
npm run seed
# Access MongoDB shell
npm run mongo:shell
Build & Deploy
# Build both frontend and backend
npm run build
# Build Docker images for production
npm run docker:build
# Deploy to production (docker-compose up)
npm run deploy
Testing & Quality
# Run all tests (backend + frontend)
npm test
# Run backend tests only (Mocha/Chai)
npm run test:backend
# Run frontend tests only
npm run test:app
# Lint all code
npm run lint
💾 Data Management
⚠️ Important: No Interactive Data Entry
This application currently does NOT support adding or editing data through the UI. All profile and message data is seeded from static JSON files.
How to Add/Edit Content
-
Edit the seed data file:
backend/data/profiles.json -
Re-seed the database:
npm run seed -
For production deployments: The database is wiped and reseeded on each deployment, so all changes must be committed to
profiles.jsonbefore deploying.
Data Structure
Profiles are stored in backend/data/profiles.json with this structure:
{
"order": 1,
"details": {
"name": "John",
"age": 28,
"location": "San Francisco, CA",
"about": "User's story...",
"pic": {
"thumb": "profile/john_thumbnail.png",
"detail": "profile/john_detail.png"
}
},
"messages": [
{
"text": "What's your story?",
"isUser": false
},
{
"text": "I've been using dating apps for...",
"isUser": true
}
],
"submitted": true,
"approved": true
}
📚 Documentation Links
- App Documentation - Frontend architecture, pages, and services
- Backend Documentation - API server, routes, and models
- API Reference - Complete REST API endpoint documentation
- Database Schema - MongoDB collection schemas and relationships
- DevContainer Guide - Development environment setup
- Deployment Guide - Production deployment with Docker and Traefik
🔧 Troubleshooting
DevContainer Issues
Problem: Container fails to start or build
# Solution: Rebuild container without cache
F1 → "Dev Containers: Rebuild Container Without Cache"
Problem: Port conflicts (8100, 3069, 27017, 8081 already in use)
# Solution: Stop conflicting services
docker ps # Find conflicting containers
docker stop <container-id>
# Or change ports in .devcontainer/docker-compose.yml
Problem: node_modules issues or permission errors
# Solution: Remove node_modules and reinstall
rm -rf app/node_modules backend/node_modules node_modules
npm run install:all
Frontend Issues
Problem: node-sass build failed
# Solution: Python 2.7 is required (included in DevContainer)
# If running locally without DevContainer:
npm install --legacy-peer-deps
Problem: Peer dependency warnings during npm install
# Solution: Use legacy peer deps flag (included in postCreateCommand.sh)
cd app
npm install --legacy-peer-deps
Problem: Module not found errors
# Solution: Clear cache and reinstall
cd app
rm -rf node_modules package-lock.json
npm install --legacy-peer-deps
Problem: JavaScript heap out of memory
# Solution: Increase Node.js memory limit
export NODE_OPTIONS="--max-old-space-size=4096"
npm run dev:app
Backend Issues
Problem: MongoDB connection failed
# Solution: Verify MongoDB container is running
docker ps | grep mongo
# Check MongoDB health
docker exec -it <mongo-container-id> mongo --eval "db.adminCommand('ping')"
# Restart MongoDB service
docker-compose -f .devcontainer/docker-compose.yml restart mongo
Problem: JWT token invalid errors
# Solution: Verify JWT_SECRET is set in .devcontainer/dev.env
# Check backend/.env.example for required environment variables
Problem: Image upload fails
# Solution: Check volume permissions and multer configuration
# Verify backend/src/images directory exists and is writable
ls -la backend/src/images
Problem: Cannot connect to API from frontend
# Solution: Verify backend is running on port 3069
curl http://localhost:3069/profiles
# Check CORS settings in backend/src/app.js
Database Issues
Problem: Seed data not loading
# Solution: Manually run seed script
cd backend
npm run seed
# Or check data file exists
ls -la backend/data/profiles.json
Problem: Mongo Express not accessible
# Solution: Verify service is running and credentials are correct
# Default: http://localhost:8081 (admin/password)
docker logs <mongo-express-container-id>
⚠️ Technical Debt & Security
Outdated Dependencies
This project uses legacy technologies (circa 2017-2018) that are significantly outdated:
| Component | Current Version | Latest Stable | Status |
|---|---|---|---|
| Node.js | 14.x | 20.x LTS | ⛔ EOL April 2023 |
| Angular | 5.0.3 | 17.x | ⛔ 12 major versions behind |
| Ionic | 3.9.2 | 7.x | ⛔ 4 major versions behind |
| Express | 4.14.0 | 4.18.x | ⚠️ Missing security patches |
| MongoDB | 4.4 | 7.0 | ⚠️ 3 major versions behind |
| Mongoose | 4.7.4 | 8.x | ⛔ 4 major versions behind |
Security Concerns
-
CORS Configuration: Wide open (
Access-Control-Allow-Origin: *)- Risk: Any domain can make requests to API
- Fix: Restrict to specific origins in production (already configured in docker-compose.yml)
-
No Rate Limiting: API has no request throttling
- Risk: Vulnerable to brute force and DoS attacks
- Fix: Add
express-rate-limitmiddleware
-
Missing Input Validation: No validation library
- Risk: Potential injection attacks
- Fix: Add Joi or express-validator
-
JWT Secret Management: Secret must be set via environment variable
- Risk: If leaked, tokens can be forged
- Fix: Use strong secrets, rotate regularly, consider refresh tokens
-
Image Upload Security: No file type/size restrictions visible
- Risk: Malicious file uploads
- Fix: Validate MIME types, set size limits, sanitize filenames
-
Node.js 14 EOL: No longer receives security updates
- Risk: Unpatched vulnerabilities
- Fix: Upgrade to Node 20 LTS (see modernization path below)
Code Quality Issues
- No TypeScript in backend (JavaScript only)
- Limited test coverage (backend has Mocha tests, frontend has none)
- No automated CI/CD pipeline
ionic-app-scriptsis deprecated- Gulp is dated for task running
🚀 Future Modernization Path
For developers tasked with modernizing this codebase, follow this incremental upgrade strategy:
Phase 1: Critical Security Updates (2-4 weeks)
-
Upgrade Node.js:
# Update Dockerfile to use Node 20 LTS FROM node:20-bullseye # Remove Python 2.7 symlinks (modern node-sass doesn't need it) -
Update Backend Dependencies:
cd backend npm update express mongoose jsonwebtoken npm install express-rate-limit express-validator helmet -
Add Security Middleware:
// backend/src/app.js const rateLimit = require("express-rate-limit"); const helmet = require("helmet"); const { body, validationResult } = require("express-validator"); app.use(helmet()); app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 })); -
Fix CORS (already done in production docker-compose.yml):
// Restrict to specific origin res.header("Access-Control-Allow-Origin", "https://pfosi.mifi.dev");
Phase 2: Backend Modernization (4-6 weeks)
-
Convert Backend to TypeScript:
npm install -D typescript @types/express @types/node @types/mongoose npx tsc --init # Incrementally convert .js files to .ts -
Upgrade MongoDB & Mongoose:
# Update docker-compose.yml mongo: image: mongo:7.0 # Update Mongoose npm install mongoose@latest -
Modern Testing Setup:
npm install -D jest ts-jest @types/jest supertest # Migrate from Mocha/Chai to Jest -
Add API Documentation:
npm install swagger-jsdoc swagger-ui-express # Generate OpenAPI/Swagger docs from code
Phase 3: Frontend Modernization (8-12 weeks)
This is the most complex phase due to breaking changes.
Option A: Incremental Angular Upgrade (Slower but safer)
# Upgrade through each major version
ng update @angular/cli@6 @angular/core@6
ng update @angular/cli@7 @angular/core@7
# ... continue through each version to 17
Option B: Fresh Ionic 7 Rewrite (Faster, cleaner)
# Create new Ionic 7 app with Angular 17
ionic start looking-v2 tabs --type=angular
# Port components one by one
# Benefits: Standalone components, Signals, better performance
Recommendation: For novice developers, Option B (rewrite) is recommended because:
- Angular 5 → 17 migration is complex with many breaking changes
- Ionic 3 → 7 requires complete UI component rewrites
- Fresh start allows modern architecture (standalone components, no NgModules)
- Cleaner codebase without legacy workarounds
Phase 4: Modern Build Pipeline (2-3 weeks)
-
Replace deprecated build tools:
# Remove ionic-app-scripts, use Angular CLI # Remove Gulp, use npm scripts -
Add CI/CD:
# .github/workflows/ci.yml or .gitlab-ci.yml - Run tests on every commit - Automated Docker builds - Deployment to staging/production -
Code Quality Tools:
npm install -D eslint prettier husky lint-staged # Pre-commit hooks for linting
Estimated Total Effort
- Phase 1 (Security): 2-4 weeks - START HERE
- Phase 2 (Backend): 4-6 weeks
- Phase 3 (Frontend): 8-12 weeks - Most complex
- Phase 4 (DevOps): 2-3 weeks
Total: 16-25 weeks (4-6 months) for full modernization
Resources for Learning
- Angular Update Guide - Step-by-step migration instructions
- Ionic Migration Guide
- Node.js Best Practices
- Express Security Best Practices
🤝 Contributing
This is an art project with specific artistic intent. Before making changes:
- Understand the artistic and documentary purpose
- Preserve the original narrative and user stories
- Consult with the artist (Nick Pfosi) for content changes
- Follow the modernization path for technical improvements
📄 License
See project repository for license information.
👤 Author
Nick Pfosi - Artist & Creator
Mike Fitzpatrick - Technical Implementation (badmf@mifi.dev)
Questions or Issues? Check the troubleshooting section or refer to component-specific documentation linked above.