Complete pipeline for CamelBak Thrive Flip Straw Water Bottle (catalog 848) on Printful. Covers UV print design, product creation, variant management, mockup generation, and Supabase integration. Use when creating CamelBak water bottle products, generating bottle mockups, or managing drinkware products with UV printing.
Scanned 6/1/2026
Install to Claude Code
npx -y skills add lroy-stack/ai-pod-store --skill printful-camelbak-thrive --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Printful Camelbak Thrive?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lroy-stack-printful-camelbak-thrive)More formats (shields.io, HTML) on the badges page.
---
name: Printful CamelBak Thrive Production
description: >-
Complete pipeline for CamelBak Thrive Flip Straw Water Bottle (catalog 848) on Printful.
Covers UV print design, product creation, variant management, mockup generation,
and Supabase integration. Use when creating CamelBak water bottle products, generating
bottle mockups, or managing drinkware products with UV printing.
---
# Printful CamelBak Thrive Production Pipeline
Full production pipeline for SKAPARA-branded CamelBak Thrive Flip Straw Water Bottles using UV printing on Printful. This is a premium outsourced drinkware product with a cylindrical wrap print area.
> **EU FULFILLMENT WARNING**: This product is an outsourced CamelBak-branded item. Printful does NOT manufacture this in-house. EU fulfillment is UNCERTAIN and likely US-only. Verify via Printful dashboard before creating products intended for EU customers. If EU fulfillment is unavailable, this product should be marketed with a shipping notice or restricted to non-EU storefronts.
For Printify-based drinkware (mugs, tumblers), see the `design-sublimation` skill instead.
---
## Product Specifications
| Property | Value |
|---|---|
| **Blank** | CamelBak Thrive Flip Straw Water Bottle |
| **Catalog ID** | 848 |
| **Tier** | PREMIUM DRINKWARE |
| **Material** | BPA-free Tritan Renew (50% recycled plastic) |
| **Capacity** | 25 oz (739 ml) |
| **Construction** | Stain/shatter/odor-resistant, leak-proof, bite valve |
| **Colors** | 5 (Charcoal, Clear, Cove, Forest Green, Oxford Blue) |
| **Sizes** | 25 oz (single size) |
| **Print Method** | UV Printing |
| **Variants** | 22016-22020 (5 total) |
| **Producer** | Printful (outsourced — CamelBak brand) |
| **EU Fulfillment** | UNCERTAIN — likely US only |
---
## When to Use
- Create a new CamelBak water bottle product on Printful
- Upload wrap designs for UV printing on cylindrical bottles
- Generate mockups for CamelBak Thrive products
- Manage CamelBak variant colors (5 bottle colors)
- Update Supabase with CamelBak product data and mockup images
---
## UV Printing — Technique Specifications
UV printing uses ultraviolet light to cure ink directly onto the surface. Unlike sublimation (which infuses ink into the material), UV printing sits ON TOP of the surface.
| Property | Value |
|---|---|
| **Color space** | Full CMYK — photographic quality |
| **Resolution** | 300 DPI |
| **Surface** | Cylindrical wrap (bottle body) |
| **Durability** | Dishwasher-safe (top rack), scratch-resistant |
| **Opacity** | Opaque — white underbase auto-generated by Printful |
| **Fill mode** | `fit` (design scaled to fit within print area) |
### Design Considerations for Cylindrical UV Print
1. **Curvature distortion**: The design wraps around a cylinder. Horizontal elements near the edges will appear foreshortened when viewed from a single angle. Keep critical elements (text, logos) centered horizontally.
2. **Seam area**: There is a vertical seam where the wrap meets. Avoid placing critical design elements at the far left/right edges (first/last ~100px).
3. **Vertical safe zone**: The top and bottom of the print area approach the cap and base. Keep content away from the top/bottom 50px.
4. **White on dark bottles**: UV ink is opaque with white underbase — white elements print true white even on dark bottle colors (Charcoal, Oxford Blue, Forest Green).
5. **Transparency**: Transparent areas show the bottle color underneath. Use this intentionally for design integration with bottle color.
### Canvas & Printfile
| Placement | Printfile | Canvas (px) | DPI | Physical | Fill |
|---|---|---|---|---|---|
| `default` | PF#445 | 2914 x 1196 | 300 | ~9.71" x 3.99" wrap | fit |
**Wrap coverage**: The canvas wraps approximately 270-300 degrees around the bottle. There is a small unprinted seam strip.
---
## SKAPARA Branding for Bottle Wrap
The CamelBak Thrive has a single `default` placement — the full wrap. SKAPARA branding must be **integrated into the wrap design itself**.
### Recommended Layout (2914 x 1196 px)
```
+------------------------------------------------------------------+
| |
| MAIN DESIGN AREA |
| (center 2200px, full height) |
| |
| [SKAPARA logo lockup] [skapara.com] |
| (bottom-left, ~400x80px) (bottom-right, small text) |
| |
+------------------------------------------------------------------+
^seam zone (~100px) seam zone (~100px)^
```
**Branding variants per design style:**
- **Gradient/colorful designs**: Use full-color SKAPARA gradient lockup
- **Dark/minimal designs**: Use white SKAPARA wordmark
- **Light/clean designs**: Use dark SKAPARA wordmark
- **Photo-heavy designs**: Use small S mark isotipo in corner, semi-transparent
**Branding assets** (in `/frontend/public/brand/`):
- `skapara-mark-color.svg` — Full color S mark
- `skapara-mark-dark.svg` — Dark S mark
- `skapara-mark-white.svg` — White S mark
- `skapara-wordmark-dark.svg` — Dark wordmark
---
## Base Costs (Production)
All 5 variants have the same base cost:
| Size | Base Cost (EUR) | Notes |
|---|---|---|
| 25 oz (all colors) | 22.95 | Single size, single placement |
No additional placement costs — the `default` placement is included.
---
## Pricing Strategy
Target minimum 35% margin per SKAPARA pricing rules.
| Retail Price (EUR) | Base Cost | Margin | Notes |
|---|---|---|---|
| 35.99 | 22.95 | 36.2% | Recommended minimum |
| 37.99 | 22.95 | 39.6% | Standard pricing |
| 39.99 | 22.95 | 42.6% | Premium design pricing |
**CRITICAL:** Set prices in Printful FIRST. The cron sync margin fixer overwrites prices if margin falls below 35%.
---
## Printful API Reference
**Auth headers (ALL requests):**
```
Authorization: Bearer ${PRINTFUL_API_TOKEN}
X-PF-Store-Id: ${PRINTFUL_STORE_ID}
Content-Type: application/json
User-Agent: POD-AI-Store/1.0
```
**Rate limits:**
- General API: ~120 req/min. Use `delay(2000)` between calls
- Mockup Generator: ~10 req/min. Use `delay(10000)` between tasks
- On 429: read `x-ratelimit-reset` header, wait that many seconds, retry
**Shared utility:** For scripts, use `import { createPrintfulClient } from './lib/printful-rate-limiter.mjs'`
**Key endpoints:**
| Endpoint | Method | Use |
|---|---|---|
| `/files` | POST | Upload image to File Library |
| `/store/products` | POST | Create new sync product |
| `/store/products/{id}` | GET/PUT | Read/update sync product + all variants |
| `/store/variants/{vid}` | PUT | Update single variant |
| `/mockup-generator/create-task/848` | POST | Create CamelBak mockup task |
| `/mockup-generator/task?task_key=gt-xxx` | GET | Poll mockup task status |
| `/mockup-generator/printfiles/848` | GET | List CamelBak print positions |
---
## Workflow: Create New CamelBak Thrive Product
### Step 1: Design the Wrap (2914 x 1196 px @ 300 DPI)
Create the UV print design as a PNG file:
- Canvas: 2914 x 1196 px
- Resolution: 300 DPI
- Color mode: sRGB
- Format: PNG (transparency allowed — transparent areas show bottle color)
- Integrate SKAPARA branding into the design (see Branding section above)
**Design safe zones:**
- Left/right edges: 100px seam buffer
- Top/bottom: 50px buffer
- Critical content: center 2714 x 1096 px
### Step 2: Upload Design to File Library
Upload to Supabase Storage first (permanent hosting), then POST the public URL to Printful.
```bash
# Upload to Supabase Storage
curl -X POST "${SUPABASE_URL}/storage/v1/object/designs/uploads/${FILENAME}" \
-H "Authorization: Bearer ${SUPABASE_SERVICE_KEY}" \
-H "apikey: ${SUPABASE_SERVICE_KEY}" \
-H "Content-Type: image/png" \
-H "x-upsert: true" \
--data-binary "@${LOCAL_FILE_PATH}"
# Get public URL
PUBLIC_URL="${SUPABASE_URL}/storage/v1/object/public/designs/uploads/${FILENAME}"
# Upload to Printful File Library
curl -X POST "https://api.printful.com/files" \
-H "Authorization: Bearer ${PRINTFUL_API_TOKEN}" \
-H "X-PF-Store-Id: ${PRINTFUL_STORE_ID}" \
-H "Content-Type: application/json" \
-H "User-Agent: POD-AI-Store/1.0" \
-d '{
"url": "'${PUBLIC_URL}'",
"filename": "'${FILENAME}'"
}'
```
**Response:** `{ "result": { "id": 123456789, "type": "default", "preview_url": "..." } }`
Save the `id` — this is the `WRAP_FILE_ID` used in all subsequent API calls.
### Step 3: Create Sync Product
```bash
curl -X POST "https://api.printful.com/store/products" \
-H "Authorization: Bearer ${PRINTFUL_API_TOKEN}" \
-H "X-PF-Store-Id: ${PRINTFUL_STORE_ID}" \
-H "Content-Type: application/json" \
-H "User-Agent: POD-AI-Store/1.0" \
-d '{
"sync_product": {
"name": "Product Name — CamelBak Thrive",
"thumbnail": "https://files.cdn.printful.com/files/.../preview.png"
},
"sync_variants": [
{
"variant_id": 22016,
"retail_price": "37.99",
"files": [
{ "type": "default", "id": WRAP_FILE_ID }
]
},
{
"variant_id": 22017,
"retail_price": "37.99",
"files": [
{ "type": "default", "id": WRAP_FILE_ID }
]
},
{
"variant_id": 22018,
"retail_price": "37.99",
"files": [
{ "type": "default", "id": WRAP_FILE_ID }
]
},
{
"variant_id": 22019,
"retail_price": "37.99",
"files": [
{ "type": "default", "id": WRAP_FILE_ID }
]
},
{
"variant_id": 22020,
"retail_price": "37.99",
"files": [
{ "type": "default", "id": WRAP_FILE_ID }
]
}
]
}'
```
**Key points:**
- `variant_id` is the **catalog variant ID** from VARIANTS.md (22016-22020)
- `retail_price` is the customer-facing price as a string
- `files[].type` = `"default"` for the wrap placement
- Include ALL 5 color variants
- The `files` array is identical for all variants (same design wraps all colors)
### Step 4: Set Variant Prices
All variants use the same price (single size product):
| Variant | Color | Retail Price | Base Cost | Margin |
|---|---|---|---|---|
| 22016-22020 | All | 37.99 | 22.95 | 39.6% |
**CRITICAL:** Set prices in Printful FIRST. The cron sync margin fixer overwrites prices if margin falls below 35%.
### Step 5: Generate Mockups
```bash
curl -X POST "https://api.printful.com/mockup-generator/create-task/848" \
-H "Authorization: Bearer ${PRINTFUL_API_TOKEN}" \
-H "X-PF-Store-Id: ${PRINTFUL_STORE_ID}" \
-H "Content-Type: application/json" \
-H "User-Agent: POD-AI-Store/1.0" \
-d '{
"variant_ids": [22016],
"format": "png",
"width": 1000,
"files": [
{
"placement": "default",
"image_url": "DESIGN_PREVIEW_URL",
"position": {
"area_width": 2914,
"area_height": 1196,
"width": 2914,
"height": 1196,
"top": 0,
"left": 0
}
}
]
}'
```
**Generate mockups for ALL 5 colors.** Each color shows through transparent areas differently.
Poll for completion:
```bash
curl -s "https://api.printful.com/mockup-generator/task?task_key=gt-XXXXXXXX" \
-H "Authorization: Bearer ${PRINTFUL_API_TOKEN}" \
-H "X-PF-Store-Id: ${PRINTFUL_STORE_ID}" \
-H "User-Agent: POD-AI-Store/1.0"
```
### Step 6: Download Mockups & Upload to Supabase Storage
Mockup S3 URLs expire in ~24h. Always download and re-upload to permanent storage:
```javascript
const storagePath = `designs/mockups/${productSlug}/${colorSlug}-default.png`
const ts = Math.floor(Date.now() / 1000)
const publicUrl = `${SUPABASE_URL}/storage/v1/object/public/designs/${storagePath}?v=${ts}`
```
### Step 7: Update Supabase products Table
```javascript
const ts = Math.floor(Date.now() / 1000)
const images = [
{ src: `https://.../mockups/slug/charcoal-default.png?v=${ts}`, alt: 'Title - Charcoal' },
{ src: `https://.../mockups/slug/clear-default.png?v=${ts}`, alt: 'Title - Clear' },
{ src: `https://.../mockups/slug/cove-default.png?v=${ts}`, alt: 'Title - Cove' },
{ src: `https://.../mockups/slug/forest-green-default.png?v=${ts}`, alt: 'Title - Forest Green' },
{ src: `https://.../mockups/slug/oxford-blue-default.png?v=${ts}`, alt: 'Title - Oxford Blue' },
]
// 1. Create or update product in Supabase
await supabase.from('products').upsert({
id: productId,
title: 'Product Name',
description: 'Creative marketing description only. No specs here.',
translations: {
es: { title: 'Titulo en espanol', description: 'Descripcion en espanol' },
de: { title: 'Titel auf Deutsch', description: 'Beschreibung auf Deutsch' }
},
category_id: 'DRINKWARE_CATEGORY_UUID', // FK to categories table — drinkware
pod_provider: 'printful',
product_template_id: '848', // CamelBak Thrive catalog ID
provider_product_id: String(pfProductId), // Printful sync product ID
base_price_cents: 3799,
compare_at_price_cents: 5999, // Strikethrough price
images,
product_details: {
safety_information: GPSR_HTML,
material: 'BPA-free Tritan Renew (50% recycled plastic)',
care_instructions: 'Dishwasher safe (top rack only). Hand wash lid assembly. Do not microwave. Do not freeze.',
print_technique: 'UV Printing',
manufacturing_country: 'USA (outsourced — CamelBak)', // NOTE: Not EU manufactured
brand: 'SKAPARA',
blank: 'CamelBak Thrive Flip Straw Water Bottle',
capacity: '25 oz (739 ml)',
construction: 'Stain/shatter/odor-resistant, leak-proof, bite valve',
recycled_content: '50% recycled Tritan Renew plastic'
},
status: 'active'
})
// 2. Create product variants (all 5 colors)
for (const { color, variantId } of variants) {
await supabase.from('product_variants').upsert({
product_id: productId,
color,
color_hex: colorHexMap[color],
size: '25 oz',
is_enabled: true,
external_variant_id: String(variantId),
image_url: `https://.../mockups/slug/${colorSlug}-default.png?v=${ts}`
})
}
```
### Step 8: GPSR Compliance (MANDATORY for EU)
Every product MUST have GPSR data before going live. EU Regulation 2023/988.
```html
<p><strong>Manufacturer:</strong> CamelBak Products, LLC (outsourced via Printful Inc.)</p>
<p><strong>Material:</strong> BPA-free Tritan Renew (50% recycled plastic)</p>
<p><strong>Capacity:</strong> 25 oz (739 ml)</p>
<p><strong>Construction:</strong> Stain-resistant, shatter-resistant, odor-resistant, leak-proof with bite valve</p>
<p><strong>Print technique:</strong> UV Printing — cured with ultraviolet light, dishwasher-safe</p>
<p><strong>Care:</strong> Dishwasher safe (top rack only). Hand wash lid assembly. Do not microwave. Do not freeze.</p>
<p><strong>Compliance:</strong> BPA-free, FDA food-contact safe</p>
<p><strong>WARNING:</strong> EU fulfillment unverified — product may ship from US facility</p>
```
Store in `products.product_details.safety_information` (JSONB).
### Step 9: Post-Creation Verification
- [ ] Product appears in shop with correct category (drinkware)
- [ ] All 5 color variants show in ProductCard color toggles
- [ ] Size correctly shows as "25 oz"
- [ ] Price is correct (not overridden by margin fixer)
- [ ] Mockup images load for all 5 colors
- [ ] GPSR safety information stored in `product_details`
- [ ] EU fulfillment warning noted in product details or admin notes
- [ ] Description is clean (no HTML tags, max 2000 chars)
- [ ] Alt text follows pattern: "Title - Color"
- [ ] Cache-buster `?v=timestamp` appended to all image URLs
- [ ] Translations present for ES and DE
---
## Known Issues & Gotchas
| Issue | Detail | Workaround |
|---|---|---|
| EU fulfillment uncertain | CamelBak is outsourced, likely US-only | Verify in Printful dashboard; add shipping notice if US-only |
| Cylindrical distortion | Flat design wraps around cylinder — edges foreshorten | Keep critical elements centered, avoid edge placement |
| Seam line | Vertical seam where wrap meets | Leave 100px buffer on left/right edges |
| Temporary mockup URLs | S3 URLs expire ~24h | Always download + re-upload to Supabase Storage |
| Python urllib blocked | Cloudflare rejects Python urllib against Printful API | Use curl or Node.js fetch |
| Margin fixer | Cron sync overwrites prices if margin <35% | Set correct price in Printful FIRST |
| Cloudflare 403 | Missing User-Agent causes blocks | Always include `User-Agent: POD-AI-Store/1.0` |
| Cache-busting | Browser/CDN cache images by URL | ALWAYS append `?v=timestamp` when overwriting Supabase Storage files |
| Single placement only | Only `default` — no back, no label | All branding must be integrated into the wrap design |
| Transparency shows bottle color | UV print — transparent areas reveal underlying bottle color | Design intentionally for this OR use fully opaque backgrounds |
---
## Description Rules
**What goes in `description`** (creative text only):
- Product context, design inspiration, target audience
- 2-3 sentences max, casual but smart tone
- Highlight eco-friendly angle: "50% recycled Tritan Renew", "BPA-free"
- Mention durability: "shatter-resistant", "dishwasher safe"
- Reference the CamelBak quality: "The hydration brand trusted by athletes"
- Must be translated to EN, ES, DE
**What does NOT go in `description`:**
- Material composition -> `product_details.material`
- Care instructions -> `product_details.care_instructions`
- Manufacturing info -> `product_details.manufacturing_country`
- Safety/compliance -> `product_details.safety_information`
- Capacity specs -> `product_details.capacity`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!