diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4e8061a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +# Docker ignore file +node_modules +.next +.git +.env.local +.env.development +*.log +npm-debug.log* +.DS_Store +*.tgz +*.tar.gz \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..6ad37c4 --- /dev/null +++ b/.env.production @@ -0,0 +1,28 @@ +# Production Environment Configuration +# Domain: lcc-tt-booking.mikicvi.com + +# Database +DATABASE_URL="./data/sqlite.db" + +# NextAuth.js +NEXTAUTH_URL="https://lcc-tt-booking.mikicvi.com" +NEXTAUTH_SECRET="qHYNaq516ByAY6H4HdxacMICd05I1DqvrTitIuVtT20=" + +# Email Configuration (Gmail - Update with your credentials) +EMAIL_USER="your-email@gmail.com" +EMAIL_PASSWORD="your-app-password-here" + +# Admin Configuration (Change these for production!) +ADMIN_EMAIL="admin@lcc-tt-booking.mikicvi.com" +ADMIN_PASSWORD="ChangeMeInProduction123!" + +# Application Settings +NODE_ENV="production" +PORT="3000" + +# Rate Limiting +RATE_LIMIT_MAX="100" +RATE_LIMIT_WINDOW="900000" + +# Logging +LOG_LEVEL="info" \ No newline at end of file diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..258df88 --- /dev/null +++ b/DEPLOYMENT_GUIDE.md @@ -0,0 +1,506 @@ +# Deployment Strategy for Table Tennis Booking System + +## Overview + +This document outlines comprehensive deployment strategies for the Table Tennis Booking System, considering both self-hosting and cloud deployment options. The application is a Next.js-based system with SQLite database, designed for production use. + +## 1. Self-Hosting Strategy + +### Option A: Raspberry Pi + Cloudflare Tunnel (Recommended) + +**Architecture:** + +``` +Internet → Cloudflare → Cloudflare Tunnel → Raspberry Pi → Docker Container +``` + +**Requirements:** + +- Raspberry Pi 4 (4GB+ RAM recommended) +- Stable internet connection +- Cloudflare account (free tier sufficient) +- Domain name (can be managed through Cloudflare) + +**Setup Steps:** + +1. **Raspberry Pi Preparation** + + ```bash + # Update system + sudo apt update && sudo apt upgrade -y + + # Install Docker + curl -fsSL https://get.docker.com -o get-docker.sh + sudo sh get-docker.sh + sudo usermod -aG docker $USER + + # Install Docker Compose + sudo apt install docker-compose -y + ``` + +2. **Application Deployment** + + ```bash + # Clone repository + git clone + cd tt-booking + + # Create production environment file + cp .env.example .env.production + # Edit .env.production with your values + + # Deploy with Docker + docker-compose -f docker-compose.production.yml up -d + ``` + +3. **Cloudflare Tunnel Setup** + + ```bash + # Install cloudflared + wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb + sudo dpkg -i cloudflared-linux-arm64.deb + + # Authenticate + cloudflared tunnel login + + # Create tunnel + cloudflared tunnel create tt-booking + + # Configure tunnel (create config.yml) + cloudflared tunnel route dns tt-booking yourdomain.com + + # Run tunnel + cloudflared tunnel run tt-booking + ``` + +**Cloudflare Tunnel Config (`~/.cloudflared/config.yml`):** + +```yaml +tunnel: +credentials-file: /home/pi/.cloudflared/.json + +ingress: + - hostname: yourdomain.com + service: http://localhost:3000 + - service: http_status:404 +``` + +**Production Docker Compose (`docker-compose.production.yml`):** + +```yaml +version: '3.8' + +services: + tt-booking: + build: . + ports: + - '3000:3000' + environment: + - NODE_ENV=production + - DATABASE_URL=/app/data/sqlite.db + - NEXTAUTH_URL=https://yourdomain.com + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - EMAIL_USER=${EMAIL_USER} + - EMAIL_PASSWORD=${EMAIL_PASSWORD} + - ADMIN_EMAIL=${ADMIN_EMAIL} + - ADMIN_PASSWORD=${ADMIN_PASSWORD} + volumes: + - ./data:/app/data + - ./backups:/app/backups + restart: unless-stopped + healthcheck: + test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/health'] + interval: 30s + timeout: 10s + retries: 3 + + # Backup service + backup: + image: alpine:latest + volumes: + - ./data:/data:ro + - ./backups:/backups + command: > + sh -c " + while true; do + cp /data/sqlite.db /backups/sqlite-$(date +%Y%m%d-%H%M%S).db + find /backups -name 'sqlite-*.db' -mtime +7 -delete + sleep 86400 + done" + restart: unless-stopped +``` + +**Advantages:** + +- No need for port forwarding or exposing home IP +- Free SSL certificates through Cloudflare +- DDoS protection and CDN benefits +- Easy domain management +- Cost-effective (only domain cost ~$10-15/year) + +**Disadvantages:** + +- Dependent on home internet stability +- Limited by residential bandwidth +- Requires basic Linux administration skills + +### Option B: Traditional Self-Hosting with Reverse Proxy + +**Architecture:** + +``` +Internet → Router/Firewall → Nginx → Docker Container +``` + +**Requirements:** + +- Dedicated server or powerful Raspberry Pi +- Static IP address or Dynamic DNS service +- SSL certificate (Let's Encrypt) +- Port forwarding configuration + +**Setup includes all the Docker setup above, plus:** + +1. **Nginx Configuration** + + ```bash + # Install Nginx + sudo apt install nginx certbot python3-certbot-nginx + + # Configure SSL + sudo certbot --nginx -d yourdomain.com + ``` + +2. **Updated Docker Compose with Nginx** + Use the existing [docker-compose.yml](docker-compose.yml) with Nginx service. + +**Advantages:** + +- Full control over infrastructure +- No dependency on third-party tunneling services +- Better performance for local network access + +**Disadvantages:** + +- Requires static IP or Dynamic DNS +- More complex firewall/security configuration +- SSL certificate management overhead + +## 2. Cloud Deployment Strategies + +### Option A: DigitalOcean App Platform (Recommended for Small Scale) + +**Cost Estimate:** $12-25/month + +**Features:** + +- Automatic deployments from Git +- Built-in SSL certificates +- Automatic scaling +- Integrated monitoring + +**Deployment:** + +1. Connect GitHub repository +2. Configure environment variables +3. Add persistent volume for SQLite database +4. Deploy with zero-config + +**Configuration:** + +```yaml +# .do/app.yaml +name: tt-booking +services: + - name: web + source_dir: / + github: + repo: your-username/tt-booking + branch: main + run_command: npm start + environment_slug: node-js + instance_count: 1 + instance_size_slug: basic-xxs + envs: + - key: NODE_ENV + value: production + - key: DATABASE_URL + value: /app/data/sqlite.db +``` + +### Option B: Railway (Developer-Friendly) + +**Cost Estimate:** $5-20/month + +**Features:** + +- Git-based deployments +- Built-in databases available +- Simple pricing model +- Excellent developer experience + +**Deployment:** + +```bash +# Install Railway CLI +npm install -g @railway/cli + +# Login and deploy +railway login +railway init +railway up +``` + +### Option C: Vercel + PlanetScale (Serverless) + +**Cost Estimate:** $0-20/month (depending on usage) + +**Modifications needed:** + +- Replace SQLite with PlanetScale MySQL +- Update database schema for MySQL compatibility +- Modify connection configuration + +**Deployment:** + +```bash +# Install Vercel CLI +npm install -g vercel + +# Deploy +vercel --prod +``` + +### Option D: AWS/GCP/Azure (Enterprise Scale) + +**Cost Estimate:** $30-100+/month + +**AWS Deployment Options:** + +1. **ECS Fargate + RDS** + + - Container-based deployment + - Managed database + - Auto-scaling capabilities + +2. **Elastic Beanstalk** + + - Simple deployment model + - Built-in monitoring + - Easy environment management + +3. **App Runner** + - Serverless container platform + - Automatic scaling + - Pay-per-use pricing + +## 3. Database Considerations + +### For Self-Hosting + +- **SQLite**: Perfect for small to medium loads +- **Backup Strategy**: Automated daily backups to external storage +- **Monitoring**: Simple file-based health checks + +### For Cloud Deployment + +- **Small Scale**: Keep SQLite with persistent volumes +- **Medium Scale**: PostgreSQL (Railway, DigitalOcean Managed DB) +- **Large Scale**: Multi-region database (AWS RDS, Google Cloud SQL) + +## 4. Monitoring and Maintenance + +### Essential Monitoring + +```bash +# Add to crontab for health checks +*/5 * * * * curl -f https://yourdomain.com/api/health || echo "App down" | mail -s "Alert" admin@example.com +``` + +### Backup Strategy + +1. **Database Backups**: Daily automated SQLite file copies +2. **Environment Config**: Version controlled `.env` files +3. **Application Code**: Git-based source control + +### Update Strategy + +```bash +#!/bin/bash +# update.sh +cd /path/to/tt-booking +git pull origin main +docker-compose -f docker-compose.production.yml down +docker-compose -f docker-compose.production.yml up -d --build +``` + +## 5. Security Considerations + +### Self-Hosting Security Checklist + +- [ ] Firewall configured (only necessary ports open) +- [ ] Regular OS updates automated +- [ ] Non-root user for application +- [ ] SSL certificates properly configured +- [ ] Database backups encrypted +- [ ] Rate limiting configured (already in nginx.conf) +- [ ] Log monitoring for suspicious activity + +### Cloud Security + +- [ ] Environment variables properly secured +- [ ] Database access restricted +- [ ] API rate limiting enabled +- [ ] Regular dependency updates +- [ ] Security headers configured (already in app) + +## 6. Cost Comparison + +| Deployment Method | Monthly Cost | Effort | Scalability | Reliability | +| ------------------------- | ------------ | -------- | ----------- | ----------- | +| Raspberry Pi + CF Tunnel | $1-2 | Medium | Low | Medium | +| Traditional Self-Host | $5-10 | High | Low | Medium | +| DigitalOcean App Platform | $12-25 | Low | Medium | High | +| Railway | $5-20 | Very Low | Medium | High | +| Vercel + PlanetScale | $0-20 | Low | High | High | +| AWS/GCP/Azure | $30-100+ | High | Very High | Very High | + +## 7. Recommended Approach + +### For Personal/Small Group Use: + +**Raspberry Pi + Cloudflare Tunnel** - Most cost-effective with good reliability + +### For Small Business: + +**Railway or DigitalOcean App Platform** - Balance of simplicity and reliability + +### For Enterprise: + +**AWS/GCP with proper CI/CD pipeline** - Maximum scalability and reliability + +## 8. Local Development Best Practices + +### Standalone Development + +```bash +# Quick development setup +npm install +npm run dev +``` + +### Docker Development + +```bash +# Development with Docker +docker-compose up -d +``` + +### Production-like Local Testing + +```bash +# Test production build locally +npm run build +npm start +``` + +## 9. Health Check Endpoint + +The application includes a health check endpoint at `/api/health` for monitoring purposes. You should create this endpoint: + +```typescript +// app/api/health/route.ts +import { NextResponse } from 'next/server'; +import { db } from '@/lib/db'; + +export async function GET() { + try { + // Basic database connectivity check + await db.select().from(settings).limit(1); + + return NextResponse.json({ + status: 'healthy', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + }); + } catch (error) { + return NextResponse.json({ status: 'unhealthy', error: 'Database connection failed' }, { status: 500 }); + } +} +``` + +## 10. Environment Variables for Production + +Create a `.env.production` file with the following required variables: + +```bash +# Application +NODE_ENV=production +NEXTAUTH_URL=https://yourdomain.com +NEXTAUTH_SECRET=your-very-long-random-secret-here + +# Database +DATABASE_URL=/app/data/sqlite.db + +# Email Configuration (optional) +EMAIL_USER=your-email@gmail.com +EMAIL_PASSWORD=your-app-specific-password + +# Admin Account +ADMIN_EMAIL=admin@yourdomain.com +ADMIN_PASSWORD=secure-admin-password + +# Optional: Rate limiting +RATE_LIMIT_MAX=100 +RATE_LIMIT_WINDOW=900000 +``` + +## 11. Docker Production Optimization + +Create a production-optimized `Dockerfile.production`: + +```dockerfile +FROM node:18-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm ci --only=production && npm cache clean --force + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy built application +COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/public ./public + +# Create data directory for SQLite +RUN mkdir -p /app/data && chown nextjs:nodejs /app/data + +USER nextjs + +EXPOSE 3000 + +ENV PORT 3000 +ENV HOSTNAME "0.0.0.0" + +CMD ["npm", "start"] +``` + +This deployment strategy provides multiple pathways depending on your technical expertise, budget, and scaling requirements. The Cloudflare Tunnel approach is particularly attractive for self-hosting as it eliminates many traditional networking complexities while maintaining security and reliability. diff --git a/Dockerfile.production b/Dockerfile.production new file mode 100644 index 0000000..392caef --- /dev/null +++ b/Dockerfile.production @@ -0,0 +1,74 @@ +# Multi-stage production Dockerfile for LCC Table Tennis Booking +FROM node:22-slim AS base + +# Install dependencies only when needed +FROM base AS deps +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json package-lock.json* ./ +RUN \ + if [ -f package-lock.json ]; then npm ci --ignore-scripts; \ + else echo "Lockfile not found." && exit 1; \ + fi + +# Rebuild the source code only when needed +FROM base AS builder +RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Rebuild better-sqlite3 for Alpine Linux +RUN npm rebuild better-sqlite3 + +# Build the application +RUN npm run build + +# Production image, copy all the files and run next +FROM base AS runner +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +# Create system user and group +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy necessary files from builder stage +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +# Create public directory if it doesn't exist +RUN mkdir -p public + +# Create directories for data and backups +RUN mkdir -p /app/data /app/backups /app/logs && \ + chown -R nextjs:nodejs /app/data /app/backups /app/logs + +# Create startup script +COPY --chown=nextjs:nodejs < +credentials-file: /home/pi/.cloudflared/.json + +# Ingress rules +ingress: + # Main application + - hostname: lcc-tt-booking.mikicvi.com + service: http://localhost:3000 + originRequest: + # Enable HTTP/2 + httpHostHeader: lcc-tt-booking.mikicvi.com + # Connection settings + connectTimeout: 30s + tlsTimeout: 10s + # Health checks + proxyType: http + # Disable chunked encoding for better compatibility + disableChunkedEncoding: true + + # Health check endpoint (optional, for monitoring) + - hostname: health.lcc-tt-booking.mikicvi.com + service: http://localhost:3000/api/health + + # Catch-all rule (must be last) + - service: http_status:404 + +# Optional: Logging configuration +loglevel: info +transport-loglevel: warn + +# Optional: Metrics +metrics: 0.0.0.0:2000 + +# Optional: Enable compression +compression: gzip diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..76e2493 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +# LCC Table Tennis Booking - Production Deployment Script +# Domain: lcc-tt-booking.mikicvi.com + +set -e + +echo "🚀 Starting production deployment for LCC Table Tennis Booking..." + +# Check if .env.production exists +if [ ! -f .env.production ]; then + echo "❌ .env.production file not found!" + echo "Please create .env.production with your production environment variables." + exit 1 +fi + +# Create necessary directories +echo "📁 Creating necessary directories..." +mkdir -p data backups logs + +# Set proper permissions +echo "🔒 Setting directory permissions..." +chmod 755 data backups logs + +# Pull latest changes (if using git) +if [ -d ".git" ]; then + echo "📦 Pulling latest changes..." + git pull origin main || echo "⚠️ Git pull failed or not needed" +fi + +# Setup database +echo "🛠️ Setting up the database..." +npx tsx scripts/setup-database.ts + +# Build and deploy with Docker Compose +echo "🐳 Building and starting Docker containers..." + +# Stop existing containers +docker-compose -f docker-compose.production.yml down || echo "No existing containers to stop" + +# Build and start containers +docker-compose -f docker-compose.production.yml up -d --build + +# Wait for containers to be healthy +echo "⏳ Waiting for containers to be healthy..." +sleep 30 + +# Check health +echo "🔍 Checking application health..." +for i in {1..10}; do + if curl -f http://localhost:3000/api/health >/dev/null 2>&1; then + echo "✅ Application is healthy!" + break + elif [ $i -eq 10 ]; then + echo "❌ Application health check failed after 10 attempts" + echo "📋 Container logs:" + docker-compose -f docker-compose.production.yml logs tt-booking + exit 1 + else + echo "⏳ Attempt $i/10: Application not ready yet, waiting..." + sleep 10 + fi +done + +# Show running containers +echo "📊 Running containers:" +docker-compose -f docker-compose.production.yml ps + +# Show logs +echo "📋 Recent application logs:" +docker-compose -f docker-compose.production.yml logs --tail=20 tt-booking + +echo "" +echo "🎉 Deployment completed successfully!" +echo "" +echo "📊 Application Status:" +echo " • URL: https://lcc-tt-booking.mikicvi.com" +echo " • Health Check: http://localhost:3000/api/health" +echo " • Container Status: $(docker-compose -f docker-compose.production.yml ps -q tt-booking | xargs docker inspect -f '{{.State.Status}}')" +echo "" +echo "🔧 Useful commands:" +echo " • View logs: docker-compose -f docker-compose.production.yml logs -f tt-booking" +echo " • Restart: docker-compose -f docker-compose.production.yml restart tt-booking" +echo " • Stop: docker-compose -f docker-compose.production.yml down" +echo "" +echo "⚠️ Don't forget to:" +echo " 1. Set up Cloudflare Tunnel to expose your application" +echo " 2. Update your .env.production with real email credentials" +echo " 3. Change the default admin password" +echo "" \ No newline at end of file diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 0000000..75ffdf1 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,97 @@ +version: '3.8' + +services: + tt-booking: + build: + context: . + dockerfile: Dockerfile + container_name: lcc-tt-booking + ports: + - '3000:3000' + environment: + - NODE_ENV=production + - DATABASE_URL=/app/data/sqlite.db + - NEXTAUTH_URL=https://lcc-tt-booking.mikicvi.com + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - EMAIL_USER=${EMAIL_USER} + - EMAIL_PASSWORD=${EMAIL_PASSWORD} + - ADMIN_EMAIL=${ADMIN_EMAIL} + - ADMIN_PASSWORD=${ADMIN_PASSWORD} + - PORT=3000 + - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100} + - RATE_LIMIT_WINDOW=${RATE_LIMIT_WINDOW:-900000} + - LOG_LEVEL=${LOG_LEVEL:-info} + volumes: + - ./data:/app/data + - ./backups:/app/backups + restart: unless-stopped + healthcheck: + test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/health'] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + networks: + - lcc-network + + # Automated backup service + backup: + image: alpine:latest + container_name: lcc-backup + volumes: + - ./data:/data:ro + - ./backups:/backups + environment: + - TZ=Europe/Dublin + command: > + sh -c " + apk add --no-cache tzdata && + while true; do + timestamp=$$(date +%Y%m%d-%H%M%S) + echo \"Creating backup at $$timestamp\" + cp /data/sqlite.db \"/backups/sqlite-$$timestamp.db\" 2>/dev/null || echo 'No database file found yet' + # Keep backups for 30 days + find /backups -name 'sqlite-*.db' -mtime +30 -delete 2>/dev/null || true + echo \"Backup completed, sleeping for 24 hours\" + sleep 86400 + done" + restart: unless-stopped + depends_on: + - tt-booking + networks: + - lcc-network + + # Log rotation service + logrotate: + image: alpine:latest + container_name: lcc-logrotate + volumes: + - ./logs:/logs + command: > + sh -c " + apk add --no-cache logrotate && + echo '/logs/*.log { + daily + missingok + rotate 30 + compress + delaycompress + notifempty + }' > /etc/logrotate.d/app && + while true; do + logrotate /etc/logrotate.d/app + sleep 86400 + done" + restart: unless-stopped + networks: + - lcc-network + +networks: + lcc-network: + driver: bridge + +volumes: + lcc-data: + driver: local + lcc-backups: + driver: local diff --git a/drizzle.config.ts b/drizzle.config.ts index 85de5a3..16f0fc8 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -5,6 +5,6 @@ export default { out: './lib/db/migrations', driver: 'better-sqlite', dbCredentials: { - url: './sqlite.db', + url: process.env.DATABASE_URL || './data/sqlite.db', }, } satisfies Config; diff --git a/lib/db/index.ts b/lib/db/index.ts index 97f7766..f55498d 100644 --- a/lib/db/index.ts +++ b/lib/db/index.ts @@ -3,7 +3,9 @@ import { drizzle } from 'drizzle-orm/better-sqlite3'; import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import * as schema from './schema'; -const sqlite = new Database('./sqlite.db'); +// Get database path from environment variable or use default +const dbPath = process.env.DATABASE_URL || './data/sqlite.db'; +const sqlite = new Database(dbPath); export const db = drizzle(sqlite, { schema }); // Only run migrations if explicitly requested diff --git a/next.config.js b/next.config.js index fd19e7f..f32741d 100644 --- a/next.config.js +++ b/next.config.js @@ -8,6 +8,10 @@ const nextConfig = { }, ], }, + // Enable standalone output for Docker production builds + output: process.env.NODE_ENV === 'production' ? 'standalone' : undefined, + // External packages for better SQLite3 compatibility (Next.js 15+ syntax) + serverExternalPackages: ['better-sqlite3'], }; module.exports = nextConfig; diff --git a/scripts/setup-database.ts b/scripts/setup-database.ts index 1e7b31c..233b9d7 100644 --- a/scripts/setup-database.ts +++ b/scripts/setup-database.ts @@ -5,7 +5,8 @@ import { sql, eq } from 'drizzle-orm'; import { randomUUID } from 'crypto'; import bcrypt from 'bcryptjs'; -const sqlite = new Database('./sqlite.db'); +const dbPath = process.env.DATABASE_URL || './data/sqlite.db'; +const sqlite = new Database(dbPath); const db = drizzle(sqlite, { schema }); interface SetupOptions { diff --git a/scripts/test-irish-localization.js b/scripts/test-irish-localization.js deleted file mode 100644 index a58c0b5..0000000 --- a/scripts/test-irish-localization.js +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env node - -// Test script to verify Irish localization settings -console.log('🇮🇪 Testing Irish Localization Settings\n'); - -console.log('1. Week starts on Monday (Irish standard)'); -console.log(' JavaScript getDay() values:'); -console.log(' Sunday = 0, Monday = 1, ..., Saturday = 6'); -console.log(' Irish display order should be: Monday, Tuesday, ..., Sunday\n'); - -// Test date formatting -const testDate = new Date('2025-09-25'); // This is a Thursday -console.log('2. Date Formatting Test:'); -console.log(` Test date: ${testDate.toDateString()}`); -console.log( - ` Irish format (en-IE): ${testDate.toLocaleDateString('en-IE', { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - })}` -); -console.log(` Irish short format: ${testDate.toLocaleDateString('en-IE', { weekday: 'short' })}`); - -console.log('\n3. Day of Week Conversion:'); -const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; -for (let jsDay = 0; jsDay <= 6; jsDay++) { - const irishDisplayOrder = jsDay === 0 ? 6 : jsDay - 1; // Convert Sunday(0) to position 6, others shift down - console.log(` JS Day ${jsDay} (${daysOfWeek[jsDay]}) -> Irish position ${irishDisplayOrder}`); -} - -console.log('\n4. Week Structure for Admin Panel:'); -const irishWeekOrder = [1, 2, 3, 4, 5, 6, 0]; // Monday through Sunday in JS values -irishWeekOrder.forEach((jsDay, displayIndex) => { - console.log(` Display position ${displayIndex}: ${daysOfWeek[jsDay]} (JS day ${jsDay})`); -}); - -console.log('\n✅ Irish localization configuration complete!'); -console.log('📅 Calendar will now start with Monday'); -console.log('🇮🇪 All dates will use en-IE locale format'); -console.log('⏰ 24-hour time format maintained'); diff --git a/setup-tunnel.sh b/setup-tunnel.sh new file mode 100755 index 0000000..58d0f71 --- /dev/null +++ b/setup-tunnel.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Cloudflare Tunnel Setup Script for LCC Table Tennis Booking +# Domain: lcc-tt-booking.mikicvi.com + +set -e + +DOMAIN="lcc-tt-booking.mikicvi.com" +TUNNEL_NAME="lcc-tt-booking" + +echo "🌐 Setting up Cloudflare Tunnel for $DOMAIN" +echo "" + +# Check if cloudflared is installed +if ! command -v cloudflared &> /dev/null; then + echo "📥 Installing cloudflared..." + + # Detect architecture + ARCH=$(uname -m) + if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then + CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64" + elif [ "$ARCH" = "armv7l" ]; then + CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm" + else + CLOUDFLARED_URL="https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64" + fi + + # Download and install + curl -L --output cloudflared "$CLOUDFLARED_URL" + sudo mv cloudflared /usr/local/bin + sudo chmod +x /usr/local/bin/cloudflared + + echo "✅ cloudflared installed successfully!" +else + echo "✅ cloudflared is already installed" +fi + +echo "" +echo "🔐 Please follow these steps:" +echo "" +echo "1. Authenticate with Cloudflare:" +echo " cloudflared tunnel login" +echo "" +echo "2. Create the tunnel:" +echo " cloudflared tunnel create $TUNNEL_NAME" +echo "" +echo "3. Copy the tunnel ID from the output and update cloudflare-tunnel-config.yml" +echo "" +echo "4. Create DNS record:" +echo " cloudflared tunnel route dns $TUNNEL_NAME $DOMAIN" +echo "" +echo "5. Copy the config to cloudflared directory:" +echo " mkdir -p ~/.cloudflared" +echo " cp cloudflare-tunnel-config.yml ~/.cloudflared/config.yml" +echo " # Update in the config file with your actual tunnel ID" +echo "" +echo "6. Test the tunnel:" +echo " cloudflared tunnel run $TUNNEL_NAME" +echo "" +echo "7. Install as a service (optional):" +echo " sudo cloudflared service install" +echo " sudo systemctl enable cloudflared" +echo " sudo systemctl start cloudflared" +echo "" +echo "📋 Tunnel configuration template is available in: cloudflare-tunnel-config.yml" +echo "🚀 After setup, your app will be available at: https://$DOMAIN" +echo "" \ No newline at end of file