@bacano/sdk 1.0.1 → 1.1.8

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.
Files changed (72) hide show
  1. package/README.md +439 -18
  2. package/STOREFRONT_CLARITY.md +140 -0
  3. package/STOREFRONT_CONSTRUCTION.md +105 -0
  4. package/STOREFRONT_LEADS.md +130 -0
  5. package/STOREFRONT_LEGAL.md +66 -0
  6. package/STOREFRONT_MARKETING.md +291 -0
  7. package/STOREFRONT_PERFORMANCE.md +304 -0
  8. package/STOREFRONT_PREVIEW.md +499 -0
  9. package/STOREFRONT_PRODUCT_SPECIFICATIONS.md +127 -0
  10. package/STOREFRONT_VOLUME_PRICING.md +131 -0
  11. package/client.d.ts +8 -1
  12. package/errors.d.ts +9 -1
  13. package/graphql.cjs +266 -3
  14. package/graphql.d.ts +2 -2
  15. package/graphql.js +266 -3
  16. package/index.cjs +2035 -255
  17. package/index.d.ts +8 -6
  18. package/index.js +2035 -255
  19. package/marketing/attribution.d.ts +53 -0
  20. package/marketing/clarity.d.ts +3 -0
  21. package/marketing/domain.d.ts +1 -0
  22. package/marketing/ga4.d.ts +2 -0
  23. package/marketing/index.d.ts +5 -0
  24. package/marketing/runtime.d.ts +2 -0
  25. package/marketing/sanitize.d.ts +2 -0
  26. package/marketing/types.d.ts +111 -0
  27. package/media.d.ts +45 -2
  28. package/modules/auth.d.ts +3 -2
  29. package/modules/availability.d.ts +2 -2
  30. package/modules/cart-errors.d.ts +2 -0
  31. package/modules/cart-session.d.ts +2 -2
  32. package/modules/cart.d.ts +4 -3
  33. package/modules/catalog.d.ts +15 -3
  34. package/modules/content.d.ts +2 -2
  35. package/modules/marketing.d.ts +5 -0
  36. package/modules/orders.d.ts +2 -2
  37. package/modules/profile.d.ts +1 -1
  38. package/modules/static-catalog.d.ts +13 -0
  39. package/modules/website.d.ts +7 -1
  40. package/package.json +14 -3
  41. package/react/context-registry.d.ts +9 -0
  42. package/react/context.d.ts +1 -1
  43. package/react/hooks.d.ts +24 -2
  44. package/react/marketing-context.d.ts +3 -0
  45. package/react/marketing-provider.d.ts +10 -0
  46. package/react/preview/cache.d.ts +23 -0
  47. package/react/preview/context.d.ts +5 -0
  48. package/react/preview/navigation.d.ts +9 -0
  49. package/react/preview/provider.d.ts +3 -0
  50. package/react/preview/shell.d.ts +3 -0
  51. package/react/preview/toolbar.d.ts +3 -0
  52. package/react/preview/types.d.ts +60 -0
  53. package/react/preview.cjs +742 -0
  54. package/react/preview.d.ts +14 -0
  55. package/react/preview.js +730 -0
  56. package/react/website-gate.d.ts +22 -0
  57. package/react.cjs +3893 -1795
  58. package/react.d.ts +8 -4
  59. package/react.js +3891 -1789
  60. package/skills/bacano-web/SKILL.md +116 -0
  61. package/skills/bacano-web/agents/openai.yaml +4 -0
  62. package/skills/bacano-web/references/architecture-runtime.md +109 -0
  63. package/skills/bacano-web/references/common.md +92 -0
  64. package/skills/bacano-web/references/informational.md +39 -0
  65. package/skills/bacano-web/references/report.md +70 -0
  66. package/skills/bacano-web/references/storefront.md +116 -0
  67. package/skills/bacano-web/scripts/audit-http.mjs +284 -0
  68. package/skills/bacano-web/scripts/cli.mjs +222 -0
  69. package/skills/bacano-web/scripts/postinstall.mjs +8 -0
  70. package/transport/documents.d.ts +23 -18
  71. package/transport/graphql.d.ts +13 -1
  72. package/types.d.ts +338 -0
@@ -0,0 +1,140 @@
1
+ # Microsoft Clarity en storefronts Bacano
2
+
3
+ Este documento define la integración oficial de Microsoft Clarity para todos
4
+ los storefronts que usan `@bacano/sdk`. Clarity aporta mapas de calor,
5
+ grabaciones de sesión y análisis de comportamiento; no reemplaza GA4, Meta ni
6
+ los eventos comerciales autoritativos de Bacano.
7
+
8
+ ## Responsabilidades
9
+
10
+ El comercio crea y administra su proyecto en Microsoft Clarity. Se recomienda
11
+ un proyecto diferente por dominio. En Bacano, dentro de **Sitios web > Marketing
12
+ y medición > Microsoft Clarity**, registra el `Project ID`, guarda, prueba la
13
+ conexión y la activa.
14
+
15
+ El `Project ID` es público. Bacano lo guarda por `website_id`; no existe un
16
+ secreto de servidor para esta integración. El SDK solo lo recibe cuando la
17
+ integración está activa, validada y la petición corresponde al dominio canónico
18
+ de producción.
19
+
20
+ El storefront es responsable únicamente de:
21
+
22
+ 1. Usar una versión del SDK que incluya este contrato.
23
+ 2. Montar una sola vez el `BacanoMarketingProvider` existente.
24
+ 3. Seguir emitiendo los eventos canónicos mediante `useMarketing().track()`.
25
+
26
+ No debe instalar otro paquete de Clarity, copiar el snippet de Microsoft,
27
+ consultar GraphQL ni construir una segunda petición de configuración.
28
+
29
+ ```tsx
30
+ import { getWebsitePublicConfig } from "@bacano/sdk";
31
+ import { BacanoMarketingProvider } from "@bacano/sdk/react";
32
+
33
+ const publicConfig = await getWebsitePublicConfig({ apiUrl, websiteSlug });
34
+
35
+ <BacanoMarketingProvider publicConfig={publicConfig} scriptLoadStrategy="idle">
36
+ <Storefront />
37
+ </BacanoMarketingProvider>;
38
+ ```
39
+
40
+ Cuando Clarity está activo, el provider carga una sola vez
41
+ `https://www.clarity.ms/tag/{projectId}`. En localhost, preview y dominios no
42
+ canónicos se mantiene como `no-op`.
43
+
44
+ Si el storefront aplica una Content Security Policy, debe permitir los
45
+ endpoints oficiales de Clarity (`https://*.clarity.ms` y
46
+ `https://c.bing.com`) en las directivas correspondientes de scripts y
47
+ conexiones. Conviene probar primero la política en modo report-only y revisar
48
+ la consola del navegador antes de aplicarla.
49
+
50
+ La matriz distribuible de CSP para Clarity, GA4 y Meta vive únicamente en
51
+ [`STOREFRONT_MARKETING.md`](./STOREFRONT_MARKETING.md). No mantener una segunda
52
+ lista dentro del storefront: componer desde allí solo los proveedores activos
53
+ y añadir por separado los orígenes propios de autenticación, pagos o video.
54
+
55
+ Las imágenes y videos públicos entregados por
56
+ `/storage/v1/files/{fileId}` aceptan lectura credentialless desde renderizadores
57
+ externos. Bacano valida que el archivo pertenezca a media pública de una empresa
58
+ con un storefront activo antes de servirlo y mantiene privados los archivos no
59
+ elegibles. El storefront no debe crear un proxy, reenviar cookies ni modificar
60
+ las URLs de media para que aparezcan en las reproducciones de Clarity.
61
+
62
+ Una política CSP solo puede componerse con datos conocidos durante el build.
63
+ El runtime no intenta modificar una cabecera CSP después de cargar la página.
64
+ Si un proveedor incorpora un origen dinámico no documentado —por ejemplo, un
65
+ endpoint auxiliar de Meta alojado en infraestructura cloud— no se deben abrir
66
+ comodines amplios como `*.on.aws` o `*.run.app`. Ese origen debe validarse y
67
+ declararse de manera exacta en el hosting hasta que el proveedor ofrezca un
68
+ contrato estable que Bacano pueda publicar de forma segura.
69
+
70
+ ## Eventos y alcance
71
+
72
+ Clarity captura automáticamente navegación, clics, desplazamiento, errores y
73
+ la representación necesaria para sus mapas y grabaciones. Adicionalmente, el
74
+ SDK reenvía cada evento canónico de navegador como un evento personalizado de
75
+ Clarity con el mismo nombre, por ejemplo:
76
+
77
+ - `view_item`
78
+ - `add_to_cart`
79
+ - `begin_checkout`
80
+ - `contact`
81
+
82
+ Esto permite filtrar grabaciones y mapas por pasos del embudo sin instrumentar
83
+ handlers paralelos. El storefront no debe llamar a `window.clarity()`.
84
+
85
+ Clarity es un destino exclusivo de navegador. `order_placed`, `purchase` y
86
+ `refund` continúan enviándose de forma autoritativa a GA4 y Meta desde Bacano;
87
+ no se crea un outbox de servidor para Clarity.
88
+
89
+ ## Privacidad y seguridad
90
+
91
+ - No enviar email, teléfono, documento, dirección, tokens ni otros datos
92
+ personales a eventos o etiquetas de Clarity.
93
+ - Clarity enmascara por defecto entradas, números y correos. Los storefronts
94
+ deben añadir `data-clarity-mask` a cualquier zona personalizada sensible que
95
+ requiera protección adicional.
96
+ - No usar `data-clarity-unmask` en checkout, cuenta, autenticación o formularios
97
+ con datos personales.
98
+ - Microsoft indica que Clarity no debe utilizarse en sitios o aplicaciones
99
+ dirigidos a menores de 18 años. El comercio debe evaluar su audiencia antes
100
+ de activarlo.
101
+ - El aviso informativo de cookies de Bacano no es un gestor de consentimiento.
102
+ Si un comercio opera en una jurisdicción que exige consentimiento previo,
103
+ debe implementar un mecanismo de consentimiento válido antes de activar la
104
+ recolección completa.
105
+
106
+ No se utiliza la API `identify`: Bacano no entrega a Clarity identidades de
107
+ clientes ni compradores.
108
+
109
+ ## Verificación
110
+
111
+ Después de desplegar el storefront en su dominio canónico:
112
+
113
+ 1. Abrir el sitio sin modo preview.
114
+ 2. Confirmar en la pestaña Network la carga de `clarity.ms/tag/{projectId}` y
115
+ solicitudes de recolección a Clarity.
116
+ 3. Navegar, abrir un producto y agregarlo al carrito.
117
+ 4. Revisar sesiones en tiempo real, mapas y eventos personalizados dentro del
118
+ proyecto correcto de Clarity.
119
+ 5. Abrir una reproducción y confirmar que las imágenes públicas de productos y
120
+ Content cargan desde `api.bacanoerp.com/storage/v1/files/`.
121
+ 6. Confirmar que localhost, preview y otro dominio no envíen datos.
122
+ 7. Confirmar que una falla o bloqueo del script no afecte catálogo, carrito o
123
+ checkout.
124
+
125
+ Microsoft puede tardar algunos minutos en mostrar la primera información. Una
126
+ prueba válida en Bacano confirma el Project ID y la disponibilidad del tag; no
127
+ demuestra que un navegador concreto esté libre de bloqueadores.
128
+
129
+ ## Checklist para agentes de storefront
130
+
131
+ - [ ] Uso un único `BacanoMarketingProvider`.
132
+ - [ ] No instalé el snippet ni un paquete paralelo de Clarity.
133
+ - [ ] Los eventos continúan saliendo solo de `useMarketing().track()`.
134
+ - [ ] Preview y localhost no cargan Clarity.
135
+ - [ ] Las zonas sensibles permanecen enmascaradas.
136
+ - [ ] No uso `identify`, PII ni etiquetas con datos personales.
137
+ - [ ] Las imágenes públicas se reconstruyen sin un proxy del storefront.
138
+ - [ ] Validé carga, recolección, sesiones y eventos en producción.
139
+
140
+ El contrato general de eventos permanece en `STOREFRONT_MARKETING.md`.
@@ -0,0 +1,105 @@
1
+ # Sitio en construcción para storefronts Bacano
2
+
3
+ Este documento define el contrato oficial para ocultar temporalmente un sitio
4
+ Bacano sin reconstruir su export estático. Aplica a SiteGround y otros hostings
5
+ estáticos; una futura integración con CloudFront podrá aplicar la misma
6
+ configuración en el edge.
7
+
8
+ ## Responsabilidades
9
+
10
+ - Bacano conserva la configuración por `website_id`, valida las imágenes y
11
+ entrega únicamente datos públicos.
12
+ - `public-config` decide si la pantalla debe aplicarse. Localhost, desarrollo y
13
+ orígenes no canónicos nunca quedan bloqueados.
14
+ - El SDK administra la consulta en vivo, la pantalla responsive y el acceso
15
+ temporal de vista previa.
16
+ - El storefront solo monta `BacanoWebsiteGate`. No consulta GraphQL, no lee
17
+ `websites.config` y no construye URLs de Storage.
18
+
19
+ ## Integración React
20
+
21
+ El gate debe envolver autenticación, marketing y la aplicación. De esta forma
22
+ Clerk, GA4, Meta y Clarity no se cargan mientras la pantalla esté activa.
23
+
24
+ ```tsx
25
+ "use client";
26
+
27
+ import { BacanoWebsiteGate } from "@bacano/sdk/react";
28
+
29
+ export function WebsiteVisibility({ children }: { children: React.ReactNode }) {
30
+ return (
31
+ <BacanoWebsiteGate
32
+ config={{
33
+ apiUrl: process.env.NEXT_PUBLIC_BACANO_API_URL!,
34
+ websiteSlug: process.env.NEXT_PUBLIC_BACANO_WEBSITE_SLUG!,
35
+ }}
36
+ >
37
+ {children}
38
+ </BacanoWebsiteGate>
39
+ );
40
+ }
41
+ ```
42
+
43
+ Después del gate se montan `ClerkProvider`, `BacanoProvider`,
44
+ `BacanoMarketingProvider` y el resto del storefront. Puede entregarse
45
+ `initialConfig` si el build ya obtuvo `public-config`; el gate vuelve a
46
+ consultarlo antes de montar el sitio para detectar cambios posteriores al
47
+ despliegue.
48
+
49
+ Mientras confirma la configuración, el gate serializa `children` dentro de un
50
+ `<noscript>` semántico. El catálogo, los productos, encabezados y enlaces siguen
51
+ presentes en el HTML exportado y son visibles cuando JavaScript está
52
+ deshabilitado, pero React no monta esos descendientes. Así evita cargar Clerk,
53
+ GA4, Meta o Clarity y tampoco muestra fugazmente la tienda si construcción está
54
+ activa. `loadingFallback` es únicamente la UI visible para navegadores con
55
+ JavaScript durante esa consulta; por defecto permanece vacío.
56
+
57
+ La pantalla oficial usa la imagen mobile hasta 767 px y la desktop desde 768
58
+ px. En ambos casos emplea las fuentes responsivas generadas por Bacano. Si solo
59
+ existe una de las dos imágenes la reutiliza de forma segura; si no existe
60
+ ninguna, conserva el fondo y muestra el título y mensaje configurados. El
61
+ storefront puede proporcionar `constructionFallback` si requiere una UI propia,
62
+ pero no debe alterar la decisión `construction.enforced`.
63
+
64
+ ## Vista previa temporal
65
+
66
+ Desde Bacano, un usuario con `websites.manage` puede generar un enlace válido
67
+ durante dos horas:
68
+
69
+ ```text
70
+ https://tienda.example/#bacano-preview=<token-firmado>
71
+ ```
72
+
73
+ El fragmento no viaja al hosting ni se incluye en el `Referer`. El gate lo
74
+ guarda en `sessionStorage`, limpia la barra de direcciones y valida el token
75
+ contra `public-config`. La vista previa termina al cerrar esa sesión, al vencer
76
+ el token o al borrar los datos del navegador.
77
+
78
+ No convertir el token en query string, cookie permanente ni variable de build.
79
+
80
+ ## Seguridad y límites de hosting estático
81
+
82
+ En SiteGround esta es una barrera de presentación ejecutada por JavaScript. No
83
+ impide descargar el HTML estático ni devuelve HTTP 503, por lo que no debe
84
+ usarse como control de acceso para información sensible. El contenido privado
85
+ nunca debe formar parte del export público. Mientras la pantalla está activa,
86
+ el gate añade `noindex,nofollow`; en un hosting estático esto sigue dependiendo
87
+ de que el crawler ejecute JavaScript.
88
+
89
+ Cuando Bacano opere el storefront en CloudFront, la misma bandera podrá
90
+ resolverse antes de servir la página, devolver 503 y aplicar `noindex` desde el
91
+ edge. El contrato del SDK y la configuración por website permanecen válidos.
92
+
93
+ ## Checklist del storefront
94
+
95
+ - `BacanoWebsiteGate` está por fuera de auth y marketing.
96
+ - El export contiene el catálogo estático dentro del fallback `<noscript>`.
97
+ - Sin JavaScript, catálogo, productos y enlaces continúan visibles.
98
+ - La configuración se consulta en runtime con `cache: no-store`.
99
+ - La pantalla activa no inicializa Clerk, GA4, Meta ni Clarity.
100
+ - Localhost y dominios de desarrollo siguen mostrando la web.
101
+ - Las imágenes desktop y mobile usan `srcset` y `sizes`.
102
+ - El enlace temporal abre el storefront y desaparece de la barra de dirección.
103
+ - Un token vencido no concede acceso y se elimina de `sessionStorage`.
104
+ - La pantalla oficial sigue siendo útil aunque no tenga imágenes.
105
+ - Un fallo de `public-config` degrada de forma abierta y no tumba el sitio.
@@ -0,0 +1,130 @@
1
+ # Captura de leads en storefronts Bacano
2
+
3
+ Este es el contrato canónico para formularios comerciales construidos por un
4
+ storefront. Bacano no impone un constructor visual: cada tienda decide sus
5
+ campos y diseño, pero toda captura debe entrar por `@bacano/sdk`.
6
+
7
+ ## Responsabilidades
8
+
9
+ El storefront:
10
+
11
+ - Renderiza el formulario y valida su experiencia básica.
12
+ - Muestra exactamente `publicConfig.legal.directMarketingConsent.statement`.
13
+ - Mantiene la aceptación opcional desmarcada hasta una acción explícita.
14
+ - Genera una clave de idempotencia por envío y la conserva durante reintentos.
15
+ - Envía únicamente respuestas necesarias para el propósito informado.
16
+
17
+ Bacano:
18
+
19
+ - Deriva y valida el website y su dominio.
20
+ - Resuelve la campaña por su clave pública.
21
+ - Conserva la versión y huella del texto aceptado.
22
+ - Reutiliza la identidad, el lead o el cliente existente sin duplicarlos.
23
+ - Completa un correo o teléfono faltante únicamente cuando la coincidencia de
24
+ identidad es inequívoca; nunca reemplaza un dato existente.
25
+ - Conserva el contacto enviado dentro de la evidencia de autorización ligada a
26
+ la captura, incluso cuando el participante ya era cliente.
27
+ - Conserva la captura, atribución y respuestas como evidencia inmutable.
28
+ - Aplica límites de frecuencia, tamaño e idempotencia.
29
+
30
+ ## Configuración previa
31
+
32
+ 1. Configura el texto de **Autorización de comunicaciones comerciales** en la
33
+ pestaña Legal del website.
34
+ 2. Crea una campaña en Bacano y actívala.
35
+ 3. Usa su clave pública estable en el formulario.
36
+
37
+ Una campaña en borrador, pausada, finalizada, fuera de vigencia o asociada a
38
+ otro website no acepta capturas. Si el texto legal no existe, el storefront no
39
+ debe mostrar ni habilitar el formulario comercial.
40
+
41
+ ## Implementación
42
+
43
+ ```tsx
44
+ const consent = publicConfig.legal.directMarketingConsent;
45
+
46
+ if (!consent) return null;
47
+
48
+ // Renderiza consent.statement junto a un checkbox desmarcado.
49
+ // Ejecuta esta llamada únicamente después de validar el formulario y aceptar.
50
+ // Conserva esta clave en el estado del formulario mientras reintentas el envío.
51
+ const idempotencyKey = crypto.randomUUID();
52
+ const result = await client.marketing.captureLead({
53
+ campaignKey: "newsletter-baby-rex",
54
+ idempotencyKey,
55
+ commercialConsent: true,
56
+ contact: {
57
+ partyKind: "PERSON",
58
+ firstName: "Ana",
59
+ email: "ana@example.com",
60
+ },
61
+ answers: {
62
+ interest: "bebe-nina",
63
+ },
64
+ });
65
+ ```
66
+
67
+ Debe existir al menos correo o teléfono. Los nombres son opcionales. Para una
68
+ empresa pueden usarse `partyKind: "COMPANY"`, `legalName` y `commercialName`.
69
+
70
+ `source` se omite para formularios normales y será `WEBSITE`. Usa `QR`
71
+ únicamente cuando el formulario se abrió mediante una entrada QR controlada por
72
+ el storefront. UTM, referidor y click IDs se toman automáticamente de la
73
+ atribución segura del SDK.
74
+
75
+ El storefront no debe construir ni enviar manualmente el payload HTTP. El SDK
76
+ serializa este contrato como JSON y la ruta pública de Bacano lo procesa antes
77
+ de validar la campaña. Un SDK `1.0.14` o posterior conserva esta forma del
78
+ payload; no se requieren adaptadores específicos por tienda.
79
+
80
+ ## Respuestas personalizadas
81
+
82
+ `answers` es un snapshot del formulario, no un constructor de campos del CRM.
83
+
84
+ - Máximo 50 claves, cada una de hasta 80 caracteres.
85
+ - Payload total aproximado máximo: 30 KB.
86
+ - No incluyas contraseñas, tokens, datos de pago, documentos adjuntos ni HTML.
87
+ - No dupliques correo o teléfono dentro de `answers`; usa `contact`.
88
+ - Un cambio futuro del formulario no modifica capturas anteriores.
89
+
90
+ ## Idempotencia y privacidad
91
+
92
+ - La misma interacción debe reutilizar el mismo `idempotencyKey` hasta obtener
93
+ respuesta. Un nuevo envío voluntario usa una clave nueva.
94
+ - La respuesta es deliberadamente genérica y nunca revela si la persona ya era
95
+ lead o cliente.
96
+ - Si correo y teléfono pertenecen a identidades activas diferentes, Bacano no
97
+ sobrescribe ninguna de ellas y conserva el caso para revisión manual.
98
+ - No llames GraphQL, Hasura ni endpoints internos directamente.
99
+ - No captures un lead si el visitante no aceptó el texto comercial vigente.
100
+ - Una revocación posterior conserva el historial, pero impide comunicaciones
101
+ futuras hasta una nueva aceptación expresa.
102
+
103
+ ## Beneficio de primera compra
104
+
105
+ Cuando la campaña activa tiene objetivo `FIRST_PURCHASE_COUPON` y referencia un
106
+ cupón online vigente, Bacano puede encolar el correo de bienvenida después de
107
+ aceptar la captura. Esta operación es completamente del servidor:
108
+
109
+ - el storefront no envía correos ni consulta Resend;
110
+ - no debe afirmar que el cupón ya fue enviado;
111
+ - repetir la misma captura no duplica el beneficio;
112
+ - una falla de correo nunca convierte la captura en error;
113
+ - Bacano revalida autorización, campaña, website, cupón y compras anteriores
114
+ inmediatamente antes del envío.
115
+
116
+ El contrato de `captureLead()` no cambia y no expone estados internos del
117
+ correo. La evidencia operativa queda en `outbound_emails` dentro de Bacano. El
118
+ newsletter masivo y las automatizaciones visuales continúan fuera de alcance.
119
+
120
+ ## Checklist para agentes
121
+
122
+ - [ ] Leí este contrato antes de crear el formulario.
123
+ - [ ] Uso un único `BacanoClient` inicializado.
124
+ - [ ] Leo el texto desde `publicConfig.legal.directMarketingConsent`.
125
+ - [ ] La aceptación empieza desmarcada y es explícita.
126
+ - [ ] Uso `client.marketing.captureLead()` y no GraphQL directo.
127
+ - [ ] Conservo la clave de idempotencia durante reintentos.
128
+ - [ ] No envío secretos ni información innecesaria en `answers`.
129
+ - [ ] No afirmo que el correo o el cupón fueron entregados a partir de la
130
+ respuesta genérica de `captureLead()`.
@@ -0,0 +1,66 @@
1
+ # Storefront legal settings
2
+
3
+ This document is the canonical contract for legal content exposed by the
4
+ Bacano SDK. Storefronts must use this configuration instead of maintaining
5
+ parallel legal documents in Content or querying GraphQL directly.
6
+
7
+ ## Public contract
8
+
9
+ `getWebsitePublicConfig()` returns the current configuration for the resolved
10
+ website:
11
+
12
+ ```ts
13
+ const config = await getWebsitePublicConfig(options);
14
+
15
+ config.legal = {
16
+ schemaVersion: 1,
17
+ version: 3,
18
+ contentHash: "...",
19
+ documents: {
20
+ terms: { type: "doc", content: [] },
21
+ shipping: { type: "doc", content: [] },
22
+ returns: { type: "doc", content: [] },
23
+ privacy: { type: "doc", content: [] },
24
+ cookies: { type: "doc", content: [] },
25
+ },
26
+ inquiriesChannel: "privacidad@example.com",
27
+ cookieNotice: {
28
+ enabled: true,
29
+ message: "Usamos cookies propias y de terceros...",
30
+ buttonLabel: "Entendido",
31
+ },
32
+ };
33
+ ```
34
+
35
+ All documents and the inquiries channel are optional. Missing documents are
36
+ returned as `null`. Documents use Bacano's rich-text JSON format and must be
37
+ rendered safely; do not inject untrusted HTML.
38
+
39
+ The configuration is included in the existing public-config request. Do not
40
+ add a second request, direct GraphQL access, or local fallback copies of legal
41
+ text.
42
+
43
+ ## Informational cookie notice
44
+
45
+ Render the notice only when `config.legal.cookieNotice.enabled` is `true`.
46
+ Display the message and button label supplied by Bacano, allow the visitor to
47
+ close it, and store that dismissal locally if the storefront should avoid
48
+ showing it again in the same browser.
49
+
50
+ The notice is informational. It is not a consent manager and does not gate,
51
+ delay, or reconfigure the GA4, Meta, or Microsoft Clarity runtime. Marketing remains governed by
52
+ `config.marketing`.
53
+
54
+ ## Storefront checklist
55
+
56
+ - Preserve existing public legal routes and their SEO behavior.
57
+ - Source terms, shipping, returns, privacy, cookies, and the contact channel only from
58
+ `config.legal`.
59
+ - Handle every nullable document without crashing or inventing content.
60
+ - Remove only the obsolete legal Content keys; keep unrelated Content data.
61
+ - Do not add direct GraphQL calls or duplicate public-config requests.
62
+ - Verify the notice in enabled, disabled, and dismissed states.
63
+ - Verify GA4, Meta, and Clarity continue operating in every notice state.
64
+ - Do not present the informational notice as consent for Clarity. Review the
65
+ privacy rules in `STOREFRONT_CLARITY.md` before activating it.
66
+ - Run typecheck, lint, unit tests, E2E tests, and the production build.