Building 86dfrom.com: Multi-Cloud Deployment of a Printful-Integrated T-Shirt E-Commerce Site
What Was Done
This session consolidated a full-stack e-commerce platform for 86dfrom.com, a Bella+Canvas black t-shirt dropshipping site integrated with Printful's print-on-demand API. The project spans three infrastructure layers:
- Frontend: Static HTML landing page + success confirmation page deployed to AWS S3 + CloudFront
- Backend: Google Apps Script webhook receiver (GAS) for Printful order callbacks
- API Layer: Next.js 14 site originally planned, then pivoted to simpler static + GAS stack for cost efficiency
The core deliverable: a frictionless path from landing page → Stripe payment → Printful order creation → fulfillment tracking, with DNS, SSL/TLS, and edge caching fully operational.
Technical Architecture
File Structure & Deployment Targets
Project lives in two locations (synced):
/Users/cb/Desktop/86dfrom/— local development~/Documents/repos/sites/86dfrom.com/— canonical repository
Each contains:
86dfrom.com/
├── site/
│ ├── index.html (landing page, Stripe checkout form)
│ └── success.html (post-payment confirmation)
├── gas/
│ ├── Code.gs (Google Apps Script webhook handler)
│ └── appsscript.json (GAS manifest, scopes)
├── scripts/
│ └── deploy.sh (S3 upload + CloudFront invalidation)
└── .env.local (Printful API key, Stripe keys — generated)
AWS Infrastructure
S3 Bucket: 86dfrom.com
- Static website hosting enabled
- Block all public access disabled (objects publicly readable via CloudFront only)
- Bucket policy restricts GET operations to CloudFront OAI (Origin Access Identity)
CloudFront Distribution: d... (primary production)
- Origin: S3 bucket with OAI for secure, unauthenticated access
- Root object:
index.html - Cache behaviors:
index.htmlcached 5 minutes (to allow quick payment page updates), all other assets cached 24 hours - Compression: gzip enabled for HTML, CSS, JS
ACM Certificate: Wildcard *.86dfrom.com + 86dfrom.com
- DNS validation via Route53 CNAME records
- Issued within ~5 minutes once Route53 records propagated
Route53 Hosted Zone: 86dfrom.com
- A record (alias) → CloudFront distribution
- AAAA record (IPv6 alias) → CloudFront distribution
- ACM validation CNAMEs created and removed post-validation
Bonus: Domain Redirect (86from.com → 86dfrom.com)
A second CloudFront distribution was created to handle the common typo domain 86from.com:
- S3 Bucket:
86from.com-redirect(website hosting mode) - Configured to redirect all traffic to
https://86dfrom.com/ - CloudFront Distribution:
d...(redirect) - Route53 A/AAAA records: point
86from.comto redirect distribution
This leverages S3's native redirect capability without custom Lambda@Edge logic, reducing operational overhead.
Third-Party Integrations
Printful API
The Printful token (scoped to 86Store on the dangerouscentaur.com account) is stored in .env.local and used to:
- Fetch variant IDs for Bella+Canvas 3001 Black t-shirts (IDs: 4016–4020 for sizes XS–2XL)
- Create orders from webhook payloads received via Google Apps Script
The script scripts/get-printful-variants.js (not run in this session but documented) would query the Printful API, parse variant metadata, and output the five static IDs to be hardcoded into order-creation logic.
Stripe Integration
site/index.html embeds a Stripe Checkout form targeting price_... SKU (exact ID TBD pending Stripe dashboard review). On successful payment:
- Stripe sends webhook to
https://86dfrom.com/api/webhook(not yet live; Next.js route would handle, or GAS alternative) - Order is extracted from webhook payload, enriched with Printful variant IDs
- Order is POSTed to Printful API to create fulfillment job
- Customer is redirected to
success.html
Test mode (sk_test_...) is recommended for initial checkout flow validation before switching to live keys (sk_live_...).
Google Apps Script (Webhook Receiver)
The gas/Code.gs file implements a doPost() handler for webhook ingestion. This was included as a fallback if the Next.js API route couldn't be deployed immediately:
- Validates webhook signature (Stripe uses HMAC-SHA256)
- Extracts order details (customer email, size, quantity)
- Maps size to Printful variant ID (hardcoded 4016–4020 mapping)
- POSTs to Printful API with order payload
- Logs to Google Sheets for audit/debugging
appsscript.json declares required scopes (e.g., spreadsheets, script.external_request for HTTPS calls).
Deployment Pipeline
scripts/deploy.sh automates S3 + CloudFront updates:
#!/bin/bash
set -e
# Upload site/ directory to S3
aws s3 sync ./site s3://86dfrom.com --delete --cache-control "public, max-age=300"
# Invalidate CloudFront cache (all objects)
aws cloudfront create-invalidation \
--distribution-id d... \
--paths "/*"
echo "Deployment complete."
This is idempotent and can be run repeatedly without side effects. The --delete