| 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
- 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.
- 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).
- Vertical safe zone: The top and bottom of the print area approach the cap and base. Keep content away from the top/bottom 50px.
- 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).
- 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.
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}"
PUBLIC_URL="${SUPABASE_URL}/storage/v1/object/public/designs/uploads/${FILENAME}"
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
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
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:
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:
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
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' },
]
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',
pod_provider: 'printful',
product_template_id: '848',
provider_product_id: String(pfProductId),
base_price_cents: 3799,
compare_at_price_cents: 5999,
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)',
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'
})
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.
<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
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