@tokenoftrust/storefront-runner 0.1.0
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 +58 -0
- package/README.md +40 -0
- package/apps/storefront/.dev.vars.example +41 -0
- package/apps/storefront/.env.example +24 -0
- package/apps/storefront/astro.config.mjs +245 -0
- package/apps/storefront/env.d.ts +155 -0
- package/apps/storefront/lib/ensure-preview-reconcile-secret.sh +31 -0
- package/apps/storefront/lib/resolve-cf-token.sh +48 -0
- package/apps/storefront/lib/resolve-tot-credentials.sh +69 -0
- package/apps/storefront/migrations/0000_baseline.sql +54 -0
- package/apps/storefront/migrations/0001_products_fts.sql +9 -0
- package/apps/storefront/migrations/README.md +54 -0
- package/apps/storefront/migrations/meta/0000_snapshot.json +347 -0
- package/apps/storefront/migrations/meta/0001_snapshot.json +347 -0
- package/apps/storefront/migrations/meta/_journal.json +20 -0
- package/apps/storefront/package.json +41 -0
- package/apps/storefront/public/brand/northwind-logo-dark.svg +4 -0
- package/apps/storefront/public/brand/northwind-logo-light.svg +4 -0
- package/apps/storefront/public/brand/northwind-og.svg +13 -0
- package/apps/storefront/public/favicon.svg +5 -0
- package/apps/storefront/public/js/dashboard-team.js +147 -0
- package/apps/storefront/public/js/dashboard-vendor-search.js +115 -0
- package/apps/storefront/src/components/Badge.astro +34 -0
- package/apps/storefront/src/components/Breadcrumbs.astro +45 -0
- package/apps/storefront/src/components/CollectionCard.astro +56 -0
- package/apps/storefront/src/components/EmptyState.astro +35 -0
- package/apps/storefront/src/components/Img.astro +68 -0
- package/apps/storefront/src/components/ProductCard.astro +228 -0
- package/apps/storefront/src/components/Section.astro +39 -0
- package/apps/storefront/src/components/Seo.astro +70 -0
- package/apps/storefront/src/components/WidgetFrame.astro +34 -0
- package/apps/storefront/src/components/auth/AuthBadge.astro +44 -0
- package/apps/storefront/src/components/chrome/AnnouncementBar.astro +108 -0
- package/apps/storefront/src/components/chrome/MegaMenu.astro +26 -0
- package/apps/storefront/src/components/chrome/NavDropdown.astro +116 -0
- package/apps/storefront/src/components/chrome/SiteFooter.astro +181 -0
- package/apps/storefront/src/components/chrome/SiteHeader.astro +181 -0
- package/apps/storefront/src/components/chrome/UtilityNav.astro +79 -0
- package/apps/storefront/src/components/commerce/FoxyLoader.astro +23 -0
- package/apps/storefront/src/components/commerce/PriceDisplay.astro +91 -0
- package/apps/storefront/src/components/commerce/ProductCarousel.astro +197 -0
- package/apps/storefront/src/components/commerce/ProductGrid.astro +75 -0
- package/apps/storefront/src/components/commerce/RatingStars.astro +58 -0
- package/apps/storefront/src/components/compliance/NicotineWarning.astro +33 -0
- package/apps/storefront/src/components/home/Hero.astro +164 -0
- package/apps/storefront/src/components/islands/AgeGate.tsx +105 -0
- package/apps/storefront/src/components/islands/ImageGallery.tsx +237 -0
- package/apps/storefront/src/components/islands/IsolatedAgeGate.tsx +73 -0
- package/apps/storefront/src/components/islands/MobileNav.tsx +239 -0
- package/apps/storefront/src/components/islands/QuickView.tsx +138 -0
- package/apps/storefront/src/components/islands/RecentlyViewed.tsx +122 -0
- package/apps/storefront/src/components/islands/SavedList.tsx +99 -0
- package/apps/storefront/src/components/islands/SearchTypeahead.tsx +248 -0
- package/apps/storefront/src/components/islands/VariantSelector.tsx +378 -0
- package/apps/storefront/src/components/marketing/CardGrid.astro +72 -0
- package/apps/storefront/src/components/marketing/CodeSample.astro +20 -0
- package/apps/storefront/src/components/marketing/CtaBand.astro +24 -0
- package/apps/storefront/src/components/marketing/Faq.astro +37 -0
- package/apps/storefront/src/components/marketing/Integrations.astro +63 -0
- package/apps/storefront/src/components/marketing/MarketingBlocks.astro +53 -0
- package/apps/storefront/src/components/marketing/MarketingCtas.astro +48 -0
- package/apps/storefront/src/components/marketing/MarketingHero.astro +72 -0
- package/apps/storefront/src/components/marketing/ProofStrip.astro +37 -0
- package/apps/storefront/src/components/marketing/SplitCompare.astro +53 -0
- package/apps/storefront/src/components/marketing/Steps.astro +36 -0
- package/apps/storefront/src/components/marketing/Testimonials.astro +38 -0
- package/apps/storefront/src/components/marketing/TrustBar.astro +22 -0
- package/apps/storefront/src/components/nav/Footer.astro +148 -0
- package/apps/storefront/src/components/nav/Header.astro +190 -0
- package/apps/storefront/src/components/plp/ActiveFilters.astro +79 -0
- package/apps/storefront/src/components/plp/FacetSidebar.astro +146 -0
- package/apps/storefront/src/components/plp/Pagination.astro +99 -0
- package/apps/storefront/src/components/plp/SortSelect.astro +64 -0
- package/apps/storefront/src/config/devTenants.ts +16 -0
- package/apps/storefront/src/config/kvTenantResolver.ts +87 -0
- package/apps/storefront/src/config/resolver.ts +46 -0
- package/apps/storefront/src/config/tenants.ts +193 -0
- package/apps/storefront/src/layouts/Layout.astro +303 -0
- package/apps/storefront/src/lib/analytics/index.ts +47 -0
- package/apps/storefront/src/lib/auth/brokerAssertion.ts +136 -0
- package/apps/storefront/src/lib/auth/devAuth.ts +90 -0
- package/apps/storefront/src/lib/auth/gatePage.ts +81 -0
- package/apps/storefront/src/lib/auth/identityToken.ts +341 -0
- package/apps/storefront/src/lib/auth/loginGate.ts +107 -0
- package/apps/storefront/src/lib/auth/route.ts +146 -0
- package/apps/storefront/src/lib/auth/session.ts +203 -0
- package/apps/storefront/src/lib/auth/totAccessClient.ts +503 -0
- package/apps/storefront/src/lib/basePath.ts +41 -0
- package/apps/storefront/src/lib/cfImage.ts +55 -0
- package/apps/storefront/src/lib/chrome/model.ts +65 -0
- package/apps/storefront/src/lib/colors.ts +97 -0
- package/apps/storefront/src/lib/content-edit/client.ts +230 -0
- package/apps/storefront/src/lib/content-edit/index.ts +14 -0
- package/apps/storefront/src/lib/content-edit/route.ts +25 -0
- package/apps/storefront/src/lib/content-edit/types.ts +19 -0
- package/apps/storefront/src/lib/cspStaticHashes.ts +24 -0
- package/apps/storefront/src/lib/d1/catalog.ts +289 -0
- package/apps/storefront/src/lib/dashboard/staffAdmission.ts +43 -0
- package/apps/storefront/src/lib/dashboard/staffVendorAccess.ts +449 -0
- package/apps/storefront/src/lib/dashboard/tenantSelection.ts +136 -0
- package/apps/storefront/src/lib/dashboard/vendorQuery.ts +61 -0
- package/apps/storefront/src/lib/demoGate.ts +113 -0
- package/apps/storefront/src/lib/dev/ai-widget-client.js +127 -0
- package/apps/storefront/src/lib/dev/cliSignInCode.ts +132 -0
- package/apps/storefront/src/lib/diag/redact.ts +20 -0
- package/apps/storefront/src/lib/edgeCache.ts +128 -0
- package/apps/storefront/src/lib/email/magicLinkInviteEmail.ts +62 -0
- package/apps/storefront/src/lib/env.ts +60 -0
- package/apps/storefront/src/lib/fixtures/sampleProducts.ts +130 -0
- package/apps/storefront/src/lib/format.ts +29 -0
- package/apps/storefront/src/lib/foxyCommerce.ts +49 -0
- package/apps/storefront/src/lib/imageAttrs.ts +55 -0
- package/apps/storefront/src/lib/jsonld.ts +136 -0
- package/apps/storefront/src/lib/maintenance.ts +71 -0
- package/apps/storefront/src/lib/memoryKv.ts +32 -0
- package/apps/storefront/src/lib/messaging/messagesClient.ts +143 -0
- package/apps/storefront/src/lib/placeholder.ts +99 -0
- package/apps/storefront/src/lib/previewReload.ts +125 -0
- package/apps/storefront/src/lib/rawMarketingHtml.ts +133 -0
- package/apps/storefront/src/lib/search/index.ts +74 -0
- package/apps/storefront/src/lib/sections.ts +129 -0
- package/apps/storefront/src/lib/securityHeaders.ts +31 -0
- package/apps/storefront/src/lib/storyblok/content-model.ts +289 -0
- package/apps/storefront/src/lib/storyblok/provider.ts +524 -0
- package/apps/storefront/src/lib/tenantRouting.ts +91 -0
- package/apps/storefront/src/lib/tot/ToTClient.ts +177 -0
- package/apps/storefront/src/lib/tot/d1Client.ts +62 -0
- package/apps/storefront/src/lib/tot/query.ts +187 -0
- package/apps/storefront/src/lib/tot/totClientInterface.ts +30 -0
- package/apps/storefront/src/lib/url.ts +119 -0
- package/apps/storefront/src/lib/wishlist.ts +63 -0
- package/apps/storefront/src/middleware/index.ts +413 -0
- package/apps/storefront/src/pages/404.astro +61 -0
- package/apps/storefront/src/pages/[...slug].astro +90 -0
- package/apps/storefront/src/pages/api/auth/logout.ts +21 -0
- package/apps/storefront/src/pages/api/auth/magic-exchange.ts +107 -0
- package/apps/storefront/src/pages/api/auth/send.ts +85 -0
- package/apps/storefront/src/pages/api/auth/verify.ts +135 -0
- package/apps/storefront/src/pages/api/cache-purge.ts +44 -0
- package/apps/storefront/src/pages/api/content-edit/ai-edit.ts +64 -0
- package/apps/storefront/src/pages/api/csp-report.ts +25 -0
- package/apps/storefront/src/pages/api/dashboard/enter-vendor.ts +124 -0
- package/apps/storefront/src/pages/api/dashboard/vendor-search.ts +120 -0
- package/apps/storefront/src/pages/api/dev/cli-signin-code.ts +44 -0
- package/apps/storefront/src/pages/api/newsletter.ts +104 -0
- package/apps/storefront/src/pages/api/request-access.ts +172 -0
- package/apps/storefront/src/pages/auth/login.astro +149 -0
- package/apps/storefront/src/pages/auth/magic.astro +105 -0
- package/apps/storefront/src/pages/capabilities.astro +292 -0
- package/apps/storefront/src/pages/collections/[handle].astro +154 -0
- package/apps/storefront/src/pages/collections/index.astro +59 -0
- package/apps/storefront/src/pages/dashboard/[appDomain]/index.astro +100 -0
- package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +154 -0
- package/apps/storefront/src/pages/dashboard/index.astro +160 -0
- package/apps/storefront/src/pages/dev.astro +653 -0
- package/apps/storefront/src/pages/index.astro +290 -0
- package/apps/storefront/src/pages/llms.txt.ts +92 -0
- package/apps/storefront/src/pages/products/[handle].astro +443 -0
- package/apps/storefront/src/pages/robots.txt.ts +24 -0
- package/apps/storefront/src/pages/saved.astro +35 -0
- package/apps/storefront/src/pages/search.astro +150 -0
- package/apps/storefront/src/pages/sitemap.xml.ts +78 -0
- package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +646 -0
- package/apps/storefront/src/pages/style-guide/[tenant]/index.astro +85 -0
- package/apps/storefront/src/pages/style-guide/index.astro +94 -0
- package/apps/storefront/src/pages/tenants/[id]/[...path].ts +57 -0
- package/apps/storefront/src/styles/global.css +277 -0
- package/apps/storefront/src/themes/reference.ts +61 -0
- package/apps/storefront/src/themes/schema.ts +111 -0
- package/apps/storefront/src/themes/tenants/index.ts +51 -0
- package/apps/storefront/tsconfig.json +16 -0
- package/apps/storefront/vitest.config.ts +22 -0
- package/apps/storefront/wrangler.toml +175 -0
- package/package.json +23 -0
- package/packages/public-runtime/LICENSE +58 -0
- package/packages/public-runtime/package.json +22 -0
- package/packages/public-runtime/src/binary-path.ts +68 -0
- package/packages/public-runtime/src/capabilities.ts +89 -0
- package/packages/public-runtime/src/catalog-api.ts +81 -0
- package/packages/public-runtime/src/catalog-d1.ts +192 -0
- package/packages/public-runtime/src/csp.ts +109 -0
- package/packages/public-runtime/src/customization-preview.ts +197 -0
- package/packages/public-runtime/src/customization-reconcile.ts +63 -0
- package/packages/public-runtime/src/customization-runtime.ts +157 -0
- package/packages/public-runtime/src/customization-scripts.ts +64 -0
- package/packages/public-runtime/src/customization-versioning.ts +95 -0
- package/packages/public-runtime/src/foxy.ts +184 -0
- package/packages/public-runtime/src/index.ts +30 -0
- package/packages/public-runtime/src/product.ts +159 -0
- package/packages/public-runtime/src/search.ts +45 -0
- package/packages/public-runtime/src/tenant-assets.ts +444 -0
- package/packages/public-runtime/src/tenant.ts +243 -0
- package/packages/public-runtime/tsconfig.json +8 -0
- package/packages/public-runtime/vitest.config.ts +8 -0
- package/pnpm-workspace.yaml +7 -0
- package/scripts/build/copy-tenant-assets.mjs +69 -0
- package/scripts/tot-dev.mjs +439 -0
- package/tenants/bigdvapor/content/blog.json +52 -0
- package/tenants/bigdvapor/content/chrome.html +149 -0
- package/tenants/bigdvapor/content/chrome.json +47 -0
- package/tenants/bigdvapor/content/home.html +463 -0
- package/tenants/bigdvapor/content/home.json +73 -0
- package/tenants/bigdvapor/content/pages/about.json +5 -0
- package/tenants/bigdvapor/content/pages/privacy.json +6 -0
- package/tenants/bigdvapor/content/pages/shipping-returns.json +6 -0
- package/tenants/bigdvapor/content/pages-html/blogs/news.html +86 -0
- package/tenants/bigdvapor/content/pages-html/pages/about-us.html +106 -0
- package/tenants/bigdvapor/content/pages-html/pages/contact-us.html +61 -0
- package/tenants/bigdvapor/content/pages-html/pages/privacy-policy.html +72 -0
- package/tenants/bigdvapor/content/pages-html/pages/shipping-returns.html +172 -0
- package/tenants/bigdvapor/content/themes/bigd-navy.json +109 -0
- package/tenants/bigdvapor/public/img/brands/adjust-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/again-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/al-fakher-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/arro-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/cookies-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/core-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/cyclone-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/dinner-lady-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/extre-bar-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/fifty-bar-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/firerose-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/flavor-beast-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/foger-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/kk-energy-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/kumi-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/lost-vape-dispoable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/melo-labs-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/brands/mixo-vape-disposable.webp +0 -0
- package/tenants/bigdvapor/public/img/brands/one-tank-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/oxbar-vape-disposable.webp +0 -0
- package/tenants/bigdvapor/public/img/brands/pillow-talk-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/pod-king-vape-disposable.jpg +0 -0
- package/tenants/bigdvapor/public/img/brands/raz-vape-disposable.png +0 -0
- package/tenants/bigdvapor/public/img/hero-texas.jpg +0 -0
- package/tenants/bigdvapor/public/img/og.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/AdobeStock_202106312_web.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/CREW_web.jpg +0 -0
- package/tenants/bigdvapor/public/img/pages/Hero-Image.jpg +0 -0
- package/tenants/bigdvapor/public/img/tiles/adjust.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/again.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/al-fakher.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/arro.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/cookies.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/core.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/cyclone.png +0 -0
- package/tenants/bigdvapor/public/img/tiles/disposables.svg +23 -0
- package/tenants/bigdvapor/public/logo-wordmark.png +0 -0
- package/tenants/bigdvapor/public/pages/home.css +118 -0
- package/tenants/bigdvapor/public/pages/mkt.css +185 -0
- package/tenants/bigdvapor/public/pages/page.css +148 -0
- package/tenants/bigdvapor/public/themes/bigd-navy.css +73 -0
- package/tenants/bigdvapor/theme.json +12 -0
- package/tenants/giantvapes/content/chrome.html +152 -0
- package/tenants/giantvapes/content/chrome.json +94 -0
- package/tenants/giantvapes/content/home.html +194 -0
- package/tenants/giantvapes/content/home.json +50 -0
- package/tenants/giantvapes/content/pages/about.json +10 -0
- package/tenants/giantvapes/content/pages/privacy.json +6 -0
- package/tenants/giantvapes/content/pages/shipping-returns.json +6 -0
- package/tenants/giantvapes/content/pages-html/blogs/news.html +68 -0
- package/tenants/giantvapes/content/pages-html/pages/about-us.html +95 -0
- package/tenants/giantvapes/content/pages-html/pages/contact-us.html +68 -0
- package/tenants/giantvapes/content/pages-html/pages/privacy-policy.html +65 -0
- package/tenants/giantvapes/content/pages-html/pages/shipping-returns.html +77 -0
- package/tenants/giantvapes/content/themes/giant-navy.json +73 -0
- package/tenants/giantvapes/public/img/hero-suicide-bunny.jpg +0 -0
- package/tenants/giantvapes/public/img/hero.webp +0 -0
- package/tenants/giantvapes/public/img/og.jpg +0 -0
- package/tenants/giantvapes/public/logo-wordmark.png +0 -0
- package/tenants/giantvapes/public/pages/home.css +120 -0
- package/tenants/giantvapes/public/pages/mkt.css +185 -0
- package/tenants/giantvapes/public/pages/page.css +155 -0
- package/tenants/giantvapes/public/themes/giant-navy.css +76 -0
- package/tenants/giantvapes/theme.json +39 -0
- package/tenants/home/content/chrome.json +11 -0
- package/tenants/home/content/home.html +304 -0
- package/tenants/home/content/home.json +13 -0
- package/tenants/home/public/js/storefront.js +210 -0
- package/tenants/home/public/logo-wordmark.png +0 -0
- package/tenants/home/public/pages/storefront.css +212 -0
- package/tenants/home/theme.json +6 -0
- package/tenants/tokenoftrust/.tot/config.json +9 -0
- package/tenants/tokenoftrust/content/chrome.json +55 -0
- package/tenants/tokenoftrust/content/home.html +723 -0
- package/tenants/tokenoftrust/content/home.json +233 -0
- package/tenants/tokenoftrust/content/pages-html/careers.html +231 -0
- package/tenants/tokenoftrust/content/pages-html/company.html +275 -0
- package/tenants/tokenoftrust/content/pages-html/contact/contact-sales.html +188 -0
- package/tenants/tokenoftrust/content/pages-html/contact/startup-apply.html +206 -0
- package/tenants/tokenoftrust/content/pages-html/contact.html +178 -0
- package/tenants/tokenoftrust/content/pages-html/industries/adult-content-age-verification.html +286 -0
- package/tenants/tokenoftrust/content/pages-html/industries/cannabis.html +277 -0
- package/tenants/tokenoftrust/content/pages-html/pact-act-pricing.html +289 -0
- package/tenants/tokenoftrust/content/pages-html/pricing.html +483 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-estimation.html +278 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-gate.html +279 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance/age-verification.html +265 -0
- package/tenants/tokenoftrust/content/pages-html/product/age-assurance.html +173 -0
- package/tenants/tokenoftrust/content/pages-html/product/compliance/aml.html +214 -0
- package/tenants/tokenoftrust/content/pages-html/product/compliance/pact-act.html +226 -0
- package/tenants/tokenoftrust/content/pages-html/product/fraud-prevention.html +254 -0
- package/tenants/tokenoftrust/content/pages-html/product/social-profile-verification.html +212 -0
- package/tenants/tokenoftrust/content/pages-html/product/tax/excise-tax.html +213 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/aml.html +259 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/biometric-selfie.html +305 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/coverage.html +254 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/document-verification.html +306 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/electronic-identity-verification.html +304 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification/government-id-verification.html +308 -0
- package/tenants/tokenoftrust/content/pages-html/product/verification.html +183 -0
- package/tenants/tokenoftrust/content/pages-html/product.html +228 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/bigcommerce-integration.html +220 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/shopify-integration.html +221 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations/wordpress.html +220 -0
- package/tenants/tokenoftrust/content/pages-html/resources/integrations.html +172 -0
- package/tenants/tokenoftrust/content/pages-html/resources/refer-a-friend-program.html +317 -0
- package/tenants/tokenoftrust/content/pages-html/resources.html +177 -0
- package/tenants/tokenoftrust/content/pages-html/reviews.html +273 -0
- package/tenants/tokenoftrust/content/pages-html/solutions.html +292 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-alcohol.html +289 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-cigars-and-tobacco.html +286 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-firearm-accessories.html +267 -0
- package/tenants/tokenoftrust/content/pages-html/vlp-peptides.html +273 -0
- package/tenants/tokenoftrust/content/themes/tot-navy.json +88 -0
- package/tenants/tokenoftrust/public/favicon.png +0 -0
- package/tenants/tokenoftrust/public/logo-icon.png +0 -0
- package/tenants/tokenoftrust/public/logo-wordmark.png +0 -0
- package/tenants/tokenoftrust/public/pages/company.css +108 -0
- package/tenants/tokenoftrust/public/pages/home.css +457 -0
- package/tenants/tokenoftrust/public/pages/mkt.css +482 -0
- package/tenants/tokenoftrust/public/pages/pricing.css +214 -0
- package/tenants/tokenoftrust/public/pages/solutions.css +66 -0
- package/tenants/tokenoftrust/public/themes/tot-navy-1.0.0.css +136 -0
- package/tenants/tokenoftrust/public/themes/tot-navy.css +358 -0
- package/tenants/tokenoftrust/theme.json +31 -0
- package/tsconfig.base.json +20 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant configuration + theme token contract.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 resolves tenants from a static config map/KV by hostname. The lookup
|
|
5
|
+
* interface (resolveTenant) is intentionally async + many-ready so the same seam
|
|
6
|
+
* scales to Cloudflare-for-SaaS custom hostnames later without a rewrite.
|
|
7
|
+
*/
|
|
8
|
+
import type { FoxyCommerceConfig } from "./foxy.js";
|
|
9
|
+
import type { CapabilityConfig } from "./capabilities.js";
|
|
10
|
+
|
|
11
|
+
export interface ThemeColorTokens {
|
|
12
|
+
bg: string;
|
|
13
|
+
surface: string;
|
|
14
|
+
text: string;
|
|
15
|
+
muted: string;
|
|
16
|
+
primary: string;
|
|
17
|
+
"primary-contrast": string;
|
|
18
|
+
accent: string;
|
|
19
|
+
border: string;
|
|
20
|
+
success: string;
|
|
21
|
+
sale: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ThemeFontFamily {
|
|
25
|
+
family: string;
|
|
26
|
+
weights: number[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ThemeTypeTokens {
|
|
30
|
+
display: ThemeFontFamily;
|
|
31
|
+
body: ThemeFontFamily;
|
|
32
|
+
mono?: ThemeFontFamily;
|
|
33
|
+
/** Type scale ratio, e.g. 1.25 (major third). */
|
|
34
|
+
scale: number;
|
|
35
|
+
tracking?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ThemeSpaceTokens {
|
|
39
|
+
/** Base spacing unit in px. */
|
|
40
|
+
base: number;
|
|
41
|
+
/** Multiplier scale, e.g. [0, 0.25, 0.5, 1, 1.5, 2, 3, 4, 6, 8]. */
|
|
42
|
+
scale: number[];
|
|
43
|
+
containerMaxWidth: string;
|
|
44
|
+
sectionRhythm: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ThemeShapeTokens {
|
|
48
|
+
radius: { sm: string; md: string; lg: string; full: string };
|
|
49
|
+
borderWeights: { thin: string; medium: string; thick: string };
|
|
50
|
+
shadow: { sm: string; md: string; lg: string };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ThemeBrandTokens {
|
|
54
|
+
logoLight: string;
|
|
55
|
+
logoDark: string;
|
|
56
|
+
favicon: string;
|
|
57
|
+
ogImage: string;
|
|
58
|
+
/** "full" | "reduced" — tenant-level default motion preference. */
|
|
59
|
+
motion: "full" | "reduced";
|
|
60
|
+
/**
|
|
61
|
+
* Header treatment. "dark" renders the bar in the primary color carrying the
|
|
62
|
+
* light logo (matches brands whose header is dark + white logo, e.g. vape
|
|
63
|
+
* stores); "light" (default) is a light bar with the dark logo/wordmark.
|
|
64
|
+
*/
|
|
65
|
+
headerVariant?: "light" | "dark";
|
|
66
|
+
/**
|
|
67
|
+
* Hero treatment. "bold" (default) paints the hero full-bleed in the primary
|
|
68
|
+
* color (one signature moment). "light" renders the hero on the page
|
|
69
|
+
* background with the brand color used only as an accent on the headline/CTA —
|
|
70
|
+
* matches merchants whose own site is a light page with color accents. The
|
|
71
|
+
* brand adopter sets "light" when it captures a real hero image.
|
|
72
|
+
*/
|
|
73
|
+
heroVariant?: "bold" | "light";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ThemeTokens {
|
|
77
|
+
color: ThemeColorTokens;
|
|
78
|
+
type: ThemeTypeTokens;
|
|
79
|
+
space: ThemeSpaceTokens;
|
|
80
|
+
shape: ThemeShapeTokens;
|
|
81
|
+
brand: ThemeBrandTokens;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Regulated-commerce compliance (e.g. vape/nicotine). Browse-surface only —
|
|
86
|
+
* the actual identity/age VERIFICATION is Token of Trust's product and is wired
|
|
87
|
+
* in a later phase; this config drives storefront affordances (FDA warning, the
|
|
88
|
+
* soft 21+ affirmation gate, shipping-restriction notices). Omit/undefined for
|
|
89
|
+
* unregulated tenants and none of it renders.
|
|
90
|
+
*/
|
|
91
|
+
export interface ComplianceConfig {
|
|
92
|
+
/** Minimum age to enter. Drives the soft affirmation gate (e.g. 21). */
|
|
93
|
+
minAge?: number;
|
|
94
|
+
/** Render the FDA nicotine warning sitewide + reinforced on PDP. */
|
|
95
|
+
nicotineWarning?: boolean;
|
|
96
|
+
/** Short PACT-Act / no-ship-states / adult-signature notice (plain text). */
|
|
97
|
+
shippingRestriction?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* What a tenant's site is FOR. "commerce" (default) is the browse/discover
|
|
102
|
+
* ecommerce storefront the platform was born as. "marketing" is a non-commerce
|
|
103
|
+
* B2B/SaaS site — chrome, rich page composition, and conversion CTAs, with the
|
|
104
|
+
* catalog/cart affordances switched off. The mode picks feature DEFAULTS
|
|
105
|
+
* (see resolveTenantFeatures); `features` overrides individual flags.
|
|
106
|
+
*/
|
|
107
|
+
export type SiteType = "commerce" | "marketing";
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Per-tenant capability switches. These gate whole surfaces so the same
|
|
111
|
+
* component library renders both a store and a marketing site without any
|
|
112
|
+
* tenant-specific `if` in shared code. Every flag has a sensible default keyed
|
|
113
|
+
* off `siteType`; a tenant only lists the ones it wants to flip.
|
|
114
|
+
*/
|
|
115
|
+
export interface TenantFeatures {
|
|
116
|
+
/** Catalog surfaces: /collections, /products/*, listing grids, PDPs. */
|
|
117
|
+
catalog: boolean;
|
|
118
|
+
/** Header search typeahead island. */
|
|
119
|
+
productSearch: boolean;
|
|
120
|
+
/** Wishlist / "saved items" surface + header heart control. */
|
|
121
|
+
savedItems: boolean;
|
|
122
|
+
/** Product quick-view dialog island. */
|
|
123
|
+
quickView: boolean;
|
|
124
|
+
/** Newsletter capture forms (footer + homepage block). */
|
|
125
|
+
newsletter: boolean;
|
|
126
|
+
/** Product/collection URLs in the XML sitemap. */
|
|
127
|
+
commerceSitemap: boolean;
|
|
128
|
+
/** Product-offer JSON-LD on product/collection pages. */
|
|
129
|
+
productJsonLd: boolean;
|
|
130
|
+
/** Soft age-affirmation gate + regulated-commerce chrome (also needs `compliance`). */
|
|
131
|
+
ageGate: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const COMMERCE_FEATURES: TenantFeatures = {
|
|
135
|
+
catalog: true,
|
|
136
|
+
productSearch: true,
|
|
137
|
+
savedItems: true,
|
|
138
|
+
quickView: true,
|
|
139
|
+
newsletter: true,
|
|
140
|
+
commerceSitemap: true,
|
|
141
|
+
productJsonLd: true,
|
|
142
|
+
ageGate: true,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const MARKETING_FEATURES: TenantFeatures = {
|
|
146
|
+
catalog: false,
|
|
147
|
+
productSearch: false,
|
|
148
|
+
savedItems: false,
|
|
149
|
+
quickView: false,
|
|
150
|
+
newsletter: false,
|
|
151
|
+
commerceSitemap: false,
|
|
152
|
+
productJsonLd: false,
|
|
153
|
+
ageGate: false,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** Feature defaults for a site type (returns a fresh copy — safe to mutate). */
|
|
157
|
+
export function siteTypeDefaults(siteType: SiteType): TenantFeatures {
|
|
158
|
+
return { ...(siteType === "marketing" ? MARKETING_FEATURES : COMMERCE_FEATURES) };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Resolve a tenant's effective features: siteType defaults, with any explicit
|
|
163
|
+
* `features` overrides layered on top (undefined entries ignored, so a tenant
|
|
164
|
+
* can flip one flag without restating the rest). Unset `siteType` == "commerce",
|
|
165
|
+
* preserving the platform's original behavior for existing tenants.
|
|
166
|
+
*/
|
|
167
|
+
export function resolveTenantFeatures(
|
|
168
|
+
tenant: Pick<TenantConfig, "siteType" | "features">,
|
|
169
|
+
): TenantFeatures {
|
|
170
|
+
const base = siteTypeDefaults(tenant.siteType ?? "commerce");
|
|
171
|
+
if (!tenant.features) return base;
|
|
172
|
+
for (const [k, v] of Object.entries(tenant.features)) {
|
|
173
|
+
if (v !== undefined) base[k as keyof TenantFeatures] = v;
|
|
174
|
+
}
|
|
175
|
+
return base;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface TenantConfig {
|
|
179
|
+
tenant_id: string;
|
|
180
|
+
/** ToT-side merchant identifier (appDomain), e.g. "pilot.tokenoftrust.com". */
|
|
181
|
+
appDomain: string;
|
|
182
|
+
/** The hostname(s) that resolve to this tenant. */
|
|
183
|
+
domains: string[];
|
|
184
|
+
/** Primary canonical domain for SEO/canonical URLs. */
|
|
185
|
+
canonicalDomain: string;
|
|
186
|
+
displayName: string;
|
|
187
|
+
/** Storyblok delivery token for this tenant's child space. */
|
|
188
|
+
storyblok_space_token: string;
|
|
189
|
+
/** Data scope passed to the ToT catalog API (usually == appDomain). */
|
|
190
|
+
tot_data_scope: string;
|
|
191
|
+
/** Per-tenant theme overrides; merged over the reference theme defaults. */
|
|
192
|
+
theme_tokens: DeepPartial<ThemeTokens>;
|
|
193
|
+
/** Currency for display formatting. */
|
|
194
|
+
currency: string;
|
|
195
|
+
locale: string;
|
|
196
|
+
/**
|
|
197
|
+
* What the site is for: "commerce" (default) or "marketing". Drives feature
|
|
198
|
+
* defaults (resolveTenantFeatures) and non-commerce chrome. Omitted == commerce.
|
|
199
|
+
*/
|
|
200
|
+
siteType?: SiteType;
|
|
201
|
+
/** Explicit feature overrides layered atop the siteType defaults. */
|
|
202
|
+
features?: Partial<TenantFeatures>;
|
|
203
|
+
/** Regulated-commerce affordances; undefined for unregulated tenants. */
|
|
204
|
+
compliance?: ComplianceConfig;
|
|
205
|
+
/**
|
|
206
|
+
* Cart/checkout engine wiring (FoxyCart, Track A). Present on commerce tenants
|
|
207
|
+
* that have a FoxyCart store; drives the loader + signed add-to-cart. The
|
|
208
|
+
* `storeSubDomain` here is a default — middleware may override it from env
|
|
209
|
+
* (FOXY_STORE_SUBDOMAIN) so the demo store swaps with zero code change. The
|
|
210
|
+
* signing SECRET is never stored on the tenant; it's an env Worker binding.
|
|
211
|
+
*/
|
|
212
|
+
commerce?: {
|
|
213
|
+
foxy?: FoxyCommerceConfig;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* PR-gated capability switches (cart/checkout, age/identity verification,
|
|
217
|
+
* excise tax). Source of truth is the tenant repo's `.tot/config.json`; this
|
|
218
|
+
* build-time default is overridden per environment by the published
|
|
219
|
+
* capabilities artifact (localhost=working tree, preview=PR head, live=promoted).
|
|
220
|
+
* Undefined entries default from siteType/compliance — see resolveCapabilities.
|
|
221
|
+
*/
|
|
222
|
+
capabilities?: Partial<CapabilityConfig>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export type DeepPartial<T> = {
|
|
226
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/** The interface the tenant-resolution middleware implements. */
|
|
230
|
+
export interface TenantResolver {
|
|
231
|
+
/**
|
|
232
|
+
* Resolve a tenant for a hostname, falling back to a default tenant for
|
|
233
|
+
* unknown hosts (Phase 1 convenience so preview/local hosts still render).
|
|
234
|
+
*/
|
|
235
|
+
resolveByHost(host: string): Promise<TenantConfig | null>;
|
|
236
|
+
/**
|
|
237
|
+
* Strict match: return the tenant that explicitly claims `host` in its
|
|
238
|
+
* `domains`, or null. Unlike resolveByHost it never falls back to a default,
|
|
239
|
+
* so callers can detect "this host/segment owns no tenant" — used by the
|
|
240
|
+
* `/<domain>/*` path-prefix routing fallback.
|
|
241
|
+
*/
|
|
242
|
+
resolveStrict(host: string): Promise<TenantConfig | null>;
|
|
243
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Prebuild step for the colocated tenant layout.
|
|
4
|
+
*
|
|
5
|
+
* A tenant IS the repo-root directory `tenants/<id>/` (holding content, public,
|
|
6
|
+
* theme.json). Astro serves static assets from `apps/storefront/public/`, so a
|
|
7
|
+
* tenant's public files must land at `apps/storefront/public/tenants/<id>/`
|
|
8
|
+
* for the `/tenants/<id>/...` URLs to resolve. This script mirrors every tenant's
|
|
9
|
+
* public directory into that generated location.
|
|
10
|
+
*
|
|
11
|
+
* The destination (`apps/storefront/public/tenants/`) is a BUILD ARTIFACT
|
|
12
|
+
* (gitignored) — the source of truth is `tenants/<id>/public/`. Wired into the
|
|
13
|
+
* storefront `prebuild`/`predev` lifecycle (package.json) and invoked directly by
|
|
14
|
+
* `scripts/tot-dev.mjs` before it boots `astro dev`.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent: it wipes+rewrites the destination on every run. `TENANT_ASSETS_DEST`
|
|
17
|
+
* overrides the destination (used by tests / spikes).
|
|
18
|
+
*
|
|
19
|
+
* VERSIONED TENANTS (decision `assets-r2-versioned`): a tenant whose assets are
|
|
20
|
+
* served version-scoped from R2 (src/pages/tenants/[id]/[...path].ts) must NOT be
|
|
21
|
+
* baked here — otherwise the static file would shadow the R2 route. Opt a tenant
|
|
22
|
+
* out by adding a `tenants/<id>/.tot/assets-versioned` marker file, or by listing
|
|
23
|
+
* its id in the `TENANT_ASSETS_VERSIONED` env (comma-separated). Non-versioned
|
|
24
|
+
* tenants keep the baked path unchanged (back-compat).
|
|
25
|
+
*/
|
|
26
|
+
import { cp, mkdir, readdir, rm } from "node:fs/promises";
|
|
27
|
+
import { existsSync } from "node:fs";
|
|
28
|
+
import { join, resolve, dirname } from "node:path";
|
|
29
|
+
import { fileURLToPath } from "node:url";
|
|
30
|
+
|
|
31
|
+
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
32
|
+
const src = resolve(repoRoot, "tenants");
|
|
33
|
+
const dest = process.env.TENANT_ASSETS_DEST
|
|
34
|
+
? resolve(process.env.TENANT_ASSETS_DEST)
|
|
35
|
+
: resolve(repoRoot, "apps/storefront/public/tenants");
|
|
36
|
+
|
|
37
|
+
if (!existsSync(src)) process.exit(0);
|
|
38
|
+
|
|
39
|
+
await rm(dest, { recursive: true, force: true });
|
|
40
|
+
|
|
41
|
+
const versionedEnv = new Set(
|
|
42
|
+
(process.env.TENANT_ASSETS_VERSIONED ?? "")
|
|
43
|
+
.split(",")
|
|
44
|
+
.map((s) => s.trim())
|
|
45
|
+
.filter(Boolean),
|
|
46
|
+
);
|
|
47
|
+
const isVersioned = (id) =>
|
|
48
|
+
versionedEnv.has(id) ||
|
|
49
|
+
existsSync(join(src, id, ".tot", "assets-versioned"));
|
|
50
|
+
|
|
51
|
+
let copied = 0;
|
|
52
|
+
let skipped = 0;
|
|
53
|
+
for (const id of await readdir(src)) {
|
|
54
|
+
const pub = join(src, id, "public");
|
|
55
|
+
if (!existsSync(pub)) continue;
|
|
56
|
+
// Versioned tenants are served from R2 — baking would shadow the R2 route.
|
|
57
|
+
if (isVersioned(id)) {
|
|
58
|
+
skipped++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
await mkdir(join(dest, id), { recursive: true });
|
|
62
|
+
await cp(pub, join(dest, id), { recursive: true });
|
|
63
|
+
copied++;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const skipNote = skipped ? ` (skipped ${skipped} versioned → R2)` : "";
|
|
67
|
+
console.log(
|
|
68
|
+
`copy-tenant-assets: mirrored ${copied} tenant public/ tree(s) → ${dest}${skipNote}`,
|
|
69
|
+
);
|