```html

Building a Printful-Integrated T-Shirt E-Commerce Site: Next.js 14, Vercel, and AWS Multi-Domain Setup

This post documents the complete build and deployment of 86dfrom.com, a Printful-integrated t-shirt storefront. We cover the full stack: Next.js 14 API routes for Printful variant fetching, Stripe payment integration, multi-domain DNS routing across Route53, and CloudFront distribution setup for both primary and redirect domains.

What Was Done

  • Built a Next.js 14 full-stack application with clean, production-ready routing
  • Integrated Printful API for real-time product variant management
  • Configured Stripe payment processing with webhook support
  • Deployed dual-domain infrastructure: 86dfrom.com (primary) and 86from.com (redirect)
  • Set up AWS S3, CloudFront, Route53, and ACM certificate validation across two domains
  • Established Google Apps Script backend for order fulfillment workflows

Architecture Overview

The system uses a three-tier architecture:

  • Frontend: Next.js 14 deployed to Vercel (primary site)
  • Static Assets: S3 buckets with CloudFront distributions for fast global delivery
  • Payment Processing: Stripe API with webhook handlers at /api/webhook
  • Print Fulfillment: Printful API integration + Google Apps Script automation
  • DNS/Routing: Route53 hosted zones managing both 86dfrom.com and 86from.com with domain consolidation via CloudFront

Technical Details: Project Structure

The project is organized across multiple directories:


/Users/cb/Documents/repos/sites/86dfrom.com/
├── site/                 # Static HTML (pre-rendered or backup)
│   ├── index.html       # Main storefront
│   └── success.html     # Order confirmation page
├── gas/                 # Google Apps Script
│   ├── Code.gs          # Fulfillment automation
│   └── appsscript.json  # GAS manifest with scopes
└── scripts/
    └── deploy.sh        # Automated S3 + CloudFront deploy

The Next.js application at /Users/cb/Desktop/86dfrom (monorepo structure) contains:

  • pages/api/variants.js — Fetches Printful variant IDs for Bella+Canvas 3001 Black (SKU variants 4016–4020)
  • pages/api/webhook — Stripe webhook endpoint for payment confirmations
  • .env.local — Environment variables (Printful API key, Stripe secret, webhook secret)
  • public/fonts/Anton.woff2 — Preloaded Google Font (self-hosted to avoid external dependency)

Printful API Integration: Variant Fetching

The scripts/get-printful-variants.js script queries the Printful API to retrieve product variant IDs:


node scripts/get-printful-variants.js

Why this approach: Variant IDs are stable but must be fetched once per product configuration. Hardcoding them would break if the product changes; fetching them at build time keeps .env.local minimal and allows runtime updates.

For 86dfrom.com, we target the Bella+Canvas 3001 unisex t-shirt in Black. The API returns variant objects; we extract the five size variants (4016–4020) representing XS through XL.

Infrastructure: AWS Multi-Domain Setup

S3 Buckets:

  • 86dfrom.com — Primary static site bucket
  • 86from.com — Redirect bucket (lower traffic, domain consolidation)

ACM Certificates:

  • Requested separate certificates for both 86dfrom.com and 86from.com
  • DNS validation via Route53 CNAME records (fully automated, no manual email confirmation required)
  • Certificate status polled until ISSUED before creating distributions

CloudFront Distributions:

  • Primary Distribution (86dfrom.com):
    • Origin: S3 bucket 86dfrom.com
    • Default root object: index.html
    • Viewer protocol policy: Redirect HTTP to HTTPS
    • Cache behavior: TTL 3600s for HTML, 31536000s for versioned assets
    • Alternate domain names: www.86dfrom.com
  • Redirect Distribution (86from.com):
    • Origin: S3 bucket (redirect bucket)
    • Function: CloudFront Function at us-east-1 rewrites all requests to HTTPS redirect to primary domain
    • Prevents duplicate content; consolidates traffic to primary domain

Route53 Configuration:


# Primary domain
86dfrom.com            A    [CloudFront dist alias]
www.86dfrom.com        A    [CloudFront dist alias]

# Redirect domain
86from.com             A    [CloudFront redirect dist alias]

Alias records point to CloudFront distributions (no additional costs, auto-health-checked).

Deployment Strategy

Static Assets (S3 + CloudFront):

The scripts/deploy.sh script handles automated deployment:


#!/bin/bash
aws s3 sync site/ s3://86dfrom.com --delete
aws cloudfront create-invalidation --distribution-id [DIST_ID] --paths "/*"

This ensures:

  • Files deleted locally are removed from S3 (no stale assets)
  • CloudFront cache is invalidated immediately (no wait for TTL expiration)
  • Global CDN refresh within seconds

Next.js Application (Vercel):

The primary application deploys to Vercel:


npx vercel@latest --prod

Why Vercel: Zero-config Next.js deployment, automatic HTTPS, environment variable management, and webhook endpoint accessibility (critical for Stripe).

Environment Variables in Vercel:

  • PRINTFUL_API