```html

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.html cached 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.com to 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