19 KiB
19 KiB
Eliza Kragh v. MAD Court Docket Website - Design Specification
Project Overview
A public-facing website to display court documents and filings for the ongoing lawsuit: Eliza Kragh v. Montana Association of the Deaf. The system provides public transparency for court proceedings while allowing administrative management of documents and user notifications.
Technical Architecture
System Components
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Next.js 15.4 │ │ Express.js 6 │ │ PostgreSQL 17.5 │
│ Frontend │◄──►│ Backend API │◄──►│ Database │
│ (Port 3000) │ │ (Port 3001) │ │ (Port 5432) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ ┌─────────────────┐ │
│ │ Redis │ │
└──────────────►│ Cache/Session │◄─────────────┘
│ (Port 6379) │
└─────────────────┘
│
┌─────────────────┐
│ File System │
│ /uploads/ │
└─────────────────┘
Technology Stack (June 2025 Latest Versions):
- Frontend: Next.js 15.4.0 with React 19, TypeScript 6.0, Tailwind CSS
- Backend: Node.js 22 LTS, Express.js 6.0, TypeScript 6.0, Prisma 5.0
- Database: PostgreSQL 17.5 with Redis caching
- Infrastructure: Docker Engine 28.1.1, Nginx reverse proxy
Database Schema
Tables Structure
-- Docket Entries (main court filings)
CREATE TABLE docket_entries (
id SERIAL PRIMARY KEY,
date DATE NOT NULL,
document_type VARCHAR(100) NOT NULL,
summary TEXT NOT NULL,
court_notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Documents (PDFs associated with entries)
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
docket_entry_id INTEGER REFERENCES docket_entries(id) ON DELETE CASCADE,
original_filename VARCHAR(255) NOT NULL,
stored_filename VARCHAR(255) NOT NULL UNIQUE,
file_path VARCHAR(500) NOT NULL,
title VARCHAR(255) NOT NULL,
summary TEXT,
notes TEXT,
is_primary BOOLEAN DEFAULT FALSE,
file_size INTEGER NOT NULL,
display_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Email Subscriptions
CREATE TABLE subscriptions (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
unsubscribe_token VARCHAR(255) UNIQUE
);
-- Admin Users
CREATE TABLE admin_users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP
);
-- Indexes for performance
CREATE INDEX idx_docket_entries_date ON docket_entries(date DESC);
CREATE INDEX idx_documents_docket_entry ON documents(docket_entry_id);
CREATE INDEX idx_documents_display_order ON documents(docket_entry_id, display_order);
CREATE INDEX idx_subscriptions_active ON subscriptions(is_active);
API Endpoints
Public Endpoints
GET /api/docket-entries
Response: Array of docket entries with associated documents
{
"entries": [
{
"id": 1,
"date": "2024-12-15",
"document_type": "Motion to Dismiss",
"summary": "Defendant's motion...",
"court_notes": "Motion filed within deadline...",
"documents": [
{
"id": 1,
"title": "Main Document",
"summary": "Primary motion document",
"notes": "Filed by defendant's counsel",
"is_primary": true,
"display_order": 0
}
]
}
]
}
GET /api/documents/:id/download
Response: PDF file stream
Headers: Content-Type: application/pdf
POST /api/subscribe
Body: { "email": "user@example.com" }
Response: { "success": true, "message": "Subscribed successfully" }
GET /api/unsubscribe/:token
Response: Unsubscribe confirmation page
Admin Endpoints (Protected)
POST /api/auth/login
Body: { "username": "admin", "password": "password" }
Response: { "token": "jwt-token", "expires": "timestamp" }
POST /api/docket-entries
Body: {
"date": "2024-12-15",
"document_type": "Motion",
"summary": "Entry summary",
"court_notes": "Court notes",
"documents": [
{
"title": "Main Document",
"summary": "Document summary",
"notes": "Document notes",
"is_primary": true,
"file": "base64-encoded-pdf"
}
]
}
PUT /api/docket-entries/:id
Body: Updated entry data
Response: Updated entry object
DELETE /api/docket-entries/:id
Response: { "success": true }
POST /api/documents
Body: FormData with file and metadata
Response: Created document object
PUT /api/documents/:id
Body: Updated document metadata
Response: Updated document object
PUT /api/documents/:id/replace
Body: FormData with new file
Response: Updated document object
DELETE /api/documents/:id
Response: { "success": true }
File Management System
UUID-Based Naming Scheme
Format: {entry-id}_{document-type}_{uuid}.pdf
Examples:
001_main_a7b3c9d2-4e5f-6789-abcd-ef0123456789.pdf
001_exhibit_b8c4d0e3-5f60-789a-bcde-f01234567890.pdf
002_main_c9d5e1f4-6071-890b-cdef-012345678901.pdf
Directory Structure
uploads/
├── 2024/
│ ├── 12/
│ │ ├── 001_main_a7b3c9d2-4e5f-6789-abcd-ef0123456789.pdf
│ │ ├── 001_exhibit_b8c4d0e3-5f60-789a-bcde-f01234567890.pdf
│ │ └── 002_main_c9d5e1f4-6071-890b-cdef-012345678901.pdf
│ └── 11/
│ └── [previous month files]
└── 2025/
└── [future files]
File Upload Process
- Validate file type (PDF only) and size (max 10MB)
- Generate UUID for filename
- Create year/month directory structure
- Save file with UUID-based name
- Store metadata in database
- Return success response with document ID
Frontend Components
Public Interface Components
components/
├── Layout/
│ ├── Header.tsx # Site header with title and subscribe button
│ ├── Footer.tsx # Site footer
│ └── Layout.tsx # Main layout wrapper
├── Docket/
│ ├── DocketList.tsx # List of all docket entries
│ ├── DocketEntry.tsx # Individual entry display
│ ├── DocumentList.tsx # Documents within an entry
│ └── DocumentViewer.tsx # PDF viewing modal
├── Subscription/
│ ├── SubscribeForm.tsx # Email subscription form
│ └── SubscribeModal.tsx # Subscription confirmation modal
└── Common/
├── LoadingSpinner.tsx # Loading states
├── ErrorMessage.tsx # Error display
└── Button.tsx # Reusable button component
Admin Interface Components
components/admin/
├── Auth/
│ └── LoginForm.tsx # Admin login form
├── Dashboard/
│ ├── Dashboard.tsx # Main admin dashboard
│ ├── EntryList.tsx # Manage existing entries
│ └── Stats.tsx # Basic statistics
├── Entry/
│ ├── CreateEntry.tsx # New docket entry form
│ ├── EditEntry.tsx # Edit existing entry
│ └── DeleteEntry.tsx # Delete confirmation
├── Document/
│ ├── DocumentUpload.tsx # Multi-file upload component
│ ├── DocumentEdit.tsx # Edit document metadata
│ └── DocumentReplace.tsx # Replace PDF file
└── Layout/
├── AdminLayout.tsx # Admin layout wrapper
└── AdminNav.tsx # Admin navigation
User Interface Layouts
Public Docket Page
┌─────────────────────────────────────────────────────────────┐
│ ELIZA KRAGH v. MAD DOCKET │
│ [Subscribe] │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Case Information │
│ ───────────────── │
│ Case: Eliza Kragh v. Montana Association of the Deaf │
│ Status: Ongoing │
│ Last Updated: December 15, 2024 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Docket Entries │
│ ───────────────── │
│ [Date] | [Document Type] | [Summary] | [View] │
│ ──────────────────────────────────────────────────────── │
│ 12/15/24 | Motion to Dismiss | Defendant's motion... |[+] │
│ └─ 📄 Main Document │
│ └─ 📄 Exhibit A - Financial Records │
│ └─ 📄 Exhibit B - Email Correspondence │
│ ──────────────────────────────────────────────────────── │
│ 12/10/24 | Complaint | Plaintiff's initial filing... |[+] │
│ └─ 📄 Main Document │
│ └─ 📄 Exhibit 1 - Contract Agreement │
│ ──────────────────────────────────────────────────────── │
│ [More entries...] │
└─────────────────────────────────────────────────────────────┘
Admin Dashboard
┌─────────────────────────────────────────────────────────────┐
│ ADMIN DASHBOARD [Logout] │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ [+ New Docket Entry] │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Manage Existing Entries │
│ ────────────────────── │
│ 12/15/24 | Motion to Dismiss | [Edit] [Delete] │
│ └─ 📄 Main Document [Edit] [Replace] [Del] │
│ └─ 📄 Exhibit A [Edit] [Replace] [Del] │
│ └─ 📄 Exhibit B [Edit] [Replace] [Del] │
│ └─ [+ Add Document to Entry] │
│ ──────────────────────────────────────────────────────── │
│ 12/10/24 | Complaint | [Edit] [Delete] │
│ └─ 📄 Main Document [Edit] [Replace] [Del] │
│ └─ 📄 Exhibit 1 [Edit] [Replace] [Del] │
│ └─ [+ Add Document to Entry] │
└─────────────────────────────────────────────────────────────┘
Docker Configuration
docker-compose.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://backend:3001/api
depends_on:
- backend
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "3001:3001"
environment:
- DATABASE_URL=postgresql://docket_user:docket_pass@postgres:5432/docket_db
- REDIS_URL=redis://redis:6379
- JWT_SECRET=your-secret-key
- UPLOAD_DIR=/app/uploads
volumes:
- uploads:/app/uploads
depends_on:
- postgres
- redis
postgres:
image: postgres:15
environment:
- POSTGRES_DB=docket_db
- POSTGRES_USER=docket_user
- POSTGRES_PASSWORD=docket_pass
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/ssl:/etc/nginx/ssl
depends_on:
- frontend
- backend
volumes:
postgres_data:
uploads:
Security Implementation
Authentication & Authorization
- JWT tokens for admin authentication
- Token expiration and refresh mechanism
- Protected routes middleware
- Role-based access control
File Security
- Files served through API endpoints only
- No direct file system access
- File type validation (PDF only)
- File size limits (10MB max)
- UUID-based naming prevents enumeration
Input Validation
- All API inputs validated with Joi/Zod
- SQL injection prevention with Prisma ORM
- XSS protection with input sanitization
- CSRF protection for admin forms
Rate Limiting
- API endpoint rate limiting
- File upload rate limiting
- Login attempt limiting
- Email subscription rate limiting
Email Notification System
Subscription Process
- User enters email on public site
- Email validated and stored in database
- Confirmation email sent with unsubscribe token
- User added to active subscribers list
Notification Trigger
- Admin uploads new docket entry
- System checks for active subscribers
- Email notification queued for each subscriber
- Background job processes email queue
- Emails sent with entry summary and link
Email Template
Subject: New Filing in Eliza Kragh v. Montana Association of the Deaf
Dear Subscriber,
A new document has been filed in the case of Eliza Kragh v. Montana Association of the Deaf:
Date: December 15, 2024
Document Type: Motion to Dismiss
Summary: Defendant's motion to dismiss based on lack of jurisdiction...
View the complete filing and all documents at:
https://docket-site.com
To unsubscribe from these notifications, click here:
https://docket-site.com/unsubscribe/[token]
Best regards,
Court Docket Notification System
Performance Optimization
Frontend Optimization
- Next.js static generation for public pages
- Image optimization for any graphics
- Code splitting and lazy loading
- PDF.js worker for document rendering
- Caching strategies for API responses
Backend Optimization
- Database query optimization with indexes
- Redis caching for frequently accessed data
- File streaming for PDF downloads
- Connection pooling for database
- Compression middleware for API responses
Infrastructure Optimization
- Nginx reverse proxy with caching
- Gzip compression for static assets
- CDN integration for file serving
- Database connection pooling
- Redis session storage
Deployment Strategy
Development Environment
- Docker Compose for local development
- Hot reloading for both frontend and backend
- Development database with sample data
- Email testing with local SMTP server
Production Environment
- Docker Swarm or Kubernetes deployment
- SSL/TLS certificates with Let's Encrypt
- Production database with backups
- Real SMTP service for email notifications
- Monitoring and logging with ELK stack
CI/CD Pipeline
- GitHub Actions for automated testing
- Docker image building and pushing
- Automated deployment to staging
- Manual approval for production deployment
- Database migration automation
Testing Strategy
Unit Testing
- Backend API endpoints with Jest
- Frontend components with React Testing Library
- Database operations with test database
- File upload functionality testing
Integration Testing
- End-to-end user workflows with Cypress
- API integration testing
- Email notification testing
- File serving and download testing
Security Testing
- Authentication and authorization testing
- Input validation testing
- File upload security testing
- SQL injection prevention testing
This comprehensive design specification serves as the complete technical reference for implementing the Eliza Kragh v. MAD court docket website.