2025-12-28 13:52:25 -03:00
2025-12-28 13:52:25 -03:00
2025-12-28 13:52:25 -03:00
2025-12-28 13:52:25 -03:00
2018-03-03 13:07:07 -05:00
2018-03-02 03:00:51 -05:00
2025-12-28 13:52:25 -03:00
2025-12-28 13:52:25 -03:00

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

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-scripts 3.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:

Note

: You do NOT need Node.js, npm, or MongoDB installed locally. The DevContainer provides everything.


🚀 Quick Start

  1. Clone the repository:

    git clone <repository-url>
    cd PfosiLooking-monorepo
    
  2. Open in VS Code:

    code .
    
  3. Reopen in Container:

    • VS Code should prompt: "Reopen in Container"
    • Or manually: Press F1 → "Dev Containers: Reopen in Container"
  4. 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
  5. Start development servers:

    npm run dev:all
    
  6. Access the application:


📁 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

  1. Edit the seed data file: backend/data/profiles.json

  2. Re-seed the database:

    npm run seed
    
  3. For production deployments: The database is wiped and reseeded on each deployment, so all changes must be committed to profiles.json before 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
}


🔧 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

  1. 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)
  2. No Rate Limiting: API has no request throttling

    • Risk: Vulnerable to brute force and DoS attacks
    • Fix: Add express-rate-limit middleware
  3. Missing Input Validation: No validation library

    • Risk: Potential injection attacks
    • Fix: Add Joi or express-validator
  4. 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
  5. Image Upload Security: No file type/size restrictions visible

    • Risk: Malicious file uploads
    • Fix: Validate MIME types, set size limits, sanitize filenames
  6. 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-scripts is 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)

  1. 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)
    
  2. Update Backend Dependencies:

    cd backend
    npm update express mongoose jsonwebtoken
    npm install express-rate-limit express-validator helmet
    
  3. 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 }));
    
  4. 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)

  1. Convert Backend to TypeScript:

    npm install -D typescript @types/express @types/node @types/mongoose
    npx tsc --init
    # Incrementally convert .js files to .ts
    
  2. Upgrade MongoDB & Mongoose:

    # Update docker-compose.yml
    mongo:
      image: mongo:7.0
    
    # Update Mongoose
    npm install mongoose@latest
    
  3. Modern Testing Setup:

    npm install -D jest ts-jest @types/jest supertest
    # Migrate from Mocha/Chai to Jest
    
  4. 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)

  1. Replace deprecated build tools:

    # Remove ionic-app-scripts, use Angular CLI
    # Remove Gulp, use npm scripts
    
  2. Add CI/CD:

    # .github/workflows/ci.yml or .gitlab-ci.yml
    - Run tests on every commit
    - Automated Docker builds
    - Deployment to staging/production
    
  3. 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


🤝 Contributing

This is an art project with specific artistic intent. Before making changes:

  1. Understand the artistic and documentary purpose
  2. Preserve the original narrative and user stories
  3. Consult with the artist (Nick Pfosi) for content changes
  4. 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.

Description
A combined monorepo for the reconstruction of Nick Pfosi's Looking project.
Readme 14 MiB
Languages
JavaScript 73.6%
TypeScript 10.5%
SCSS 7.7%
HTML 6.5%
Dockerfile 1%
Other 0.7%