StoreLingo help
Back to app Legal

StoreLingo - Webflow Marketplace resubmission changelog

Date: 2026-06-19 Submission: v2 (resubmission after initial rejection) Reviewer: Pablo Miranda + Webflow Marketplace team

This document accompanies the resubmission. It explains what changed since the first submission, why each change exists, and what reviewers should look at to validate.

The headline change: StoreLingo now leads with ownership. Every architectural choice in this product flows from the promise that translated content belongs to the customer's Webflow site, not to StoreLingo's servers. We rewrote the landing page, the docs, and the comparison pages around this single message, and we added or hardened the features that make the promise real.


What was wrong with v1

Pablo's rejection feedback pointed at three categories of problem:

  1. Demo video was unclear. Reviewers couldn't follow what the app actually did or how a customer would use it.
  2. Edge-case flows were untested. Disconnecting and reconnecting a site exposed broken states. Slug collisions on re-publish bricked the flow. Designer threw "Unable to open this product because a variant is missing" on translated duplicates.
  3. The value prop wasn't legible. Why does this exist when Weglot and Linguana exist? What problem is StoreLingo uniquely solving?

We addressed each.


What changed: features

Hreflang automation (new, end-to-end)

Reviewer concern from v1: how does SEO work on a duplicate-row architecture?

StoreLingo now registers a per-site script via the Webflow Custom Code API that injects <link rel="alternate" hreflang> tags into every translated page's head. Three modes:

OAuth scopes added: custom_code:read, custom_code:write. Both are gated behind a per-feature re-auth UX: if a customer connected before the scopes existed, the Hreflang dialog renders an inline "Reauthorize StoreLingo" CTA instead of failing silently.

Verification: open any translated product URL on the live demo site, view source - the script tag and 3+ <link rel="alternate"> entries are in the head.

Docs: /docs/seo-and-hreflang

Orphan Recovery (new dialog + collision-safe matching)

The disconnect/reconnect flow was the v1 review's biggest stumbling block. Now:

Verification: disconnect a connected site in the panel, reconnect, watch the toast appear with the previously published rows.

Docs: /docs/orphan-recovery

Per-item completion chip (new)

Every locale in the sidebar now shows a done / total chip. The count aggregates products + every CMS item across every collection. An item is "done" when every source-content field has a non-empty translation. Auto-updates after every save, AI translate, or orphan adoption.

Verification: open the panel, look at the DE chip. Translate a product, watch the count go up. No refresh needed.

Scope-aware re-auth UX (new)

Customers who connected before a new OAuth scope existed previously had no clean recovery path. Now: granted scopes are persisted at the OAuth handshake; feature gates check before calling Webflow; missing scopes surface as an inline "Reauthorize for [feature]" CTA on the specific feature, not a forced full re-install.


What changed: bugs fixed

"Unable to open this product because a variant is missing" in Webflow Designer

The most damaging v1 bug. Translated product duplicates couldn't be opened in Webflow Designer because their default-sku field pointed at the SOURCE product's SKU ID, not the duplicate's own SKU ID. The publish flow was spreading the source's full fieldData into the duplicate's PATCH body, clobbering the linkage.

Fix: strip default-sku and sku-properties from the source spread before every CREATE and PATCH. Existing duplicates were repaired with a one-time backfill script. Designer now opens every translated product cleanly with the correct price showing.

Slug-collision on republish (after disconnect/reconnect)

Previously: customers who disconnected and reconnected a site lost the DB linkage to existing Webflow duplicates. The publish flow then tried CREATE instead of PATCH, hit "slug already in database," and the slug-retry exhausted after 10 attempts. Stuck.

Fix: Orphan Recovery (above) restores the linkage with one click. The publish flow correctly does PATCH on adopted rows, no slug conflict.

Webflow PATCH 404 on duplicate self-heal

When a duplicate was deleted in Webflow Designer between publishes, our PATCH 404'd and the whole batch crashed. Now the PATCH 404 path nulls the stored ID and falls through to CREATE, so the publish self-heals instead of failing.

Initial-sync polling race (read-after-write)

After the initial sync job flipped to "completed," the next listProducts call could land before all the product upserts had settled on the DB pool. Result: empty product list visible briefly until manual refresh.

Fix: the watcher retries listProducts with backoff (0, 400, 800, 1500 ms) when the job claims completedItems > 0 but the query returns empty.

Initial-sync polling tolerance

The watcher was bailing on the first "no job found" poll because the backend writes the job row after kicking off the sync (small lag window). Now it tolerates up to 15s of "no job yet" before giving up.

Per-tab publish indicator stuck stale

After publishing a locale, the green dot on Products / CMS tabs stayed stale until manual refresh. Now a publishTick is bumped from both publish flows (Products + each CMS tab) and the per-tab status effect re-fires immediately.

Translation-set completeness mismatch

The completion chip was counting source fields that bulk translate doesn't actually translate (e.g., fields outside the per-collection translatable-fields allowlist). Customers saw "9/21" forever even after translating everything. Now the chip intersects the source-field set with the same allowlist the editor and AI translate use - what the customer can see is what the customer gets counted for.

Add-locale backfill used the wrong field list

The Add-Locale path was backfilling empty translation rows using a hardcoded [name, description, summary] instead of the site's actual translatableFields allowlist. Custom fields like short-description were never seeded, so AI translate had nothing to fill, and the chip stayed below 100%. Fixed: backfill respects the site's current allowlist.

Orphan matcher collision guard

The fuzzy matcher could silently pick the wrong source product when two compacted slugs collided. Now the matcher tracks collision keys and drops colliding entries from the suggestion pool, surfacing "No match" instead of an incorrect auto-match.

Reusable docs + screenshots route

Added /docs/screenshots/*.png static route so embedded screenshots in markdown docs render correctly. Layout CSS caps full-panel shots at content width, sidebar crops at 320px, toast notifications at 380px.


What changed: landing page + comparison pages

The v1 landing led with "Flat pricing, native API." Reviewers (correctly) couldn't tell why anyone would pick StoreLingo over Weglot from that pitch alone.

v2 landing leads with ownership:

Comparison pages (/vs/weglot, /vs/linguana) updated with the same ownership angle and new feature rows (automatic hreflang, orphan recovery).


What changed: docs

The v1 docs were 9 thin markdown files. v2 has 10 files (added ownership.md + orphan-recovery.md) and every existing file was substantially expanded.

Headline additions:

15 screenshots embedded across the docs, captured at 2x retina and sized correctly by CSS.


What changed: OAuth and session management

Two related architectural cleanups:

  1. OAuth token is account-level, not per-site. Disconnecting a site no longer invalidates the OAuth token. Customers can connect/disconnect/reconnect without going through Webflow's consent screen each time. Matches the standard Marketplace app pattern (Stripe, Slack, GitHub apps).

  2. Granted scopes persisted at handshake. When OAuth completes, we save the exact scope list Webflow granted. Feature gates check the stored scopes before calling Webflow, so a missing scope surfaces as an inline "Reauthorize for [feature]" CTA instead of a 403 error after the fact.


What didn't change

Honest list of things v1 had that v2 still has at the same level:

These are all v1.1 candidates, not Marketplace gating issues.


What reviewers should test

In priority order:

  1. Install + initial sync. Connect the demo site, watch products + CMS sync without manual refresh.
  2. AI translate to one locale. Translate the Products tab to DE, watch the completion chip go from 0/21 to N/21 live.
  3. Publish. Click Publish DE, watch the publish-complete toast, open the published German URL.
  4. Open a published product in Webflow Designer. Should open cleanly with price showing (this was the worst v1 bug).
  5. View source on a translated URL. Confirm the hreflang script + alternate link tags in the head.
  6. Disconnect + reconnect. Watch the orphan toast appear, click Recover, Adopt all, confirm translations survive intact.
  7. Hreflang dialog. Toggle Auto → Manual → Off → Auto. Confirm each mode behaves correctly.
  8. Cancel subscription. Confirm translated pages stay live in the Webflow site after cancellation (the ownership promise made real).

Demo video

Loom: https://www.loom.com/share/18de6d78168648518fb9f2a45368a316

The video is silent (~2:15). Three onscreen captions hit the resubmission narrative:

Sequence: connect → orphan recovery → adopt all → AI translate → manual edit + approve → hreflang dialog → publish.

The video opens with the disconnect-reconnect orphan recovery flow on purpose - that was the v1 review's biggest stumbling block, so we lead by demonstrating it works cleanly.


One-line summary for the reviewer

StoreLingo writes real translated CMS rows into the customer's own Webflow site. Customers own them forever. Strategy A. Every fix in this changelog protects that promise.

Pablo: thank you for the v1 review. Every flag you raised is addressed above. Happy to answer questions on any specific item.