Files
website/docs/HARBORSMITH_IMPLEMENTATION_PLAN.md
matt ec72c5d62b
Some checks failed
build-website / build (push) Failing after 1m2s
Initial import of HarborSmith website
2025-09-18 22:20:01 +02:00

41 KiB

HarborSmith Platform Implementation Plan

Complete Technical Guide for Production Development

Version: 1.0
Date: September 2025
Status: Ready for Development


📋 Executive Summary

HarborSmith is a comprehensive marine services platform bridging yacht owners and maritime service providers through two primary verticals: Maintenance Services and Charter Services. This document provides the complete technical implementation plan for migrating from HTML mockups to a production-ready platform using modern, scalable architecture without cutting corners.

Key Objectives

  • Build a robust, scalable platform from day one
  • Implement microservices architecture for future growth
  • Ensure enterprise-grade security with SSO
  • Enable real-time capabilities for enhanced UX
  • Maintain SEO optimization through SSR
  • Deploy rapidly without compromising quality

🏗️ Technology Stack

Core Technologies

# Frontend
Framework: Next.js 14 (App Router)
Language: TypeScript
Styling: TailwindCSS + Shadcn/UI
State Management: Zustand + TanStack Query
Forms: React Hook Form + Zod
SEO: Server-Side Rendering (SSR)

# Backend
Architecture: Microservices
Runtime: Node.js
Framework: Fastify
API Design: RESTful
Validation: Zod
Documentation: OpenAPI/Swagger

# Database
Primary: Supabase (PostgreSQL)
Cache: Redis
Real-time: Supabase Realtime
File Storage: MinIO S3

# Authentication
SSO Provider: Keycloak
Session Management: JWT + Refresh Tokens
Authorization: RBAC with Casbin

# Infrastructure
Containerization: Docker
Reverse Proxy: Nginx
Orchestration: Docker Compose → Kubernetes (future)
Monitoring: Umami Analytics

# Third-Party Services
Payments: Stripe
Invoicing: InvoiceNinja API
Email: Poste.io (SMTP)
Marketing: Listmonk
Maps: Mapbox
Weather: OpenWeatherMap
CMS: Directus

📁 Project Structure

harborsmith-platform/
├── docker-compose.yml              # Production orchestration
├── docker-compose.dev.yml          # Development overrides
├── .env.example                    # Environment variables template
├── Makefile                        # Common commands and shortcuts
├── README.md                       # Project overview
│
├── docs/                           # Documentation
│   ├── HARBORSMITH_IMPLEMENTATION_PLAN.md (this file)
│   ├── API_DOCUMENTATION.md
│   ├── DEPLOYMENT_GUIDE.md
│   └── TROUBLESHOOTING.md
│
├── nginx/                          # Reverse proxy configuration
│   ├── nginx.conf                  # Main Nginx config
│   ├── ssl/                        # SSL certificates
│   └── sites/
│       ├── app.conf               # Frontend routing
│       ├── api.conf               # API gateway routing
│       └── services.conf          # Microservices routing
│
├── apps/
│   ├── web/                       # Next.js Frontend Application
│   │   ├── src/
│   │   │   ├── app/              # App Router pages
│   │   │   │   ├── (public)/     # Public routes
│   │   │   │   │   ├── page.tsx  # Homepage
│   │   │   │   │   ├── charter/
│   │   │   │   │   │   ├── page.tsx
│   │   │   │   │   │   └── booking/
│   │   │   │   │   │       ├── [step]/page.tsx
│   │   │   │   │   │       └── components/
│   │   │   │   │   ├── maintenance/
│   │   │   │   │   │   ├── page.tsx
│   │   │   │   │   │   └── booking/
│   │   │   │   │   ├── about/
│   │   │   │   │   ├── contact/
│   │   │   │   │   └── faq/
│   │   │   │   ├── (auth)/       # Protected routes
│   │   │   │   │   ├── layout.tsx
│   │   │   │   │   ├── dashboard/
│   │   │   │   │   │   ├── page.tsx
│   │   │   │   │   │   ├── charter/
│   │   │   │   │   │   └── maintenance/
│   │   │   │   │   ├── vessels/
│   │   │   │   │   ├── bookings/
│   │   │   │   │   ├── documents/
│   │   │   │   │   ├── invoices/
│   │   │   │   │   └── profile/
│   │   │   │   └── api/          # API route handlers
│   │   │   │       ├── auth/[...nextauth]/route.ts
│   │   │   │       └── webhooks/
│   │   │   ├── components/
│   │   │   │   ├── ui/           # Shadcn components
│   │   │   │   ├── layout/
│   │   │   │   │   ├── Navigation.tsx
│   │   │   │   │   ├── Footer.tsx
│   │   │   │   │   └── ThemeSwitcher.tsx
│   │   │   │   ├── home/
│   │   │   │   ├── charter/
│   │   │   │   ├── maintenance/
│   │   │   │   └── shared/
│   │   │   ├── lib/
│   │   │   │   ├── auth/         # Keycloak integration
│   │   │   │   ├── db/           # Supabase client
│   │   │   │   ├── api/          # API client
│   │   │   │   ├── stripe/       # Payment processing
│   │   │   │   └── utils/
│   │   │   ├── hooks/
│   │   │   ├── styles/
│   │   │   │   └── globals.css
│   │   │   └── types/
│   │   ├── public/
│   │   │   ├── images/
│   │   │   └── fonts/
│   │   ├── Dockerfile
│   │   ├── next.config.js
│   │   ├── tailwind.config.js
│   │   ├── tsconfig.json
│   │   └── package.json
│   │
│   └── api/                       # API Gateway
│       ├── src/
│       │   ├── server.ts          # Main server file
│       │   ├── routes/
│       │   │   ├── index.ts
│       │   │   ├── charter.routes.ts
│       │   │   ├── maintenance.routes.ts
│       │   │   ├── payment.routes.ts
│       │   │   └── user.routes.ts
│       │   ├── middleware/
│       │   │   ├── auth.middleware.ts
│       │   │   ├── cors.middleware.ts
│       │   │   ├── rate-limit.middleware.ts
│       │   │   └── validation.middleware.ts
│       │   ├── services/
│       │   │   ├── service.discovery.ts
│       │   │   └── circuit-breaker.ts
│       │   └── utils/
│       ├── Dockerfile
│       ├── tsconfig.json
│       └── package.json
│
├── services/                      # Microservices
│   ├── charter/
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── controllers/
│   │   │   ├── models/
│   │   │   ├── repositories/
│   │   │   └── services/
│   │   ├── tests/
│   │   ├── Dockerfile
│   │   └── package.json
│   │
│   ├── maintenance/
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── controllers/
│   │   │   ├── models/
│   │   │   ├── repositories/
│   │   │   └── services/
│   │   ├── tests/
│   │   ├── Dockerfile
│   │   └── package.json
│   │
│   ├── payments/
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── stripe/
│   │   │   ├── invoice-ninja/
│   │   │   └── webhooks/
│   │   ├── Dockerfile
│   │   └── package.json
│   │
│   └── notifications/
│       ├── src/
│       │   ├── index.ts
│       │   ├── email/
│       │   ├── sms/
│       │   └── templates/
│       ├── Dockerfile
│       └── package.json
│
├── packages/                      # Shared packages (monorepo)
│   ├── types/                    # TypeScript type definitions
│   │   ├── src/
│   │   │   ├── models.ts
│   │   │   ├── api.ts
│   │   │   └── enums.ts
│   │   └── package.json
│   │
│   ├── utils/                    # Shared utilities
│   │   ├── src/
│   │   │   ├── dates.ts
│   │   │   ├── validation.ts
│   │   │   └── formatters.ts
│   │   └── package.json
│   │
│   └── config/                   # Shared configurations
│       ├── src/
│       │   ├── theme.ts
│       │   ├── constants.ts
│       │   └── api-routes.ts
│       └── package.json
│
├── migrations/                    # Database migrations
│   ├── 001_initial_schema.sql
│   ├── 002_create_organizations.sql
│   ├── 003_create_users.sql
│   ├── 004_create_vessels.sql
│   ├── 005_create_bookings.sql
│   ├── 006_create_services.sql
│   ├── 007_create_invoices.sql
│   └── seed_data.sql
│
└── scripts/                       # Utility scripts
    ├── setup.sh                   # Initial project setup
    ├── migrate-mockups.js         # Convert HTML mockups to React
    ├── seed-database.js           # Populate with demo data
    └── deploy.sh                  # Deployment script

🗄️ Database Architecture

Multi-Tenant Strategy: Row-Level Security with Shared Database

-- Core schema design
CREATE SCHEMA IF NOT EXISTS public;
CREATE SCHEMA IF NOT EXISTS maintenance;
CREATE SCHEMA IF NOT EXISTS charter;

-- Organizations table (tenants)
CREATE TABLE public.organizations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    type VARCHAR(20) CHECK (type IN ('maintenance', 'charter', 'both')),
    subscription_tier VARCHAR(50) DEFAULT 'basic',
    settings JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Users table with organization relationship
CREATE TABLE public.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    email VARCHAR(255) UNIQUE NOT NULL,
    keycloak_id VARCHAR(255) UNIQUE,
    role VARCHAR(50) NOT NULL,
    profile JSONB DEFAULT '{}',
    preferences JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Vessels table
CREATE TABLE public.vessels (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    name VARCHAR(255) NOT NULL,
    type VARCHAR(50),
    make VARCHAR(100),
    model VARCHAR(100),
    year INTEGER,
    length_ft DECIMAL(5,2),
    capacity INTEGER,
    specifications JSONB DEFAULT '{}',
    health_score INTEGER DEFAULT 100,
    status VARCHAR(50) DEFAULT 'active',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Charter bookings
CREATE TABLE charter.bookings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    vessel_id UUID REFERENCES public.vessels(id),
    user_id UUID REFERENCES public.users(id),
    booking_date DATE NOT NULL,
    start_time TIME NOT NULL,
    duration_hours INTEGER NOT NULL,
    guest_count INTEGER NOT NULL,
    total_price DECIMAL(10,2),
    status VARCHAR(50) DEFAULT 'pending',
    payment_intent_id VARCHAR(255),
    special_requests TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Maintenance work orders
CREATE TABLE maintenance.work_orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    vessel_id UUID REFERENCES public.vessels(id),
    user_id UUID REFERENCES public.users(id),
    service_type VARCHAR(100) NOT NULL,
    priority VARCHAR(20) CHECK (priority IN ('emergency', 'urgent', 'routine')),
    scheduled_date DATE,
    description TEXT,
    status VARCHAR(50) DEFAULT 'pending',
    estimated_cost DECIMAL(10,2),
    actual_cost DECIMAL(10,2),
    technician_notes TEXT,
    completed_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Documents table
CREATE TABLE public.documents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    entity_type VARCHAR(50) NOT NULL,
    entity_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(100),
    s3_key VARCHAR(500) NOT NULL,
    size_bytes BIGINT,
    metadata JSONB DEFAULT '{}',
    uploaded_by UUID REFERENCES public.users(id),
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Invoices table
CREATE TABLE public.invoices (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    organization_id UUID REFERENCES public.organizations(id),
    invoice_number VARCHAR(50) UNIQUE NOT NULL,
    type VARCHAR(20) CHECK (type IN ('charter', 'maintenance')),
    booking_id UUID,
    work_order_id UUID,
    amount DECIMAL(10,2) NOT NULL,
    status VARCHAR(50) DEFAULT 'pending',
    invoice_ninja_id VARCHAR(255),
    due_date DATE,
    paid_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable Row Level Security
ALTER TABLE public.organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.vessels ENABLE ROW LEVEL SECURITY;
ALTER TABLE charter.bookings ENABLE ROW LEVEL SECURITY;
ALTER TABLE maintenance.work_orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.invoices ENABLE ROW LEVEL SECURITY;

-- Create RLS policies
CREATE POLICY tenant_isolation_organizations ON public.organizations
    USING (id = current_setting('app.current_organization')::UUID);

CREATE POLICY tenant_isolation_users ON public.users
    USING (organization_id = current_setting('app.current_organization')::UUID);

CREATE POLICY tenant_isolation_vessels ON public.vessels
    USING (organization_id = current_setting('app.current_organization')::UUID);

-- Indexes for performance
CREATE INDEX idx_vessels_org_id ON public.vessels(organization_id);
CREATE INDEX idx_bookings_date ON charter.bookings(booking_date);
CREATE INDEX idx_work_orders_status ON maintenance.work_orders(status);
CREATE INDEX idx_invoices_status ON public.invoices(status);
CREATE INDEX idx_documents_entity ON public.documents(entity_type, entity_id);

🔌 API Design

RESTful API Endpoints

// API Routes Structure
const API_ROUTES = {
  // Authentication
  'POST   /api/auth/login': 'User login with Keycloak',
  'POST   /api/auth/logout': 'User logout',
  'POST   /api/auth/refresh': 'Refresh JWT token',
  'GET    /api/auth/me': 'Get current user',
  
  // Organizations
  'GET    /api/organizations/:id': 'Get organization details',
  'PUT    /api/organizations/:id': 'Update organization',
  'GET    /api/organizations/:id/users': 'List organization users',
  
  // Vessels
  'GET    /api/vessels': 'List vessels',
  'POST   /api/vessels': 'Create vessel',
  'GET    /api/vessels/:id': 'Get vessel details',
  'PUT    /api/vessels/:id': 'Update vessel',
  'DELETE /api/vessels/:id': 'Delete vessel',
  
  // Charter Service
  'GET    /api/charter/availability': 'Check vessel availability',
  'GET    /api/charter/bookings': 'List bookings',
  'POST   /api/charter/bookings': 'Create booking',
  'GET    /api/charter/bookings/:id': 'Get booking details',
  'PUT    /api/charter/bookings/:id': 'Update booking',
  'POST   /api/charter/bookings/:id/cancel': 'Cancel booking',
  'GET    /api/charter/packages': 'List available packages',
  'POST   /api/charter/calculate-price': 'Calculate booking price',
  
  // Maintenance Service
  'GET    /api/maintenance/services': 'List available services',
  'GET    /api/maintenance/work-orders': 'List work orders',
  'POST   /api/maintenance/work-orders': 'Create work order',
  'GET    /api/maintenance/work-orders/:id': 'Get work order details',
  'PUT    /api/maintenance/work-orders/:id': 'Update work order',
  'GET    /api/maintenance/schedule': 'Get maintenance schedule',
  'POST   /api/maintenance/schedule': 'Schedule maintenance',
  
  // Payments
  'POST   /api/payments/create-intent': 'Create Stripe payment intent',
  'POST   /api/payments/confirm': 'Confirm payment',
  'GET    /api/payments/history': 'Get payment history',
  'POST   /api/payments/refund': 'Process refund',
  
  // Invoices
  'GET    /api/invoices': 'List invoices',
  'GET    /api/invoices/:id': 'Get invoice details',
  'POST   /api/invoices/:id/pay': 'Pay invoice',
  'GET    /api/invoices/:id/download': 'Download invoice PDF',
  
  // Documents
  'GET    /api/documents': 'List documents',
  'POST   /api/documents/upload': 'Upload document',
  'GET    /api/documents/:id': 'Get document',
  'DELETE /api/documents/:id': 'Delete document',
  
  // Notifications
  'POST   /api/notifications/email': 'Send email notification',
  'GET    /api/notifications/preferences': 'Get notification preferences',
  'PUT    /api/notifications/preferences': 'Update preferences',
  
  // Reports & Analytics
  'GET    /api/analytics/dashboard': 'Dashboard metrics',
  'GET    /api/analytics/revenue': 'Revenue reports',
  'GET    /api/analytics/utilization': 'Vessel utilization'
};

🐳 Docker Configuration

Complete docker-compose.yml

version: '3.9'

networks:
  harborsmith:
    driver: bridge

volumes:
  postgres_data:
  minio_data:
  keycloak_data:
  directus_uploads:
  redis_data:

services:
  # ===== FRONTEND =====
  web:
    build:
      context: ./apps/web
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
    container_name: harborsmith-web
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_API_URL=http://api:4000
      - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}
      - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - NEXT_PUBLIC_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY}
      - NEXT_PUBLIC_KEYCLOAK_URL=http://keycloak:8080
      - NEXT_PUBLIC_KEYCLOAK_REALM=harborsmith
      - NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=harborsmith-web
    depends_on:
      - api
      - keycloak
    networks:
      - harborsmith

  # ===== API GATEWAY =====
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile
    container_name: harborsmith-api
    restart: unless-stopped
    ports:
      - "4000:4000"
    environment:
      - NODE_ENV=production
      - PORT=4000
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith
      - REDIS_URL=redis://redis:6379
      - KEYCLOAK_URL=http://keycloak:8080
      - KEYCLOAK_REALM=harborsmith
      - KEYCLOAK_CLIENT_ID=harborsmith-api
      - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET}
      - JWT_SECRET=${JWT_SECRET}
      - CHARTER_SERVICE_URL=http://charter-service:5001
      - MAINTENANCE_SERVICE_URL=http://maintenance-service:5002
      - PAYMENT_SERVICE_URL=http://payment-service:5003
      - NOTIFICATION_SERVICE_URL=http://notification-service:5004
    depends_on:
      - postgres
      - redis
      - keycloak
    networks:
      - harborsmith

  # ===== MICROSERVICES =====
  charter-service:
    build:
      context: ./services/charter
      dockerfile: Dockerfile
    container_name: harborsmith-charter
    restart: unless-stopped
    ports:
      - "5001:5001"
    environment:
      - NODE_ENV=production
      - PORT=5001
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - harborsmith

  maintenance-service:
    build:
      context: ./services/maintenance
      dockerfile: Dockerfile
    container_name: harborsmith-maintenance
    restart: unless-stopped
    ports:
      - "5002:5002"
    environment:
      - NODE_ENV=production
      - PORT=5002
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - harborsmith

  payment-service:
    build:
      context: ./services/payments
      dockerfile: Dockerfile
    container_name: harborsmith-payments
    restart: unless-stopped
    ports:
      - "5003:5003"
    environment:
      - NODE_ENV=production
      - PORT=5003
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
      - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
      - INVOICE_NINJA_URL=${INVOICE_NINJA_URL}
      - INVOICE_NINJA_TOKEN=${INVOICE_NINJA_TOKEN}
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/harborsmith
    depends_on:
      - postgres
    networks:
      - harborsmith

  notification-service:
    build:
      context: ./services/notifications
      dockerfile: Dockerfile
    container_name: harborsmith-notifications
    restart: unless-stopped
    ports:
      - "5004:5004"
    environment:
      - NODE_ENV=production
      - PORT=5004
      - SMTP_HOST=${POSTE_HOST}
      - SMTP_PORT=${POSTE_PORT}
      - SMTP_SECURE=${POSTE_SECURE}
      - SMTP_USER=${POSTE_USER}
      - SMTP_PASS=${POSTE_PASS}
      - LISTMONK_URL=${LISTMONK_URL}
      - LISTMONK_USER=${LISTMONK_USER}
      - LISTMONK_PASS=${LISTMONK_PASS}
    networks:
      - harborsmith

  # ===== DATABASES & STORAGE =====
  postgres:
    image: supabase/postgres:15.1.0.117
    container_name: harborsmith-db
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=harborsmith
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./migrations:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - harborsmith

  redis:
    image: redis:7-alpine
    container_name: harborsmith-redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - harborsmith

  # ===== AUTHENTICATION =====
  keycloak:
    image: quay.io/keycloak/keycloak:23.0
    container_name: harborsmith-keycloak
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - KEYCLOAK_ADMIN=${KEYCLOAK_ADMIN}
      - KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD}
      - KC_DB=postgres
      - KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak
      - KC_DB_USERNAME=postgres
      - KC_DB_PASSWORD=${POSTGRES_PASSWORD}
      - KC_HOSTNAME_STRICT=false
      - KC_HTTP_ENABLED=true
      - KC_HEALTH_ENABLED=true
    command: start-dev
    volumes:
      - keycloak_data:/opt/keycloak/data
    depends_on:
      - postgres
    networks:
      - harborsmith

  # ===== FILE STORAGE =====
  minio:
    image: minio/minio:latest
    container_name: harborsmith-minio
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
      - MINIO_BROWSER_REDIRECT_URL=http://localhost:9001
    volumes:
      - minio_data:/data
    command: server /data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - harborsmith

  createbuckets:
    image: minio/mc:latest
    container_name: harborsmith-minio-setup
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      /usr/bin/mc config host add harborsmith http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};
      /usr/bin/mc mb harborsmith/documents;
      /usr/bin/mc mb harborsmith/images;
      /usr/bin/mc mb harborsmith/directus;
      /usr/bin/mc policy set public harborsmith/images;
      exit 0;
      "
    networks:
      - harborsmith

  # ===== CMS =====
  directus:
    image: directus/directus:10.8
    container_name: harborsmith-cms
    restart: unless-stopped
    ports:
      - "8055:8055"
    environment:
      - KEY=${DIRECTUS_KEY}
      - SECRET=${DIRECTUS_SECRET}
      - DB_CLIENT=pg
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_DATABASE=directus
      - DB_USER=postgres
      - DB_PASSWORD=${POSTGRES_PASSWORD}
      - ADMIN_EMAIL=${DIRECTUS_ADMIN_EMAIL}
      - ADMIN_PASSWORD=${DIRECTUS_ADMIN_PASSWORD}
      - PUBLIC_URL=http://localhost:8055
      - STORAGE_LOCATIONS=s3
      - STORAGE_S3_DRIVER=s3
      - STORAGE_S3_ENDPOINT=http://minio:9000
      - STORAGE_S3_BUCKET=directus
      - STORAGE_S3_REGION=us-east-1
      - STORAGE_S3_KEY=${MINIO_ROOT_USER}
      - STORAGE_S3_SECRET=${MINIO_ROOT_PASSWORD}
    volumes:
      - directus_uploads:/directus/uploads
    depends_on:
      - postgres
      - minio
    networks:
      - harborsmith

  # ===== ANALYTICS =====
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    container_name: harborsmith-analytics
    restart: unless-stopped
    ports:
      - "3001:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/umami
      - DATABASE_TYPE=postgresql
      - HASH_SALT=${UMAMI_HASH_SALT}
      - TRACKER_SCRIPT_NAME=script.js
      - DISABLE_UPDATES=true
    depends_on:
      - postgres
    networks:
      - harborsmith

🔄 Migration Strategy: Mockups to Production

Phase 1: Component Extraction (Days 1-3)

1. Extract Design System

// scripts/migrate-mockups.js
const fs = require('fs');
const path = require('path');
const cheerio = require('cheerio');

// Extract colors, fonts, and styles from existing CSS
const extractDesignTokens = () => {
  const cssFiles = [
    'website-mockups/css/styles.css',
    'website-mockups/css/themes.css',
    'website-mockups/css/voyage-layout.css'
  ];
  
  // Parse CSS and generate Tailwind config
  // Extract color variables
  // Extract font definitions
  // Generate component classes
};

// Convert HTML components to React
const convertToReact = (htmlFile) => {
  const html = fs.readFileSync(htmlFile, 'utf8');
  const $ = cheerio.load(html);
  
  // Extract components
  const navigation = $('.voyage-nav').html();
  const hero = $('.hero-voyage').html();
  const footer = $('.voyage-footer').html();
  
  // Generate React components
  // Handle event listeners
  // Convert class names to Tailwind
  // Extract inline styles
};

2. Component Mapping

// Component extraction map
interface ComponentMap {
  source: string;           // HTML file location
  target: string;           // React component location
  dependencies: string[];   // Required components
  data: string[];          // Required data/props
}

const componentMappings: ComponentMap[] = [
  {
    source: 'website-mockups/index.html',
    target: 'apps/web/src/components/home/Hero.tsx',
    dependencies: ['Button', 'Container'],
    data: ['heroTitle', 'heroSubtitle', 'ctaText']
  },
  {
    source: 'website-mockups/charter.html',
    target: 'apps/web/src/components/charter/FleetGrid.tsx',
    dependencies: ['Card', 'Badge', 'Image'],
    data: ['vessels', 'pricing', 'availability']
  },
  // ... more mappings
];

Phase 2: React Component Generation (Days 4-7)

Example: Hero Component

// apps/web/src/components/home/Hero.tsx
'use client';

import { motion } from 'framer-motion';
import { ArrowRight, Anchor } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useTheme } from '@/hooks/useTheme';
import Link from 'next/link';

export const Hero = () => {
  const { theme } = useTheme();
  
  return (
    <section className="relative min-h-screen flex items-center">
      {/* Background gradient from mockup */}
      <div className="absolute inset-0 bg-gradient-to-br from-[#001f3f] via-[#003366] to-[#001f3f]" />
      
      {/* Wave animation from original */}
      <div className="absolute bottom-0 left-0 right-0">
        <svg viewBox="0 0 1440 320" className="w-full">
          <motion.path
            fill="rgba(255,255,255,0.1)"
            d="M0,96L48,112C96,128,192,160,288,160C384,160,480,128,576,112C672,96,768,96,864,112C960,128,1056,160,1152,165.3C1248,171,1344,149,1392,138.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"
            animate={{
              d: [
                "M0,96L48,112C96,128,192,160,288,160C384,160,480,128,576,112C672,96,768,96,864,112C960,128,1056,160,1152,165.3C1248,171,1344,149,1392,138.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z",
                "M0,128L48,138.7C96,149,192,171,288,165.3C384,160,480,128,576,112C672,96,768,96,864,112C960,128,1056,160,1152,160C1248,160,1344,128,1392,112L1440,96L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"
              ]
            }}
            transition={{
              repeat: Infinity,
              repeatType: "reverse",
              duration: 10,
              ease: "easeInOut"
            }}
          />
        </svg>
      </div>
      
      {/* Content */}
      <div className="container mx-auto px-4 relative z-10">
        <motion.div
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.8 }}
          className="max-w-4xl mx-auto text-center text-white"
        >
          <motion.div
            initial={{ scale: 0 }}
            animate={{ scale: 1 }}
            transition={{ delay: 0.2, type: "spring" }}
            className="inline-flex items-center gap-2 mb-6 px-4 py-2 bg-white/10 backdrop-blur rounded-full"
          >
            <Anchor className="w-5 h-5" />
            <span className="text-sm font-medium">San Francisco Bay's Premier Yacht Services</span>
          </motion.div>
          
          <h1 className="font-display text-5xl md:text-7xl font-bold mb-6">
            Your Journey Begins at{' '}
            <span className="bg-gradient-to-r from-[#dc143c] to-[#ef4444] bg-clip-text text-transparent">
              HarborSmith
            </span>
          </h1>
          
          <p className="text-xl md:text-2xl mb-8 text-white/90">
            Experience luxury yacht charters and professional maintenance services
            with San Francisco's most trusted maritime partner
          </p>
          
          <div className="flex flex-col sm:flex-row gap-4 justify-center">
            <Button
              asChild
              size="lg"
              className="bg-gradient-to-r from-[#dc143c] to-[#ef4444] hover:from-[#b91c3c] hover:to-[#dc143c]"
            >
              <Link href="/charter">
                Explore Charters
                <ArrowRight className="ml-2 w-5 h-5" />
              </Link>
            </Button>
            
            <Button
              asChild
              size="lg"
              variant="outline"
              className="border-white text-white hover:bg-white hover:text-[#001f3f]"
            >
              <Link href="/maintenance">
                Maintenance Services
              </Link>
            </Button>
          </div>
        </motion.div>
      </div>
    </section>
  );
};

📅 Implementation Timeline

Week 1: Infrastructure & Foundation

Day 1-2: Project Setup

  • Initialize Git repository
  • Set up monorepo with pnpm workspaces
  • Configure Docker environments (dev/prod)
  • Set up environment variables
  • Initialize Next.js with TypeScript
  • Configure ESLint and Prettier

Day 3-4: Database & Auth

  • Deploy PostgreSQL with Supabase
  • Run initial migrations
  • Configure Keycloak realm
  • Set up SSO clients
  • Test authentication flow
  • Configure Row Level Security

Day 5: Services Setup

  • Create API Gateway structure
  • Initialize microservices
  • Set up service discovery
  • Configure Redis caching
  • Set up MinIO buckets
  • Deploy Directus CMS

Week 2: Core Application

Day 6-7: Frontend Foundation

  • Convert mockup styles to Tailwind
  • Create component library
  • Implement theme system
  • Set up routing structure
  • Create layout components
  • Implement navigation

Day 8-9: Public Pages

  • Homepage with all sections
  • Charter service pages
  • Maintenance service pages
  • About page
  • Contact page
  • FAQ page

Day 10: Authentication Integration

  • Keycloak provider setup
  • Login/Register flows
  • Protected routes
  • Role-based access
  • Session management
  • Logout functionality

Week 3: Portal Development

Day 11-12: User Dashboard

  • Dashboard layout
  • Charter dashboard widgets
  • Maintenance dashboard widgets
  • Activity timeline
  • Quick actions
  • Notifications panel

Day 13-14: Booking Systems

  • Charter booking wizard
  • Maintenance scheduling
  • Calendar integration
  • Availability checking
  • Price calculation
  • Booking confirmation

Day 15: Document Management

  • File upload to MinIO
  • Document viewer
  • Document categorization
  • Download functionality
  • Document sharing
  • Version control

Week 4: Integration & Launch

Day 16-17: Payment & Invoicing

  • Stripe integration
  • Payment intents
  • InvoiceNinja API
  • Invoice generation
  • Payment history
  • Refund processing

Day 18-19: Testing & Optimization

  • End-to-end testing
  • Performance optimization
  • Security audit
  • Load testing
  • Bug fixes
  • Mobile optimization

Day 20: Deployment

  • Production configuration
  • SSL certificates
  • DNS configuration
  • Monitoring setup
  • Backup configuration
  • Go-live checklist

🚀 Quick Start Guide

Prerequisites

# Required software
- Node.js 20+ 
- Docker & Docker Compose
- pnpm (npm install -g pnpm)
- Git

Initial Setup

# 1. Clone the repository
git clone [repository-url]
cd harborsmith-platform

# 2. Install dependencies
pnpm install

# 3. Set up environment variables
cp .env.example .env
# Edit .env with your configuration

# 4. Start Docker services
docker-compose up -d

# 5. Run database migrations
docker exec harborsmith-db psql -U postgres -d harborsmith -f /docker-entrypoint-initdb.d/001_initial_schema.sql
docker exec harborsmith-db psql -U postgres -d harborsmith -f /docker-entrypoint-initdb.d/002_create_organizations.sql
# ... run all migrations

# 6. Seed demo data
pnpm run seed

# 7. Start development servers
pnpm run dev

# 8. Convert mockups to React components
pnpm run migrate:mockups

Access Points

Frontend:         http://localhost:3000
API Gateway:      http://localhost:4000
Keycloak:         http://localhost:8080
Directus CMS:     http://localhost:8055
MinIO Console:    http://localhost:9001
Umami Analytics:  http://localhost:3001

Development Commands

# Start all services
pnpm run dev

# Run tests
pnpm run test

# Build for production
pnpm run build

# Deploy to production
pnpm run deploy

# Generate API documentation
pnpm run docs:api

# Run database migrations
pnpm run db:migrate

# Seed database
pnpm run db:seed

# Format code
pnpm run format

# Lint code
pnpm run lint

🎯 Critical Path to MVP

Must-Have Features (Week 1-2)

  1. User Authentication

    • Login/Register with Keycloak
    • Role-based access (Customer, Admin, Service Provider)
    • Session management
  2. Core Booking Flow

    • Browse available services
    • Select yacht/service
    • Choose date/time
    • Complete payment
    • Receive confirmation
  3. Basic Dashboard

    • View bookings
    • Manage vessels
    • View invoices
    • Upload documents

Should-Have Features (Week 3)

  1. Communication

    • Email notifications
    • Booking confirmations
    • Reminder emails
  2. Payment Processing

    • Stripe integration
    • Invoice generation
    • Payment history
  3. Admin Panel

    • Manage users
    • View all bookings
    • Generate reports

Nice-to-Have Features (Week 4+)

  1. Advanced Features

    • Real-time availability
    • Dynamic pricing
    • Weather integration
    • Route planning
  2. Analytics

    • Revenue tracking
    • Utilization reports
    • Customer insights

🔒 Security Considerations

Authentication & Authorization

  • Keycloak SSO with MFA support
  • JWT tokens with refresh mechanism
  • Role-based access control (RBAC)
  • API key management for services

Data Protection

  • TLS/SSL for all communications
  • Encryption at rest (database)
  • Encryption in transit
  • PII data isolation
  • GDPR compliance measures

Infrastructure Security

  • Container security scanning
  • Regular dependency updates
  • Rate limiting on APIs
  • DDoS protection
  • Regular security audits

📊 Performance Targets

Frontend Performance

Metrics:
  First Contentful Paint: < 1.5s
  Time to Interactive: < 3.5s
  Cumulative Layout Shift: < 0.1
  Largest Contentful Paint: < 2.5s
  
Optimization:
  - Next.js ISR for static content
  - Image optimization with next/image
  - Code splitting per route
  - Lazy loading components
  - CDN for static assets

Backend Performance

API Response Times:
  GET endpoints: < 200ms (p95)
  POST endpoints: < 300ms (p95)
  Database queries: < 50ms (p95)
  
Optimization:
  - Redis caching layer
  - Database query optimization
  - Connection pooling
  - Horizontal scaling ready

🚨 Monitoring & Alerts

Application Monitoring

  • Umami Analytics for user behavior
  • Custom dashboards for business metrics
  • Error tracking with Sentry (optional)
  • Performance monitoring

Infrastructure Monitoring

  • Container health checks
  • Database performance metrics
  • API response times
  • Resource utilization

Alerting Rules

  • Downtime > 1 minute
  • Error rate > 1%
  • Response time > 1s
  • Database connection failures
  • Payment processing failures

📝 Deployment Checklist

Pre-Deployment

  • All tests passing
  • Security audit complete
  • Performance benchmarks met
  • Documentation updated
  • Environment variables configured
  • SSL certificates ready

Deployment Steps

  • Backup existing data
  • Deploy database migrations
  • Deploy backend services
  • Deploy frontend application
  • Verify all services running
  • Run smoke tests

Post-Deployment

  • Monitor error rates
  • Check performance metrics
  • Verify email delivery
  • Test payment processing
  • Update DNS records
  • Announce go-live

🤝 Team Collaboration

Git Workflow

main
├── develop
│   ├── feature/user-authentication
│   ├── feature/booking-system
│   └── feature/payment-integration
├── staging
└── production

Code Review Process

  1. Create feature branch from develop
  2. Implement feature with tests
  3. Create pull request
  4. Automated tests run
  5. Code review by team
  6. Merge to develop
  7. Deploy to staging
  8. Test in staging
  9. Merge to main
  10. Deploy to production

📚 Additional Resources

Documentation

  • API Documentation: /docs/API_DOCUMENTATION.md
  • Deployment Guide: /docs/DEPLOYMENT_GUIDE.md
  • Contributing Guide: /docs/CONTRIBUTING.md
  • Security Policy: /docs/SECURITY.md

External Resources

Support


🎯 Success Metrics

Technical Metrics

  • 99.9% uptime
  • < 3s page load time
  • < 300ms API response time
  • Zero critical security vulnerabilities

Business Metrics

  • 500+ vessels onboarded (Year 1)
  • 100+ service providers
  • 1000+ monthly active users
  • 15% month-over-month growth

Conclusion

This implementation plan provides everything needed to build HarborSmith from the ground up:

  1. Modern Architecture: Microservices, SSR, real-time capabilities
  2. Enterprise Security: Keycloak SSO, RLS, encryption
  3. Scalable Infrastructure: Docker, Redis, horizontal scaling ready
  4. Developer Experience: TypeScript, hot reloading, automated testing
  5. Production Ready: Monitoring, analytics, backup strategies

With this plan, you can start development immediately and have a production-ready MVP within 4 weeks.

Next Steps:

  1. Set up development environment
  2. Begin with Week 1 infrastructure tasks
  3. Convert mockups to React components
  4. Implement core booking flows
  5. Deploy to staging for testing
  6. Launch MVP to production

This document is a living guide and should be updated as the project evolves.