Repository navigation
feat(apps-nuvemshop): customer accounts, sitemap and skill - #631
Merged
Merged
Conversation
JonasJesus42
changed the base branch from
JonasJesus42/nuvemshop-admin-props
to
main
October 7, 2026 01:19
…op skill The Storefront API has no customer endpoints. Validated against a live store: - register: Admin API POST /customers (custom-app `adminToken`). The store's own form needs a domain-bound reCAPTCHA and silently drops posts without it; the Admin API has no captcha, so the action requires Cloudflare Turnstile (`turnstileSecret`) unless `allowUnverifiedRegistration`. Duplicate email maps to `email_taken`. - login/logout: the store's /account/login/ and /account/logout/, called server-side. Failure reasons come from the login page markup (`js-login-general-error`, `js-account-validation-pending`). - user loader: customer id from the store's /account/ page, profile from the Admin API; null when logged out. - store.ts bridges the session: only `store_*` cookies go upstream, and only `store_*` Set-Cookie come back, re-emitted on our domain. - nuvemshopSitemap(): products + categories from the API with our URLs; matches the store's own sitemap (50/50 products, same categories). - Config/admin form: storeUrl, adminToken and turnstileSecret (secrets), allowUnverifiedRegistration. Operation names for store/admin/turnstile calls. - New skill .agents/skills/apps-nuvemshop (API fields/limits, listing parity, accounts, cart/checkout findings incl. the /comprar/ IP block). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
JonasJesus42
force-pushed
the
JonasJesus42/nuvemshop-account
branch
from
October 7, 2026 01:20
49db110 to
e0fff42
Compare
JonasJesus42
added a commit
that referenced
this pull request
Oct 7, 2026
…632) ## What The minicart data for `@decocms/apps-nuvemshop`, using the Storefront API. The cart stays in the browser (`useCart`, `localStorage`). Checkout goes through `POST /checkouts`. We don't use the theme's classic `/comprar/` endpoint: after about 15 carts created in a few minutes, Nuvemshop returned 403 on every `/comprar/` from that IP for over 40 minutes. A server-side proxy would send every buyer through the Worker's egress IPs, so one spike could block add-to-cart for the whole store. Details are in the `apps-nuvemshop` skill. - **`loaders/cart`** turns the client items into minicart lines: name, variant, image, price, list price, subtotal and `maxQuantity`, plus totals and savings. - Products are fetched by `ids`, up to 30 per call, through the existing SWR cache. - **Quantities are clamped to stock**, because `POST /checkouts` rejects a line above it with `422 checkout_rejected`. - Missing, hidden and sold-out variants go to `unavailable` and are left out of the totals. - **`createCheckout`** now returns `{ error, message }` instead of throwing. The success shape (`{ checkoutUrl }`) is unchanged. | API response | `error` | |---|---| | `422 coupon_rejected` | `coupon_rejected` | | `422 checkout_rejected` | `out_of_stock` | | `404 resource_not_found` | `unavailable` | | `400 invalid_request` | `invalid` | `NuvemshopApiError` carries the API's status and code. - **Hooks:** `fetchCartDetails` and `useCartDetails()` back the minicart; `checkout()` throws a `CheckoutError` with the code, so the UI can show the right message. - There is no coupon preview before checkout, because the API has none. The checkout validates the coupon. Stacked on #631. ## Verified - 103 tests pass; `tsc`, biome and `skills:check` are clean. - Live against the demo store: - a 50-unit line is clamped to the variant's stock of 17, and the same line without the clamp is rejected as `out_of_stock`; - a promotional item shows R$169.90 against a list price of R$199.90; - a removed variant lands in `unavailable`; - an invalid coupon returns `coupon_rejected`; - the created checkout's subtotal and total (R$3,698.10) equal the loader's subtotal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds a minicart loader and typed checkout errors to `@decocms/apps-nuvemshop`, using the Storefront API instead of the classic `/comprar/` endpoint (which IP-blocks server-side proxies after a handful of carts). - New `loaders/cart` resolves client-held `useCart` items into minicart lines (name, variant, image, prices, subtotal) with totals and savings, fetching products by `ids` (≤30 per call, cached like the checkout proxy). - Quantities are clamped to stock so `POST /checkouts` doesn't reject lines with `422 checkout_rejected`; missing, hidden, and sold-out variants are moved to `unavailable` and excluded from totals. - `createCheckout` now returns `{ error, message }` on failures instead of throwing, mapping API responses (`coupon_rejected`, `checkout_rejected` → `out_of_stock`, `resource_not_found` → `unavailable`, `invalid_request` → `invalid`); the success shape `{ checkoutUrl }` is unchanged. - New `fetchCartDetails`/`useCartDetails` hooks back the minicart; `checkout()` throws a `CheckoutError` carrying the code so the UI can react. - There is no coupon preview before checkout because the API has none. <sup>Written for commit f767ad2. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/decocms/blocks/pull/632?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <a href="https://www.cubic.dev/action/auto-fix/pr/decocms/blocks/632?returnTo=https%3A%2F%2Fgithub.com%2Fdecocms%2Fblocks%2Fpull%2F632&source=description" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img alt="Turn on auto-fix" src="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
|
🎉 This PR is included in version 7.76.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Customer accounts, a sitemap, and the
apps-nuvemshopskill. The Storefront API has no customer endpoints, so each piece uses whichever upstream works. All of it was validated against a live store.actions/account/registerPOST /customers, with a custom-app token (adminToken)turnstileSecret) unlessallowUnverifiedRegistrationis set (demos only). A duplicate email returns 422, mapped toemail_taken.actions/account/login/logout/account/login/and/account/logout/, called server-side/account/. On failure, the reason is read from the login page's markup:js-login-general-errorfor wrong credentials,js-account-validation-pendingwhen the email hasn't been confirmed yet (the store requires that for every new account).loaders/user/account/forLS.customer, then Admin API/customers/<id>nullwhen logged out. Exposes only id, name, email and phone.nuvemshopSitemap()/sitemap.xml: 50/50 products, same categories. The only difference is theme-only pages (/contato,/produtos).store.tsbridges the session between our domain and the store:store_*cookies are sent upstream, never the site's own;store_*Set-Cookieheaders are re-emitted, throughRequestContext.responseHeaders, withDomainrewritten to our host. The store's Cloudflare cookies are dropped.The block's admin form gains
storeUrl,adminToken(secret),turnstileSecret(secret) andallowUnverifiedRegistration.The new skill,
.agents/skills/apps-nuvemshop, covers:/comprar/(add to cart) from one IP after about 15 carts created in a few minutes.It also gets a row in the
CLAUDE.mdskills table.Stacked on #630.
Verified
tsc, biome,skills:check,skills:readme:checkandbun install --frozen-lockfileare clean.RequestContext:userreturnsnull;invalid_credentials;loginsucceeds, anduserthen returns the customer;logoutworks, anduserreturnsnullagain;email_taken.store_session_payload_*andstore_login_session.🤖 Generated with Claude Code
Summary by cubic
Adds customer accounts (register, login, logout, user), a sitemap, and the
apps-nuvemshopskill to the Nuvemshop app. The Storefront API has no customer or sitemap endpoints, so each piece uses whichever upstream works, validated against a live store.Accounts
registerposts to the Admin APIPOST /customerswith a custom-app token (adminToken). The store's form needs a domain-bound reCAPTCHA and silently drops unverified posts; the Admin API has no captcha, so the action requires Cloudflare Turnstile (turnstileSecret) unlessallowUnverifiedRegistrationis set. Duplicate emails map toemail_taken.loginandlogoutcall the store's own/account/login/and/account/logout/server-side. Login failure reasons are read from the login page markup:js-login-general-errorfor wrong credentials,js-account-validation-pendingfor unconfirmed email.userloader returns the customer from the session — id from the store's/account/page, profile from the Admin API — andnullwhen logged out, exposing only id, name, email, and phone.store.tsbridges the session: only the request'sstore_*cookies go upstream, and onlystore_*Set-Cookieheaders return, re-emitted on the site's domain withDomainrewritten.Sitemap and skill
nuvemshopSitemap()builds product and category URLs from the paginated Storefront API, matching the store's own sitemap paths.storeUrl,adminToken(secret),turnstileSecret(secret), andallowUnverifiedRegistration; store, admin, and Turnstile calls get operation names..agents/skills/apps-nuvemshopskill documents API fields and limits, listing parity with the theme, accounts, and cart/checkout findings, including the Nuvemshop/comprar/403 IP block.Written for commit e0fff42. Summary will update on new commits.