Publishing Charter Manifests to S3 + CloudFront: A Multi-Layer Document Pipeline for JADA Operations
This post documents the technical implementation of a document publishing pipeline for JADA's charter operations, specifically the workflow for generating, validating, and distributing charter manifests and trip sheets to crew-facing systems via S3 and CloudFront.
What Was Done
We implemented an end-to-end document pipeline for the Quinn Male charter (weekend of May 29, 2026) that:
- Generated HTML manifests and trip sheets from charter booking data
- Published documents to two separate S3 locations for redundancy and access control
- Invalidated CloudFront cache to ensure immediate availability across the crew-facing web app
- Verified document integrity and live URL accessibility before declaring the pipeline complete
The implementation moves charter documentation from static file generation into a dynamic, verifiable publishing workflow—critical for ensuring crew has accurate passenger manifests before embarkation.
Technical Architecture
Document Generation Layer
Charter documents are generated as HTML files from booking and crew data sources:
/tmp/quinn-male-manifest.html— HTML manifest with passenger names, contact info, and trip details/tmp/quinn-male-trip-sheet.html— Crew-facing operational sheet with timing, assignments, and logistics
Both files use a standardized HTML template structure derived from reference charters (e.g., McLaughlin), ensuring consistency across all JADA operations. The templates include inline CSS for print-friendly formatting—crew typically prints these documents for deck reference.
S3 Storage Strategy: Dual-Prefix Architecture
Documents are published to two distinct S3 locations within the same bucket (shipcaptaincrew):
# Primary location: JADA operations archive
s3://shipcaptaincrew/jada-ops/quinn-male/quinn-male-manifest.html
s3://shipcaptaincrew/jada-ops/quinn-male/quinn-male-trip-sheet.html
# Secondary location: Crew-facing document delivery
s3://shipcaptaincrew/docs/crew-page/{event_id}/quinn-male-manifest.html
s3://shipcaptaincrew/docs/crew-page/{event_id}/quinn-male-trip-sheet.html
Why two locations?
jada-ops/serves as a durable archive of all operational decisions and document versions—useful for auditing and historical analysisdocs/crew-page/is the active serving path that the shipcaptaincrew frontend SPA queries when rendering event detail pages
This dual-prefix pattern allows crew-page document rendering logic to reference a stable, predictable path while operations maintains a comprehensive historical record.
CloudFront Distribution & Cache Invalidation
The shipcaptaincrew CloudFront distribution sits in front of the S3 bucket, providing:
- Global edge caching for fast manifest downloads to crew at multiple locations
- TLS termination and DDoS protection
- Origin request handling for the crew-page document serving flow
After publishing updated manifests, we invalidate cache for both document paths to ensure CloudFront immediately fetches the latest version from S3:
# CloudFront invalidation command pattern
aws cloudfront create-invalidation \
--distribution-id <DIST_ID> \
--paths "/jada-ops/quinn-male/*" "/docs/crew-page/*/quinn-male-*"
Without invalidation, crew might receive stale manifests (cached up to 24 hours by default). For operational documents with time-sensitive passenger info, this is unacceptable.
Document Rendering Pipeline
The crew-facing web app (React/Vue SPA) implements a document fetch handler that:
- Receives an event detail request from the crew page (e.g.,
/event/quinn-male) - Extracts the
event_idfrom the booking system - Constructs document URLs using the
docs/crew-page/{event_id}/prefix - Checks for the existence of
{event_id}-manifest.htmland{event_id}-trip-sheet.html - Returns download links if documents exist; hides links if not yet published
This approach decouples document generation (backend, periodic) from document serving (frontend, on-demand). When a new charter is booked, operations generates and publishes documents to the crew-page prefix asynchronously—crew sees them appear on the event detail page within seconds of invalidation.
Key Technical Decisions
1. HTML Over PDF
Documents are generated as HTML, not PDF. This allows:
- Direct rendering in browser for crew on tablets/phones
- Copy-paste functionality for passenger names (useful for radio comms)
- Smaller file sizes and faster downloads on limited bandwidth connections at sea
- Easier version updates—no need to regenerate binary PDFs if formatting changes
2. Inline CSS for Print Resilience
Templates include inline styles (no external stylesheets) to ensure consistent printing regardless of crew's browser or print settings. This prevents last-minute formatting surprises when crew prints manifests on departure morning.
3. Dual Publishing for Operational Resilience
Publishing to both jada-ops/ and docs/crew-page/ ensures:
- If the crew-page document is accidentally deleted, operations has a backup copy
- Historical audit trail (all operations decisions recorded in jada-ops/)
- Clear separation of concerns—operations owns the archive; frontend owns the active serving path
4. CloudFront Invalidation Over Cache Headers
Rather than relying on short cache TTLs (which increase CloudFront origin traffic), we use explicit invalidation. This is more cost-effective at JADA's scale (~10-20 charters/week) and guarantees crew sees new documents immediately—no guessing about cache expiry.
Verification Workflow
After publishing, we verify document integrity:
# Verify HTTP 200 and content matches local file
curl -s -o /dev/null -w "%{http_code}" \
https://shipcaptaincrew.com/docs/crew-page/{event_id}/quinn-male-manifest.html
# Spot-check that passenger names appear in live document
curl -s https://shipcaptaincrew.com/jada-ops/quinn-male/quinn-male-manifest.html \
| grep "Passenger Name" | head -5
This two-step verification ensures both paths are live and the document content is accurate before crew notifications are sent.
Operational Workflow
The full pipeline runs as part of charter readiness preparation:
- Operations team pulls latest charter data from booking system
- Scripts generate manifest + trip sheet HTML files
- Documents are published to both S3 pref