← back to Shopify Apps
initial scaffold (gitify-all 2026-05-06)
a7a5c9a26efcbb4f043c3be456cc1885e188cd6f · 2026-05-06 10:25:47 -0700 · Steve Abrams
Files touched
A .gitignoreA color-dots/APP-SPEC.md
Diff
commit a7a5c9a26efcbb4f043c3be456cc1885e188cd6f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed May 6 10:25:47 2026 -0700
initial scaffold (gitify-all 2026-05-06)
---
.gitignore | 12 ++
color-dots/APP-SPEC.md | 480 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 492 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7e6a9c3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/color-dots/APP-SPEC.md b/color-dots/APP-SPEC.md
new file mode 100644
index 0000000..ebc6dc4
--- /dev/null
+++ b/color-dots/APP-SPEC.md
@@ -0,0 +1,480 @@
+# Color Dots by DW -- Shopify App Specification
+
+## Overview
+
+**App Name:** Color Dots by DW
+**Type:** Shopify App (Theme App Extension + Backend)
+**Status:** Future Product (spec phase)
+
+Color Dots displays AI-analyzed color swatches as hex dot circles below product images on Shopify product pages. Each dot represents a color found in the product image, labeled with its hex code and the percentage of the image it occupies.
+
+---
+
+## How It Works
+
+1. Store owner installs the app from the Shopify App Store.
+2. The app adds a Theme App Extension (app block) that renders color dots on the product page.
+3. The app backend uses Gemini AI vision to analyze product images.
+4. Results are stored as product metafields: `color_dots.color_details` (JSON array of `[{name, hex, pct}]`).
+5. The theme block reads the metafield and renders colored circles.
+6. Colors also auto-populate product tags for Smart Collection integration.
+
+---
+
+## Technical Architecture
+
+### Theme App Extension (Frontend)
+
+- **App block:** `color-dots-block.liquid` -- renders dots from metafield data.
+- No JavaScript framework needed -- vanilla JS reads a data attribute and creates DOM elements.
+- Responsive design, works on all Shopify Online Store 2.0 themes.
+- Merchant-configurable settings:
+ - Dot size (small / medium / large)
+ - Max colors to display (1--8)
+ - Show/hide color name labels
+ - Show/hide percentage labels
+ - Position (below images, below title, in sidebar, custom)
+
+### App Backend (Node.js)
+
+- **Shopify App Bridge + Polaris** for the embedded settings UI inside Shopify Admin.
+- **Gemini 2.0 Flash** integration for image analysis (vision model).
+- Bulk analysis queue with progress tracking.
+- Webhook listener for `products/create` and `products/update` -- auto-analyze new products.
+- Rate limiting and cost tracking per store.
+- OAuth 2.0 install flow with session tokens.
+
+### Data Flow
+
+```
+Product Image
+ |
+ v
+Gemini 2.0 Flash (Vision API)
+ |
+ v
+Color extraction: [{name, hex, pct}, ...]
+ |
+ +---> Shopify Metafield (color_dots.color_details)
+ |
+ +---> Shopify Product Tags (color names)
+ |
+ v
+Theme App Block reads metafield --> renders dots on storefront
+```
+
+---
+
+## Metafield Schema
+
+```json
+{
+ "namespace": "color_dots",
+ "key": "color_details",
+ "type": "json",
+ "value": [
+ { "name": "Coral", "hex": "#F05B4A", "pct": 45 },
+ { "name": "Olive Green", "hex": "#D2D687", "pct": 30 },
+ { "name": "Cream", "hex": "#FFF5E1", "pct": 15 },
+ { "name": "Charcoal", "hex": "#36454F", "pct": 10 }
+ ]
+}
+```
+
+Each entry:
+- `name` (string) -- Human-readable color name (e.g., "Coral", "Dusty Rose").
+- `hex` (string) -- Hex color code including `#` prefix.
+- `pct` (integer) -- Percentage of the image occupied by this color (0--100). Values should sum to approximately 100.
+
+---
+
+## API Endpoints
+
+| Method | Path | Description |
+|--------|------|-------------|
+| POST | `/api/analyze` | Analyze a single product image. Accepts `{product_id}` or `{image_url}`. Returns color data. |
+| POST | `/api/bulk-analyze` | Queue bulk analysis for an entire catalog or a filtered set of products. Returns `{job_id}`. |
+| GET | `/api/progress` | Bulk analysis progress. Returns `{job_id, total, completed, failed, status}`. |
+| GET | `/api/colors/:product_id` | Get color data for a specific product. Returns the metafield JSON. |
+| POST | `/api/settings` | Update app settings (dot size, max colors, auto-tag toggle, etc.). |
+| POST | `/api/webhooks/products` | Webhook receiver for `products/create` and `products/update` events. |
+
+### Authentication
+
+All API endpoints require a valid Shopify session token (App Bridge) or webhook HMAC verification.
+
+---
+
+## Pricing Tiers
+
+### Free Plan
+
+- 50 product analyses per month
+- Basic color dots display
+- Up to 4 colors per product
+- Standard dot sizes
+
+### Pro Plan -- $9.99/month
+
+- Unlimited product analyses
+- Up to 8 colors per product
+- Color-based Smart Collection auto-builder (create collections like "Blue Products", "Earth Tones")
+- "Search by Color" storefront page (color picker that filters products)
+- Pinterest Rich Pin color data integration
+- Priority analysis queue
+
+### Enterprise Plan -- $29.99/month
+
+- Everything in Pro
+- API access for headless / Hydrogen stores
+- Color trend analytics dashboard (most popular colors in your catalog, seasonal trends)
+- Custom color matching / brand palette enforcement (flag products that deviate from brand colors)
+- White-label (remove "Color Dots" branding)
+- Priority support (24h response)
+
+---
+
+## Competitive Advantage
+
+- **AI-powered** -- competitors rely on manual color tagging or basic pixel sampling.
+- **Hex codes with percentages** -- not just vague color names; precise data for each color.
+- **Background color identification** -- unique feature that separates background from subject colors.
+- **Feeds into search, collections, and external channels** -- colors become actionable data, not just display.
+- **Zero manual work** -- fully automated from install to rendering.
+- **Proven at scale** -- prototype already tested on 388K+ product catalog.
+
+---
+
+## Development Stack
+
+| Layer | Technology |
+|-------|-----------|
+| Backend | Node.js + Express |
+| App Framework | Shopify CLI + App Bridge |
+| Admin UI | Shopify Polaris (React components) |
+| AI Vision | Gemini 2.0 Flash API |
+| Database | PostgreSQL (analysis cache, deduplication, job queue) |
+| Frontend (storefront) | Theme App Extension -- Liquid + vanilla JS |
+| Hosting | Railway / Fly.io / self-hosted VPS |
+| Queue | Bull (Redis-backed) or pg-boss (PostgreSQL-backed) |
+
+---
+
+## MVP Features (v1.0)
+
+1. **Theme app block** -- color dot circles rendered from metafield data on the product page.
+2. **Single product analysis** -- analyze one product at a time via the app UI in Shopify Admin.
+3. **Bulk analysis** -- analyze the entire catalog with a progress bar in the admin UI.
+4. **Settings panel** -- configure dot size, max colors, label visibility, and position.
+5. **Auto-tag products** -- automatically add color name tags to products after analysis.
+6. **Webhook auto-analysis** -- new products are analyzed automatically on creation.
+
+---
+
+## Future Features (v2.0+)
+
+- **Search by Color page** -- a storefront page with a color picker; selecting a color shows matching products.
+- **Color palette generator** -- "products that match this color scheme" recommendations.
+- **Shopify Flow integration** -- trigger on new product creation to auto-analyze (Flow connector).
+- **Multi-language color names** -- localized color names (EN, FR, DE, ES, JP, etc.).
+- **Color accessibility checker** -- WCAG contrast ratio checks for text-over-image scenarios.
+- **Color trend reports** -- monthly email digest showing catalog color distribution and trends.
+- **Complementary product suggestions** -- "This product pairs well with..." based on color harmony rules.
+- **Inventory-by-color dashboard** -- view stock levels grouped by dominant color.
+
+---
+
+## Existing Prototype
+
+A working prototype is deployed on the DW development store:
+
+- **Store:** designer-laboratory-sandbox.myshopify.com
+- **Snippet:** `snippets/color-dots.liquid`
+- **Backend enrichment:** `/root/DW-Agents/vendor-scrapers/enrich-ai-tags.js`
+- **Tracking table:** `enrichment_tracking` (388K+ products, deduplication built in)
+- **Test product:** Thibaut T75490 -- 4 colors with hex codes and percentages rendering correctly.
+
+The prototype validates the core concept and AI analysis pipeline. The Shopify App packaging (OAuth, App Bridge, Theme App Extension, billing) is what remains for productization.
+
+---
+
+## Theme App Block -- Rendering Specification
+
+### Liquid Template (`color-dots-block.liquid`)
+
+The block reads `product.metafields.color_dots.color_details` and renders a row of circular swatches.
+
+```liquid
+{% assign color_data = product.metafields.color_dots.color_details.value %}
+{% if color_data != blank %}
+<div class="color-dots-container" data-colors='{{ color_data | json }}'>
+ {% for color in color_data limit: block.settings.max_colors %}
+ <div class="color-dot-item">
+ <span class="color-dot"
+ style="background-color: {{ color.hex }};
+ width: {{ block.settings.dot_size }}px;
+ height: {{ block.settings.dot_size }}px;">
+ </span>
+ {% if block.settings.show_label %}
+ <span class="color-dot-label">{{ color.name }}</span>
+ {% endif %}
+ {% if block.settings.show_pct %}
+ <span class="color-dot-pct">{{ color.pct }}%</span>
+ {% endif %}
+ </div>
+ {% endfor %}
+</div>
+{% endif %}
+```
+
+### Block Settings Schema
+
+```json
+{
+ "name": "Color Dots",
+ "target": "section",
+ "settings": [
+ {
+ "type": "range",
+ "id": "dot_size",
+ "label": "Dot size (px)",
+ "min": 16,
+ "max": 48,
+ "step": 4,
+ "default": 28
+ },
+ {
+ "type": "range",
+ "id": "max_colors",
+ "label": "Max colors to display",
+ "min": 1,
+ "max": 8,
+ "step": 1,
+ "default": 4
+ },
+ {
+ "type": "checkbox",
+ "id": "show_label",
+ "label": "Show color name",
+ "default": true
+ },
+ {
+ "type": "checkbox",
+ "id": "show_pct",
+ "label": "Show percentage",
+ "default": false
+ }
+ ]
+}
+```
+
+### CSS
+
+```css
+.color-dots-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin: 16px 0;
+ align-items: center;
+}
+
+.color-dot-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+}
+
+.color-dot {
+ display: inline-block;
+ border-radius: 50%;
+ border: 2px solid #e0e0e0;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
+ cursor: pointer;
+ transition: transform 0.15s ease;
+}
+
+.color-dot:hover {
+ transform: scale(1.15);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
+}
+
+.color-dot-label {
+ font-size: 11px;
+ color: #666;
+ text-align: center;
+ max-width: 60px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.color-dot-pct {
+ font-size: 10px;
+ color: #999;
+}
+```
+
+---
+
+## Gemini AI Analysis -- Prompt Specification
+
+The image analysis prompt sent to Gemini 2.0 Flash:
+
+```
+Analyze this product image and identify the distinct colors present.
+
+For each color, provide:
+- name: A human-readable color name (e.g., "Dusty Rose", "Navy Blue", "Sage Green")
+- hex: The hex color code (e.g., "#F05B4A")
+- pct: The approximate percentage of the image this color occupies (integer, 0-100)
+
+Return ONLY a JSON array. No markdown, no explanation. Example:
+[
+ {"name": "Coral", "hex": "#F05B4A", "pct": 45},
+ {"name": "Olive Green", "hex": "#D2D687", "pct": 30},
+ {"name": "Cream", "hex": "#FFF5E1", "pct": 15},
+ {"name": "Charcoal", "hex": "#36454F", "pct": 10}
+]
+
+Rules:
+- Return between 2 and 8 colors.
+- Percentages should sum to approximately 100.
+- Order by percentage descending (most dominant first).
+- Use descriptive, customer-friendly color names (not "Color 1").
+- Identify background colors separately from product colors.
+```
+
+---
+
+## Database Schema (PostgreSQL)
+
+```sql
+CREATE TABLE color_analyses (
+ id SERIAL PRIMARY KEY,
+ shop_domain TEXT NOT NULL,
+ product_id BIGINT NOT NULL,
+ image_url TEXT NOT NULL,
+ image_hash TEXT, -- SHA256 for dedup
+ color_data JSONB NOT NULL, -- [{name, hex, pct}]
+ model_used TEXT DEFAULT 'gemini-2.0-flash',
+ tokens_used INTEGER,
+ analysis_cost NUMERIC(8,6),
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ UNIQUE(shop_domain, product_id)
+);
+
+CREATE TABLE analysis_jobs (
+ id SERIAL PRIMARY KEY,
+ shop_domain TEXT NOT NULL,
+ job_type TEXT NOT NULL, -- 'single' or 'bulk'
+ status TEXT DEFAULT 'pending', -- pending, running, completed, failed
+ total_products INTEGER DEFAULT 0,
+ completed_products INTEGER DEFAULT 0,
+ failed_products INTEGER DEFAULT 0,
+ started_at TIMESTAMPTZ,
+ completed_at TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE TABLE app_settings (
+ id SERIAL PRIMARY KEY,
+ shop_domain TEXT UNIQUE NOT NULL,
+ plan TEXT DEFAULT 'free', -- free, pro, enterprise
+ auto_analyze BOOLEAN DEFAULT TRUE,
+ auto_tag BOOLEAN DEFAULT TRUE,
+ max_colors INTEGER DEFAULT 4,
+ dot_size INTEGER DEFAULT 28,
+ show_labels BOOLEAN DEFAULT TRUE,
+ show_pct BOOLEAN DEFAULT FALSE,
+ monthly_analyses_used INTEGER DEFAULT 0,
+ monthly_reset_at TIMESTAMPTZ,
+ installed_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE INDEX idx_color_analyses_shop ON color_analyses(shop_domain);
+CREATE INDEX idx_color_analyses_product ON color_analyses(product_id);
+CREATE INDEX idx_analysis_jobs_shop ON analysis_jobs(shop_domain);
+```
+
+---
+
+## Shopify App Configuration
+
+### `shopify.app.toml`
+
+```toml
+name = "Color Dots"
+client_id = "" # Assigned on app creation
+application_url = "https://colordots.app"
+embedded = true
+
+[access_scopes]
+scopes = "read_products,write_products"
+
+[auth]
+redirect_urls = ["https://colordots.app/auth/callback"]
+
+[webhooks]
+api_version = "2025-01"
+
+ [webhooks.subscriptions]
+ topics = ["products/create", "products/update", "app/uninstalled"]
+ uri = "/api/webhooks"
+
+[app_proxy]
+url = "https://colordots.app/api/proxy"
+subpath = "color-dots"
+prefix = "apps"
+
+[pos]
+embedded = false
+```
+
+### Required Shopify Scopes
+
+- `read_products` -- Read product data and images for analysis.
+- `write_products` -- Write metafields and tags back to products.
+
+---
+
+## Billing Integration
+
+Use Shopify Billing API (`recurring_application_charge`) for subscription management.
+
+- Free plan: no charge created.
+- Pro plan: `$9.99/month`, `test: true` in development.
+- Enterprise plan: `$29.99/month`, `test: true` in development.
+- Usage charges for overage on free plan (optional future feature).
+- 7-day free trial on Pro and Enterprise.
+
+---
+
+## Security Considerations
+
+- All webhook payloads verified via HMAC-SHA256.
+- Session tokens validated on every API request.
+- Gemini API key stored as environment variable, never exposed to client.
+- Product image URLs fetched server-side only (no client-side AI calls).
+- Rate limiting: max 10 single analyses per minute per store, bulk limited to 1 concurrent job.
+- GDPR compliance: `/api/gdpr/customers-data-request`, `/api/gdpr/customers-redact`, `/api/gdpr/shop-redact` endpoints.
+
+---
+
+## App Store Listing (Draft)
+
+**Name:** Color Dots -- AI Color Swatches
+**Tagline:** Automatically display AI-detected color swatches on your product pages.
+**Category:** Store design
+
+**Key Benefits:**
+- Zero manual work -- colors detected automatically from product images.
+- Beautiful color dot circles display on any Online Store 2.0 theme.
+- Powers Smart Collections by color ("All Blue Products", "Earth Tones").
+- Increases search relevance with accurate color tags.
+- Gives customers instant visual color information.
+
+**Keywords:** color swatch, color picker, product colors, AI color detection, color tags, smart collections, color search
(oldest)
·
back to Shopify Apps
·
(newest)