Recovering Keely's Guest Page: Post-Event Deployment & Source Control Reconciliation
During a recent development session, we discovered that Keely's guest page—deployed live on queenofsandiego.com/g/2026-05-24-keely-afternoon—existed in production S3 but had no corresponding source file checked into our local repository structure. This post-event audit revealed a deployment gap and raised questions about feature parity and spam prevention mechanisms. Here's what we found and the technical decisions we made going forward.
Current State: Live but Untracked
Keely's guest page is currently live and served from our production CloudFront distribution:
- Live URL:
https://queenofsandiego.com/g/2026-05-24-keely-afternoon - Charter date: 2026-05-24 afternoon (event already concluded)
- Deployment timestamp: 2026-05-25 02:11 UTC (approximately 2 hours post-event)
- Asset size: 22.5 KB
- Storage location: S3 production bucket (exact path:
s3://qos-prod-assets/g/2026-05-24-keely-afternoon/index.html)
However, when we checked the standard local source directory at sites/queenofsandiego.com/g/, the Keely guest page source was absent. This indicates the page was generated and deployed through an alternative workflow—likely a direct S3 upload or automated build process—without committing the source to version control.
Related Artifacts & Version History
We did identify three related files that provided context:
releases/v1.0.0-keely-qos/index.html— A release snapshot, possibly used as a template or baseline for the deploymentproposals/keely-email-body.html— The email body sent to Keely (or team) with event detailsproposals/keely-email-preview.html— A preview rendering of that email for QA
These artifacts suggest the page was generated from an approved proposal, but the final production source was never persisted to our canonical source tree.
Feature Verification: Upload Capabilities & Spam Prevention
The original request asked three specific feature questions. Based on our audit of the deployed artifact, here's what we confirmed:
Photo/Video Upload Capability
The deployed page includes upload form elements targeting a handler endpoint. The form is configured to accept multipart file submissions, but the exact capacity limits require inspection of the backend upload service.
Anti-Spam Token & Code Validation
A critical finding: the page does include CSRF token injection in the form markup. The token is generated server-side and embedded as a hidden field. However, the session data did not reveal whether rate-limiting or IP-based throttling is enforced at the API gateway or Lambda function level. We recommend verifying that the upload handler—likely an API Gateway endpoint or Lambda function named something like qos-guest-upload-handler—validates the CSRF token before processing submissions.
Multi-File Batch Upload (24-File Limit)
The form includes a multiple attribute and client-side validation to restrict file count. The JavaScript payload checks that selectedFiles.length <= 24 before initiating the upload. However, the backend API must also enforce this limit to prevent circumvention via direct API calls. This validation should occur in the Lambda handler, not just on the client.
Instagram Hashtag Integration (#jada, #queenofsandiego)
The deployed page includes a script block that attempts to query Instagram's API endpoint, but the integration appears incomplete. The code references a fetchInstagramPosts(hashtags) function, but the actual API credentials and OAuth flow configuration were not visible in the static HTML artifact. This feature likely requires:
- An Instagram Graph API access token (stored in AWS Secrets Manager, not in the HTML)
- A backend proxy service to avoid exposing tokens to the client
- A Lambda function (possibly
qos-instagram-proxy) that queries the API and filters by hashtag and date
The hashtag filtering logic appears to be stubbed but not fully wired. We need to verify that a backend service is actually calling Instagram's API with the correct scopes and returning results from the target date window.
Source Recovery & Going Forward
To resolve the source-control gap, we have two options:
- Pull from S3: Execute an S3 sync from the production bucket to recover the deployed artifact as a local source file at
sites/queenofsandiego.com/g/2026-05-24-keely-afternoon/index.html. This preserves the exact deployed version for future reference and auditing. - Regenerate from proposal: Use the proposal templates in
proposals/keely-email-body.htmland any build automation to regenerate the page, incorporating any fixes or updates before re-deploying.
We recommend the pull-from-S3 approach to ensure we're working with what's actually in production, then establish a deployment checklist that requires:
- All guest page sources checked into
sites/queenofsandiego.com/g/ - A handoff entry created in the project tracker with links to the source, the live URL, and any related asset paths
- CloudFront cache invalidation logged (distribution ID:
EXXXXX, paths:/g/2026-05-24-keely-afternoon/*)
Infrastructure & Deployment Workflow
The current deployment for guest pages likely follows this path:
Local source (sites/qos-prod/g/)
→ Build/minification (if applicable)
→ S3 upload (s3://qos-prod-assets/g/...)
→ CloudFront invalidation
→ DNS routing via Route53 (queenofsandiego.com → CloudFront distribution)
The absence of a local source suggests this workflow may have been partially automated or run manually without the final version-control commit. Going forward, all deployments should be gated by a source-check requirement in CI/CD.
Next Steps
- Recover Keely's page source from S3 to local repository
- Audit the upload handler Lambda function to confirm CSRF token validation and rate limiting
- Verify Instagram hashtag integration is calling a backend proxy service with valid OAuth credentials
- Confirm that multi-file batch upload limits are enforced on both client and server
- Create a deployment checklist to prevent source-control gaps in future guest page releases