Skip to content

Repository files navigation

Shoploop

Full-funnel positionless AI marketing for tabletop brands.

Any SKU a customer can grip, rotate, and inspect in 3D — bottles, jars, tubes, tins, boxes, sachets. Paste one web page URL from the brand's own domain and get back a brand-safe 3D configurator plus publishable creative. AGPL-3.0, self-hostable.

Status: pre-v0.1. apps/landing is the only app with runtime code. Every other apps/*, packages/*, and infra/* entry is a scaffold — the tree below is a build plan, not a shipped system. Dates and definitions of done live in MILESTONES.md; the $/mo baseline lives in COSTS.md; locked decisions and their reasoning live in docs/decisions/.

Shoploop turns an existing brand's own web pages into a governed, measurable content supply chain: one reusable product twin per SKU powers the shopper experience, campaign production, publishing, and the feedback loop that decides what to make next.

Positioning: Shoploop Core with Pimcore as the preferred product-graph adapter

Shoploop is a CPG-specialized, agentic 3D commerce layer whose canonical Product Graph Port is Shoploop-owned, with Pimcore as its first and preferred adapter — not another PIM, and not a closed twin factory.

The Product Graph Port is the canonical contract, and Pimcore is the one bound product spine in Phase 1: Data Objects, Classification Store, Data Quality, Studio Backend REST, Datahub GraphQL (ADR 0003). Out of the box those are horizontal, category-agnostic primitives. Shoploop specializes them for the workflows tabletop CPG actually has — volume and pack variant axes on one parametric container, regulated-claim and compliance fields that are human-locked, ingredient trees deep enough to drive molecular storytelling, and a twin manifest that points at OpenUSD layers instead of at flat renders — and then adds the two planes Pimcore is architecturally wrong for:

Plane Runtime Why not Pimcore
Behaviour + posterior PostHog (one shared partition) + pybandits inside Temporal PHP-FPM on single-AZ RDS is a cold-path system of record. High-frequency shopper events never touch a Pimcore field; only versioned aggregates cross back.
Twin + render Blender headless authoring → usd-runtime canonicalization → Kit-App-Template + OVAS There is no GPU path in PHP. Pimcore holds the manifest and the artifact versions, not the pixels.

The result is the surface no one in the category ships: a streamed 3D configurator the shopper actually uses, wired as the sensor that feeds the production loop. The enterprise twin factories generate channel assets and read back aggregate campaign performance; the CDPs read customer events but have no product twin. Shoploop closes the gap between them with Shoploop Core at $0 and AGPL-3.0, self-hostable in the brand's own infrastructure. Third-party adapters and deployment components keep their own licences and costs; the complete Pimcore-backed stack is not unconditionally $0 to self-host (ADR 0021).

The full technical teardown of the vendors that own the adjacent planes — and the OSS bill of materials proving each piece is adopted rather than rebuilt — is in docs/competitive/. The commercial matrix is docs/competitive-matrix.md.

Intake is still one URL. The parser resolves whatever page is pasted to a PDP (ADR 0011), then discovers the rest of that same domain's public PDPs to build the catalog (ADR 0018). Same-domain only, robots.txt honoured, authorized domains only. Catalog discovery is the Phase 2 acceptance target, not shipped — see the status note above.

Infrastructure, not formats

Shoploop is an infrastructure project. The work is plumbing — NVIDIA Omniverse, Pimcore, and AWS wired into one governed, scalable, enterprise-ready pipeline. The work is not inventing schemas, hashes, validators, or protocols.

Law 0 — never rebuild a solved problem. Every layer here already has a governed standard, an official SDK, or a maintained reference implementation. docs/STANDARDS.md is the normative registry of all of them, locked by ADR 0012. A PR that re-encodes anything in it is closed, not reviewed.

Layer Standard adopted Never build
Product + variant contract OpenUSDUsdGeom, UsdShade, UsdVariantSets a product/geometry JSON Schema
Domain schema authoring usdGenSchema + applied API schemas a schema compiler
Material fidelity OpenPBR Surface + MaterialX a private PBR spec
Asset identity SdfLayer + Ar 2.0 a content-hash scheme
Validation usdchecker an asset linter
USD authoring OpenUSD Exchange SDK raw Sdf/Usd helpers
Delivery packaging USDZ a single-file 3D format
Canonical product-data boundary Shoploop-owned Product Graph Port with one bound adapter (ADR 0021) a second graph or multi-adapter runtime
Product data implementation Pimcore Data Objects / Classification Store / Data Quality a mirrored product table
PIM access Pimcore Studio Backend REST + Datahub GraphQL a REST gateway
GPU app kit-app-template + Kit Extensions a Kit bootstrapper
Streaming Omniverse App Streaming (OVAS) + NGC Helm charts a WebRTC session broker
Browser viewport web-viewer-sample a client-side USD renderer
GPU on AWS NVIDIA GPU Operator on EKS device-plugin manifests
Geometry + material authoring Blender headless + bpy + Geometry Nodes a modelling kernel, UV unwrapper, or texture baker
Authoring + batch render plane AWS Deadline Cloud (Blender) an SQS render farm
Page → product data schema.org Product + Open Graph via extruct a DOM/regex extractor
Product identity GS1 Digital Link a private product-ID scheme
Orchestration Temporal a Postgres job queue
Experimentation PostHog Experiments + Holdouts an A/B stats engine
Bandit posterior pybandits hand-written sampling math
Publishing Postiz Public API + MCP a scheduling API
OAuth Nango per-platform OAuth flows
Agent tool-calling MCP a function-schema convention

Full registry, licenses, and license traps: docs/STANDARDS.md. What gets built in what order, and what closes each phase: docs/BUILD_ORDER.md.

v1 and v2

v1 is the twin and the world around the twin. URL → Product Graph Port → bound Pimcore record → OpenUSD twin (OpenPBR/MaterialX materials, variant sets, BrandRulesAPI applied schema) → usdchecker gate → Kit app on AWS GPU → Omniverse App Streaming → configurator link. One neutral tenant, end to end, streaming — that is the plumbing gate.

The target demonstration is the catalog-scale content factory (ADR 0018): one existing brand website URL in, public PDPs discovered on that domain, ≥10 accepted tabletop SKUs written through the Product Graph Port into bound Pimcore, one real OpenUSD twin each, and ≥250 assets out — 5 compositions × 5 aspect ratios (9:16, 1:1, 16:9, 3:4, 4:5) per SKU — from shared twins and manifests, with a single human gate on the Pimcore record.

v2 is everything downstream of the twin: operator shot builder, Postiz publishing, Nango connectors, PostHog posterior, Thompson Sampling, multi-tenancy, page-writer, embed, i18n. Specified and scaffolded — not started until the v1 twin streams. See ADR 0012.

What tabletop means

Countertop / shelf-visible SKUs. Not injectables, devices, or Rx-only. First wedge: Ayurveda + nutraceutical + OTC wellness — molecular storytelling plus near-zero 3D adoption makes it the softest target. Beyond the wedge: skincare, spirits, coffee, sauces, supplements, candles.

One repo

Shoploop is a single pnpm monorepo. One workspace, one PR queue, one CI pipeline. Earlier prose describing a four- or five-repo split (shoploop-core, shoploop-delivery, shoploop-growth, shoploop-postiz) is obsolete.

apps/
  landing            → shoploop.studio marketing + URL intake
  operator-studio    → shoploop.studio/op/{slug}
  configurator       → shoploop.studio/{slug}
packages/
  page-parser        → URL → DOM + JSON-LD + OG + PDP heuristics → product draft
  product-graph      → canonical vendor-neutral Product Graph Port + conformance suite
  pimcore-sdk        → first and preferred Pimcore adapter behind the port
  usd-runtime        → Blender job manifests + pinned bpy scripts; canonicalizes the
                       Blender export into the OpenUSD twin, variant sets, stage
                       composition (Exchange SDK)
  brand-rules        → BrandRulesAPI applied schema (usdGenSchema) + usdchecker/OpenPBR CI gate
  page-writer        → page updates: PR against the page repo, or hosted publish API (Loop 6)
  embed              → embeddable configurator/viewer widget
  postiz-client      → arm's-length client for the Postiz public API + MCP
  i18n               → locale contract + Language-QA fixtures (Loop 7 — deferred, ADR 0008)
  connector-shopify      → optional secondary ingest (never the front door)
  connector-google-ads   → optional secondary ingest (never the front door)
infra/
  kit-app-template   → Omniverse Kit app for streaming
  streaming          → Omniverse App Streaming plane
  pimcore            → Pimcore deployment
  postiz             → Postiz deployment (upstream image, pinned by digest)

The tree above is canonical. packages/product-graph is accepted by ADR 0021 but is not on disk until the separate contract implementation PR; every other entry shown reflects the 2026-07-27 tree cleanup. campaigns/, growth/, shopify/ and landings/ were deleted; connectors/* became packages/connector-*; apps/shoploop-studio-site became apps/landing; root design.md became docs/design-system.md. Everything is recoverable from the archive/pre-cleanup-2026-07-27 tag. Do not recreate those directories.

Intake: one URL

The only intake is a product web page link. Paste any PDP, landing page, Linktree, or brand homepage and Shoploop parses it through the Product Graph Port into a product record in the bound Pimcore adapter, a USD product twin, brand rules, and a variant graph. No catalog upload, no OAuth wizard, no CSV.

Platform connectors (Shopify, Google Ads, and anything brokered through Nango) are optional secondary ingest — enrichment after the URL, never the front door.

Inspired by the NVIDIA OpenUSD product configurator reference architecture: aggregate the product data, express it as OpenUSD, expose variants (model × material × style × artwork), render, QC, distribute.

The loop

One web page URL on the brand's own domain
  → page-parser: resolve to a PDP (ADR 0011), then discover the same-domain catalog (ADR 0018)
  → Product Graph Port → bound Pimcore PXM graph — the Phase 1 source of truth, one object per accepted SKU
  → Blender headless: parametric geometry, UV unwrap, label projection,
      material authoring, texture bake — a deterministic executor, typed
      manifest in, pinned scripts, editable .blend retained and versioned
  → usd-runtime: canonicalizes the Blender export → one OpenUSD twin per SKU
      + UsdVariantSets, OpenPBR/MaterialX materials via UsdShade
  → usd-content-agents: Material/Texture enrichment where evidence is
      uncertain; the Validation Agent advises the pbr_score
  → brand-rules: BrandRulesAPI applied schema, usdchecker is the hard gate,
      the OpenPBR fidelity score (≥ 0.85) advises alongside it
  → render: Kit-App-Template + Omniverse App Streaming, or Blender/Cycles still + MP4
  → two links out per tenant: /op/{slug} (operator) and /{slug} (shopper)
  → Postiz publishes to Meta / Google / YouTube Shorts — gate runs first
  → PostHog (one shared partition) measures impact
  → posterior compounds nightly → BrandRulesAPI

Two links out is the deliverable — exactly two entry links per tenant, however many SKUs one URL discovers. Everything else is plumbing.

Deployment targets

Component Platform Target
apps/landing Vercel shoploop.studio
apps/operator-studio Vercel shoploop.studio/op/{slug}
apps/configurator Vercel shoploop.studio/{slug}
Postiz AWS internal publishing service
Pimcore AWS first and preferred Product Graph Port adapter; Phase 1 source of truth
Temporal AWS separate namespaces/task queues per domain
PostHog AWS single shared partition
Nango AWS OAuth broker for optional connectors
Omniverse Kit app AWS GPU
Streaming plane AWS GPU

shoploop.studio is the canonical production landing and URL-intake surface. All Shoploop customer-facing frontends deploy to Vercel; everything non-frontend runs on AWS. GPU workloads never run on Vercel. The Postiz admin/frontend bundled in the upstream image is an internal AWS surface, not a Shoploop customer-facing frontend.

Authoring and rendering

Blender headless authors the twin — parametric geometry via Geometry Nodes, UV unwrap, label projection, Principled BSDF materials, texture baking, Cycles reference renders. It runs as a deterministic executor driven by a typed job manifest and pinned Shoploop-owned scripts, invoked by Temporal, with no arbitrary tenant Python. The editable .blend source is a retained, versioned artifact, not a build temporary. packages/usd-runtime then canonicalizes that export into the real contract: OpenPBR/MaterialX via UsdShade, UsdVariantSets, BrandRulesAPI, correct layers. A Blender export is never the shipped layer (ADR 0019).

The agent-facing path for bounded operator authoring and diagnosis is the official Blender Foundation Lab MCP server (Blender 5.1+), preferred over any community reimplementation. It executes LLM-generated code with no guards, so it runs only inside per-job/per-tenant isolation with scoped job-only credentials and allowlisted egress — never on the unattended batch path, and its output re-enters through canonicalization and the same gates.

Real Pimcore USD twins with BrandRulesAPI materials and lighting are streamed via NVIDIA Kit-App-Template + Omniverse App Streaming through the official web-viewer-sample client. The offline path is Blender/Cycles stills and MP4 via AWS Deadline Cloud — the same Blender, in its second role. No cheap Three.js stand-in for a real twin — React Three Fiber is chrome only (ADR 0005).

Runtime hierarchy

Four runtimes, strictly ordered. 1. Temporal — the deterministic workflow/control plane and the only orchestrator · 2. NemoClaw / OpenShell — the primary governed agent runtime for reasoning, tool use, and specialist orchestration, and the isolation boundary for the Blender MCP server · 3. Pimcore — canonical PXM state, not an agent runtime · 4. Blender headless — the deterministic batch authoring executor, not an orchestrator. Alongside them, NVIDIA usd-content-agents are post-authoring Material/Texture/Validation specialists, not the pipeline — and because Texture and Validation are Research Preview, the pbr_score advises alongside usdchecker, never instead of it. Kit + OVAS render and stream; they neither author nor orchestrate. Locked by ADR 0019.

Distribution

Postiz is deployed as a separate AWS service from the official ghcr.io/gitroomhq/postiz-app image, pinned by immutable digest. No Postiz source is vendored into this workspace for v0.1; integration is arm's-length through the Postiz public API and MCP. Brand-rules gates run before anything publishes. See docs/orchestration-postiz.md and infra/postiz/UPSTREAM.md.

Shoploop ships its own scheduling frontend. Operators schedule, review, and track posts in apps/operator-studio on Vercel — a native Shoploop wrapper over Postiz capabilities, talking through packages/postiz-client to the AWS-hosted Postiz public API. The raw Postiz admin UI bundled in the upstream image stays internal on AWS for ops and debugging. It is never iframed into a Shoploop surface and never publicly exposed as the Shoploop product.

The 10 loops

See LOOP_SPEC.md — ten loops, eleven entries (Loop 1b is the optional-connector sub-loop of Loop 1). Each loop is defined against the 9-primitive framework (Target · Fitness · Search Space · Stopping · Mutation · Memory · Ground Truth · Boundary · Decay). None of the loops run yet; see MILESTONES.md.

Stack

Frontend: TypeScript · React 19 · Next.js 15 · React Three Fiber (UI/scene chrome, never product twins) · Framer Motion · Tailwind Product graph: Shoploop-owned Product Graph Port; Pimcore is the first, preferred, and only Phase 1 adapter — Data Objects, Classification Store, Data Quality, Studio Backend REST, Datahub GraphQL 3D contract: OpenUSD (UsdGeom · UsdShade · UsdVariantSets) · usdGenSchema applied API schemas · OpenPBR Surface · MaterialX · USDZ · Ar 2.0 · usdchecker · OpenUSD Exchange SDK Authoring: Blender headless CLI + bpy · Geometry Nodes · UV unwrap + label projection · Principled BSDF → MaterialX · texture baking · Cycles reference renders — typed job manifests, pinned Shoploop-owned scripts only · official Blender Foundation Lab MCP server for bounded, isolated intervention Rendering: NVIDIA Kit-App-Template · Kit SDK Extensions · Omniverse App Streaming (OVAS) · web-viewer-sample · usd-content-agents (post-authoring enrichment + advisory validation) · Blender/Cycles + MolecularNodes offline path Intake: URL fetch → extruct (JSON-LD + microdata + RDFa + OG) → schema.org Product → Product Graph Port → bound Pimcore adapter → USD twin + BrandRulesAPI Backend / Infra: Node.js · Python · Postgres/Supabase · Nango (self-hosted OAuth broker) · Temporal (per-domain namespaces) · AWS EKS + NVIDIA GPU Operator · g5.xlarge spot · AWS Deadline Cloud · S3 + CloudFront · Vercel (frontends only) AI / Agent: Mistral / Codestral · MCP · pybandits Thompson Sampling · autoresearch loops Analytics: PostHog — one shared partition, tenant-scoped, native Experiments + Holdouts Distribution: Postiz (upstream image, arm's-length API/MCP) · Google Ads · Meta Ads · Klaviyo

Every entry above is an adopted standard or upstream component, not a Shoploop invention. Licenses and traps: docs/STANDARDS.md.

Rejected / gated commercial dependencies

Dependency Status
Polotno production SDK Rejected for now. Commercial, closed-source, $899/month self-serve (pricing, license). Not approved, not budgeted, and must not become a production dependency.

Polotno publishes an open JSON scene schema, offers a free hosted Studio demo, and is built on the open-source Konva canvas library. None of that makes the Polotno SDK open source — the SDK is proprietary and separately licensed, and adopting it means paying for it. Treat the schema, the demo, and Konva as three separate things from the product we would be buying.

No editor is being selected — the requirement is deleted (ADR 0009). The Operator link authors a shot list: a typed spec of camera, lighting, variant, molecule and overlay text, constrained by brand_rules, stored on the Pimcore record and composited server-side by Omniverse Kit on AWS. Nothing is hand-positioned in a browser, because Loop 3's nightly Thompson Sampling pass has to be able to mutate the composition — and a declarative spec is a search space where a canvas document is opaque state. grip.tools has no canvas editor either; it wins on production at scale, which is where the dev time goes.

Also evaluated and rejected: Konva/react-konva and Fabric.js (right tools, deleted requirement), PixiJS (wrong category), tldraw (production license key), Penpot (a second application to operate), and Jaaz — its Community License prohibits team deployment, modification, redistribution inside another product, and competing commercial use, which is incompatible with AGPL-3.0, and it ships as an Electron desktop app rather than an embeddable component.

Positioning

See POSITIONING.md, the summary near the top of this file, and the technical teardowns in docs/competitive/.

One line: Shoploop is grip.tools, democratized — for every tabletop brand with a web page.

License

Shoploop's own code and documentation are AGPL-3.0 — full text in LICENSE. Self-hostable. Fork it, ship your own version, contribute back.

Third-party components (Pimcore, PostHog, Postiz, Nango, NVIDIA Omniverse) are governed by their own upstream licences. They do not inherit Shoploop's licence; conversely, Shoploop's AGPL-3.0 does not make their terms disappear. A deployment that includes them is governed by those terms too, and Shoploop neither restates nor warrants them.

Getting started

git clone https://github.com/ninan-versioning/shoploop
cd shoploop
pnpm install
pnpm dev          # runs apps/landing on http://localhost:3000
pnpm typecheck    # what CI runs

pnpm dev runs apps/landing, the only app with runtime code today. apps/operator-studio and apps/configurator are scaffolds — there is no local twin render yet. Read AGENTS.md before opening a PR, and CONTRIBUTING.md for the gate every PR has to clear.

Pricing

Two tiers. $0 Shoploop Core — Shoploop's own AGPL-3.0 source, self-hostable in your own infrastructure. Locked; does not move. Third-party adapters and deployment components retain their own licence and infrastructure costs; Pimcore Community eligibility follows Pimcore's stated EUR/USD 5M annual-revenue threshold, with a commercial subscription required above it. And Managed — hosted twin, GPU streaming, operator link, publishing, the loop running on your data, 30-day trial, no card — whose price is to be determined after production benchmarks (ADR 0017). The former $299/mo was reopened and deliberately not replaced with another number: product quality defines architecture, cost is telemetry, and a price fixed before unit economics are measured turns every cost question into a capability question. No $99 tier. No enterprise tier at v0.

Contributing

Contributors wanted in:

  • Blender headless authoring — bpy scripts and Geometry Nodes for parametric containers, UV unwrap, and label projection
  • OpenPBR / MaterialX material accuracy in Blender + MolecularNodes
  • BrandRulesAPI applied schema via usdGenSchema, and the usdchecker CI gate
  • URL → USD product-twin extractor built on extruct + schema.org Product
  • OVAS deployment on EKS via the NGC Helm charts
  • Postiz public-API and MCP integration (client-side only — no forking upstream)

Read AGENTS.md and docs/STANDARDS.md first. Every PR answers the seven-question decision gate, including which existing standard does this use? Open a PR or a discussion.

Design partner

An Ayurvedic operator is evaluating Shoploop as a design partner. No partner or prospect brand name, domain, contact, or logo appears in this repo or on any customer-facing surface. Public wording is tabletop brands, with Ayurveda as the wedge. ashwagandha.shoploop.studio is Shoploop's own brand-neutral reference tenant.

Motto

Offense. Attack attack attack, never defense.

About

Full-funnel positionless AI marketing for tabletop products. Paste one product page URL, get two links out: a 3D configurator for shoppers and an operator studio for marketers. Pimcore + OpenUSD + OpenPBR + MaterialX + Blender + Postiz + Posthog + NVIDIA Omniverse. AGPL-3.0.

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages