22 KiB
Active Context - Current Work Status
Current Task: DNS SWITCHOVER COMPLETE + EMAIL NOTIFICATIONS ENABLED ✅
MAD Lawsuit Website v2.0 - NOW LIVE AT MAIN DOMAIN:
- v1.0 Status: DECOMMISSIONED (containers stopped)
- v2.0 Status: LIVE AT https://mad-lawsuit.org (Laravel + Inertia + Vue)
- Current Phase: Phase 5 - DNS Switchover COMPLETE ✅
- Status: All systems operational at main domain 🎉
Latest Changes (December 19, 2025)
Phase 5.1 - DNS Switchover ✅ COMPLETE:
- Old Domain: v2.mad-lawsuit.org (preview)
- New Domain: mad-lawsuit.org (production)
- Changes Made:
- Updated
.env: Changed APP_URL and ASSET_URL to https://mad-lawsuit.org - Updated
docker-compose.yml: Changed port from 8080 to 806 (matching v1) - Updated Caddyfile: Point mad-lawsuit.org → localhost:806
- Added redirects: v2.mad-lawsuit.org → mad-lawsuit.org
- Stopped old v1.0 containers
- Updated
- SSL Certificate: Automatically issued by Caddy/Let's Encrypt
- Status: Website fully accessible at https://mad-lawsuit.org ✅
Phase 5.2 - Email Notifications to All Subscribers ✅ COMPLETE:
- Previous: Only sent test emails to chris@deafgain.org
- Now: Sends to all active subscribers in database
- Implementation:
- Modified
app/Http/Controllers/Admin/DocketEntryController.php - Queries all active subscribers:
Subscription::where('is_active', true)->get() - Loops through each subscriber and sends personalized email
- Each email includes unique unsubscribe token
- Added detailed logging (success/failure tracking)
- Handles individual failures gracefully
- Modified
- Subscriber Count: 27 active subscribers (28 total, 1 inactive)
- Status: Deployed and ready to use ✅
Phase 5.3 - iPad PDF Viewing Fix ✅ COMPLETE:
- Issue: iPad Safari couldn't scroll PDFs in modal viewer
- Solution: Detect iOS devices and open PDFs in new tab (native Safari viewer)
- Implementation:
- Updated
resources/js/Pages/Home.vue - Added iOS detection:
/iPad|iPhone|iPod/.test(navigator.userAgent) - Desktop: Opens PDF in modal viewer
- iOS/Mobile: Opens PDF in new tab
- Updated
- Status: Deployed and working perfectly ✅
Latest Enhancements (December 18, 2025)
Phase 4.1 - PDF Upload Fix ✅ COMPLETE:
- Problem: PDF uploads failing with "Permission denied" error
- Root Cause: nginx temp directories had incorrect permissions (750 on parent
/var/lib/nginx) - Solution: Updated Dockerfile to set parent directory to 755
- Files Modified:
Dockerfile- Addedchmod 755 /var/lib/nginxcommand- Rebuilt container with proper permissions
- Status: PDF uploads now working perfectly (tested with large files)
Phase 4.2 - Unsubscribe Confirmation Page ✅ COMPLETE:
- Feature: Two-step unsubscribe confirmation to prevent accidental unsubscribes
- Implementation:
- Created
resources/js/Pages/Unsubscribe.vuewith beautiful confirmation UI - Matches site styling (#6E6362 background, #6b9080 green buttons)
- Shows user's email address
- Two buttons: "Yes, Unsubscribe" (red) and "Cancel" (green)
- Success/error feedback with appropriate icons
- "Return to Home" button after completion
- Created
- Backend Changes:
- Added
showUnsubscribe()method toSubscriptionController - Updated routes:
GET /unsubscribe/{token}→ confirmation page - Kept
POST /api/unsubscribe/{token}for processing - Updated email template to use new route
- Added
- CSRF Fix: Fixed token retrieval with proper TypeScript casting
- Status: Fully deployed and working at https://v2.mad-lawsuit.org/unsubscribe/{token}
Phase 4.3 - Date Format Consistency ✅ COMPLETE:
- Issue: Subscriber page showing inconsistent date format
- Fix: Updated
resources/js/Pages/Admin/Subscribers/Index.vue - Format: Now shows American format (MM/DD/YYYY) matching home page and docket entries
- Implementation:
new Date(subscriber.created_at).toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }) - Status: All dates now consistent across the application
Phase 4.4 - Remove Pagination from Docket Entries ✅ COMPLETE:
- Change: Admin docket entries page now shows all entries on one page (no pagination)
- Backend Changes:
app/Http/Controllers/Admin/DocketEntryController.php:- Changed from
paginate(20)toget() - Removed pagination data from response
- Changed from
- Frontend Changes:
resources/js/Pages/Admin/DocketEntries/Index.vue:- Removed pagination interface and props
- Removed pagination UI (Previous/Next buttons)
- Shows total count: "X total entries"
- Rationale: Simpler interface for managing all entries at once
- Status: Deployed and working at https://v2.mad-lawsuit.org/admin/docket-entries
Production URLs
- v1.0 (Current): https://mad-lawsuit.org
- v2.0 (Ready): https://v2.mad-lawsuit.org
- v2.0 Admin: https://v2.mad-lawsuit.org/admin/login
- v2.0 Unsubscribe: https://v2.mad-lawsuit.org/unsubscribe/{token}
Admin Credentials
- Username: eliza
- Password: AXEoZWk2AMAD0naw
- Access: Full CRUD operations on docket entries, documents, and subscribers
v2.0 Phase 2 COMPLETED ✅
Admin Dashboard - Fully Functional:
Controllers Implemented:
- ✅ AuthController - Login/logout with session management
- ✅ DashboardController - Statistics and recent entries
- ✅ DocketEntryController - Full CRUD (7 resource methods, no pagination)
- ✅ DocumentController - PDF upload/delete with UUID naming (working perfectly)
- ✅ SubscriberController - List and deactivate subscribers
Vue Pages Created:
- ✅ Admin/Login.vue - Professional authentication page
- ✅ Admin/Dashboard.vue - Statistics cards, quick actions, recent entries
- ✅ Admin/DocketEntries/Index.vue - All entries on one page (no pagination)
- ✅ Admin/DocketEntries/Create.vue - Form for new entries
- ✅ Admin/DocketEntries/Edit.vue - Update existing entries
- ✅ Admin/DocketEntries/Show.vue - View details + upload documents
- ✅ Admin/Subscribers/Index.vue - Manage email subscribers (50 per page, American dates)
- ✅ Unsubscribe.vue - Two-step confirmation page with matching styling
Features Implemented:
- ✅ Session-based authentication (separate from Breeze)
- ✅ Full CRUD operations for docket entries
- ✅ PDF document upload with validation (500MB max, PDF only) - WORKING
- ✅ UUID-based file naming for security
- ✅ File storage in
storage/app/public/documents - ✅ Storage symlink configured (
php artisan storage:link) - ✅ No pagination for docket entries (all on one page)
- ✅ Pagination for subscribers (50 per page)
- ✅ Soft delete for subscribers (deactivate)
- ✅ Cascade delete for entries (removes documents)
- ✅ Professional UI with Tailwind CSS
- ✅ Form validation with error display
- ✅ Success/error flash messages
- ✅ Responsive design
- ✅ Mobile PDF viewing optimized (opens in new tab on screens < 768px)
- ✅ Unsubscribe confirmation page (prevents accidental unsubscribes)
- ✅ Consistent American date format (MM/DD/YYYY) across all pages
v2.0 Technology Stack
Backend:
- Framework: Laravel 12.43.1 (latest stable)
- PHP: 8.3.28
- Database: PostgreSQL 16-alpine (production)
- ORM: Eloquent (replacing Prisma)
- Auth: Laravel Sanctum + Session
- API: Inertia.js server-side
Frontend:
- Framework: Vue 3 + TypeScript
- Routing: Inertia.js (SSR-like experience)
- Styling: Tailwind CSS 3.x
- Build Tool: Vite 7.x
- Components: Vue SFC (Single File Components)
Production Environment:
- Server: 10.4.0.205 (dedicated server behind NAT)
- Docker: Alpine Linux containers
- Web Server: nginx 1.28.0
- PHP: PHP-FPM 8.3.28
- Database: PostgreSQL 16-alpine
- Reverse Proxy: Caddy (with auto-SSL)
v2.0 Progress Checklist
Phase 1 - Public Website ✅ COMPLETE:
- Install PHP 8.3 and Composer locally
- Create Laravel 12 project
- Install Laravel Breeze with Vue + Inertia + TypeScript
- Resolve NPM dependency conflicts (Vite 7 compatibility)
- Install all NPM packages successfully
- Create database migrations (docket_entries, documents, subscriptions, admin_users)
- Create Eloquent models with relationships
- Run migrations successfully (SQLite)
- Create HomeController with Inertia
- Build Vue home page component matching v1.0 design
- Test locally with development servers (php artisan serve + npm run dev)
- Verify website rendering correctly
- Implement email subscription API
- Add document download functionality
Phase 2 - Admin Dashboard ✅ COMPLETE:
- Build admin authentication (session-based)
- Create AdminUser model and migration
- Implement AuthController (login/logout)
- Create AdminAuth middleware
- Build Admin/Login.vue page
- Implement DashboardController with statistics
- Create Admin/Dashboard.vue page
- Implement DocketEntryController (all 7 CRUD methods)
- Create all DocketEntry Vue pages (Index, Create, Edit, Show)
- Implement DocumentController (store, destroy)
- Implement SubscriberController (index, destroy)
- Create Admin/Subscribers/Index.vue page
- Set up file storage for PDFs
- Configure storage symlink
Phase 3 - Data Migration ✅ COMPLETE (100%):
- Export v1.0 production data (PostgreSQL dump)
- Copy PDF files from production (69 files, 158MB)
- Create V1DataMigrationSeeder (tested with sample data)
- Create Python parser script (parse_sql_to_seeder.py)
- Identify parser limitation (only captured 32/63 entries)
- Create improved parser v2 (parse_sql_to_seeder_v2.py) with multi-line support
- Generate complete PHP arrays (63 entries, 63 docs, 28 subs)
- Update seeder with all production data
- Run seeder to import ALL data
- Verify 100% data integrity in database (63/63/28)
Phase 4 - Production Deployment ✅ COMPLETE (100%):
- Create Dockerfile and docker-compose.yml
- Build Docker image with PHP-FPM + nginx
- Fix PHP-FPM command issue (php-fpm8.3 → php-fpm)
- Deploy container to production server
- Configure Caddy reverse proxy
- Create production .env file
- Generate APP_KEY
- Fix AdminUser password double-hashing issue
- Update AdminSeeder with correct bcrypt hash
- Add TrustProxies middleware for HTTPS detection
- Match v1 background colors exactly
- Run migrations on production database
- Seed production database with v1 data
- Verify SSL certificate provisioning
- Test admin login (working perfectly)
- Test all functionality (all working)
- Visual design matches v1 exactly
Phase 4.1 - Post-Deployment Enhancements ✅ COMPLETE (100%):
- Fix PDF upload permissions (nginx temp directories)
- Create unsubscribe confirmation page
- Fix CSRF token issue in unsubscribe page
- Update email template with new unsubscribe route
- Fix subscriber date format to American (MM/DD/YYYY)
- Remove pagination from docket entries admin page
- Deploy all enhancements to production
- Test all new features
Phase 5 - DNS Switchover (PENDING USER DECISION):
- Update DNS: mad-lawsuit.org → v2.mad-lawsuit.org
- Monitor for 24-48 hours
- Decommission v1 containers
- Implement email notifications (future enhancement)
v2.0 Design Specifications
Complete v1.0 documentation captured:
- ✅ Visual design (colors, typography, layout)
- ✅ Component specifications (forms, cards, buttons)
- ✅ Functional requirements (interactions, animations)
- ✅ Data structures (63 entries, 63 PDFs, 28 subscribers)
- ✅ Admin dashboard specs (complete CRUD operations)
- ✅ Production data verified from live database
- ✅ Exact color matching from v1 container
Reference Document: cline_docs/v1_design_specifications.md (400+ lines)
Next Steps (Optional Enhancements)
Future Improvements:
- Email Notifications - Configure SMTP for subscriber notifications
- Monitoring - Set up application monitoring and alerts
- Backups - Automated database and file backups
- Performance - Redis caching for improved speed
- Analytics - Track visitor statistics
Data Migration Details
v1.0 Production Data:
- Docket Entries: 63 entries with dates, titles, summaries
- Documents: 63 PDF files (UUID filenames)
- Subscriptions: 28 email subscribers (27 active)
- Total Size: 158MB of PDF files
Schema Mapping (v1.0 → v2.0):
docket_entries.id→docket_entries.iddocket_entries.date→docket_entries.datedocket_entries.title→docket_entries.titledocket_entries.summary→docket_entries.summarydocket_entries.notes→docket_entries.notesdocket_entries.createdAt→docket_entries.created_atdocket_entries.updatedAt→docket_entries.updated_atdocuments.docketEntryId→documents.docket_entry_iddocuments.storedFilename→documents.stored_filenamedocuments.originalFilename→documents.original_filenamedocuments.fileSize→documents.file_sizedocuments.mimeType→documents.mime_typedocuments.displayOrder→documents.display_ordersubscriptions.isActive→subscriptions.is_activesubscriptions.unsubscribeToken→subscriptions.unsubscribe_tokensubscriptions.createdAt→subscriptions.created_at
Previous Task: v1.0 PRODUCTION SERVER MIGRATION COMPLETED ✅
MAD Lawsuit Website Successfully Migrated to New Infrastructure:
- Old Server: chrishaulmark.com (DigitalOcean VPS - being decommissioned)
- New Server: 10.4.0.205 (Dedicated server behind NAT)
- Status: FULLY OPERATIONAL WITH ALL DATA MIGRATED ✅
- v1.0 Tagged: Git tag
v1.0created and pushed to Gitea
Migration Implementation Details
Infrastructure Changes:
-
Package Upgrades ✅ COMPLETED
- Frontend: React 18→19, Next.js 15→16, Tailwind 3→4
- Backend: Prisma 5→7, Express 4→5
- All Dependencies: Updated to latest stable versions
- Docker Images: Rebuilt with new package versions
-
Caddy Reverse Proxy Fix ✅ COMPLETED
- Problem: Docker DNS resolving container hostnames to wrong network IPs
- Impact: Caddy timing out trying to reach containers
- Solution: Updated Caddyfile to use direct IP addresses on caddy_network
- Frontend IP: 172.18.0.6:806 (instead of hostname)
- Backend IP: 172.18.0.5:901 (instead of hostname)
- File:
/home/chaulmark/docker/caddy/config/Caddyfileon server
-
Data Migration ✅ COMPLETED
- Database: PostgreSQL data (47MB) migrated from old server
- PDF Files: 158MB of court documents (69 files) migrated
- Redis Cache: Cache data migrated
- Method: Created tar archive, transferred via rsync, extracted on new server
- Location:
/docker/websites/mad-lawsuit/on 10.4.0.205
-
SSL Certificates ✅ COMPLETED
- Provider: Let's Encrypt via Caddy
- Domains: mad-lawsuit.org, files.mad-lawsuit.org, v2.mad-lawsuit.org
- Status: Active and auto-renewing
Final Production Architecture
┌─────────────────────────────────────────────────────────┐
│ Caddy Reverse Proxy (10.4.0.205) │
│ │
│ mad-lawsuit.org → 172.18.0.6:806 (Frontend v1) │
│ files.mad-lawsuit.org → 172.18.0.5:901 (Backend v1) │
│ v2.mad-lawsuit.org → localhost:8080 (v2 LIVE) │
└─────────────────────────────────────────────────────────┘
│
├─────────────────────────────┐
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ Frontend │ │ Backend │
│ Port 806 │──────────────│ Port 901 │
│ Next.js 16 │ API Calls │ Express 5 │
│ React 19 │ │ Prisma 7 │
└─────────────┘ └─────────────┘
│
┌──────▼──────┐
│ PostgreSQL │
│ + Redis │
└─────────────┘
Deployment Server Information
IMPORTANT: All deployments now go to 10.4.0.205 (NOT chrishaulmark.com)
Server Details:
- Hostname: public-websites (internal: 10.4.0.205)
- External Access: Via NAT through dedicated server
- SSH Access:
ssh chaulmark@10.4.0.205 - v1 Project:
~/websites/mad-lawsuit.org/ - v2 Project:
~/websites/v2.mad-lawsuit.org/ - Docker Volumes:
/docker/websites/mad-lawsuit/
v2 Deployment Commands:
# SSH to production server
ssh chaulmark@10.4.0.205
# Navigate to v2 project
cd ~/websites/v2.mad-lawsuit.org
# Pull latest code
git pull origin main
# Build frontend assets inside container
docker exec mad-lawsuit-v2 npm run build
# For major changes, rebuild container
docker compose down
docker compose up -d --build
# Check container status
docker compose ps
docker compose logs -f app
# Run migrations
docker exec mad-lawsuit-v2 php artisan migrate --force
# Seed database
docker exec mad-lawsuit-v2 php artisan db:seed --class=V1DataMigrationSeeder --force
# Clear caches
docker exec mad-lawsuit-v2 php artisan config:clear
docker exec mad-lawsuit-v2 php artisan cache:clear
docker exec mad-lawsuit-v2 php artisan route:clear
Verification ✅
- v1 Website: https://mad-lawsuit.org (HTTP/2 200 ✓)
- v1 Backend API: https://files.mad-lawsuit.org (HTTP/2 200 ✓)
- v1 Database: 63 docket entries with all historical data ✓
- v1 PDF Files: 69 court documents accessible ✓
- v1 All Containers: Running and healthy ✓
- v2 Website: https://v2.mad-lawsuit.org (HTTP/2 200 ✓)
- v2 Admin: https://v2.mad-lawsuit.org/admin/login (Working ✓)
- v2 Database: 63 entries, 63 documents, 27 subscribers ✓
- v2 All Features: Fully operational ✓
- v2 PDF Upload: Working perfectly ✓
- v2 Unsubscribe: Confirmation page working ✓
- v2 Date Format: Consistent American format ✓
- v2 Pagination: Removed from docket entries ✓
Current Status
What's Working ✅
- v1.0 Production: Fully operational at https://mad-lawsuit.org
- v2.0 Production: FULLY OPERATIONAL at https://v2.mad-lawsuit.org
- v2.0 Admin: Login working, all CRUD operations functional
- v2.0 Database: All data migrated and verified
- v2.0 Design: Matches v1 exactly (colors, layout, functionality)
- v2.0 PDF Upload: Working perfectly with proper permissions
- v2.0 Unsubscribe: Two-step confirmation page prevents accidental unsubscribes
- v2.0 Date Format: Consistent American format (MM/DD/YYYY) across all pages
- v2.0 Docket Entries: All entries on one page (no pagination)
- SSL Certificates: Active on all domains
- File Storage: PDFs uploading and downloading correctly
- Authentication: Admin login persists across rebuilds
Ready for DNS Switchover 🎉
The v2.0 website is production-ready and can replace v1.0 at any time:
- All features working
- All data migrated
- Visual design matches exactly
- Admin dashboard fully functional
- PDF upload working
- Unsubscribe confirmation page active
- Date formats consistent
- Simplified admin interface (no pagination)
- SSL certificates active
- Performance tested
Next Steps for User
Optional - DNS Switchover:
- Update DNS: Point mad-lawsuit.org to v2.mad-lawsuit.org
- Monitor for 24-48 hours
- Decommission v1 containers once stable
- Consider future enhancements (email notifications, monitoring, etc.)
Files Modified (Latest Session - December 18, 2025)
PDF Upload Fix:
Dockerfile- Addedchmod 755 /var/lib/nginxfor proper permissions
Unsubscribe Feature:
resources/js/Pages/Unsubscribe.vue- Created confirmation pageapp/Http/Controllers/SubscriptionController.php- AddedshowUnsubscribe()methodroutes/web.php- Added GET route for confirmation pageresources/views/emails/new-docket-entry.blade.php- Updated unsubscribe link
Date Format Fix:
resources/js/Pages/Admin/Subscribers/Index.vue- American date format
Pagination Removal:
app/Http/Controllers/Admin/DocketEntryController.php- Changed toget()frompaginate()resources/js/Pages/Admin/DocketEntries/Index.vue- Removed pagination UI
Deployment Notes
- Phase 4.1 Complete: All post-deployment enhancements operational
- DNS Ready: v2.mad-lawsuit.org fully functional with all improvements
- SSL Active: Let's Encrypt certificates auto-renewed
- Data Verified: 100% migration success
- Design Verified: Exact match to v1
- Latest Commit:
b48b51ab(December 18, 2025)
Investigation Process
- Phase 1: Built public website matching v1.0 design ✅
- Phase 2: Implemented complete admin dashboard with CRUD ✅
- Phase 3: Exported production data and transferred PDF files, created seeders, imported all data ✅
- Phase 4: Deployed to production, fixed all issues, verified functionality ✅
- Phase 4.1: Post-deployment enhancements (PDF upload, unsubscribe, dates, pagination) ✅
The MAD lawsuit website v2.0 rebuild is 100% COMPLETE with all enhancements and ready for production use! 🎉