Overview
Complete AWS S3 integration for managing builder assets. Files are uploaded directly from the browser to S3 using pre-signed PUT URLs, keeping AWS credentials secure on the server while eliminating server-side file proxying.
Features
S3 Client (lib/s3.ts)
- Lazy Singleton - S3 client instantiated once and reused across requests
- Environment Validation - Throws descriptive errors if required env vars are missing
- CRC32 Checksum Fix - Disabled automatic checksum computation to prevent 403 errors on pre-signed PUT uploads
- Pre-Signed URL Generation -
createPresignedUploadUrl()with configurable expiry (default 5 minutes) - Public URL Construction -
getPublicAssetUrl()builds virtual-hosted-style S3 URLs - Object Tagging - Supports key/value tags for querying and lifecycle management
API Route (/api/upload/presigned-url)
- Zod Validation - Request body validated with strict schema for fileName, contentType, and folder
- Allowed MIME Types -
image/svg+xml,image/png,image/jpeg - Folder Whitelist - 8 organized folders:
logos/- Team logos and graphicsbrand-library/- Brand assetslibrary/- Shared asset librarydesigns/- Design templatesfabrics/- Fabric texturespatterns/- Pattern filesproducts/- Product imagesscreenshots/- Builder screenshots
- Collision-Free Keys - Timestamp-prefixed, sanitized file names (e.g.
logos/1707321600000-team_logo.svg) - S3 Object Tags - Each upload tagged with folder, source (
builder-upload), and content-type
Client Hook (useS3Upload)
- Two-Step Flow - Request pre-signed URL, then PUT directly to S3
- State Management - Exposes
isUploading,uploadError, andclearUploadError - Error Recovery - Catches and surfaces errors from both the API and S3 upload steps
- Typed Response - Full TypeScript types for the presigned URL response
Architecture
Browser Next.js API AWS S3
│ │ │
├─ POST /presigned-url ─────►│ │
│ ├─ createPresignedUrl ─►│
│ │◄─ signed URL ─────────┤
│◄─ { presignedUrl, publicUrl } │
│ │ │
├─ PUT file directly ────────────────────────────────►│
│◄─ 200 OK ─────────────────────────────────────────┤
│ │ │
└─ Store publicUrl in form │ │
Environment Variables
AWS_S3_BUCKET_NAME- S3 bucket name (e.g.asb-sports-assets)AWS_S3_REGION- AWS region (e.g.eu-central-1)AWS_S3_ACCESS_KEY_ID- IAM access key for S3 operationsAWS_S3_SECRET_ACCESS_KEY- IAM secret key for S3 operations
Dependencies Added
@aws-sdk/client-s3- AWS S3 client@aws-sdk/s3-request-presigner- Pre-signed URL generation