Building a Printful-Integrated T-Shirt E-Commerce Site: Next.js 14, Stripe Payments, and AWS Infrastructure
This post documents the technical architecture and deployment pipeline for 86dfrom.com, a Printful-integrated t-shirt storefront built with Next.js 14, Stripe payments, and AWS infrastructure. The goal was to create a production-ready e-commerce site with minimal overhead and maximum scalability.
What Was Built
A full-stack t-shirt storefront with the following components:
- Frontend: Next.js 14 with React Server Components, serving static and dynamic product pages
- Backend: Next.js API routes handling Printful variant fetching, Stripe payment processing, and order webhooks
- Infrastructure: Vercel for Next.js hosting, AWS S3 + CloudFront for static assets, Route53 for DNS, ACM for SSL/TLS
- Payment Processing: Stripe integration with webhook endpoint for order fulfillment
- Print Fulfillment: Printful API integration for variant management and order routing
Architecture Overview
The site uses a hybrid deployment strategy:
- Primary domain (86dfrom.com): Hosted on Vercel with full Next.js runtime support for dynamic API routes
- Redirect domain (86from.com): Lightweight CloudFront distribution with Lambda@Edge redirect function routing traffic to primary domain
- Static assets: Optimized through Next.js image optimization and Google Fonts caching
Why this approach? Vercel provides automatic HTTPS, global edge caching, and serverless functions out of the box. The redirect domain uses CloudFront + Lambda@Edge because it's cheaper than running a separate Vercel project when you only need HTTP-to-HTTPS redirects. AWS Route53 manages all DNS records for both domains, centralizing DNS management.
Infrastructure Setup
AWS Resources Created
The following AWS resources were provisioned:
- S3 Bucket:
86dfrom.com-assets— Originally intended for static asset hosting, now primarily used for CloudFront origin configuration and future backup/archive purposes - CloudFront Distribution (Primary): Configured as origin for
86dfrom.com, pointing to Vercel's origin with appropriate cache behaviors - CloudFront Distribution (Redirect): Dedicated distribution for
86from.com, running a Lambda@Edge function at viewer request to redirect all traffic to the primary domain - ACM Certificates: Wildcard certificates for both
86dfrom.comand86from.com, validated via Route53 DNS CNAME records - Route53 Hosted Zone: Single zone managing DNS for both domains, with A records pointing to CloudFront distributions
Why S3 + CloudFront over direct Vercel? While Vercel provides global CDN caching, adding CloudFront in front gives us additional control over cache headers, request/response transformations, and the ability to implement Lambda@Edge functions at the edge. This is particularly useful for the redirect domain, where a simple Lambda function eliminates the need for a full Vercel deployment.
File Structure
The project is organized as follows:
~/Documents/repos/sites/86dfrom.com/
├── site/
│ ├── index.html (landing page)
│ └── success.html (post-purchase confirmation)
├── gas/
│ ├── Code.gs (Google Apps Script for future automation)
│ ├── appsscript.json (GAS project config)
│ └── .clasp.json (clasp deployment metadata)
├── scripts/
│ └── deploy.sh (S3 + CloudFront deployment script)
└── .env.local (local development environment variables)
The core Next.js app remains at /Users/cb/Desktop/86dfrom/ during development, with production code synced to the git repository.
Printful Integration
The Printful API integration is the backbone of product management. The workflow is:
- Fetch available product variants from Printful API endpoint using store-specific API key
- Filter for the Black t-shirt variant (Bella+Canvas 3001, colors 4016–4020 representing size range)
- Store variant IDs in
.env.localfor use in checkout flow - When a customer purchases, create order via Printful API with variant ID and shipping details
The Printful account is scoped to the "Hello Dangerous" store with full API access across all Printful stores. This allows centralized variant management while maintaining separation from other stores within the same Printful organization.
Stripe Payment Processing
Stripe handles payment processing and order management:
- Checkout flow: Customer submits form → Next.js API route creates Stripe Session
- Webhook endpoint:
/api/webhookreceivespayment_intent.succeededevents - Order creation: Upon successful payment, webhook route creates order in Printful and records transaction in database
- Environment variables:
STRIPE_SECRET_KEYandSTRIPE_PUBLISHABLE_KEYstored in Vercel environment variables
Webhook secret management: The webhook signing secret (whsec_...) is obtained from Stripe Dashboard → Developers → Webhooks after initial Vercel deployment. This ensures the webhook endpoint can verify that incoming requests are actually from Stripe, preventing replay attacks.
Deployment Pipeline
Deployments happen in stages:
- Code validation: Next.js build must compile cleanly without errors
npm run build - Environment setup:
.env.localpopulated with:NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRET(after webhook setup)- Printful variant IDs
- Printful API key
- Vercel deployment:
Environment variables are synced to Vercel project settings before deploy.npx vercel@latest --prod - DNS configuration: Route53 A records point both domains to their respective CloudFront distributions
- Webhook setup: Stripe Dashboard → Developers → Webhooks → Add endpoint pointing to
https://86dfrom.com/api/webhook
Key Technical Decisions
- Next.js 14 over other frameworks: Server Components allow data fetching directly in components without additional middleware. API Routes provide serverless functions without infrastructure overhead. Vercel integration is seamless.