Skip to content

feat(apps-nuvemshop): CMS Props for the deco-nuvemshop admin form - #630

Merged
JonasJesus42 merged 1 commit into
mainfrom
JonasJesus42/nuvemshop-admin-props
Oct 7, 2026
Merged

JonasJesus42 merged 1 commit into
mainfrom
JonasJesus42/nuvemshop-admin-props

Conversation

@JonasJesus42

@JonasJesus42 JonasJesus42 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

What

@decocms/apps-nuvemshop now exports Props and a default export from mod.ts, following apps-vtex. Before this, the deco-nuvemshop block had no fields in the admin, so the store couldn't be configured from the CMS.

generate-schema builds an app's admin form from the Props that the app's mod exports, re-exported by a bridge file in the site's src/apps/.

Fields

Field Admin widget
storeId (required) text
token secret (Secret from @decocms/apps-website, as in VTEX)
currency text, default BRL
defaultSort select listing the 8 supported sorts, default created-descending
apiVersion text, default v2026-11

Verified

I ran generate-schema on a scratch site whose bridge src/apps/nuvemshop.ts re-exports @decocms/apps-nuvemshop/mod:

  • Before: ○ site/apps/nuvemshop.ts (0 props).
  • After: ✓ site/apps/nuvemshop.ts (5 props), with the widgets above.
  • Loaders: all 7 are listed with their output types (ProductListingPage, Product[], …), and the injected __pageUrl/__pagePath stay hidden.

66 tests pass; tsc and biome are clean.

🤖 Generated with Claude Code


Summary by cubic

Adds CMS props to @decocms/apps-nuvemshop so the deco-nuvemshop block gets an admin form. Previously the block had no fields and the store couldn't be configured from the CMS; generate-schema builds the form from the Props re-exported by a bridge in the site's src/apps/.

The form exposes five fields: required storeId (text), optional token (secret via the Secret type from @decocms/apps-website), currency (default BRL), defaultSort (select with the 8 supported sorts, default created-descending), and apiVersion (default v2026-11). Adds @decocms/apps-website as a dependency. Verified with generate-schema: 5 props and all 7 loaders listed with their output types.

Written for commit 27fa15f. Summary will update on new commits.

Review in cubic Turn on auto-fix

generate-schema builds the app block form from the `Props` exported by the
app's mod (re-exported by the site's src/apps/ bridge). Without it the
block showed 0 fields, so the store couldn't be configured from the admin.
Adds Props (storeId, token as a Secret, currency, defaultSort as an enum
of the supported sorts, apiVersion) plus the default export bridges use,
following apps-vtex. Verified by running generate-schema on a site with a
bridge: 5 props, all 7 loaders listed with their output types.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@JonasJesus42
JonasJesus42 requested a review from a team October 6, 2026 23:51
@JonasJesus42
JonasJesus42 merged commit 3295dc0 into main Oct 7, 2026
2 checks passed
JonasJesus42 added a commit that referenced this pull request Oct 7, 2026
## What

Customer accounts, a sitemap, and the `apps-nuvemshop` skill. The
Storefront API has no customer endpoints, so each piece uses whichever
upstream works. All of it was validated against a live store.

| Feature | Upstream | Why this one |
|---|---|---|
| `actions/account/register` | Admin API `POST /customers`, with a
custom-app token (`adminToken`) | The store's own form needs a reCAPTCHA
tied to its domain. Posting without it fails silently: a 302 back to the
form and no account is created. The Admin API has no captcha, so this
action requires **Cloudflare Turnstile** (`turnstileSecret`) unless
`allowUnverifiedRegistration` is set (demos only). A duplicate email
returns 422, mapped to `email_taken`. |
| `actions/account/login` / `logout` | the store's `/account/login/` and
`/account/logout/`, called server-side | Success is a 302 to
`/account/`. On failure, the reason is read from the login page's
markup: `js-login-general-error` for wrong credentials,
`js-account-validation-pending` when the email hasn't been confirmed yet
(the store requires that for every new account). |
| `loaders/user` | the store's `/account/` for `LS.customer`, then Admin
API `/customers/<id>` | Returns `null` when logged out. Exposes only id,
name, email and phone. |
| `nuvemshopSitemap()` | Storefront API, paginated | Matches the store's
own `/sitemap.xml`: 50/50 products, same categories. The only difference
is theme-only pages (`/contato`, `/produtos`). |

`store.ts` bridges the session between our domain and the store:
- only the request's `store_*` cookies are sent upstream, never the
site's own;
- only `store_*` `Set-Cookie` headers are re-emitted, through
`RequestContext.responseHeaders`, with `Domain` rewritten to our host.
The store's Cloudflare cookies are dropped.

The block's admin form gains `storeUrl`, `adminToken` (secret),
`turnstileSecret` (secret) and `allowUnverifiedRegistration`.

The new skill, `.agents/skills/apps-nuvemshop`, covers:
- Storefront API fields and limits;
- listing parity with the theme;
- accounts;
- cart and checkout findings, including that Nuvemshop starts returning
403 on every `/comprar/` (add to cart) from one IP after about 15 carts
created in a few minutes.

It also gets a row in the `CLAUDE.md` skills table.

Stacked on #630.

## Verified

- 90 tests pass (16 new account tests, 1 sitemap test), and `tsc`,
biome, `skills:check`, `skills:readme:check` and `bun install
--frozen-lockfile` are clean.
- Against the live demo store, through the package inside a
`RequestContext`:
  - anonymous `user` returns `null`;
  - a wrong password returns `invalid_credentials`;
  - `login` succeeds, and `user` then returns the customer;
  - `logout` works, and `user` returns `null` again;
  - registering a taken email returns `email_taken`.
- After login, the browser's cookie jar holds only
`store_session_payload_*` and `store_login_session`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds customer accounts, a sitemap, and the `apps-nuvemshop` skill 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**

- `register` posts to the Admin API `POST /customers` with a custom-app
token (`adminToken`). The store's own form needs a domain-bound
reCAPTCHA and silently drops unverified posts; the Admin API has none,
so the action requires Cloudflare Turnstile (`turnstileSecret`) unless
`allowUnverifiedRegistration` is set. Duplicate emails map to
`email_taken`.
- `login` and `logout` call the store's own `/account/login/` and
`/account/logout/` server-side. Login failure reasons are read from the
login page markup: `js-login-general-error` for wrong credentials,
`js-account-validation-pending` for unconfirmed email.
- The `user` loader returns the customer from the session, fetching the
id from the store's `/account/` page and the profile from the Admin API;
it returns `null` when logged out and exposes only id, name, email, and
phone.
- `store.ts` bridges the session: only the request's `store_*` cookies
go upstream, and only `store_*` `Set-Cookie` headers come back,
re-emitted on the site's domain with `Domain` rewritten.

**Sitemap and skill**

- `nuvemshopSitemap()` builds product and category URLs from the
paginated Storefront API, matching the store's own sitemap paths.
- The block's admin form gains `storeUrl`, `adminToken` (secret),
`turnstileSecret` (secret), and `allowUnverifiedRegistration`.
- The new `.agents/skills/apps-nuvemshop` skill documents API fields and
limits, listing parity with the theme, accounts, and cart/checkout
findings, including the Nuvemshop `/comprar/` 403 IP block.

<sup>Written for commit 49db110.
Summary will update on new commits.</sup>

<a href="https://cubic.dev/pr/decocms/blocks/pull/631?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/631?returnTo=https%3A%2F%2Fgithub.com%2Fdecocms%2Fblocks%2Fpull%2F631&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]>
@JonasJesus42
JonasJesus42 deleted the JonasJesus42/nuvemshop-admin-props branch October 7, 2026 01:20
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 7.75.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant