@unbox-plus/cli 0.20.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +46 -0
- package/README.md +175 -0
- package/bin/cli.js +439 -0
- package/package.json +43 -0
- package/src/colors.js +100 -0
- package/src/presets.js +241 -0
- package/src/theme.js +253 -0
- package/template/.claude/agents/assets-marca.md +40 -0
- package/template/.claude/agents/avaliador-visual.md +48 -0
- package/template/.claude/agents/branding-briefing.md +401 -0
- package/template/.claude/agents/conteudo-secao.md +46 -0
- package/template/.claude/agents/paginas-legais.md +44 -0
- package/template/.claude/settings.json +3 -0
- package/template/.claude/skills/frontend-design/ATTRIBUTION.md +3 -0
- package/template/.claude/skills/frontend-design/LICENSE.txt +177 -0
- package/template/.claude/skills/frontend-design/SKILL.md +55 -0
- package/template/.claude/skills/web-design-guidelines/ATTRIBUTION.md +3 -0
- package/template/.claude/skills/web-design-guidelines/SKILL.md +50 -0
- package/template/.claude/skills/web-design-guidelines/guidelines-snapshot.md +180 -0
- package/template/.env.example +158 -0
- package/template/.mcp.json.example +14 -0
- package/template/.nvmrc +1 -0
- package/template/CLAUDE.md +333 -0
- package/template/COVERAGE.md +80 -0
- package/template/DEPLOY.md +179 -0
- package/template/QA.md +108 -0
- package/template/README.md +152 -0
- package/template/agents/CONSTRUCAO.md +207 -0
- package/template/agents/MANAGER.md +192 -0
- package/template/agents/PADROES.md +255 -0
- package/template/agents/definitions/00-scaffold.md +56 -0
- package/template/agents/definitions/01-layout.md +47 -0
- package/template/agents/definitions/02-homepage.md +70 -0
- package/template/agents/definitions/03-catalog.md +86 -0
- package/template/agents/definitions/04-pdp.md +97 -0
- package/template/agents/definitions/05-cart.md +116 -0
- package/template/agents/definitions/06-checkout.md +146 -0
- package/template/agents/definitions/07-auth.md +130 -0
- package/template/agents/definitions/08-customer.md +55 -0
- package/template/agents/definitions/09-promotions.md +62 -0
- package/template/agents/definitions/10-feedback.md +128 -0
- package/template/agents/definitions/11-seo-infra.md +159 -0
- package/template/agents/definitions/12-deploy.md +173 -0
- package/template/agents/definitions/13-cro.md +275 -0
- package/template/agents/definitions/14-seo.md +388 -0
- package/template/agents/definitions/15-branding.md +26 -0
- package/template/agents/definitions/16-qa-visual.md +138 -0
- package/template/agents/definitions/17-aeo.md +257 -0
- package/template/app/(loja)/busca/page.tsx +72 -0
- package/template/app/(loja)/carrinho/oferta/page.tsx +57 -0
- package/template/app/(loja)/carrinho/page.tsx +160 -0
- package/template/app/(loja)/categoria/[tagSlug]/layout.tsx +31 -0
- package/template/app/(loja)/categoria/[tagSlug]/loading.tsx +17 -0
- package/template/app/(loja)/categoria/[tagSlug]/page.tsx +49 -0
- package/template/app/(loja)/checkout/page.tsx +80 -0
- package/template/app/(loja)/checkout/pix/[ref]/page.tsx +133 -0
- package/template/app/(loja)/conta/assinaturas/[referenceId]/page.tsx +112 -0
- package/template/app/(loja)/conta/assinaturas/page.tsx +51 -0
- package/template/app/(loja)/conta/enderecos/page.tsx +20 -0
- package/template/app/(loja)/conta/entrar/page.tsx +119 -0
- package/template/app/(loja)/conta/page.tsx +45 -0
- package/template/app/(loja)/conta/pedidos/[referenceId]/page.tsx +49 -0
- package/template/app/(loja)/conta/pedidos/page.tsx +104 -0
- package/template/app/(loja)/conta/preferencias/page.tsx +24 -0
- package/template/app/(loja)/devolucoes/page.tsx +36 -0
- package/template/app/(loja)/layout.tsx +22 -0
- package/template/app/(loja)/oferta/page.tsx +57 -0
- package/template/app/(loja)/page.tsx +86 -0
- package/template/app/(loja)/pedido/[referenceId]/page.tsx +78 -0
- package/template/app/(loja)/privacidade/page.tsx +113 -0
- package/template/app/(loja)/produto/[productSlug]/layout.tsx +23 -0
- package/template/app/(loja)/produto/[productSlug]/loading.tsx +20 -0
- package/template/app/(loja)/produto/[productSlug]/page.tsx +372 -0
- package/template/app/(loja)/produtos/loading.tsx +16 -0
- package/template/app/(loja)/produtos/page.tsx +33 -0
- package/template/app/(loja)/termos/page.tsx +104 -0
- package/template/app/acesso/page.tsx +129 -0
- package/template/app/api/account/addresses/route.ts +39 -0
- package/template/app/api/account/exists/route.ts +21 -0
- package/template/app/api/account/me/route.ts +25 -0
- package/template/app/api/account/otp/route.ts +26 -0
- package/template/app/api/account/preferences/route.ts +19 -0
- package/template/app/api/account/signin/route.ts +27 -0
- package/template/app/api/account/signout/route.ts +9 -0
- package/template/app/api/acesso/route.ts +171 -0
- package/template/app/api/capi/route.ts +34 -0
- package/template/app/api/cart/coupon/route.ts +49 -0
- package/template/app/api/cart/items/route.ts +45 -0
- package/template/app/api/cart/link/route.ts +69 -0
- package/template/app/api/cart/route.ts +113 -0
- package/template/app/api/cart/share/route.ts +21 -0
- package/template/app/api/cep/[code]/route.ts +18 -0
- package/template/app/api/checkout/address/route.ts +24 -0
- package/template/app/api/checkout/email/route.ts +41 -0
- package/template/app/api/checkout/installments/route.ts +16 -0
- package/template/app/api/checkout/route.ts +110 -0
- package/template/app/api/checkout/shipping/route.ts +65 -0
- package/template/app/api/checkout-destination/route.ts +31 -0
- package/template/app/api/order/[ref]/route.ts +17 -0
- package/template/app/api/payment-link/route.ts +28 -0
- package/template/app/api/revalidate/route.ts +52 -0
- package/template/app/api/shipping/quote/route.ts +29 -0
- package/template/app/api/subscriptions/[id]/route.ts +52 -0
- package/template/app/api/track/route.ts +28 -0
- package/template/app/api/unbox/catalogo/route.ts +136 -0
- package/template/app/api/unbox/paginas/route.ts +167 -0
- package/template/app/api/unbox/vitrine/route.ts +84 -0
- package/template/app/api/webhooks/unbox/route.ts +97 -0
- package/template/app/apple-icon.svg +5 -0
- package/template/app/error.tsx +15 -0
- package/template/app/globals.css +457 -0
- package/template/app/icon.svg +4 -0
- package/template/app/layout.tsx +90 -0
- package/template/app/llms.txt/route.ts +43 -0
- package/template/app/manifest.ts +21 -0
- package/template/app/not-found.tsx +18 -0
- package/template/app/opengraph-image.tsx +35 -0
- package/template/app/robots.ts +31 -0
- package/template/app/sitemap.ts +42 -0
- package/template/bootstrap.sh +87 -0
- package/template/components/account/account-shell.tsx +47 -0
- package/template/components/account/address-book.tsx +147 -0
- package/template/components/account/preferences-form.tsx +77 -0
- package/template/components/account/reorder-button.tsx +47 -0
- package/template/components/account/signout-button.tsx +20 -0
- package/template/components/account/subscription-actions.tsx +204 -0
- package/template/components/account-nav.tsx +41 -0
- package/template/components/address-fields.tsx +102 -0
- package/template/components/analytics/data-layer-ready.tsx +16 -0
- package/template/components/analytics/purchase-tracker.tsx +32 -0
- package/template/components/brand-search.tsx +34 -0
- package/template/components/cart/cart-provider.tsx +340 -0
- package/template/components/cart/mini-cart.tsx +228 -0
- package/template/components/cart-button.tsx +35 -0
- package/template/components/catalog/catalog-client.tsx +523 -0
- package/template/components/catalog/grid-skeleton.tsx +19 -0
- package/template/components/catalog/pager.tsx +66 -0
- package/template/components/catalog/product-grid-card.tsx +52 -0
- package/template/components/catalog/product-grid.tsx +27 -0
- package/template/components/checkout/checkout-client.tsx +1333 -0
- package/template/components/chrome/announce-bar.tsx +57 -0
- package/template/components/chrome/chrome-recipe.ts +13 -0
- package/template/components/chrome/footers/captura-botao.tsx +28 -0
- package/template/components/chrome/footers/colunas.tsx +110 -0
- package/template/components/chrome/footers/conversao.tsx +90 -0
- package/template/components/chrome/footers/editorial.tsx +98 -0
- package/template/components/chrome/footers/minimal.tsx +55 -0
- package/template/components/chrome/header-bar-mobile.tsx +64 -0
- package/template/components/chrome/headers/centralizado.tsx +71 -0
- package/template/components/chrome/headers/classico.tsx +64 -0
- package/template/components/chrome/headers/compacto.tsx +66 -0
- package/template/components/chrome/headers/equilibrado.tsx +73 -0
- package/template/components/chrome/headers/imersivo.tsx +62 -0
- package/template/components/chrome/registry.ts +70 -0
- package/template/components/chrome/solid-on-scroll.tsx +39 -0
- package/template/components/empty-state.tsx +22 -0
- package/template/components/home/combo-card-compact.tsx +67 -0
- package/template/components/home/combos-home.tsx +64 -0
- package/template/components/home/combos-section.tsx +177 -0
- package/template/components/home/home-recipe.ts +41 -0
- package/template/components/home/sections/attributes-marquee.tsx +178 -0
- package/template/components/home/sections/benefits.tsx +80 -0
- package/template/components/home/sections/bloco-html.tsx +47 -0
- package/template/components/home/sections/catalogo.ts +165 -0
- package/template/components/home/sections/category-pills.tsx +32 -0
- package/template/components/home/sections/combos-carousel.tsx +141 -0
- package/template/components/home/sections/comparison.tsx +73 -0
- package/template/components/home/sections/founder-story.tsx +40 -0
- package/template/components/home/sections/hero.tsx +187 -0
- package/template/components/home/sections/kits.tsx +11 -0
- package/template/components/home/sections/media-cards.tsx +70 -0
- package/template/components/home/sections/newsletter.tsx +62 -0
- package/template/components/home/sections/product-showcase.tsx +175 -0
- package/template/components/home/sections/purchase-hero.tsx +187 -0
- package/template/components/home/sections/quote-banner.tsx +50 -0
- package/template/components/home/sections/registry.ts +186 -0
- package/template/components/home/sections/reviews-carousel.tsx +66 -0
- package/template/components/home/sections/reviews.tsx +68 -0
- package/template/components/home/sections/ritual.tsx +96 -0
- package/template/components/home/sections/savings.tsx +47 -0
- package/template/components/home/sections/social-row.tsx +65 -0
- package/template/components/home/sections/spec-table.tsx +117 -0
- package/template/components/home/sections/stars.tsx +12 -0
- package/template/components/home/sections/stats-grid.tsx +54 -0
- package/template/components/home/sections/trust-bar.tsx +56 -0
- package/template/components/home/sections/trust-strip.tsx +40 -0
- package/template/components/home/sections/video-wall.tsx +59 -0
- package/template/components/landing/landing-recipe.ts +20 -0
- package/template/components/landing/oferta-sections.tsx +40 -0
- package/template/components/landing/product-picker.tsx +257 -0
- package/template/components/mobile-nav.tsx +71 -0
- package/template/components/order-status.tsx +163 -0
- package/template/components/powered-by-unbox.tsx +27 -0
- package/template/components/product/pdp/buy-box.tsx +604 -0
- package/template/components/product/pdp/catalog-grid.tsx +113 -0
- package/template/components/product/pdp/faq-modelo.ts +86 -0
- package/template/components/product/pdp/gallery.tsx +87 -0
- package/template/components/product/pdp/interactive.tsx +200 -0
- package/template/components/product/pdp/newsletter.tsx +64 -0
- package/template/components/product/pdp/payment-chips.tsx +22 -0
- package/template/components/product/pdp/pdp-view.tsx +227 -0
- package/template/components/product/pdp/recommendations.tsx +144 -0
- package/template/components/product/pdp/sections.tsx +173 -0
- package/template/components/quantity-stepper.tsx +36 -0
- package/template/components/search-box.tsx +37 -0
- package/template/components/site-footer.tsx +59 -0
- package/template/components/site-header.tsx +64 -0
- package/template/components/ui/accordion.tsx +72 -0
- package/template/components/ui/alert-dialog.tsx +187 -0
- package/template/components/ui/alert.tsx +76 -0
- package/template/components/ui/aspect-ratio.tsx +22 -0
- package/template/components/ui/avatar.tsx +109 -0
- package/template/components/ui/badge.tsx +52 -0
- package/template/components/ui/breadcrumb.tsx +125 -0
- package/template/components/ui/button.tsx +58 -0
- package/template/components/ui/card.tsx +103 -0
- package/template/components/ui/carousel.tsx +242 -0
- package/template/components/ui/command.tsx +196 -0
- package/template/components/ui/dialog.tsx +160 -0
- package/template/components/ui/dropdown-menu.tsx +268 -0
- package/template/components/ui/foto.tsx +54 -0
- package/template/components/ui/input-group.tsx +158 -0
- package/template/components/ui/input-otp.tsx +87 -0
- package/template/components/ui/input.tsx +20 -0
- package/template/components/ui/label.tsx +20 -0
- package/template/components/ui/navigation-menu.tsx +168 -0
- package/template/components/ui/pagination.tsx +132 -0
- package/template/components/ui/popover.tsx +90 -0
- package/template/components/ui/progress.tsx +83 -0
- package/template/components/ui/radio-group.tsx +38 -0
- package/template/components/ui/scroll-area.tsx +55 -0
- package/template/components/ui/select.tsx +201 -0
- package/template/components/ui/separator.tsx +25 -0
- package/template/components/ui/sheet.tsx +138 -0
- package/template/components/ui/skeleton.tsx +13 -0
- package/template/components/ui/sonner.tsx +44 -0
- package/template/components/ui/switch.tsx +32 -0
- package/template/components/ui/table.tsx +116 -0
- package/template/components/ui/tabs.tsx +82 -0
- package/template/components/ui/textarea.tsx +18 -0
- package/template/components/ui/toggle-group.tsx +89 -0
- package/template/components/ui/toggle.tsx +45 -0
- package/template/components/ui/tooltip.tsx +66 -0
- package/template/components.json +25 -0
- package/template/eslint.config.mjs +36 -0
- package/template/gitignore +21 -0
- package/template/lib/analytics.ts +369 -0
- package/template/lib/api.ts +60 -0
- package/template/lib/capi.ts +87 -0
- package/template/lib/cart-link.ts +51 -0
- package/template/lib/cart-normalize.ts +142 -0
- package/template/lib/cart-recovery.ts +23 -0
- package/template/lib/cart-response.ts +48 -0
- package/template/lib/catalog-map.ts +54 -0
- package/template/lib/catalog.ts +3 -0
- package/template/lib/checkout-lock.ts +21 -0
- package/template/lib/checkout-nav.ts +22 -0
- package/template/lib/config.ts +51 -0
- package/template/lib/crm.ts +40 -0
- package/template/lib/customer-session.ts +21 -0
- package/template/lib/dataloader.ts +23 -0
- package/template/lib/editable/config.ts +11 -0
- package/template/lib/editable/document.ts +1762 -0
- package/template/lib/editable/index.ts +3 -0
- package/template/lib/editable/primitives.tsx +821 -0
- package/template/lib/editable/provider.tsx +861 -0
- package/template/lib/editable/rastreio-navegacao.tsx +65 -0
- package/template/lib/editable/rastreio.tsx +168 -0
- package/template/lib/editable/server.ts +189 -0
- package/template/lib/editable/tokens.ts +22 -0
- package/template/lib/editable/verify.ts +24 -0
- package/template/lib/enrichment/combos.ts +184 -0
- package/template/lib/enrichment/index.ts +188 -0
- package/template/lib/enrichment/products.json +1 -0
- package/template/lib/env-check.ts +47 -0
- package/template/lib/format.ts +130 -0
- package/template/lib/icons.ts +67 -0
- package/template/lib/json-ld.ts +9 -0
- package/template/lib/llms-txt.ts +75 -0
- package/template/lib/mockup.ts +24 -0
- package/template/lib/newsletter.ts +12 -0
- package/template/lib/orders.ts +160 -0
- package/template/lib/queries.ts +66 -0
- package/template/lib/ratelimit.ts +47 -0
- package/template/lib/rotas-editaveis.ts +192 -0
- package/template/lib/sanitize.ts +36 -0
- package/template/lib/schemas.ts +78 -0
- package/template/lib/session.ts +98 -0
- package/template/lib/store-config.ts +67 -0
- package/template/lib/unbox/client.ts +829 -0
- package/template/lib/unbox/customer.ts +224 -0
- package/template/lib/unbox/errors.ts +97 -0
- package/template/lib/unbox/index.ts +10 -0
- package/template/lib/unbox/store.ts +113 -0
- package/template/lib/unbox/types.ts +195 -0
- package/template/lib/unbox/webhooks.ts +66 -0
- package/template/lib/utils.ts +6 -0
- package/template/lib/vitrine.ts +242 -0
- package/template/lib/webhook-store.ts +22 -0
- package/template/middleware.ts +178 -0
- package/template/next.config.ts +63 -0
- package/template/package.json +62 -0
- package/template/postcss.config.mjs +5 -0
- package/template/public/brand/coll/default.png +0 -0
- package/template/public/brand/hero-desktop.svg +12 -0
- package/template/public/brand/hero-mobile.svg +12 -0
- package/template/public/brand/heros/boutique-desktop.svg +11 -0
- package/template/public/brand/heros/boutique-mobile.svg +11 -0
- package/template/public/brand/heros/editorial-desktop.svg +11 -0
- package/template/public/brand/heros/editorial-mobile.svg +11 -0
- package/template/public/brand/heros/essencial-desktop.svg +12 -0
- package/template/public/brand/heros/essencial-mobile.svg +12 -0
- package/template/public/brand/heros/promocional-desktop.svg +12 -0
- package/template/public/brand/heros/promocional-mobile.svg +12 -0
- package/template/public/brand/logo-chrome.svg +6 -0
- package/template/public/brand/logo-white.svg +6 -0
- package/template/public/brand/logo.svg +7 -0
- package/template/public/brand/pay-amex.webp +0 -0
- package/template/public/brand/pay-elo.webp +0 -0
- package/template/public/brand/pay-mastercard.webp +0 -0
- package/template/public/brand/pay-pix.webp +0 -0
- package/template/public/brand/pay-visa.webp +0 -0
- package/template/public/brand/ph/avatar-a.svg +5 -0
- package/template/public/brand/ph/avatar-b.svg +5 -0
- package/template/public/brand/ph/avatar-c.svg +5 -0
- package/template/public/brand/ph/avatar-d.svg +5 -0
- package/template/public/brand/ph/photo-a.svg +7 -0
- package/template/public/brand/ph/photo-b.svg +6 -0
- package/template/public/brand/ph/photo-c.svg +6 -0
- package/template/public/brand/ph/poster-a.svg +6 -0
- package/template/public/brand/ph/poster-b.svg +6 -0
- package/template/public/brand/ph/poster-c.svg +6 -0
- package/template/public/unbox/powered-by-fundo-preto.png +0 -0
- package/template/public/unbox/powered-by-transparente.png +0 -0
- package/template/public/unbox/powered-by.png +0 -0
- package/template/scripts/abandoned-cart.ts +82 -0
- package/template/scripts/check-editable.mjs +467 -0
- package/template/scripts/check-honestidade.mjs +111 -0
- package/template/scripts/check-placeholder.mjs +200 -0
- package/template/scripts/check-recipe.mjs +76 -0
- package/template/scripts/check-unbox-brand.mjs +298 -0
- package/template/scripts/contraste.js +177 -0
- package/template/scripts/dump-catalog.ts +95 -0
- package/template/scripts/load-env.ts +13 -0
- package/template/scripts/medir-sistema.mjs +56 -0
- package/template/scripts/place-order-pix.ts +61 -0
- package/template/scripts/qa-screenshots.mjs +150 -0
- package/template/scripts/sistema.py +231 -0
- package/template/scripts/subscribe-webhook.ts +36 -0
- package/template/scripts/test-live.ts +186 -0
- package/template/scripts/vocabulario.py +264 -0
- package/template/tsconfig.json +27 -0
- package/tools/LEIA-ME.md +39 -0
- package/tools/check-template-neutro.mjs +111 -0
- package/tools/notion-doc.mjs +191 -0
- package/tools/tokenize-neutrals.mjs +0 -0
- package/tools/tokenize-radius.mjs +52 -0
- package/tools/workflow-storefront.legado.js +1207 -0
package/template/QA.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# QA — Checklist pré-go-live
|
|
2
|
+
|
|
3
|
+
> **Pré-requisito:** `.env.local` preenchido com credenciais reais e `npm run unbox:test` passando.
|
|
4
|
+
> Sem credenciais, os fluxos abaixo não funcionam — complete o `.env.local` (guia no `.env.example`).
|
|
5
|
+
|
|
6
|
+
> **OBRIGATÓRIO (contrato Unbox):** o GTM central `GTM-PZLT336` deve estar ativo em toda
|
|
7
|
+
> página (`UNBOX_GTM_ID` em `app/layout.tsx` — nunca removido/trocado). Verificar: aba
|
|
8
|
+
> Network com requisição a `googletagmanager.com/gtm.js?id=GTM-PZLT336` em qualquer página.
|
|
9
|
+
>
|
|
10
|
+
> **OBRIGATÓRIO (contrato Unbox):** selo **"Powered by Unbox"** no rodapé
|
|
11
|
+
> (`<PoweredByUnbox />` em `components/site-footer.tsx` + asset `/unbox/powered-by.png`).
|
|
12
|
+
> O `prebuild` (`scripts/check-unbox-brand.mjs`) BLOQUEIA o build/deploy sem os dois itens.
|
|
13
|
+
|
|
14
|
+
> **Pré-requisitos de back-end (configurar no painel Unbox antes de ir ao ar):**
|
|
15
|
+
> - **Frete grátis** (módulo CRO 4): regra de valor mínimo e CEPs elegíveis configurada
|
|
16
|
+
> - **Brindes** (módulo CRO 10): regra de brinde ativa, SKU do brinde com estoque
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Layout e navegação
|
|
21
|
+
|
|
22
|
+
- [ ] Favicon aparece na aba do browser (substituir `app/icon.svg` pela marca real)
|
|
23
|
+
- [ ] Apple touch icon aparece ao salvar na tela inicial do iPhone (`app/apple-icon.svg`)
|
|
24
|
+
- [ ] PWA: loja aparece com nome e `theme-color` corretos ao "Adicionar à tela inicial" (`app/manifest.ts`)
|
|
25
|
+
- [ ] Header renderiza com logo, navegação e ícone de carrinho
|
|
26
|
+
- [ ] Footer renderiza com CNPJ, endereço e links corretos
|
|
27
|
+
- [ ] Footer tem links para `/privacidade`, `/termos` e `/devolucoes`
|
|
28
|
+
- [ ] Menu de categorias carrega (via `getTags`)
|
|
29
|
+
- [ ] Página 404 customizada aparece em rotas inexistentes
|
|
30
|
+
- [ ] Links de navegação não quebram (404, 500)
|
|
31
|
+
|
|
32
|
+
## Páginas legais (obrigatório antes do go-live)
|
|
33
|
+
|
|
34
|
+
- [ ] `/privacidade` — substituídos todos os `[PLACEHOLDERS]` com dados reais da empresa
|
|
35
|
+
- [ ] `/termos` — substituídos todos os `[PLACEHOLDERS]`, incluindo foro e CNPJ
|
|
36
|
+
- [ ] `/devolucoes` — canal de contato atualizado com o e-mail/WhatsApp real da loja
|
|
37
|
+
- [ ] `npm run unbox:placeholder` — ANTES de publicar. Varre o HTML SERVIDO (build de produção) atrás de `[NOME DA LOJA]`, `[CNPJ]`, `TODO:`, "Minha Loja" e logo placeholder. Scaffold novo REPROVA de propósito: é gate de publicação, não de build
|
|
38
|
+
- [ ] Contraste: cole `scripts/contraste.js` no console e rode `contraste()` na home, PDP e checkout. Texto sobre foto não é aprovado pela conta: mede à mão
|
|
39
|
+
- [ ] `npm run unbox:medir` — leia o relatório de sistema visual: tamanhos de tipo, raios, hex fora de token e larguras de container. Não bloqueia, mas número que cresceu desde o scaffold é gordura que a marca não pediu
|
|
40
|
+
- [ ] `/llms.txt` — é ROTA (`app/llms.txt/route.ts`), montada do catálogo real: confira que lista os produtos com preço, marca os esgotados e traz links absolutos (precisa de `NEXT_PUBLIC_SITE_URL`). Nada em `public/llms.txt`, que esconderia a rota
|
|
41
|
+
|
|
42
|
+
## Catálogo
|
|
43
|
+
|
|
44
|
+
- [ ] Homepage carrega produtos em destaque
|
|
45
|
+
- [ ] Listagem de categoria abre e pagina corretamente
|
|
46
|
+
- [ ] Busca retorna resultados relevantes
|
|
47
|
+
- [ ] Produto esgotado exibe "Indisponível" e desabilita o botão
|
|
48
|
+
|
|
49
|
+
## PDP (Página de produto)
|
|
50
|
+
|
|
51
|
+
- [ ] Galeria de imagens carrega e troca corretamente
|
|
52
|
+
- [ ] Seleção de variante atualiza preço e disponibilidade
|
|
53
|
+
- [ ] Botão "Adicionar ao carrinho" funciona
|
|
54
|
+
- [ ] Preço com desconto Pix exibido quando aplicável
|
|
55
|
+
|
|
56
|
+
## Carrinho
|
|
57
|
+
|
|
58
|
+
- [ ] Mini-cart abre ao adicionar produto
|
|
59
|
+
- [ ] Quantidade atualiza e preço recalcula
|
|
60
|
+
- [ ] Remover item funciona sem recarregar a página
|
|
61
|
+
- [ ] Frete grátis acima do limiar exibido corretamente
|
|
62
|
+
|
|
63
|
+
## Checkout
|
|
64
|
+
|
|
65
|
+
- [ ] CEP calcula frete e exibe opções
|
|
66
|
+
- [ ] Endereço preenchido e salvo corretamente
|
|
67
|
+
- [ ] **PIX:** QR code gerado, pedido criado na Unbox
|
|
68
|
+
- [ ] **Cartão aprovado:** pedido confirmado, redireciona para /pedido
|
|
69
|
+
- [ ] **Cartão recusado:** mensagem de erro clara (não genérica)
|
|
70
|
+
- [ ] Duplo clique no botão de pagar não cria dois pedidos
|
|
71
|
+
|
|
72
|
+
## Login e área do cliente
|
|
73
|
+
|
|
74
|
+
- [ ] OTP request envia e-mail real
|
|
75
|
+
- [ ] Código inválido exibe erro claro
|
|
76
|
+
- [ ] Login OK redireciona para `/conta`
|
|
77
|
+
- [ ] `/conta` sem login redireciona para `/conta/entrar`
|
|
78
|
+
- [ ] Lista de pedidos carrega com status correto
|
|
79
|
+
- [ ] Logout limpa sessão e redireciona
|
|
80
|
+
|
|
81
|
+
## Pós-pedido
|
|
82
|
+
|
|
83
|
+
- [ ] Página `/pedido/[referenceId]` carrega com número e status
|
|
84
|
+
- [ ] Webhook de pedido recebido (checar logs Vercel → Functions)
|
|
85
|
+
- [ ] E-mail de confirmação da Unbox chegou ao comprador
|
|
86
|
+
|
|
87
|
+
## Honestidade (bloqueante)
|
|
88
|
+
|
|
89
|
+
- [ ] `npm run unbox:honestidade` sai LIMPO (nada fabricado SEM decisão do lojista; o que ele mandou manter está no allowlist)
|
|
90
|
+
- [ ] JSON-LD da PDP sem `aggregateRating` quando não há avaliações reais
|
|
91
|
+
- [ ] QA visual do agente 16 executado (build de produção + screenshots desktop/mobile avaliados contra `marca/DESIGN-<MARCA>.md`)
|
|
92
|
+
|
|
93
|
+
## SEO e infra
|
|
94
|
+
|
|
95
|
+
- [ ] `/sitemap.xml` retorna produtos e categorias
|
|
96
|
+
- [ ] `/robots.txt` bloqueia `/conta`, `/api`, `/checkout`
|
|
97
|
+
- [ ] OG tags preenchidas na PDP (checar com og:debugger)
|
|
98
|
+
- [ ] `noindex` ativo na página de confirmação de pedido
|
|
99
|
+
- [ ] `app/icon.svg` e `app/apple-icon.svg` trocados pelo ícone da marca (o `npm run build` avisa enquanto forem placeholder)
|
|
100
|
+
- [ ] `apple-icon` com fundo OPACO — iOS pinta transparência de preto na tela inicial
|
|
101
|
+
- [ ] Ícone maskable (se adicionar PNGs no manifest) com ~20% de margem de segurança ao redor do símbolo
|
|
102
|
+
- [ ] Nome e `theme_color` reais em `app/manifest.ts` (o CLI preenche; confira se sobrou "Minha Loja")
|
|
103
|
+
|
|
104
|
+
## Performance
|
|
105
|
+
|
|
106
|
+
- [ ] Lighthouse Mobile score ≥ 80 na homepage
|
|
107
|
+
- [ ] Imagens carregam com `next/image` (sem CLS visível)
|
|
108
|
+
- [ ] Primeira renderização da home < 3s em rede 4G simulada
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Unbox Storefront Template
|
|
2
|
+
|
|
3
|
+
Template de storefront headless para a plataforma **Unbox**, baseado em Next.js 15 (App Router),
|
|
4
|
+
Tailwind CSS v4 e shadcn/ui.
|
|
5
|
+
|
|
6
|
+
## Stack
|
|
7
|
+
|
|
8
|
+
- **Next.js 15** (App Router) + TypeScript
|
|
9
|
+
- **Tailwind CSS v4** + shadcn/ui sobre Base UI
|
|
10
|
+
- **Unbox SDK** em `lib/unbox/`
|
|
11
|
+
- Hospedagem recomendada: **Vercel**
|
|
12
|
+
|
|
13
|
+
## Setup rápido
|
|
14
|
+
|
|
15
|
+
### 1. Configurar credenciais
|
|
16
|
+
|
|
17
|
+
Projeto gerado pelo `create-unbox-store`: o CLI já criou o `.env.local` no scaffold — só
|
|
18
|
+
confira/complete as credenciais nele (veja `.env.example`).
|
|
19
|
+
|
|
20
|
+
(Só quem clonou a foundation crua, SEM o CLI, tem o `./bootstrap.sh` pra esse setup.)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
O script pergunta se você tem as credenciais Unbox. Se não tiver, sobe assim mesmo em **modo mockup** — o layout abre, mas páginas que dependem da API mostram erro. Preencha `.env.local` depois e rode `npm run unbox:test` antes do QA.
|
|
27
|
+
|
|
28
|
+
### 2. Configurar variáveis de ambiente
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cp .env.example .env.local
|
|
32
|
+
# Editar .env.local com as credenciais da loja Unbox
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Variáveis obrigatórias (modelo RECOMENDADO — api key de parceiro; ver `.env.example`):
|
|
36
|
+
```env
|
|
37
|
+
UNBOX_PARTNER_API_KEY= # api key única do PARCEIRO (recomendada; da2-...)
|
|
38
|
+
UNBOX_CAPTCHA_BYPASS= # obrigatória com a key de parceiro (pedir à Unbox)
|
|
39
|
+
UNBOX_USER= # usuário de API da loja
|
|
40
|
+
UNBOX_PASS= # senha (com # ou $? use aspas: "#senha")
|
|
41
|
+
SESSION_SECRET= # string aleatória forte
|
|
42
|
+
NEXT_PUBLIC_SITE_URL=https://minhaloja.com.br
|
|
43
|
+
# Modelo antigo (key por loja), ainda suportado: UNBOX_API_KEY=
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Configurar a marca
|
|
47
|
+
|
|
48
|
+
| Arquivo | O que personalizar |
|
|
49
|
+
|---------|-------------------|
|
|
50
|
+
| `app/globals.css` | Cores (`--store-primary`, `--store-chrome-bg`, `--store-cta`) |
|
|
51
|
+
| `app/layout.tsx` | Fonte e título padrão (favicon: `app/icon.svg`) |
|
|
52
|
+
| `public/brand/logo.svg` | Logo da loja |
|
|
53
|
+
| `lib/store-config.ts` | Limiares de frete grátis, brinde |
|
|
54
|
+
| `components/chrome/footers/*` | CNPJ, endereço, tagline (a variante ativa está em `chrome/registry.ts`) |
|
|
55
|
+
| `components/chrome/announce-bar.tsx` | Barra de anúncio, badge de cupom |
|
|
56
|
+
|
|
57
|
+
### 4. Rodar em desenvolvimento
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
nvm use 22 # Node 22 LTS — não use v26 (startup lento)
|
|
61
|
+
rm -f ~/package-lock.json # evita conflito com npm
|
|
62
|
+
npm run dev # primeira compilação demora 2-4 min
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Estrutura
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
app/
|
|
69
|
+
├── api/ # Route Handlers (BFF — nunca expõe API key)
|
|
70
|
+
├── acesso/ # Porta de preview (fora do grupo da loja: sem header/rodapé)
|
|
71
|
+
└── (loja)/ # Route group: todas as páginas da LOJA (header/rodapé no layout do grupo)
|
|
72
|
+
├── conta/ # Área do cliente (login OTP, pedidos, assinaturas)
|
|
73
|
+
├── checkout/ # Fluxo de checkout + confirmação Pix
|
|
74
|
+
└── produto/ # PDP com ISR
|
|
75
|
+
components/
|
|
76
|
+
├── cart/ # CartProvider + MiniCart + drawer
|
|
77
|
+
├── checkout/ # Formulários de checkout
|
|
78
|
+
├── product/pdp/ # Buy box, galeria, seções
|
|
79
|
+
└── account/ # Área logada
|
|
80
|
+
lib/
|
|
81
|
+
├── unbox/ # SDK Unbox (client, customer, webhooks)
|
|
82
|
+
├── queries.ts # Funções de fetch cached (catálogo, shop, tags)
|
|
83
|
+
├── config.ts # Variáveis de ambiente server-only
|
|
84
|
+
└── store-config.ts # Configuração comercial (limiares, descontos)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Enriquecimento de produtos (opcional)
|
|
88
|
+
|
|
89
|
+
O sistema em `lib/enrichment/` permite adicionar dados não fornecidos pela Unbox
|
|
90
|
+
(composição, medidas, FAQ, reviews, combos) via `products.json` gerado a partir
|
|
91
|
+
de uma planilha de metadados.
|
|
92
|
+
|
|
93
|
+
Para usar: popule `lib/enrichment/products.json` no formato descrito em `lib/enrichment/index.ts`.
|
|
94
|
+
|
|
95
|
+
## Scripts utilitários
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run unbox:test # testa a conexão com a API Unbox
|
|
99
|
+
npm run unbox:dump # raio-X da loja real (promoções, assinatura, catálogo) — fonte da verdade da store-config
|
|
100
|
+
npm run unbox:honestidade # lista prova social/afirmação fabricada sem decisão do lojista (gate do QA)
|
|
101
|
+
npm run unbox:webhook:subscribe # registra os webhooks da loja
|
|
102
|
+
npm run unbox:order:pix # cria um pedido Pix de teste
|
|
103
|
+
npm run unbox:abandoned # dispara evento de carrinho abandonado pro CRM (demo do cron)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Deploy
|
|
107
|
+
|
|
108
|
+
Ver [DEPLOY.md](./DEPLOY.md) para checklist completo, configuração do Vercel e erros comuns.
|
|
109
|
+
|
|
110
|
+
Resumo rápido:
|
|
111
|
+
1. `nvm use 22` (Node 22 LTS)
|
|
112
|
+
2. Env vars em **Production + Preview + Development** antes do primeiro deploy
|
|
113
|
+
3. Framework Preset no Vercel: **Next.js** (não "Other")
|
|
114
|
+
|
|
115
|
+
## API de Parceiros (nova API pública da Unbox)
|
|
116
|
+
|
|
117
|
+
O projeto suporta os dois modelos de credencial:
|
|
118
|
+
|
|
119
|
+
- **Novo (recomendado):** `UNBOX_PARTNER_API_KEY` — api key **única do parceiro**, vale para
|
|
120
|
+
todas as lojas dele. A loja específica é autenticada pelo `UNBOX_USER`/`UNBOX_PASS` no
|
|
121
|
+
signIn (o shopId sai do JWT — pode deixar `UNBOX_SHOP_ID` vazio). Preenchida, o SDK roteia
|
|
122
|
+
automaticamente para `partners.unbox.com.br`: signIn, **vitrine completa** (catálogo,
|
|
123
|
+
busca, PDP por slug/id, dados da loja), categorias (tags), cupons, pedido por referenceId,
|
|
124
|
+
parcelas, inventário (`getSimpleInventory`), webhooks e cart templates.
|
|
125
|
+
- **Antigo:** `UNBOX_API_KEY` (key por loja) — segue funcionando; sem a key de parceiro nada
|
|
126
|
+
muda. Carrinho/checkout/área do cliente seguem no core em qualquer modo (com o MESMO token
|
|
127
|
+
do signIn de parceiros), até a Unbox publicar essas escritas na API de parceiros.
|
|
128
|
+
|
|
129
|
+
`npm run unbox:test` mostra qual rota está ativa na primeira linha.
|
|
130
|
+
|
|
131
|
+
## MCP da Unbox (Claude Code)
|
|
132
|
+
|
|
133
|
+
A Unbox tem um servidor MCP que dá ao Claude Code acesso ao conhecimento e à execução de
|
|
134
|
+
chamadas da API de parceiros (leituras diretas; escritas com confirmação em duas etapas).
|
|
135
|
+
|
|
136
|
+
Se você informou o token do MCP no setup do CLI, o `.mcp.json` já saiu pronto — pule pro
|
|
137
|
+
passo 3. Senão:
|
|
138
|
+
|
|
139
|
+
1. Copie `.mcp.json.example` para `.mcp.json` (já está no `.gitignore` — ele carrega
|
|
140
|
+
credenciais, **nunca** o commite; o example tem só placeholders).
|
|
141
|
+
2. Preencha o `x-unbox-mcp-token` (peça à Unbox), sua `UNBOX_PARTNER_API_KEY` e o
|
|
142
|
+
login/senha da loja.
|
|
143
|
+
3. Abra o Claude Code na pasta — as tools `unbox_*` ficam disponíveis (comece por
|
|
144
|
+
`unbox_get_started`).
|
|
145
|
+
|
|
146
|
+
## Regras de segurança
|
|
147
|
+
|
|
148
|
+
- `UNBOX_API_KEY` / `UNBOX_PARTNER_API_KEY` nunca vão ao browser — apenas Route
|
|
149
|
+
Handlers/Server Actions/RSC
|
|
150
|
+
- Token de cliente (OTP) fica em cookie `httpOnly`
|
|
151
|
+
- `placeOrder` protegido contra duplo envio (`lib/checkout-lock.ts`)
|
|
152
|
+
- Rate-limit nas rotas de OTP e checkout (`lib/ratelimit.ts`)
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# CONSTRUÇÃO: o que fazer depois que a entrevista fecha
|
|
2
|
+
|
|
3
|
+
Este arquivo é a continuação do prompt do agente 15 (`.claude/agents/branding-briefing.md`).
|
|
4
|
+
Ele saiu do prompt permanente porque só vale a partir do fim do briefing: mantê-lo carregado
|
|
5
|
+
durante toda a entrevista custa contexto em algo que ainda não se aplica.
|
|
6
|
+
|
|
7
|
+
**Leia este arquivo inteiro assim que a entrevista fechar, antes de tocar no primeiro
|
|
8
|
+
componente.** O prompt principal deixa marcos (M2, M3, revisão, QA) apontando pra cá; os
|
|
9
|
+
marcos você já conhece, os detalhes de como executá-los estão aqui.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## O contrato de design: `marca/DESIGN-<MARCA>.md` ANTES do primeiro componente (M2)
|
|
14
|
+
A direção de arte NÃO pode viver só na conversa (evapora entre sessões). Terminado o
|
|
15
|
+
briefing e ANTES de tocar em qualquer componente, gere `marca/DESIGN-<MARCA>.md` (se o
|
|
16
|
+
briefing veio com anexo DESIGN-DRAFT, parta dele, é default a desafiar, não lei).
|
|
17
|
+
Estrutura mínima:
|
|
18
|
+
|
|
19
|
+
- Marca e conceito central (1 parágrafo, com a narrativa do site);
|
|
20
|
+
- Paleta como TOKENS mapeados nos `--store-*` (+ acentos próprios da marca);
|
|
21
|
+
- Tipografia com o porquê de cada família e regras de uso;
|
|
22
|
+
- Tom de voz com proibições explícitas (ex.: sem travessão, sem "revolucionário", CTAs no
|
|
23
|
+
padrão da marca);
|
|
24
|
+
- Inventário de assets com paths e LIMITAÇÕES (ex.: "fotos têm 432px: nunca full-bleed");
|
|
25
|
+
- Dados reais dos produtos (números que o site PODE afirmar, e nenhum outro);
|
|
26
|
+
- Contrato técnico do catálogo (slugs, ids, preços) quando rodar em mockup;
|
|
27
|
+
- Regras de honestidade e o que NÃO fazer.
|
|
28
|
+
|
|
29
|
+
Todo passo seguinte (inclusive sessões futuras e o QA do agente 16) LÊ este documento antes
|
|
30
|
+
de codar. Feedback do cliente vira `marca/FEEDBACK-NN.md` no mesmo formato: cada rodada de
|
|
31
|
+
revisão é executada com a mesma disciplina do build inicial.
|
|
32
|
+
|
|
33
|
+
## Antes de codar: declare a leitura (uma linha)
|
|
34
|
+
|
|
35
|
+
Antes do primeiro componente, escreva UMA linha dizendo como você está lendo o projeto:
|
|
36
|
+
|
|
37
|
+
> "Estou lendo isto como: [tipo de loja] para [público], com linguagem [x], puxando pra
|
|
38
|
+
> [referência/sistema]."
|
|
39
|
+
|
|
40
|
+
Serve pra tornar a inferência explícita e checável pelo cliente. Se você não consegue
|
|
41
|
+
escrever essa linha, ainda falta briefing, volte e pergunte, não construa no escuro.
|
|
42
|
+
|
|
43
|
+
## Copy sem travessão
|
|
44
|
+
|
|
45
|
+
Use vírgula, dois-pontos, ponto ou parênteses; `·` para separador. Vale na tela, na conversa e no
|
|
46
|
+
comentário. O build reprova travessão na copy de `app/` e `components/`.
|
|
47
|
+
|
|
48
|
+
## Como falar da plataforma
|
|
49
|
+
|
|
50
|
+
Restrição da plataforma se descreve, não se julga: diga a regra, o efeito na loja e a decisão.
|
|
51
|
+
Nada de "limitação da plataforma", "infelizmente", "a Unbox não deixa", "não dá pra resolver",
|
|
52
|
+
nem na conversa, no comentário do código ou na tela. E o comprador nunca lê explicação de plataforma:
|
|
53
|
+
ele lê a regra da loja ("os itens assinados deste pedido chegam na mesma frequência"). O build
|
|
54
|
+
reprova o julgamento. Detalhe e exemplos: `CLAUDE.md` → "Como falar da plataforma".
|
|
55
|
+
|
|
56
|
+
## Depois da entrevista, aplique nesta prioridade
|
|
57
|
+
|
|
58
|
+
**Skills com invocação OBRIGATÓRIA (M3), não opcional:** antes de desenhar qualquer seção
|
|
59
|
+
nova ou mexer em layout/tipografia, **invoque a skill `frontend-design`** (está em
|
|
60
|
+
`.claude/skills/`); no QA final, **invoque `web-design-guidelines`**. Disponível não é
|
|
61
|
+
invocado, a média só sobe com o passo explícito. Trate como passo numerado, não como
|
|
62
|
+
sugestão.
|
|
63
|
+
|
|
64
|
+
1. Logo e cores reais (bloco de tokens em `globals.css` + assets em `public/brand`). Cor sempre
|
|
65
|
+
via `var(--store-primary,#fallback)` / `var(--store-cta,...)`; nunca hex solto (quebra a
|
|
66
|
+
customização).
|
|
67
|
+
**Isto é o PRIMEIRO ato, não um item da lista.** A loja nasce em cinza + tinta porque essa é
|
|
68
|
+
a tela mais neutra pra qualquer marca, é ausência de escolha, não escolha estética. Nenhuma
|
|
69
|
+
seção deve ser construída antes das cores reais entrarem; o `npm run build` avisa enquanto a
|
|
70
|
+
paleta default estiver no ar. Confira também os `dials` do `marca/briefing.json`
|
|
71
|
+
(variância · motion · densidade), eles são a temperatura da loja, ver `agents/PADROES.md`.
|
|
72
|
+
2. Estilo e layout: confirme/ajuste a receita da home (`components/home/home-recipe.ts`),
|
|
73
|
+
a tipografia (bloco `UNBOX-FONTS`) e os neutros, conforme o briefing e `agents/PADROES.md`.
|
|
74
|
+
Troque os heros placeholder (.svg) por imagens reais da marca assim que existirem.
|
|
75
|
+
3. Menu conforme o que manter do site atual (use `tags`, nunca navigation tree).
|
|
76
|
+
4. Conteúdo real em TODAS as telas, no mesmo estilo autoral: home, catálogo, PDP, carrinho,
|
|
77
|
+
checkout, área de conta, rodapé (dados reais) e FAQ verbatim. Não pare na home/PDP.
|
|
78
|
+
5. Fotos reais onde houver; placeholder neutro onde não.
|
|
79
|
+
6. Prova social: a foundation não traz nenhuma (reviews, nota, "vendidos", estrelas somem
|
|
80
|
+
sem dado). Popule `lib/enrichment/products.json` e as props das seções SÓ com dado que o
|
|
81
|
+
lojista forneceu. Se ele explicitamente quiser manter algum placeholder, registre a
|
|
82
|
+
decisão dele em `marca/honestidade-permitido.txt`. Você nunca inventa; ele pode escolher.
|
|
83
|
+
7. Promessas comerciais (`lib/store-config.ts`): rode `npm run unbox:dump` e preencha SÓ com o
|
|
84
|
+
que o backend confirmou (Pix, frete grátis, brindes, tiers de oferta). Os defaults saem
|
|
85
|
+
zerados/vazios de propósito: com eles a loja não exibe selo nenhum, e é assim que deve
|
|
86
|
+
ficar até a promoção existir no painel Unbox. Prometer desconto que o checkout não aplica
|
|
87
|
+
é o pior bug possível: o cliente vê um total e paga outro.
|
|
88
|
+
8. Registre tudo em `marca/BRIEFING.md` (crie se não existir) pra virar registro e permitir
|
|
89
|
+
retomar depois.
|
|
90
|
+
9. Com o briefing encerrado e aprovado pelo cliente, devolva as próximas sessões ao Claude
|
|
91
|
+
normal: remova a chave `"agent"` de `.claude/settings.json` (se o arquivo ficar vazio, pode
|
|
92
|
+
removê-lo). É ela que faz toda sessão desta pasta abrir direto no briefing; cumprido o
|
|
93
|
+
briefing, ela já fez o papel dela.
|
|
94
|
+
|
|
95
|
+
## Revisão final com vários olhares (antes de entregar)
|
|
96
|
+
Depois de construir, revise o resultado vestindo vários chapéus de especialista, um de cada vez.
|
|
97
|
+
Cada olhar pega o que os outros deixam passar:
|
|
98
|
+
- **Designer / diretor de arte:** hierarquia, espaçamento, ritmo, consistência de cor e tipografia.
|
|
99
|
+
A loja respira? O minimalismo (ou o estilo definido) foi respeitado? As seções conversam ou é
|
|
100
|
+
tudo "caixinha" empilhada?
|
|
101
|
+
- **Dev front-end:** responsivo no mobile, estados de hover/foco, nada quebrado, imagens
|
|
102
|
+
otimizadas, acessibilidade básica (contraste, alt, navegação por teclado), zero erro no console.
|
|
103
|
+
- **Especialista de marketing / CRO:** a proposta de valor fica clara nos primeiros 5 segundos?
|
|
104
|
+
O CTA principal aparece? As alavancas do objetivo (ex.: ticket médio) estão lá sem poluir?
|
|
105
|
+
- **Storyteller / copy:** a marca tem alma na home? O texto soa como a marca (tom do briefing)?
|
|
106
|
+
Nada de clichê, nada de travessão, nada de dado inventado.
|
|
107
|
+
- **Cliente final (a persona do briefing):** sendo essa pessoa, eu entenderia, confiaria e compraria?
|
|
108
|
+
|
|
109
|
+
Liste o que cada olhar apontou e corrija antes de considerar pronto. O que for decisão do cliente,
|
|
110
|
+
leve pra ele; o que for execução, resolva você.
|
|
111
|
+
|
|
112
|
+
## Antes de dizer "tá pronto" (checklist de QA, nos bastidores)
|
|
113
|
+
Rode este checklist por baixo. Só anuncie "tá no ar" quando TODOS os itens passarem; se um falha,
|
|
114
|
+
conserte antes de mostrar. O cliente não vê o teste, só ouve "tá no ar" quando estiver funcionando.
|
|
115
|
+
|
|
116
|
+
**O "pronto" de verdade é o agente 16.** Depois deste checklist, execute o protocolo de QA
|
|
117
|
+
visual (`agents/definitions/16-qa-visual.md`): build de produção + screenshots de todas as
|
|
118
|
+
telas em desktop e mobile, avaliadas contra o `marca/DESIGN-<MARCA>.md`, e o gate
|
|
119
|
+
`npm run unbox:honestidade` LIMPO. Achou que terminou não é critério; frame avaliado é.
|
|
120
|
+
|
|
121
|
+
- **Funciona:** compila e sobe sem erro; zero erro no console; funciona no celular (responsivo);
|
|
122
|
+
links e botões não quebram; o motor (catálogo, carrinho, checkout) continua intacto.
|
|
123
|
+
- **Imagens (a trava):** nenhum componente sem imagem, hero e PDP incluídos; onde não há foto real,
|
|
124
|
+
fallback intencional (nunca caixa vazia, cinza ou quebrada); imagens otimizadas pra web.
|
|
125
|
+
- **Conteúdo real:** sem "lorem ipsum"/placeholder; sem avaliação, nota ou venda inventada; FAQ
|
|
126
|
+
verbatim ou ausente (nunca inventada); rodapé com dados reais ou marcados como pendentes.
|
|
127
|
+
- **Marca:** cores via token e consistentes; tipografia coerente; as páginas combinadas existem
|
|
128
|
+
(não só a home); o visual respeita o estilo definido (ex.: minimalista = sem poluição).
|
|
129
|
+
- **Fechamento:** `marca/BRIEFING.md` atualizado; o cliente viu e aprovou (houve loop de feedback),
|
|
130
|
+
não foi entrega no escuro.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Delegação: o que roda em paralelo depois do contrato (M2)
|
|
135
|
+
|
|
136
|
+
Fechado o `marca/DESIGN-<MARCA>.md`, **delegue sem perguntar.** Até o contrato, você trabalha
|
|
137
|
+
sozinho: a entrevista é conversa humana e não paraleliza, e antes do contrato não existe
|
|
138
|
+
critério comum pra distribuir. Depois dele existe, e aí paralelizar é ganho de tempo real
|
|
139
|
+
para o cliente.
|
|
140
|
+
|
|
141
|
+
Os subagentes estão declarados em `.claude/agents/`. Invoque pelo nome.
|
|
142
|
+
|
|
143
|
+
### A regra que faz isso funcionar: geração distribuída, escrita centralizada
|
|
144
|
+
|
|
145
|
+
Dois arquivos concentram decisão de várias frentes e **têm um dono só: você.**
|
|
146
|
+
|
|
147
|
+
- `components/home/home-recipe.ts`, um array com todas as seções e suas props;
|
|
148
|
+
- `app/globals.css`, cor, ritmo, largura, cards e motion.
|
|
149
|
+
|
|
150
|
+
Não existe controle de escrita por caminho: nada impede tecnicamente dois agentes de gravarem
|
|
151
|
+
no mesmo arquivo e um perder o trabalho do outro. Por isso o `conteudo-secao` e o
|
|
152
|
+
`avaliador-visual` **não recebem Write**, eles devolvem texto, você grava. Não é desconfiança,
|
|
153
|
+
é a única forma de o paralelo não corromper o resultado.
|
|
154
|
+
|
|
155
|
+
### O que vale distribuir
|
|
156
|
+
|
|
157
|
+
| Unidade | Agente | Quantas cópias | Quem escreve |
|
|
158
|
+
|---|---|---|---|
|
|
159
|
+
| Páginas legais | `paginas-legais` | 3, uma por página | o próprio (arquivos distintos) |
|
|
160
|
+
| Assets da marca | `assets-marca` | 1 | o próprio (dono de `public/brand/`) |
|
|
161
|
+
| Conteúdo de seção | `conteudo-secao` | 1 por seção da receita | **você**, em série |
|
|
162
|
+
| Avaliação no QA | `avaliador-visual` | 1 por olhar | ninguém (só devolve achados) |
|
|
163
|
+
|
|
164
|
+
Os cinco olhares do `avaliador-visual`, composição, contraste, responsivo, copy, honestidade,
|
|
165
|
+
são o ganho mais barato do conjunto: são leituras independentes do mesmo material, hoje feitas
|
|
166
|
+
em série dentro de uma conversa só, e nenhuma delas escreve nada.
|
|
167
|
+
|
|
168
|
+
### O que NÃO distribuir
|
|
169
|
+
|
|
170
|
+
Contrato de design, receita da home, paleta e chrome. São decisões de conjunto: dividir cada uma
|
|
171
|
+
entre agentes que não veem o todo produz um site coerente em cada pedaço e incoerente inteiro,
|
|
172
|
+
que é exatamente o defeito que o briefing existe pra evitar.
|
|
173
|
+
|
|
174
|
+
### Ao receber os retornos
|
|
175
|
+
|
|
176
|
+
1. **Leia antes de colar.** Subagente devolve o que acha que você pediu, não necessariamente o
|
|
177
|
+
que você pediu.
|
|
178
|
+
2. **Aplique um por vez** nos arquivos-gargalo, e rode `npm run typecheck` depois de fechar a
|
|
179
|
+
receita, nome de seção inválido o `tsc` reprova na hora.
|
|
180
|
+
3. **Junte os `[FALTA: ...]` e os bloqueios de todos os retornos numa lista só** e leve ao
|
|
181
|
+
cliente de uma vez. Cinco perguntas em cinco mensagens separadas cansam; cinco numa mensagem
|
|
182
|
+
ele responde.
|
|
183
|
+
4. **O `CLAUDE.md` da raiz não chega aos subagentes**, cada definição carrega a fatia de mapa
|
|
184
|
+
que precisa. Se um deles voltar dizendo que não achou algo, o conserto é na definição dele,
|
|
185
|
+
não uma explicação avulsa na invocação, que se perde na próxima vez.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Depois do "pronto": ofereça os opcionais, não os pule em silêncio
|
|
190
|
+
|
|
191
|
+
Com a loja aprovada pelo QA, **antes de encerrar**, apresente ao cliente os três agentes
|
|
192
|
+
opcionais em uma mensagem só, dizendo o que cada um entrega e deixando ele escolher. É aqui
|
|
193
|
+
que essa decisão faz sentido: ele está vendo a loja pronta, e você conhece a marca. (O wizard
|
|
194
|
+
do CLI perguntava sobre CRO na instalação, antes de existir loja, e a resposta ia para um
|
|
195
|
+
arquivo que ninguém lia. Não pergunta mais. A responsabilidade de oferecer é sua.)
|
|
196
|
+
|
|
197
|
+
| Agente | O que constrói | Quando vale |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| **13, CRO** | dos 10 módulos do pacote, a foundation só traz a barra de frete grátis. Os outros nove: prova social na PDP, urgência de estoque, countdown, upsell pós-checkout, recently viewed, sticky CTA mobile, trust strip customizável, kits com cross-sell, brindes | loja que já vende e quer subir conversão; cada módulo é independente |
|
|
200
|
+
| **14, SEO avançado** | schemas JSON-LD avançados, OG images dinâmicas, breadcrumbs, templates de título e description, canonical e paginação, Core Web Vitals, Search Console | toda loja que vai depender de busca orgânica |
|
|
201
|
+
| **17, AEO** | llms.txt, FAQ answer-friendly, schema com frete e troca, entidade da marca, para ser citada por ChatGPT, Claude, Perplexity e AI Overviews | marca que quer presença em resposta de IA, não só em lista de links |
|
|
202
|
+
|
|
203
|
+
Regra de honestidade vale aqui também: os módulos de prova social e urgência do agente 13 só
|
|
204
|
+
entram com **dado real** (avaliações, estoque). Sem dado, o módulo fica de fora e o cliente
|
|
205
|
+
sabe por quê.
|
|
206
|
+
|
|
207
|
+
Depois dos opcionais, o agente 12 (Deploy) publica. Ordem completa em `agents/MANAGER.md`.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Agent Manager: Unbox Storefront Builder
|
|
2
|
+
|
|
3
|
+
Sistema de agentes que originalmente construiu, seção por seção, o storefront headless que virou
|
|
4
|
+
a foundation do `create-unbox-store`. Stack: **Next.js 15 (App Router) · TypeScript · Tailwind v4 ·
|
|
5
|
+
shadcn/ui + Base UI · Vercel**.
|
|
6
|
+
|
|
7
|
+
> 🎉 **Se você chegou aqui via `npx create-unbox-store`, os agentes 00-11 já rodaram por você.**
|
|
8
|
+
> Layout, catálogo, PDP, carrinho, checkout, login, área de conta e SEO básico já estão
|
|
9
|
+
> implementados e funcionando (inclusive em "modo mockup", sem credenciais). Você **não precisa
|
|
10
|
+
> rodar 00-11 de novo**.
|
|
11
|
+
>
|
|
12
|
+
> ⚠️ **Mas isso é fundação técnica, não a loja final.** O conteúdo e o layout ainda estão em
|
|
13
|
+
> padrão. O **PRIMEIRO passo é personalizar**, com o agente **15 (Branding & Identidade)**, e a
|
|
14
|
+
> regra é **perguntar antes de mostrar**: rode o briefing e só então apresente a vitrine, já com a
|
|
15
|
+
> cara da marca. Não trate a base padrão como entregável nem mande o cliente "abrir a loja" antes
|
|
16
|
+
> do 15.
|
|
17
|
+
>
|
|
18
|
+
> Ordem recomendada dos passos manuais: **15 (Branding)** primeiro, **16 (QA Visual,
|
|
19
|
+
> obrigatório)** na sequência, depois os opcionais **13 (CRO)**, **14 (SEO avançado)** e
|
|
20
|
+
> **17 (AEO)**, e por último **12 (Deploy)**. É por isso que essa pasta `agents/` vem dentro
|
|
21
|
+
> do seu projeto: pra você rodar esses quando quiser.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Agente 15: Branding & Identidade (rode PRIMEIRO, pós-setup)
|
|
26
|
+
|
|
27
|
+
Personaliza o storefront com a identidade real da marca do cliente. Conduz uma **entrevista**
|
|
28
|
+
(não um menu de módulos como 13/14): expectativa, referências, logo, cores, fotos, textos, links
|
|
29
|
+
e o que manter do site atual. Depois aplica logo e cores reais, menu, conteúdo real, FAQ verbatim
|
|
30
|
+
e dados de rodapé, e **neutraliza a prova social fabricada** da foundation base (ver aviso abaixo).
|
|
31
|
+
|
|
32
|
+
- Definição: `.claude/agents/branding-briefing.md`. **Se você abriu o Claude Code na raiz
|
|
33
|
+
deste projeto, esse prompt já está carregado como system prompt da sua sessão**, não
|
|
34
|
+
reabra o arquivo pra "conferir o que fazer": você já o tem inteiro, e relê-lo custa ~8k
|
|
35
|
+
tokens. (`agents/definitions/15-branding.md` é só um ponteiro pra cá.)
|
|
36
|
+
- **Layout por receita (v0.9.0+):** o scaffold já aplica um ESTILO (essencial, promocional,
|
|
37
|
+
editorial ou boutique, campo `estilo` do `marca/briefing.json`) que define a receita da home
|
|
38
|
+
(`components/home/home-recipe.ts`), fontes, neutros e chrome. O agente 15 valida/refina esse
|
|
39
|
+
estilo no briefing usando o repertório de `agents/PADROES.md` e os skills de design em
|
|
40
|
+
`.claude/skills/` (`frontend-design`, `web-design-guidelines`).
|
|
41
|
+
- É o **ponto de partida do cliente**: o briefing acontece ANTES de a vitrine ser apresentada. A
|
|
42
|
+
base padrão que o CLI gera é só fundação; a primeira loja que o cliente vê já sai personalizada.
|
|
43
|
+
- Roda **antes** de 13/14/12: não faz sentido otimizar (CRO/SEO) nem publicar (Deploy) em cima de
|
|
44
|
+
conteúdo padrão. Personalize primeiro.
|
|
45
|
+
- **Ordem recomendada dos passos manuais:** 15 (Branding) → **16 (QA Visual, obrigatório)** →
|
|
46
|
+
13 (CRO, opcional) → 14 (SEO, opcional) → 17 (AEO, opcional) → 12 (Deploy, por último).
|
|
47
|
+
|
|
48
|
+
## Agente 16: QA Visual (o gate de "pronto" do 15)
|
|
49
|
+
|
|
50
|
+
O critério de pronto não é "o agente achou que terminou": é **todo frame visto e avaliado**.
|
|
51
|
+
Build de produção (`npm run build` + `next start`, nunca o dev server), screenshots de home,
|
|
52
|
+
PDP, catálogo, carrinho e checkout em desktop (1440) e mobile (390), avaliados contra o
|
|
53
|
+
contrato `marca/DESIGN-<MARCA>.md`, e o gate `npm run unbox:honestidade` LIMPO, o bloqueio
|
|
54
|
+
é contra fabricação SILENCIOSA: o agente nunca inventa dado, mas o que o LOJISTA decidir
|
|
55
|
+
manter é decisão dele, registrada no allowlist. Roda após o briefing E após cada rodada de
|
|
56
|
+
feedback.
|
|
57
|
+
|
|
58
|
+
- Definição: `agents/definitions/16-qa-visual.md`
|
|
59
|
+
|
|
60
|
+
## Agente 17: AEO (Answer Engine Optimization, opcional)
|
|
61
|
+
|
|
62
|
+
Prepara a loja pra ser **citada e recomendada por motores de resposta** (ChatGPT, Claude,
|
|
63
|
+
Perplexity, AI Overviews), o complemento do SEO: em vez de ranquear em lista de links, SER
|
|
64
|
+
a resposta. Menu de 6 módulos: `llms.txt`, FAQ answer-friendly + FAQPage schema, Product
|
|
65
|
+
schema enriquecido (frete/troca/GTIN), FAQ por produto, conferência dos bots de IA no
|
|
66
|
+
`robots.ts` (a foundation já libera) e entidade da marca (Organization + página Sobre).
|
|
67
|
+
Rode DEPOIS do 15 e do 16, AEO em cima de placeholder é otimizar mentira.
|
|
68
|
+
|
|
69
|
+
- Definição: `agents/definitions/17-aeo.md`
|
|
70
|
+
|
|
71
|
+
> **Nota para a equipe do CLI:** pra "perguntar antes de mostrar" funcionar de verdade, a mensagem
|
|
72
|
+
> final do CLI deve mandar o cliente **abrir o Claude Code e iniciar o briefing (agente 15)**, e
|
|
73
|
+
> não "rode `npm run dev` e veja sua loja". Se o CLI convidar a olhar a loja primeiro, o cliente vê
|
|
74
|
+
> a versão padrão antes da personalização, que é justamente o que queremos evitar.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Como executar um agente (16, 13, 14, 17 ou 12; o 15 abre sozinho no Claude Code)
|
|
79
|
+
|
|
80
|
+
Abra o arquivo de definição correspondente em `agents/definitions/` e passe o conteúdo como
|
|
81
|
+
system prompt para uma sessão de Claude Code com acesso a Write/Edit/Bash na raiz do seu projeto.
|
|
82
|
+
Os agentes 13 e 14 listam um menu de módulos e perguntam quais ativar (não precisa rodar todos de
|
|
83
|
+
uma vez). O agente 15 conduz uma entrevista de briefing, um bloco por vez.
|
|
84
|
+
|
|
85
|
+
Antes de abrir qualquer componente, passe pelo `CLAUDE.md` da raiz: ele diz em qual arquivo
|
|
86
|
+
mora cada tipo de mudança, e os dois registries (`components/home/sections/registry.ts` e
|
|
87
|
+
`components/chrome/registry.ts`) indexam por descrição tudo que existe de seção e de
|
|
88
|
+
header/rodapé. Ler os dois custa ~1,6k tokens e evita abrir ~27k em componentes.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Agentes 00-11: já entregues pelo `create-unbox-store`
|
|
93
|
+
|
|
94
|
+
Referência do que cada um cobriu, caso precise entender/estender alguma parte específica depois.
|
|
95
|
+
|
|
96
|
+
| # | Agente | Arquivos principais no seu projeto |
|
|
97
|
+
|---|--------|----------------------|
|
|
98
|
+
| 00 | **Scaffold** | `package.json`, `next.config.ts`, `app/globals.css`, `lib/unbox/*`, `lib/config.ts` |
|
|
99
|
+
| 01 | **Layout** | `app/layout.tsx`, `components/site-header.tsx`, `site-footer.tsx`, `mobile-nav.tsx` |
|
|
100
|
+
| 02 | **Homepage** | `app/(loja)/page.tsx`, `components/home/*.tsx` |
|
|
101
|
+
| 03 | **Catalog** | `app/(loja)/produtos/page.tsx`, `app/(loja)/categoria/[tagSlug]/page.tsx`, `app/(loja)/busca/page.tsx`, `components/catalog/*.tsx` |
|
|
102
|
+
| 04 | **PDP** | `app/(loja)/produto/[productSlug]/page.tsx`, `components/product/pdp/*.tsx` |
|
|
103
|
+
| 05 | **Cart** | `app/(loja)/carrinho/page.tsx`, `components/cart/*.tsx`, `app/api/cart/**` (inclui link de recuperação `?id=&token=`) |
|
|
104
|
+
| 06 | **Checkout** | `app/(loja)/checkout/page.tsx`, `components/checkout/checkout-client.tsx`, `app/api/checkout/**` |
|
|
105
|
+
| 07 | **Auth** | `app/(loja)/conta/entrar/page.tsx`, `lib/session.ts`, `app/api/account/{otp,signin,signout}/route.ts` |
|
|
106
|
+
| 08 | **Customer** | `app/(loja)/conta/**`, `components/account/*.tsx`, `lib/customer-session.ts` |
|
|
107
|
+
| 09 | **Promotions** | `lib/enrichment/combos.ts` (kits), `components/home/combos-*.tsx`, **infra pronta, mas `COMBOS = []` por padrão**, precisa popular |
|
|
108
|
+
| 10 | **Feedback/UX** | `sonner` (toasts), `lib/unbox/errors.ts` (`friendlyError`, `cartEventLabel`), `app/error.tsx`, `app/not-found.tsx` |
|
|
109
|
+
| 11 | **SEO + Infra** | `app/sitemap.ts`, `app/robots.ts`, JSON-LD Product básico na PDP |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Passos manuais (pós-setup): status real na foundation atual
|
|
114
|
+
|
|
115
|
+
| # | Passo | Módulos / escopo | Status hoje |
|
|
116
|
+
|---|-------|------------------|-------------|
|
|
117
|
+
| 15 | **Branding & Identidade** | entrevista de marca + aplicação (logo, cores, menu, conteúdo, FAQ verbatim, rodapé, prova social só com dado real) | **Novo.** Rodar `15-branding.md` como primeiro passo pós-setup. |
|
|
118
|
+
| 16 | **QA Visual** | build de produção + screenshots desktop/mobile avaliados contra `marca/DESIGN-<MARCA>.md` + gate `unbox:honestidade` | **Obrigatório** depois do 15 e de cada rodada de feedback. Rodar `16-qa-visual.md`. |
|
|
119
|
+
| 13 | **Unbox AI CRO Package** | 10 módulos: prova social, urgência de estoque, countdown flash sale, frete grátis¹, upsell pós-checkout, recently viewed, sticky CTA mobile, trust strip, kits & combos, brindes¹ | **Só frete grátis está implementado.** Os outros 9 exigem rodar o agente `13-cro.md`. |
|
|
120
|
+
| 14 | **Unbox AI SEO Agent** | 7 módulos: schemas JSON-LD avançados, OG images dinâmicas, breadcrumbs, templates de título/description, canonical + paginação, Core Web Vitals, Search Console setup | **Nenhum módulo completo** (só o JSON-LD básico do agente 11). Rodar `14-seo.md`. |
|
|
121
|
+
| 17 | **AEO** | 6 módulos: llms.txt, FAQ answer-friendly, Product schema enriquecido, FAQ por produto, bots de IA (conferência), entidade da marca | Opcional, depois do 14. Rodar `17-aeo.md`. |
|
|
122
|
+
| 12 | **Deploy** | build de produção, variáveis de ambiente, publicação (Vercel) | Rodar `12-deploy.md` por último. |
|
|
123
|
+
|
|
124
|
+
> ¹ Módulos **frete grátis** e **brindes** exigem configuração no painel Unbox antes do lançamento.
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Regras de ouro (todos os agentes herdam)
|
|
128
|
+
|
|
129
|
+
1. **`UNBOX_API_KEY` é server-only**, nunca `NEXT_PUBLIC_`, nunca client component
|
|
130
|
+
2. **Dois tokens distintos**: token de loja (catálogo/checkout) ≠ token do cliente (área `/conta`)
|
|
131
|
+
3. **`placeOrder` não é idempotente**, lock por `cartId` no BFF; nunca retentar cegamente
|
|
132
|
+
4. **`customerOTPRequest` manda e-mail real**, jamais em testes/loops/CI
|
|
133
|
+
5. **Preço e estoque são do servidor**, nunca computar preço no cliente
|
|
134
|
+
6. **Menu: use `tags`** (navigation tree falha com token de loja)
|
|
135
|
+
7. **`displayStatus(language)` está quebrado**, use `status` + `orderStatusLabel()` do SDK
|
|
136
|
+
8. **shadcn/ui usa Base UI** (`@base-ui/react`), prop `render`, não `asChild`
|
|
137
|
+
9. **Tailwind v4**, use utilitários/tokens do tema; evite CSS ad-hoc. Cor de marca é sempre
|
|
138
|
+
`bg-[var(--store-primary,#fallback)]`, nunca hex literal, senão a customização do CLI não
|
|
139
|
+
se propaga (achamos e corrigimos 304 ocorrências disso na foundation base)
|
|
140
|
+
10. **Erros GraphQL chegam em HTTP 200**, sempre cheque `errors[]` antes de consumir `data`
|
|
141
|
+
11. **`getTags()`/`getTopTags()` nunca filtra por `isTopLevel`**, forçar `true` esconde
|
|
142
|
+
categorias reais marcadas `false` no admin, mesmo aparecendo normalmente na vitrine padrão da
|
|
143
|
+
Unbox. Deixe o parâmetro opcional e omitido.
|
|
144
|
+
12. **GTM central da Unbox (`GTM-PZLT336`) e o selo "Powered by Unbox" no rodapé são
|
|
145
|
+
obrigatórios e intocáveis**, contrato da plataforma. O `prebuild`
|
|
146
|
+
(`scripts/check-unbox-brand.mjs`) BLOQUEIA build/deploy sem os dois. Tags da marca vão
|
|
147
|
+
nos campos próprios (GA4/Pixel/GTM adicional), nunca substituindo o central.
|
|
148
|
+
13. **Qualquer `useEffect`/handler que termina em `refresh()` do carrinho precisa esperar
|
|
149
|
+
`loading` (do `useCart()`) ficar `false` antes de rodar.** Achamos essa mesma classe de bug
|
|
150
|
+
em 4 pontos independentes do checkout (recálculo de frete por item, por CEP, troca de método
|
|
151
|
+
de frete, "continuar"), todos causavam "removo um item e ele volta" se disparassem enquanto
|
|
152
|
+
outra mutação de carrinho estava em voo. `cart-provider.tsx` também tem um contador de
|
|
153
|
+
sequência (`mutationSeq`) como proteção de segunda camada, mas o guard de `loading` evita o
|
|
154
|
+
problema na origem.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Contratos entre módulos (referência real, não a genérica de quando isso foi escrito pra "fase 2")
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
lib/unbox/store.ts → withStoreClient() / getShopContext(), client de LOJA, cache de token em memória
|
|
162
|
+
lib/customer-session.ts → getCustomerClient() / requireCustomerClient(), client do CLIENTE (token separado)
|
|
163
|
+
lib/session.ts → cookies httpOnly: unbox_cart, unbox_customer, unbox_order_<ref>
|
|
164
|
+
lib/unbox/errors.ts → friendlyError(), cartEventLabel()
|
|
165
|
+
components/cart/ → CartProvider (useCart hook) + MiniCart, usado pelo Layout inteiro
|
|
166
|
+
components/home/combos-* → consome lib/enrichment/combos.ts (Agente 09)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Variáveis de ambiente necessárias
|
|
172
|
+
|
|
173
|
+
Nomes reais (confira sempre contra `.env.example` do projeto, já houve doc desatualizada com
|
|
174
|
+
`UNBOX_USERNAME`/`UNBOX_PASSWORD`, que não existem):
|
|
175
|
+
|
|
176
|
+
```env
|
|
177
|
+
# .env.local (server-only: nunca NEXT_PUBLIC_)
|
|
178
|
+
UNBOX_PARTNER_API_KEY= # NOVA API pública de parceiros: key única do parceiro (todas as lojas).
|
|
179
|
+
# Preenchida → signIn + leituras compatíveis roteiam pra partners.unbox.com.br
|
|
180
|
+
UNBOX_CAPTCHA_BYPASS= # obrigatória com a key de parceiro: x-captcha-verification do signIn (pedir à Unbox)
|
|
181
|
+
UNBOX_API_KEY= # chave da loja (modelo antigo; opcional se a de parceiro está preenchida)
|
|
182
|
+
UNBOX_USER= # usuário de API da loja (ex.: api_minhaloja)
|
|
183
|
+
UNBOX_PASS= # senha do usuário de API
|
|
184
|
+
UNBOX_SHOP_ID= # opcional: extraído do JWT se vazio
|
|
185
|
+
UNBOX_SHOP_SLUG= # opcional: extraído do JWT se vazio
|
|
186
|
+
UNBOX_WEBHOOK_SECRET= # secret(s) do subscribeToWebhook, separados por vírgula se houver mais de um
|
|
187
|
+
|
|
188
|
+
# App
|
|
189
|
+
SESSION_SECRET=
|
|
190
|
+
REVALIDATE_SECRET=
|
|
191
|
+
NEXT_PUBLIC_SITE_URL=
|
|
192
|
+
```
|