Bulk product upload for Gelato
A powerful web application for bulk-creating Gelato print-on-demand products from templates. Upload images from local files, Dropbox, or Google Drive, map them to product variants, and create products via the Gelato API.
- Multi-source Image Upload: Upload images from local files, Dropbox, or Google Drive
- Template Management: Load one or more Gelato product templates and view variant details
- Image Mapping: Map uploaded images to template placeholders with automatic filename-based matching
- Variant Selection: Choose which product variants to create for each image (all variants selected by default)
- Metadata Configuration: Set product titles, descriptions, tags, visibility, and sales channels
- Batch Processing: Queue-based system for uploading multiple products with real-time status tracking
- State Persistence: Application state persists across page refreshes, allowing you to resume work
- Progress Tracking: Queue progress is saved and restored on page refresh
- Duplicate Prevention: Built-in safeguards prevent duplicate product creation
- Status Monitoring: Track product creation status with automatic polling and URL regeneration
- OAuth2 Authentication: Secure authentication for Dropbox and Google Drive
- Persistent Connections: Connections are automatically saved and persist across browser sessions
- Auto Token Refresh: Tokens are automatically refreshed when expired or close to expiry
- Dark Mode: Built-in dark mode support with theme-aware components
- CSV Export: Export upload results with product IDs and status information
- Success Panel: View your products in Gelato dashboard directly from the success message
- Responsive Design: Works seamlessly on desktop, tablet, and mobile devices
- Node.js (v18 or higher)
- npm or yarn
- Cloudflare Tunnel CLI (
cloudflared) or ngrok for file serving
1. Install Dependencies
npm install
cd server && npm install
cd ../client && npm install2. Configure Environment
Copy the example environment file and fill in your credentials:
# Windows
copy .env.example .env
# Linux/Mac
cp .env.example .envThen edit .env with your actual values:
# Gelato API Configuration (Required)
GELATO_API_KEY=your_api_key
GELATO_STORE_ID=your_store_id
# Optional: Default template ID
GELATO_TEMPLATE_ID=your_template_id
# Optional: Default product metadata
GELATO_PRODUCT_TITLE=Walljazzle
GELATO_PRODUCT_DESCRIPTION=A beautiful Walljazzle print
# Tunnel Configuration (Required for Gelato to access files)
PUBLIC_BASE_URL=https://your-tunnel-url.trycloudflare.com
SERVER_PORT=5175
# Cloud Storage OAuth (Optional - for Dropbox/Google Drive integration)
DROPBOX_APP_KEY=your_dropbox_app_key
DROPBOX_APP_SECRET=your_dropbox_app_secret
GOOGLE_DRIVE_CLIENT_ID=your_google_client_id
GOOGLE_DRIVE_CLIENT_SECRET=your_google_client_secret3. Set Up Tunnel
Option A: Using PowerShell scripts (Windows):
# First time setup
.\setup-tunnel.ps1
# Start tunnel (auto-updates .env file)
.\start-tunnel.ps1Option B: Manual setup:
# Using Cloudflare Tunnel
cloudflared tunnel --url http://localhost:5175
# Or using ngrok
ngrok http 5175Copy the generated HTTPS URL and update PUBLIC_BASE_URL in your .env file.
4. Start Development Servers
Option A: Using batch script (Windows):
# Double-click or run:
start-server.batOption B: Using npm:
npm run dev- Client runs on
http://localhost:5174(Vite dev server) - Server runs on
http://localhost:5175(Express API)
5. Open the App
Navigate to http://localhost:5174 in your browser.
The application uses a step-based workflow:
1. Template Selection β 2. Image Upload β 3. Variant Selection
β β β
6. Queue Monitoring β 5. Review & Upload β 4. Metadata
- Template Selection: Paste template IDs and load template details
- Image Upload: Upload images from local files, Dropbox, or Google Drive
- Variant Selection: Choose which variants to create for each image
- Metadata: Set product titles, descriptions, tags, and visibility settings
- Review: Review your configuration before uploading
- Queue: Monitor product creation with real-time status updates
Setup Instructions
-
Create a Dropbox App:
- Go to Dropbox App Console
- Create a new app with "Full Dropbox" access
- Set the redirect URI:
http://localhost:5175/api/dropbox/callback - Copy the App Key and App Secret to your
.envfile
-
Connect in the App:
- Navigate to the Image Upload step
- Click "Connect Dropbox" on the Dropbox tab
- Authorize the application
- Browse and select files from your Dropbox
-
Connection Persistence:
- Your Dropbox connection is automatically saved and persists across browser sessions
- Tokens are automatically refreshed when expired or close to expiry
- You only need to reconnect if the refresh token is revoked in Dropbox settings
-
File Selection:
- Click individual files to select/deselect
- Hold Shift and click to select a range of files
- Use "Select All" to select all visible files
Setup Instructions
-
Create a Google Cloud Project:
- Go to Google Cloud Console
- Create a new project
- Enable Google Drive API
- Create OAuth 2.0 credentials
- Add redirect URI:
http://localhost:5175/api/googledrive/callback - Copy Client ID and Client Secret to your
.envfile - Add test users in OAuth consent screen if in testing mode
-
Connect in the App:
- Navigate to the Image Upload step
- Click "Connect Google Drive" on the Google Drive tab
- Authorize the application
- Browse and select files from your Google Drive
.envfile is gitignored: Your.envfile containing API keys and secrets is automatically excluded from Git- Create
.envfrom template: Copy.env.exampleto.envand fill in your actual credentials - Check before committing: Always run
git statusbefore committing to ensure no sensitive files are included
- API Key Protection:
GELATO_API_KEYis server-only and never exposed to the client - Token Signing: Public file URLs use HMAC-SHA256 tokens with 15-minute expiry
- Token Masking: Tokens are masked in logs for security
- Directory Traversal Protection: File paths are validated against the temp directory
- CORS: Configured for localhost during development
- OAuth Tokens: Stored in browser localStorage only (never in files)
.
βββ client/ # React + TypeScript frontend
β βββ src/
β β βββ components/ # UI components
β β βββ lib/ # Utilities and API client
β β βββ pages/ # Page components
β β βββ styles/ # Global styles
βββ server/ # Express + TypeScript backend
β βββ src/
β β βββ routes/ # API routes
β β βββ services/ # Business logic
β β βββ util/ # Utilities
βββ docs/ # Documentation
# Development (runs both client and server)
npm run dev
# Or on Windows, use the batch script:
start-server.bat
# Build for production
npm run build
# Run tests (placeholder)
npm testFrontend:
- React 18
- TypeScript
- Vite
- Tailwind CSS
- React Router
Backend:
- Express
- TypeScript
- Multer (file uploads)
- Sharp (image processing)
- Logo: Theme-aware logo component that displays horizontal light/dark variants based on the current theme
- Favicon: Multi-size favicon setup using Podmate brandmark PNG files (16px to 192px) with Apple touch icon support
npm run build- Client build:
client/dist/ - Server build:
server/dist/
To run the production server:
cd server
NODE_ENV=production node dist/index.js- API Compliance: This app uses only fields documented in the official Gelato API. No undocumented fields are assumed.
- File Serving: Files must be accessible via HTTPS for Gelato to fetch them. A tunnel service is required.
- Large Files: High-resolution images (50-100MB+) may take 30-60+ minutes to process in Gelato.
- Token Expiry: Cloud storage OAuth tokens are automatically refreshed when possible.
- State Persistence: Application state (template, images, queue progress) is saved to browser sessionStorage and persists across page refreshes.
- Queue Management: Queue processing must be explicitly started via the "Start Queue" button - products are not created automatically.
Files are served locally via signed URLs with HMAC token authentication:
- Security: 15-minute expiry tokens prevent unauthorized access
- Local Storage: Files are stored in
server/tmp/with opaque identifiers - Public URLs: Generated as
${PUBLIC_BASE_URL}/public-files/:fileId?t=<token>&e=<expiry> - Tunnel Required: Gelato must be able to access your server via HTTPS, requiring a tunnel service
Tunnel Issues
- Tunnel URL Not Working:
- Verify tunnel is running and accessible from external network
- Check
PUBLIC_BASE_URLis set correctly in.env - Ensure firewall allows tunnel traffic
Gelato API Errors
- Verify
GELATO_API_KEYis correct - Check
GELATO_STORE_IDis valid - Review Gelato API documentation for exact field requirements
- Ensure request payload matches exact schema from docs
File Upload Issues
- Verify
server/tmp/directory exists and is writable - Check file size limits (default: 100MB)
- Ensure tunnel URL is accessible for file serving
- For cloud storage: verify OAuth tokens are valid and not expired
Cloud Storage Issues
- Dropbox: Ensure app is set to "Full Dropbox" (not "App Folder")
- Google Drive: Verify OAuth consent screen is configured and test users are added if in testing mode
- Token Expiry: Tokens are automatically refreshed, but reconnect if refresh fails
- Connection Lost: If your Dropbox connection is lost, simply reconnect - the app will remember your connection for future sessions
- Implementation Details - Detailed architecture and API documentation
- API Checklist - API compliance and verification checklist
Private - All Rights Reserved
Made with β€οΈ by Deep Design
