# Slab Capture & WooCommerce Publishing App — PRD ## Overview Build a mobile-first, self-hosted web app that streamlines publishing one-of-a-one wood slabs to a WooCommerce store. The app is a photo capture → calibration → inference → publish pipeline. **Primary constraints** - No slab versioning in v1. - No staff accounts or role complexity in v1. - No bulk publishing; slab-by-slab submission only. - No analytics in v1. - No pricing tiers in v1 — flat price-per-bdft per species/wood-category. - No app-level auth in v1 — app relies on HTTPS + trusted network. - Single SKU per slab; duplicate SKU publish is blocked. - Images are purged after successful publish (retained only while draft/retry). - Deploy target: .201, Docker Compose + Caddy. ## Decisions log (2026-08-27, Ty) 1. No calibration photos — user manually enters SKU, length, thickness. 2. First photo is the measurement photo (must be top-down, lens parallel to broad side). 3. All photos go through background removal + 80% frame-fill crop. 4. Output: transparent PNGs, minimum 1600 px on the smaller dimension, aspect ratio preserved. 5. Green or black sheet — algorithm auto-detects background color from image borders. 6. WooCommerce categories synced from store: Species (1 required, leaf-only), Wood Category (1+ required, leaf-only). 7. WooCommerce attributes: Edge Type (1 required), Figure (1+ required), Grade (1+ required), Thickness (1 required, rounded up to nearest Woo attribute range). 8. WooCommerce tags: fig-* only (1+ required, e.g., fig-chat = Chatoyant). 9. Two-call inference: Call 1 (vision, wood expert) → Call 2 (text, content gen). Both configurable. 10. Call 1 runs automatically after calibration. User reviews/corrects before triggering Call 2. 11. Inference timeout >45s or non-200 → error with retry. User can fill fields manually. 12. Woo product status set to "published" by default (configurable in settings). 13. All inference prompts stored server-side, editable in settings with reset-to-default. 14. Brand voice + GEO context injected into Call 2 prompt. 15. WooCommerce credentials (username + App Password) stored client-side in settings. 16. Inference endpoint: configurable OpenAI-compatible API (user provides base URL, key, model). 17. Test connection verifies text completion + vision support. 18. Offline capture not required for MVP. ## Open items - (none — all resolved 2026-08-27) ## Goals and success metrics **Goals** - Reduce per-slab prep time (target: 20-30 to 5-10 minutes). - Produce consistent, high-quality product pages (title, description, taxonomy, images). - Keep deterministic core logic testable and auditable. - Mobile-first UX with fast feedback. - Allow Ty to host and control inference via a configurable OpenAI endpoint. **Success metrics** - Average time from first photo to published product <= 10 minutes. - Dimension extraction accuracy within +/- 0.25 in. - Photo normalization produces consistent 80% frame fill for 95% of inventory photos. - Inference results accepted or corrected by user in <= 2 edits for 90% of slabs. ## Non-goals - Multi-tenant SaaS or ERP integrations in v1. - Generic SKU inventory management. - Complex user roles or staff permissions. - Bulk import/publish workflows. - Offline capture for MVP. ## Users and core use cases **Primary user** - Ty (Owner/Expert): captures, configures, reviews, and publishes slabs. **Core use cases** - Capture: Stage slab on green or black sheet with lights, take 1-5 photos. - Enter metadata: SKU, length (in), thickness (in). - Calibration: App processes first photo - BG removal, longest dimension detection, area measurement (sqft), bdft calc, then processes all photos for BG removal + crop. - Inference: Call 1 (vision) auto-runs, populating taxonomy/content. User reviews/corrects. Call 2 (text) user-triggered for title/description/short description. - Review & publish: Final review screen with full override capability; publish to WooCommerce. - Configuration: Settings for inference endpoint, Woo credentials, pricing rules, brand voice, GEO context, prompts. ## High level requirements summary - Deterministic core: all measurement math, pricing, normalization, and WooCommerce sync must be deterministic and unit-tested. - Scoped inference: species/category/attribute detection and content generation only; inference must be toggleable and use Ty's configured OpenAI endpoint. - Mobile first: usable on modern iPhone and Android browsers. - Single slab workflow: no batch publish in v1; each slab is captured, enriched, reviewed, and published individually. ## Functional requirements (detailed) ### Capture and calibration - **FR1:** Camera capture for 1-5 inventory photos. First photo must be top-down, lens parallel to the slab's broad side. - **FR2:** User manually enters SKU (3-24 chars, [A-Z0-9-]), length (in), thickness (in). - **FR3:** App detects background color from image borders (green or black sheet). - **FR4:** First photo: BG removal - find longest dimension - compute scale (longest_px / user-length) - compute area (sqft) - bdft = sqft * thickness / 12. - **FR5:** All photos: BG removal - crop to 80% frame fill - save as transparent PNG, minimum 1600 px on smaller dimension, aspect ratio preserved. - **FR6:** User can retake the first photo or abort and start fresh. ### Dimensions and calculations - **FR7:** Compute length (user-entered), area (sqft), and bdft deterministically. - **FR8:** Thickness is always manually entered and treated as authoritative. - **FR9:** All dimension math must be deterministic, unit-tested, and reproducible. ### Taxonomy (WooCommerce sync) - **FR10:** Sync categories, attributes, and tags from WooCommerce and cache locally. - **FR11:** Species category: 1 required, leaf-only selection. - **FR12:** Wood Category: 1+ required, leaf-only selection (parents shown for grouping only). - **FR13:** Edge Type attribute: 1 required. - **FR14:** Figure attribute: 1+ required. - **FR15:** Grade attribute: 1+ required. - **FR16:** Thickness attribute: 1 required, mapped by rounding up user-entered thickness to nearest Woo attribute range. - **FR17:** Tags: fig-* only, 1+ required. - **FR18:** Auto-assign taxonomy based on inference results; allow manual override. ### Pricing engine - **FR19:** UI to define bdft pricing rules by species and wood category. - **FR20:** Deterministic bdft calculation and application of pricing rules to produce a price recommendation. - **FR21:** Price recommendation editable by user; final price stored as authoritative. ### Inference (two-call architecture) - **FR22:** Call 1 (vision): auto-run after calibration. Input: all inventory photos (downscaled to 1024px max, using original pre-crop photos), user metadata, synced Woo taxonomy. Output: species, wood categories, edge type, figure, grade, character/inclusions/voids/checks with severity, top 3 wood categories with confidence. If no species match above threshold, omit and require manual selection. - **FR23:** Call 2 (text): user-triggered after Call 1 curation. Input: deterministic data + Call 1 results + brand voice + GEO context. Output: title, description, short description. - **FR24:** Inference prompts stored server-side, editable in settings, reset-to-default available. - **FR25:** Progress indicator during inference calls (latency expected). - **FR26:** Timeout >45s or non-200 - visible error with retry option. - **FR27:** All inference results editable; no automatic publish of LLM output. - **FR28:** Inference endpoint configured via settings: base URL, API key, model name. Test connection verifies text + vision support. ### Photo normalization and output - **FR29:** Background removal: chroma-key for green/black, fallback to U2Net matting. - **FR30:** Crop to 80% frame fill, slab centered, aspect ratio preserved, minimum 1600 px on smaller dimension. - **FR31:** Output as transparent PNG (ideal for WooCommerce). - **FR32:** Store both original and processed images. Purge after successful publish. ### WooCommerce sync and publish - **FR33:** Authenticate to WooCommerce using consumer key + App Password. - **FR34:** Publish is blocked if the slab SKU already exists (simple dedupe, no update path). - **FR35:** Create WooCommerce product with SKU, title, description, short description, price, categories, attributes, tags, and normalized PNG images. - **FR36:** Default product status: "published" (configurable in settings). - **FR37:** Log sync results and surface errors; store WooCommerce product ID on success. ### Drafts, review, and publish - **FR38:** Maintain a draft slab state with full metadata and photos. - **FR39:** Provide a single review screen showing all fields; every field is editable. - **FR40:** Publish action performs deterministic server-side processing and WooCommerce sync; update status to Published/Failed with error details. ### Configuration and hosting - **FR41:** Settings UI for inference endpoint, Woo credentials, pricing rules, brand voice, GEO context, prompts. - **FR42:** App deploys via Docker Compose on .201 with Caddy for HTTPS. - **FR43:** All secrets stored encrypted at rest; all client-server traffic over HTTPS. ## Non-functional requirements - **Performance:** Client capture and local processing within 1-2s; server normalization within 3-5s per slab; inference calls within 45s. - **Reliability:** Deterministic logic fully unit-tested. - **Security:** Encrypted secrets, HTTPS, minimal persistent credentials on client. - **Maintainability:** Clear separation of deterministic code and inference code. - **Usability:** One-hand operation, large touch targets, clear distinction between internal processing and customer-facing output. ## Architecture and tech stack **Client (mobile web / PWA)** - SvelteKit (mobile-first) - TailwindCSS for UI - Camera API for capture and immediate preview - No OCR, no OpenCV on client **Server (self-hosted, containerized)** - FastAPI (Python) for deterministic image pipeline, bdft math, pricing, background removal, crop/normalize, WooCommerce REST integration, inference wrappers, taxonomy sync - SQLite for v1 (slab records, pricing rules, taxonomy cache, sync history) **Inference** - Configurable OpenAI-compatible endpoint (user supplies base URL, key, model). Must support vision. Two calls: wood expert (vision) + content generation (text). All inference calls logged. **Deployment** - Docker Compose with frontend and fastapi services on .201. - Caddy for HTTPS and reverse proxy. **Security** - AES encryption for stored secrets. - No app-level auth in v1. - HTTPS enforced. ### Pricing rule schema id: uuid species: string wood_category: string price_per_bdft: float created_at: timestamp updated_at: timestamp ## Key flows and acceptance criteria ### Capture -> Calibrate -> Infer -> Publish flow 1. New slab: user stages slab and opens app. 2. Capture: take 1-5 inventory photos. 3. Enter metadata: SKU, length, thickness. 4. Calibration: server processes first photo (BG removal, area, bdft), processes all photos (BG removal, crop, PNG). 5. Inference: Call 1 auto-runs (vision), populating taxonomy/content. User reviews/corrects. Call 2 user-triggered (text), generating title/description/short description. 6. Review: user edits/overrides any field. 7. Publish: user triggers publish; FastAPI syncs taxonomy, creates WooCommerce product, purges images. Status updated and logged. ### Acceptance criteria - End-to-end slab capture to published product works on modern iPhone and Android browsers. - Area measurement accuracy within +/- 0.25 in^2. - Photo normalization produces 80% frame fill, transparent PNG, 1600px min on smaller dim. - WooCommerce product created with normalized images, correct taxonomy, and correct content. - Deterministic functions covered by unit tests; inference calls logged. ## Operational and debugging notes - Local dev: Docker Compose with frontend and fastapi. Mobile testing over LAN/Tailscale. - Logging: centralized logs per service; inference request/response payloads stored for audit. - Testing: unit tests for deterministic math and image processing; integration tests for WooCommerce sync against a staging store. - Secrets: store App Passwords and inference keys encrypted; rotate keys periodically. - Monitoring: health endpoints and job queue visibility.