```html

Building a Printful-Integrated T-Shirt Commerce Site: Next.js 14, AWS Infrastructure, and Stripe Payment Integration

This post documents the technical implementation of 86dfrom.com, a Printful-integrated t-shirt e-commerce site built with Next.js 14. We'll cover the architecture decisions, infrastructure setup, and integration patterns that enable seamless product variant management and payment processing.

Project Architecture Overview

The 86dfrom project follows a modern serverless-first architecture:

  • Frontend: Next.js 14 with React, deployed to Vercel for edge-optimized serving
  • Backend: Next.js API routes (serverless functions) for Printful and Stripe integration
  • Static Assets: AWS S3 + CloudFront for CDN distribution with Route53 DNS management
  • Payment Processing: Stripe for transactions with webhook handlers for order confirmation
  • Print Fulfillment: Printful API for real-time variant data and order creation

This architecture decouples static content delivery (S3/CloudFront) from dynamic application logic (Vercel), allowing independent scaling and cost optimization for each layer.

Printful Integration: Variant Management Strategy

The core challenge in print-on-demand commerce is managing product variants—sizes, colors, and their associated Printful IDs. Rather than hardcoding these values, we implemented a dynamic variant discovery pattern.

Directory Structure:

/Users/cb/Documents/repos/sites/86dfrom.com/
├── site/
│   ├── index.html              # Landing page with product showcase
│   └── success.html            # Order confirmation page
├── gas/
│   ├── Code.gs                 # Google Apps Script webhook handler
│   └── appsscript.json         # GAS manifest and deployment config
├── scripts/
│   ├── deploy.sh               # S3 and CloudFront deployment automation
│   └── get-printful-variants.js # Variant ID discovery utility
├── .env.local                  # Local environment variables (generated)
└── .clasp.json                 # Clasp config for GAS deployment

Variant Discovery Pattern:

The scripts/get-printful-variants.js script queries the Printful API to fetch all available variants for a specific product (in this case, Bella+Canvas 3001 Black t-shirts). This approach ensures variant IDs remain synchronized with Printful's catalog—if Printful updates their variant structure, we can regenerate without code changes.

The script runs against the Printful Store API endpoint and extracts variant IDs (e.g., 4016–4020 for black t-shirt sizes), which are then injected into .env.local as comma-separated values. This decoupling means the frontend can render product options dynamically without hardcoded Printful IDs.

Environment Configuration and Secrets Management

The project uses a three-tier secrets strategy:

  • .env.local: Local development file (git-ignored) containing Printful API key, Stripe keys, and variant IDs
  • Vercel Environment Variables: Same secrets pushed to the Vercel deployment via CLI, ensuring production deployments have access to API credentials
  • Webhook Secrets: Stripe webhook signing secrets added post-deployment, once the Vercel URL is known and DNS is configured

This separation prevents credential sprawl and ensures that sensitive data never lives in version control. The build process fails gracefully if required environment variables are missing, catching configuration errors early.

AWS Infrastructure: S3, CloudFront, and Route53

S3 Bucket: 86dfrom-site-prod

The S3 bucket serves as the origin for our CloudFront distribution. The bucket policy restricts direct public access—all traffic flows through CloudFront, enabling caching, compression, and DDoS protection at the edge.

CloudFront Distribution (Primary): Maps 86dfrom.com to the S3 bucket origin. Key configurations:

  • Origin: S3 bucket with Origin Access Control (OAC) to prevent direct bucket access
  • TTL: 86400 seconds (24 hours) for HTML, shorter for dynamic assets
  • Compression: Gzip enabled for text assets (HTML, CSS, JSON)
  • Viewer Protocol Policy: Redirect HTTP to HTTPS, enforcing encrypted delivery
  • Functions: CloudFront Functions configured for request/response manipulation (e.g., adding security headers, 301 redirects for www/non-www variants)

CloudFront Distribution (Redirect): A second distribution handles the 86from.com86dfrom.com redirect. This lightweight distribution uses CloudFront Functions to intercept requests and issue 301 redirects without touching S3, reducing costs for redirect traffic.

Route53 Hosted Zone: DNS records for both 86dfrom.com and 86from.com are managed in Route53. Alias records point to their respective CloudFront distributions:

  • 86dfrom.com A → Primary CloudFront distribution
  • www.86dfrom.com CNAME → Primary CloudFront (canonical redirect via CloudFront Functions)
  • 86from.com A → Redirect CloudFront distribution

SSL/TLS Certificates: AWS Certificate Manager (ACM) issued two certificates: one for 86dfrom.com (with *.86dfrom.com wildcard) and one for the redirect domain. Both use DNS validation via Route53 CNAME records, enabling fully automated cert renewal.

Deployment Pipeline

Static Asset Deployment:

bash ~/Documents/repos/sites/86dfrom.com/scripts/deploy.sh

This script:

  1. Syncs site/ directory to S3 bucket with aws s3 sync, setting appropriate cache headers (immutable for hashed assets, 1-hour TTL for HTML)
  2. Invalidates CloudFront cache for /*, ensuring edge nodes fetch the latest version
  3. Logs deployment status and validates S3 object metadata

Vercel Deployment (Dynamic Application):

npx vercel@latest --prod

The Next.js application (API routes for Printful and Stripe, dynamic pages) deploys to Vercel, which automatically:

  • Runs the Next.js build to compile and optimize code
  • Deploys to Vercel's edge network (100+ data centers globally)
  • Sets environment variables from the Vercel dashboard
  • Generates a production URL (e.g., 86dfrom-production-xyz.vercel.app)

This separation of