{ "version": 1, "source": "agent-6-product-user-facing", "notes": "Bodies use public static assets from apps/web/static (served at /…). Content grounded in README, site marketing data, getting-started, free-tier, store-connectors, eprel, processing API, and plan catalog.", "articles": [ { "slug": "what-is-descrybe", "title": "What is Descrybe?", "category_slugs": ["getting-started", "product"], "keywords": [ "what is descrybe", "descrybe", "product catalog", "supplier feeds", "pim", "overview", "about" ], "intent_keys": ["what_is_descrybe", "product_overview", "about_platform"], "is_published": true, "priority_weight": 100, "body_md": "# What is Descrybe?\n\nDescrybe turns **supplier CSV and XML feeds** into clean, channel-ready product catalogs. You map fields to your categories and attributes, enrich listing copy, then ship data through **export feeds**, **WooCommerce sync**, or the **public API**.\n\n![Feed to listing preview](/descrybe_preview.png)\n\n## What Descrybe does\n\n1. **Import** — Connect a supplier feed URL or upload a CSV.\n2. **Map** — Match source columns/paths to your standard fields.\n3. **Enrich** — Categorize, fill attributes, and (on paid plans) generate AI titles and descriptions.\n4. **Ship** — Generate Google Shopping / Meta / custom CSV|XML export feeds, sync WooCommerce, or pull via `/api/v1`.\n\n![Brand mark](/descrybe_logo.png)\n\n## Who it is for\n\nEcommerce teams that receive messy multi-supplier data and need consistent categories, attributes, and listing copy before products go live on storefronts or shopping channels.\n\n## What it is not\n\n- Not a general website builder.\n- Not a 500-channel marketplace connector (core paths are feeds, WooCommerce, Shopify guidance, and export poll URLs).\n- FTP/FTPS feed sync is **not** supported in the current product UI.\n\n## Next steps\n\n- See knowledge article **Getting started: feed → process → export** (`getting-started-feed-process-export`).\n- Or start the in-app tutorial from **Dashboard → Start tutorial** after you sign in.\n" }, { "slug": "getting-started-feed-process-export", "title": "Getting started: feed → process → export", "category_slugs": ["getting-started", "howto"], "keywords": [ "getting started", "how to start", "first steps", "onboarding", "tutorial", "workflow", "feed process export" ], "intent_keys": ["getting_started", "first_run", "core_workflow"], "is_published": true, "priority_weight": 95, "body_md": "# Getting started: feed → process → export\n\nThis is the main operator path in Descrybe.\n\n## 1. Sign in\n\nOpen **Login**, then land on **Dashboard**. Confirm your active company in the header switcher.\n\n## 2. Enable standard fields\n\nGo to **Standard Fields** (More → Setup) and enable the **recommended** fields. These become the dictionary your feed mappings target.\n\n## 3. Add a supplier feed\n\n- **Stores** hub → Feed URL / CSV cards, or\n- **Feeds** → add with `source=url` (public http(s) URL) or `source=file` (CSV upload).\n\nFTP/FTPS is not supported yet.\n\n![Your feeds](/import_suppliers.png)\n\n## 4. Map the feed\n\nOpen the feed → **Map**:\n\n1. Select the item element (XML) or confirm CSV columns.\n2. Run **Auto-map**, then review bindings.\n3. **Save mappings**.\n4. Use **Sync + Process sample** (or Sync, then process from Products).\n\n## 5. Process products\n\nKeep the **background worker** running. On **Products**, use tabs such as Unprocessed / Processed / Needs review / Error / Processing. Select rows and run processing, or watch jobs under **Background Tasks** (`/processing`).\n\n![Enhance products](/enhance_products.png)\n\n## 6. Export\n\nOpen **Export feeds**, create or open a template (Google Shopping CSV/XML, Meta CSV, or custom), **Generate / Refresh**, then copy the **public poll URL** into Merchant Center or your partner importer.\n\n![Export feeds](/export_data.png)\n\n## Tip\n\nUse **Start tutorial** on the dashboard for a guided click-through of the same path (standard fields → feeds → map → products → export → campaigns).\n" }, { "slug": "how-to-import-supplier-feeds", "title": "How to import supplier feeds (URL and CSV)", "category_slugs": ["feeds", "howto"], "keywords": [ "import feed", "supplier feed", "csv upload", "xml feed", "feed url", "add feed", "sync feed" ], "intent_keys": ["import_feeds", "add_feed", "csv_upload"], "is_published": true, "priority_weight": 80, "body_md": "# How to import supplier feeds\n\nDescrybe ingests supplier catalogs as **input feeds**, then stores rows as raw products for mapping and processing.\n\n## Feed URL\n\n1. Go to **Feeds** or **Stores → Feed URL**.\n2. Create a feed with a public **http(s)** CSV or XML URL.\n3. Save, open **Map**, then **Sync** (or Sync + Process sample).\n\nScheduled pull loads data into `raw_products` for your company.\n\n## CSV upload\n\n1. Choose **CSV file** when adding a feed.\n2. Upload the file (stored as a file-backed feed source).\n3. Map columns and sync.\n\n## Supported today\n\n| Source | Status |\n|--------|--------|\n| Public Feed URL (CSV/XML) | Ready |\n| CSV upload | Ready |\n| WooCommerce REST | Ready (Stores → WooCommerce) |\n| Shopify Admin API | Ready for config/test/push (see Shopify article) |\n| FTP / FTPS | **Not supported** in UI yet |\n\n## After import\n\nAlways map fields before expecting clean processed products. Unmapped syncs still create raw rows you can process later from **Products → Unprocessed**.\n" }, { "slug": "how-to-map-feed-fields", "title": "How to map feed fields to standard fields", "category_slugs": ["feeds", "howto"], "keywords": [ "mapping", "auto-map", "standard fields", "feed mapping", "field mapping", "columns" ], "intent_keys": ["feed_mapping", "auto_map", "standard_fields"], "is_published": true, "priority_weight": 78, "body_md": "# How to map feed fields\n\nMapping tells Descrybe how supplier columns/paths become your product fields.\n\n## Before you map\n\n1. Open **Standard Fields** and enable recommended fields (and any custom groups you need).\n2. Optionally set up **Categories** and **Attributes** so enrichment has a taxonomy to target.\n\n![Import taxonomy](/import_taxonomy.png)\n\n## Mapping steps\n\n1. Open **Feeds** → choose a feed → **Map** (`/feeds/{id}/mapping`).\n2. Select the repeating **item** element for XML feeds (or confirm CSV header row).\n3. Click **Auto-map** to suggest bindings to product + standard fields.\n4. Adjust transforms / paths as needed.\n5. **Save mappings**.\n6. **Sync** or **Sync + Process sample**.\n\n## Tips\n\n- Auto-map is a starting point — verify GTIN/EAN, title, price, and image fields carefully.\n- Company setting **merge-by-GTIN** (when enabled) affects how duplicate barcodes are merged across feeds.\n- If **Map** is missing from the tutorial, create a feed first; the tour does not invent demo feeds for you.\n" }, { "slug": "process-products-and-ean-api", "title": "Process products and EAN / barcode API flow", "category_slugs": ["processing", "api", "howto"], "keywords": [ "process products", "ean", "barcode", "gtin", "api process", "processing job", "products/process", "background tasks" ], "intent_keys": ["process_products", "ean_flow", "api_process"], "is_published": true, "priority_weight": 90, "body_md": "# Process products and EAN / API flow\n\nProcessing turns **raw** supplier rows into **processed** catalog products (category, attributes, titles, descriptions, optional EPREL / AI).\n\n## In the dashboard\n\n1. Ensure the **worker** process is running (`go run ./cmd/worker` in local setups).\n2. Open **Products**.\n3. Select unprocessed / raw items (or use Sync + Process sample on a feed mapping).\n4. Choose processing actions (categories, attributes, AI titles/descriptions when your plan allows).\n5. Monitor jobs under **Background Tasks** (`/processing`). Cancel/retry from the job detail when available.\n\n## Public API (EAN items)\n\nAuthenticate with an API key: `Authorization: Bearer dk_…` (create keys under **Settings → API keys**).\n\nLegacy-compatible start:\n\n- `POST /api/v1/products/process`\n- Alias: `POST /api/v1/process`\n\nEvery item in `items` **must include a non-empty `ean` field**. Missing EAN returns a validation error.\n\n`processing_type` may be:\n\n- `\"full\"` (default)\n- a single step: `category`, `title`, `description`, `attributes`\n- an array of steps, e.g. `[\"title\",\"attributes\"]`\n\nPoll status with `GET /api/v1/process/{id}` (or the products/process variant).\n\n## Credits and plan gates\n\n- **Normalize / parse specs / fill fields** can run on Free without AI credits.\n- **AI titles & descriptions** need `can_use_ai` (paid plan or remaining AI credits). Free has **0** monthly AI credits.\n- Hitting the SKU cap returns a product-limit error until you free capacity or upgrade.\n\n## Local smoke tip\n\nThe A1 demo Postman collection processes real EANs against a seeded feed after `npm run seed:a1`. Use your own EANs from your mapped feeds in production.\n" }, { "slug": "ai-titles-and-descriptions", "title": "AI titles and product descriptions", "category_slugs": ["catalog", "ai", "howto"], "keywords": [ "ai description", "ai title", "generate description", "listing copy", "meta title", "meta description", "enhance", "openai" ], "intent_keys": ["ai_descriptions", "ai_titles", "listing_copy"], "is_published": true, "priority_weight": 85, "body_md": "# AI titles and product descriptions\n\nDescrybe can generate search-friendly titles, descriptions, and meta snippets during processing.\n\n![Content tab example](/enhance_products.png)\n\n## How to run AI enrichment\n\n1. Configure AI under **Integrations → AI** (tenant BYOK) and/or rely on platform AI settings when your plan uses managed credits.\n2. On **Products**, choose AI title / description processing actions (Starter+ or any plan with AI credits).\n3. Review results on the product — tabs such as **Needs review** help you accept, edit, or reject enrichment.\n\nCategory **title formulas** and **description formulas** (Categories → formula editors) shape structured output alongside AI.\n\n## Free vs paid\n\n| Capability | Free | Starter+ |\n|------------|------|----------|\n| Map feeds, clean data, fill attributes | Yes | Yes |\n| AI titles & descriptions | No (0 AI credits; `can_use_ai` false) | Yes (monthly credits) |\n| Bring your own AI key | No | Growth+ packaging / feature flags |\n\nIf AI is skipped, processing notes may say the enhance step was skipped for Free plan — that is expected, not a worker crash.\n\n## Brand voice\n\nSet tone and preferred terms under **Brand kit** (`/brand`). When AI is allowed, brand voice can be injected into prompts (`capability.brand_ai_apply`).\n" }, { "slug": "export-feeds-channels", "title": "Export feeds to shopping channels", "category_slugs": ["export", "howto"], "keywords": [ "export feed", "google shopping", "meta catalog", "merchant center", "csv export", "xml export", "public url" ], "intent_keys": ["export_feeds", "google_shopping", "channel_export"], "is_published": true, "priority_weight": 82, "body_md": "# Export feeds to shopping channels\n\nOutbound feeds publish your processed catalog for partners and ad platforms.\n\n![Export feeds UI](/export_data.png)\n\n## Create and generate\n\n1. Open **Export feeds**.\n2. Create a template — presets include **Google Shopping** (CSV/XML) and **Meta** CSV, plus custom CSV/XML.\n3. Map export fields to Descrybe sources (titles, attributes, EPREL keys, images, price, …).\n4. Click **Generate / Refresh**.\n5. Copy the **public** URL:\n - `GET /api/public/export-feeds/{token}.csv`\n - `GET /api/public/export-feeds/{token}.xml`\n\nNo login is required to poll that URL (treat the token as a secret).\n\n## Channel notes\n\n- **Google Merchant Center** — schedule fetch against the public URL after Refresh.\n- **Meta Commerce Manager** — use the Meta CSV preset fields (id, title, availability, price, image_link, …).\n- **Custom / affiliates** — define your own keys and XML root/item names.\n\nDescrybe does **not** push arbitrary outbound product webhooks yet; partners should poll the public URL or use the REST API.\n\n## From Products\n\nYou can also export a **selected** product set from the Products page into an export template when that action is available on your plan.\n" }, { "slug": "woocommerce-and-shopify", "title": "Connect WooCommerce and Shopify", "category_slugs": ["stores", "howto"], "keywords": [ "woocommerce", "shopify", "store connector", "sync products", "stores hub", "orders", "reviews" ], "intent_keys": ["woocommerce", "shopify", "store_connectors"], "is_published": true, "priority_weight": 75, "body_md": "# Connect WooCommerce and Shopify\n\nUse the **Stores** hub (`/stores`) as the entry point for store platforms and file sources.\n\n## WooCommerce\n\n1. Open **Stores → WooCommerce** (`/woocommerce`).\n2. Enter store URL + REST credentials (stored encrypted).\n3. **Test connection**, then queue product sync.\n4. Sync **Orders** and **Reviews** from the Woo tabs when you need campaign audiences or review content.\n\nReviews also appear under Marketing → Reviews (redirects to the Woo reviews tab).\n\n## Shopify\n\n1. Open **Stores → Shopify** (`/stores/shopify`).\n2. Configure shop domain + Admin API token (SSRF-safe domain checks apply).\n3. Test connection; product push and orders pull are available (dry-run proven in local QA).\n\nNative Shopify product reviews are **not** supported (no first-party Admin API for that).\n\n## Feed URL / CSV\n\nStill the fastest path for many suppliers — see the import feeds article. Export/REST cards on the Stores hub point you to outbound feeds and `/api/v1`.\n" }, { "slug": "plans-free-tier-ai-credits", "title": "Plans, Free tier, and AI credits", "category_slugs": ["billing", "plans"], "keywords": [ "free plan", "ai credits", "upgrade", "pricing", "starter", "growth", "business", "product limit", "insufficient credits" ], "intent_keys": ["billing_plans", "ai_credits", "free_tier"], "is_published": true, "priority_weight": 88, "body_md": "# Plans, Free tier, and AI credits\n\nPublic plans: **Free → Starter → Growth → Business → Enterprise**.\n\n## At a glance\n\n| Plan | SKU cap | Monthly AI credits |\n|------|--------:|-------------------:|\n| Free | 100 | 0 |\n| Starter | 1,000 | 300 |\n| Growth | 10,000 | 2,000 |\n| Business | 100,000 | 10,000 |\n| Enterprise | Unlimited | Large managed pack |\n\n## What Free includes\n\n- Map a feed, clean product data, parse specs, fill attributes\n- EU **EPREL** energy-label enrichment (public data; not billed as AI credits)\n- One manual export feed (marketing packaging)\n- **No** AI titles/descriptions until you upgrade or obtain credits\n\n## AI credits\n\nAI credits pay for steps like generating titles and descriptions. When credits run out or Free has `can_use_ai=false`, AI-only jobs fail with an upgrade/credits error while non-AI cleanup can still run.\n\n## Hitting limits\n\n- **Product limit exceeded** — free space (delete/archive) or upgrade.\n- **Insufficient credits** — wait for the next cycle, upgrade, or use BYOK when your plan allows.\n\nUpgrade from **Plans** / **Billing** (Stripe Checkout on paid self-serve). Enterprise is sales-led.\n" }, { "slug": "api-keys-and-public-v1", "title": "API keys and the public /api/v1 catalog", "category_slugs": ["api", "howto"], "keywords": [ "api key", "bearer token", "openapi", "public api", "rest api", "documentation", "/api/v1" ], "intent_keys": ["api_keys", "public_api", "openapi"], "is_published": true, "priority_weight": 70, "body_md": "# API keys and the public /api/v1 catalog\n\nUse the REST API to automate feeds, products, processing, and exports from your own systems.\n\n## Create a key\n\n1. Open **Settings → API keys**.\n2. Create a key and **copy it immediately** — plaintext is only shown once.\n3. Send `Authorization: Bearer ` on `/api/v1/...` requests.\n\nAPI access is plan-gated (`capability.api_access`). Free marketing packaging lists API as not included; paid plans unlock read/full access per plan features.\n\n## Explore the contract\n\n- In-app docs UI: `/docs` (RapiDoc)\n- OpenAPI YAML: `GET /api/v1/openapi.yaml`\n- Health: `GET /api/v1/health` (no key)\n\n## Common calls\n\n- `GET /api/v1/feeds`\n- `GET /api/v1/products`\n- `POST /api/v1/products/process` (items require `ean`)\n- `GET /api/v1/process/{id}`\n- `GET|POST /api/v1/export-feeds`\n\nDashboard session routes under `/api/...` use cookies + CSRF; do not mix session CSRF rules with API-key v1 calls.\n" }, { "slug": "troubleshooting-processing-jobs", "title": "Troubleshooting: processing jobs stuck or failing", "category_slugs": ["troubleshooting", "processing"], "keywords": [ "stuck", "processing failed", "job not finishing", "worker", "rate limit", "no matching products", "retry", "cancel job", "error tab" ], "intent_keys": ["processing_stuck", "job_failed", "worker_down"], "is_published": true, "priority_weight": 92, "body_md": "# Troubleshooting: processing jobs stuck or failing\n\nUse this checklist when Background Tasks never finish or Products stay on **Processing** / **Error**.\n\n## 1. Is the worker running?\n\nEnrichment runs in the **worker**, not only the API process. Locally start `go run ./cmd/worker` (or your deployed worker). Without it, jobs sit queued.\n\n## 2. Read the Products tabs\n\n- **Error** — open the product / job for step notes (AI skipped, EPREL soft-fail, validation).\n- **Needs review** — AI produced content waiting for accept/edit.\n- **Unprocessed** — raw rows never selected for a job.\n\n## 3. Common API / client messages\n\n| Message (concept) | What to do |\n|-------------------|------------|\n| All items must have a valid `ean` | Add barcodes/GTINs to each process item |\n| raw_product_ids required / not found | Select products that belong to your company |\n| too many products | Split the batch |\n| rate limit: too many processing jobs | Wait and retry |\n| job not cancellable / still active | Wait for completion or use supported cancel states |\n| insufficient credits / AI requires upgrade | Upgrade plan or free AI-only steps |\n| product limit exceeded | Reduce SKUs or upgrade |\n\n## 4. AI skipped on Free\n\nIf notes say AI enhance was skipped on Free, that is **expected**. Non-AI normalize/fill can still succeed.\n\n## 5. Cancel / retry\n\nFrom the job UI or API: `POST .../cancel` or `.../retry` on the processing job routes when the job state allows it.\n\nStill stuck? Open a **Support** ticket from the app and include the job id, company name, and approximate start time.\n" }, { "slug": "troubleshooting-feeds-and-exports", "title": "Troubleshooting: feeds will not sync or export is empty", "category_slugs": ["troubleshooting", "feeds", "export"], "keywords": [ "feed sync failed", "empty export", "mapping missing", "ftp", "cannot sync", "no products", "public export url" ], "intent_keys": ["feed_sync_failed", "empty_export", "mapping_problems"], "is_published": true, "priority_weight": 86, "body_md": "# Troubleshooting: feeds and exports\n\n## Feed will not sync\n\n1. Confirm the URL is public **https** (or http in local/dev) — private LAN hosts may be blocked by allowlists.\n2. FTP/FTPS sources are **not supported**; switch to URL or CSV upload.\n3. Open **Map** and ensure mappings are **saved** before expecting processed fields.\n4. Re-run **Extract schema** if the supplier changed XML structure.\n5. Check feed sync job status on the feed page; retry Sync.\n\n## Products missing after sync\n\n- Look under **Products → Unprocessed** (processed tab only shows finished enrichment).\n- Confirm you are in the correct **company** workspace.\n- Verify merge-by-GTIN settings if duplicates seem to disappear.\n\n## Export URL empty or stale\n\n1. Confirm processed products exist for the filters your export template uses.\n2. Click **Generate / Refresh** on the export feed.\n3. Re-copy the public token URL (`/api/public/export-feeds/{token}.csv|.xml`).\n4. Map required channel fields (id, title, price, image_link, GTIN, …).\n\nAmazon-style channel presets beyond Google/Meta are **backlog** — use custom CSV/XML mappings for other marketplaces.\n" }, { "slug": "eprel-energy-labels", "title": "EU EPREL energy labels on products", "category_slugs": ["catalog", "compliance"], "keywords": [ "eprel", "energy label", "energy class", "eu label", "eprelid", "fiche" ], "intent_keys": ["eprel", "energy_label"], "is_published": true, "priority_weight": 65, "body_md": "# EU EPREL energy labels\n\nWhen a feed item includes an EPREL registration id (`EPRELID`, `eprel_id`, …), Descrybe can enrich the processed product with label and energy-class data from the public EU EPREL API.\n\n## Plan gating\n\nEPREL is available on **all plans** (including Free) from a product entitlement perspective — it is public regulatory data and is **not** charged as AI credits. Your platform operator may still disable the enricher (`EPREL_ENABLED`) in the deployment.\n\n## Pipeline position\n\nWorker steps (simplified): normalize → parse_specs → fill_fields → **eprel** → ai_enhance (optional).\n\nFailures are **soft**: the product can still complete; a note may appear on the eprel step.\n\n## Export\n\nMap fields such as `eprel_id`, `eprel_label` / `eprel_label_url`, `eprel_pdf`, `eprel_energy_class`, `eprel_energy_scale` (and aliases like `energy_class`) in your export template.\n" }, { "slug": "marketing-campaigns-brand-seo", "title": "Marketing suite: campaigns, brand kit, and SEO", "category_slugs": ["marketing", "howto"], "keywords": [ "campaigns", "black friday", "brand kit", "seo", "email marketing", "content calendar", "reviews" ], "intent_keys": ["marketing_suite", "campaigns", "seo_brand"], "is_published": true, "priority_weight": 60, "body_md": "# Marketing suite: campaigns, brand, SEO\n\n## Campaigns\n\n1. Open **Campaigns** (`/campaigns`) or prepare a season from **Content calendar**.\n2. Create a campaign (e.g. Black Friday template).\n3. Pick products/categories; optionally build audiences from synced Woo **orders**.\n4. **Generate** — template mode works on Free; **AI generate** needs Starter+ / credits.\n5. Configure **Email sending** (`/integrations/email`), send a test, then schedule/send. Free plans force **dry-run** for live blasts.\n\n## Brand kit\n\n`/brand` — tone, do/don't lists, colors, preferred terms, logo. Applied to AI prompts when brand AI apply is allowed.\n\n## SEO\n\n`/seo` — missing meta, thin/duplicate titles, weak images. Template fill on Free; AI rewrite on paid.\n\n## Reviews\n\nSync Woo reviews from the WooCommerce Reviews tab (`/reviews` redirects there). Shopify native reviews are not available.\n" }, { "slug": "in-app-tutorial-and-support", "title": "In-app tutorial and how to contact support", "category_slugs": ["getting-started", "support"], "keywords": [ "tutorial", "guided tour", "help", "support ticket", "contact support", "faq" ], "intent_keys": ["tutorial", "contact_support", "help_center"], "is_published": true, "priority_weight": 72, "body_md": "# In-app tutorial and contacting support\n\n## Tutorial\n\nFrom **Dashboard** or the header: **Start tutorial** / **Resume** / **Restart**.\n\n- Action steps advance only when you click the highlighted control or complete the real success path.\n- **Pause** or Escape keeps progress; **Skip tour** ends it.\n- Progress is stored in your browser (`localStorage`).\n\nTypical path: Standard Fields → Feeds → Map → Products → Export feeds → Campaigns.\n\n## Support Center\n\nSigned-in users can open **Support** to create tickets and reply in-thread. Staff may answer with help-center articles (like this one) when auto-reply matching is enabled by the platform team.\n\nInclude: company name, approximate time, feed/job/product ids, and screenshots when something fails.\n\n## Sales / demos\n\nPublic marketing contact: **info@descrybe.io**. Demo booking is available from the marketing site CTA.\n" } ] }