@doswiftly/cli 0.1.1
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/README.md +357 -0
- package/bin/doswiftly.js +2 -0
- package/dist/commands/auth-github.d.ts +6 -0
- package/dist/commands/auth-github.d.ts.map +1 -0
- package/dist/commands/auth-github.js +89 -0
- package/dist/commands/auth-github.js.map +1 -0
- package/dist/commands/auth-token.d.ts +12 -0
- package/dist/commands/auth-token.d.ts.map +1 -0
- package/dist/commands/auth-token.js +43 -0
- package/dist/commands/auth-token.js.map +1 -0
- package/dist/commands/auth.d.ts +22 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +348 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check.d.ts +5 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +234 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +104 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/deploy.d.ts +37 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +580 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +8 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +83 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +363 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/domain.d.ts +13 -0
- package/dist/commands/domain.d.ts.map +1 -0
- package/dist/commands/domain.js +128 -0
- package/dist/commands/domain.js.map +1 -0
- package/dist/commands/env.d.ts +25 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +228 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1028 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect.d.ts +12 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +162 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/migrate.d.ts +18 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +355 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/preview.d.ts +29 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +199 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/proxy.d.ts +9 -0
- package/dist/commands/proxy.d.ts.map +1 -0
- package/dist/commands/proxy.js +37 -0
- package/dist/commands/proxy.js.map +1 -0
- package/dist/commands/sdk.d.ts +5 -0
- package/dist/commands/sdk.d.ts.map +1 -0
- package/dist/commands/sdk.js +82 -0
- package/dist/commands/sdk.js.map +1 -0
- package/dist/commands/template.d.ts +107 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/template.js +1309 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/types.d.ts +5 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +82 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +103 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/upgrade.d.ts +18 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +55 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/verify.d.ts +5 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +232 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/whoami.d.ts +5 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +60 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config/types.d.ts +173 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +48 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +416 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-url.d.ts +14 -0
- package/dist/lib/api-url.d.ts.map +1 -0
- package/dist/lib/api-url.js +24 -0
- package/dist/lib/api-url.js.map +1 -0
- package/dist/lib/api.d.ts +67 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +36 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +39 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +195 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/env-storage.d.ts +140 -0
- package/dist/lib/env-storage.d.ts.map +1 -0
- package/dist/lib/env-storage.js +464 -0
- package/dist/lib/env-storage.js.map +1 -0
- package/dist/lib/errors.d.ts +61 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +204 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/i18n.d.ts +99 -0
- package/dist/lib/i18n.d.ts.map +1 -0
- package/dist/lib/i18n.js +184 -0
- package/dist/lib/i18n.js.map +1 -0
- package/dist/lib/logger.d.ts +95 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +168 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/package-manager.d.ts +91 -0
- package/dist/lib/package-manager.d.ts.map +1 -0
- package/dist/lib/package-manager.js +205 -0
- package/dist/lib/package-manager.js.map +1 -0
- package/dist/lib/proxy-server.d.ts +24 -0
- package/dist/lib/proxy-server.d.ts.map +1 -0
- package/dist/lib/proxy-server.js +173 -0
- package/dist/lib/proxy-server.js.map +1 -0
- package/dist/lib/select-with-back.d.ts +34 -0
- package/dist/lib/select-with-back.d.ts.map +1 -0
- package/dist/lib/select-with-back.js +94 -0
- package/dist/lib/select-with-back.js.map +1 -0
- package/dist/lib/shared-api-client.d.ts +40 -0
- package/dist/lib/shared-api-client.d.ts.map +1 -0
- package/dist/lib/shared-api-client.js +92 -0
- package/dist/lib/shared-api-client.js.map +1 -0
- package/dist/lib/wizard-engine.d.ts +128 -0
- package/dist/lib/wizard-engine.d.ts.map +1 -0
- package/dist/lib/wizard-engine.js +168 -0
- package/dist/lib/wizard-engine.js.map +1 -0
- package/package.json +85 -0
- package/templates/storefront-minimal/.env.example +10 -0
- package/templates/storefront-minimal/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-minimal/app/globals.css +18 -0
- package/templates/storefront-minimal/app/layout.tsx +26 -0
- package/templates/storefront-minimal/app/page.tsx +93 -0
- package/templates/storefront-minimal/lib/graphql-client.ts +23 -0
- package/templates/storefront-minimal/next.config.ts +15 -0
- package/templates/storefront-minimal/open-next.config.ts +3 -0
- package/templates/storefront-minimal/package.json +30 -0
- package/templates/storefront-minimal/postcss.config.mjs +5 -0
- package/templates/storefront-minimal/tailwind.config.ts +14 -0
- package/templates/storefront-minimal/tsconfig.json +27 -0
- package/templates/storefront-minimal/wrangler.toml +9 -0
- package/templates/storefront-nextjs/.env.example +68 -0
- package/templates/storefront-nextjs/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-nextjs/.github/workflows/deploy.yml +25 -0
- package/templates/storefront-nextjs/.github/workflows/preview.yml +22 -0
- package/templates/storefront-nextjs/README.md +520 -0
- package/templates/storefront-nextjs/app/account/orders/page.tsx +216 -0
- package/templates/storefront-nextjs/app/account/page.tsx +167 -0
- package/templates/storefront-nextjs/app/auth/login/page.tsx +135 -0
- package/templates/storefront-nextjs/app/auth/register/page.tsx +228 -0
- package/templates/storefront-nextjs/app/cart/page.tsx +263 -0
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +200 -0
- package/templates/storefront-nextjs/app/categories/page.tsx +58 -0
- package/templates/storefront-nextjs/app/checkout/page.tsx +351 -0
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +158 -0
- package/templates/storefront-nextjs/app/collections/page.tsx +61 -0
- package/templates/storefront-nextjs/app/globals.css +98 -0
- package/templates/storefront-nextjs/app/layout.tsx +39 -0
- package/templates/storefront-nextjs/app/page.tsx +136 -0
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +119 -0
- package/templates/storefront-nextjs/app/products/page.tsx +107 -0
- package/templates/storefront-nextjs/app/search/page.tsx +127 -0
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +94 -0
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +77 -0
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +29 -0
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +217 -0
- package/templates/storefront-nextjs/components/commerce/pagination.tsx +62 -0
- package/templates/storefront-nextjs/components/commerce/product-actions.tsx +135 -0
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +109 -0
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +375 -0
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +178 -0
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +64 -0
- package/templates/storefront-nextjs/components/commerce/variant-selector.tsx +210 -0
- package/templates/storefront-nextjs/components/layout/footer.tsx +107 -0
- package/templates/storefront-nextjs/components/layout/header.tsx +104 -0
- package/templates/storefront-nextjs/components/providers.tsx +62 -0
- package/templates/storefront-nextjs/lib/auth/routes.ts +52 -0
- package/templates/storefront-nextjs/lib/currency.tsx +140 -0
- package/templates/storefront-nextjs/lib/format.ts +159 -0
- package/templates/storefront-nextjs/lib/graphql-queries.ts +629 -0
- package/templates/storefront-nextjs/lib/hooks.ts +30 -0
- package/templates/storefront-nextjs/middleware.ts +80 -0
- package/templates/storefront-nextjs/next.config.ts +37 -0
- package/templates/storefront-nextjs/open-next.config.ts +3 -0
- package/templates/storefront-nextjs/package.dev.json +30 -0
- package/templates/storefront-nextjs/package.json +32 -0
- package/templates/storefront-nextjs/package.json.template +32 -0
- package/templates/storefront-nextjs/postcss.config.mjs +8 -0
- package/templates/storefront-nextjs/tailwind.config.ts +111 -0
- package/templates/storefront-nextjs/tsconfig.json +27 -0
- package/templates/storefront-nextjs/wrangler.toml +9 -0
- package/templates/storefront-nextjs-shadcn/.env.example +68 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +25 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +22 -0
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +282 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +96 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +190 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +263 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +135 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +142 -0
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +448 -0
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +307 -0
- package/templates/storefront-nextjs-shadcn/README.md +195 -0
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +245 -0
- package/templates/storefront-nextjs-shadcn/app/about/page.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +215 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +484 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +128 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/tracking/page.tsx +206 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +80 -0
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +195 -0
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +87 -0
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +125 -0
- package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +131 -0
- package/templates/storefront-nextjs-shadcn/app/auth/login/page.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/app/auth/register/page.tsx +20 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +323 -0
- package/templates/storefront-nextjs-shadcn/app/blog/page.tsx +159 -0
- package/templates/storefront-nextjs-shadcn/app/brands/[slug]/page.tsx +170 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +73 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +165 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +78 -0
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +75 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +1752 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/success/[orderId]/page.tsx +256 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +74 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +75 -0
- package/templates/storefront-nextjs-shadcn/app/contact/page.tsx +114 -0
- package/templates/storefront-nextjs-shadcn/app/error.tsx +90 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +125 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +57 -0
- package/templates/storefront-nextjs-shadcn/app/not-found.tsx +68 -0
- package/templates/storefront-nextjs-shadcn/app/page.tsx +21 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +246 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +343 -0
- package/templates/storefront-nextjs-shadcn/app/products/page.tsx +25 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +192 -0
- package/templates/storefront-nextjs-shadcn/app/returns/page.tsx +77 -0
- package/templates/storefront-nextjs-shadcn/app/robots.ts +53 -0
- package/templates/storefront-nextjs-shadcn/app/search/page.tsx +16 -0
- package/templates/storefront-nextjs-shadcn/app/search/search-client.tsx +47 -0
- package/templates/storefront-nextjs-shadcn/app/shipping/page.tsx +62 -0
- package/templates/storefront-nextjs-shadcn/app/sitemap.ts +144 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +179 -0
- package/templates/storefront-nextjs-shadcn/codegen.ts +51 -0
- package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +348 -0
- package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +144 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +258 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +132 -0
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +188 -0
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +305 -0
- package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +240 -0
- package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +177 -0
- package/templates/storefront-nextjs-shadcn/components/blog/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +119 -0
- package/templates/storefront-nextjs-shadcn/components/brand/brand-grid.tsx +64 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +140 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +48 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +112 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/cart/index.ts +17 -0
- package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +121 -0
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +162 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/index.ts +25 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +187 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +160 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +154 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +225 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +62 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +158 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/variant-selector.tsx +210 -0
- package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +97 -0
- package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +187 -0
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +151 -0
- package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +166 -0
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +245 -0
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +246 -0
- package/templates/storefront-nextjs-shadcn/components/discount/index.ts +19 -0
- package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +113 -0
- package/templates/storefront-nextjs-shadcn/components/error/index.ts +7 -0
- package/templates/storefront-nextjs-shadcn/components/filters/attribute-filter.tsx +153 -0
- package/templates/storefront-nextjs-shadcn/components/filters/checkbox-group-filter.tsx +167 -0
- package/templates/storefront-nextjs-shadcn/components/filters/color-swatch-filter.tsx +176 -0
- package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +220 -0
- package/templates/storefront-nextjs-shadcn/components/filters/index.ts +36 -0
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +193 -0
- package/templates/storefront-nextjs-shadcn/components/filters/toggle-filter.tsx +132 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +321 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +309 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/index.ts +24 -0
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +72 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +85 -0
- package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +108 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +133 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +341 -0
- package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +128 -0
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +147 -0
- package/templates/storefront-nextjs-shadcn/components/layout/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +211 -0
- package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +95 -0
- package/templates/storefront-nextjs-shadcn/components/layout/theme-switcher.tsx +192 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/index.ts +11 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +93 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +177 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +250 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +217 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-badge.tsx +106 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +131 -0
- package/templates/storefront-nextjs-shadcn/components/order/delivery-estimate.tsx +196 -0
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +11 -0
- package/templates/storefront-nextjs-shadcn/components/order/order-tracking.tsx +200 -0
- package/templates/storefront-nextjs-shadcn/components/order/shipment-card.tsx +407 -0
- package/templates/storefront-nextjs-shadcn/components/order/tracking-status.tsx +222 -0
- package/templates/storefront-nextjs-shadcn/components/order/tracking-timeline.tsx +205 -0
- package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +161 -0
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +250 -0
- package/templates/storefront-nextjs-shadcn/components/product/discount-badge.tsx +196 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +41 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +147 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +217 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-gallery.tsx +143 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +83 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +155 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +158 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-quantity-selector.tsx +111 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +238 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +58 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +169 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +220 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +338 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-summary.tsx +143 -0
- package/templates/storefront-nextjs-shadcn/components/product/sale-countdown.tsx +166 -0
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +213 -0
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +57 -0
- package/templates/storefront-nextjs-shadcn/components/product/stock-indicator.tsx +91 -0
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +103 -0
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/providers/query-provider.tsx +260 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +13 -0
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +26 -0
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +608 -0
- package/templates/storefront-nextjs-shadcn/components/returns/return-status-card.tsx +554 -0
- package/templates/storefront-nextjs-shadcn/components/search/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +140 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +58 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-suggestions.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/components/seo/index.ts +12 -0
- package/templates/storefront-nextjs-shadcn/components/seo/json-ld.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/components/seo/product-json-ld.ts +167 -0
- package/templates/storefront-nextjs-shadcn/components/shipping/index.ts +16 -0
- package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +337 -0
- package/templates/storefront-nextjs-shadcn/components/ui/accordion.tsx +153 -0
- package/templates/storefront-nextjs-shadcn/components/ui/alert.tsx +59 -0
- package/templates/storefront-nextjs-shadcn/components/ui/badge.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/components/ui/button.tsx +51 -0
- package/templates/storefront-nextjs-shadcn/components/ui/card.tsx +77 -0
- package/templates/storefront-nextjs-shadcn/components/ui/checkbox.tsx +30 -0
- package/templates/storefront-nextjs-shadcn/components/ui/dialog.tsx +137 -0
- package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +207 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +67 -0
- package/templates/storefront-nextjs-shadcn/components/ui/input.tsx +65 -0
- package/templates/storefront-nextjs-shadcn/components/ui/label.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/components/ui/pagination.tsx +205 -0
- package/templates/storefront-nextjs-shadcn/components/ui/radio-group.tsx +44 -0
- package/templates/storefront-nextjs-shadcn/components/ui/select.tsx +160 -0
- package/templates/storefront-nextjs-shadcn/components/ui/separator.tsx +28 -0
- package/templates/storefront-nextjs-shadcn/components/ui/skeleton.tsx +20 -0
- package/templates/storefront-nextjs-shadcn/components/ui/spinner.tsx +82 -0
- package/templates/storefront-nextjs-shadcn/components/ui/tabs.tsx +119 -0
- package/templates/storefront-nextjs-shadcn/components/ui/toast.tsx +96 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +148 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +47 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +165 -0
- package/templates/storefront-nextjs-shadcn/components.json +19 -0
- package/templates/storefront-nextjs-shadcn/generated/.gitkeep +2 -0
- package/templates/storefront-nextjs-shadcn/graphql/.gitkeep +31 -0
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +168 -0
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +160 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +310 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +286 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +110 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.test.ts +173 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.ts +298 -0
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +220 -0
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +57 -0
- package/templates/storefront-nextjs-shadcn/lib/config.ts +46 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +254 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +464 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +328 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +295 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +27 -0
- package/templates/storefront-nextjs-shadcn/lib/format.test.ts +397 -0
- package/templates/storefront-nextjs-shadcn/lib/format.ts +226 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +109 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +1183 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +267 -0
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +30 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +89 -0
- package/templates/storefront-nextjs-shadcn/lib/utils.ts +6 -0
- package/templates/storefront-nextjs-shadcn/next.config.ts +47 -0
- package/templates/storefront-nextjs-shadcn/open-next.config.ts +3 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +30 -0
- package/templates/storefront-nextjs-shadcn/package.json +60 -0
- package/templates/storefront-nextjs-shadcn/package.json.template +46 -0
- package/templates/storefront-nextjs-shadcn/postcss.config.mjs +8 -0
- package/templates/storefront-nextjs-shadcn/proxy.ts +80 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/apple-pay.svg +8 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/bank-transfer.svg +10 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/blik.svg +6 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/cash-on-delivery.svg +11 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/google-pay.svg +11 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/mastercard.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/paypal.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/payu.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/przelewy24.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/stripe.svg +4 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/visa.svg +5 -0
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +66 -0
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +56 -0
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +184 -0
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +103 -0
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +291 -0
- package/templates/storefront-nextjs-shadcn/tailwind.config.ts +111 -0
- package/templates/storefront-nextjs-shadcn/tsconfig.json +27 -0
- package/templates/storefront-nextjs-shadcn/wrangler.toml +9 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# Product Detail Page Implementation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document describes the implementation of the product detail page (Task 21) following the Next.js 15+ App Router architecture with Server Components and Client Components.
|
|
6
|
+
|
|
7
|
+
## Implementation Summary
|
|
8
|
+
|
|
9
|
+
### Files Created/Modified
|
|
10
|
+
|
|
11
|
+
1. **`app/products/[slug]/page.tsx`** - Server Component (MODIFIED)
|
|
12
|
+
- Converted from Client Component to Server Component
|
|
13
|
+
- Added metadata generation for SEO
|
|
14
|
+
- Added structured data (JSON-LD) for search engines
|
|
15
|
+
- Added static params generation for top 100 products
|
|
16
|
+
- Implemented ISR with 60-second revalidation
|
|
17
|
+
|
|
18
|
+
2. **`app/products/[slug]/product-client.tsx`** - Client Component (MODIFIED)
|
|
19
|
+
- Enhanced to handle SSR hydration with currency switching
|
|
20
|
+
- Added logic to refetch product data when user's preferred currency differs from SSR currency
|
|
21
|
+
- Added `suppressHydrationWarning` to prevent hydration mismatches
|
|
22
|
+
- Maintains selected variant across currency changes
|
|
23
|
+
|
|
24
|
+
3. **`app/not-found.tsx`** - 404 Page (CREATED)
|
|
25
|
+
- Created custom 404 page for better error handling
|
|
26
|
+
- Provides helpful navigation back to the site
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
### Server Component Flow
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
1. Build Time (SSG)
|
|
34
|
+
├─ generateStaticParams() fetches top 100 products
|
|
35
|
+
├─ Pre-renders pages for each product handle
|
|
36
|
+
└─ Uses base currency (no X-Preferred-Currency header)
|
|
37
|
+
|
|
38
|
+
2. Request Time
|
|
39
|
+
├─ Server Component fetches product data (base currency)
|
|
40
|
+
├─ Generates metadata (title, description, Open Graph)
|
|
41
|
+
├─ Generates JSON-LD structured data
|
|
42
|
+
└─ Passes initial data to Client Component
|
|
43
|
+
|
|
44
|
+
3. ISR Revalidation
|
|
45
|
+
└─ Pages revalidate every 60 seconds
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Client Component Flow
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
1. Initial Render
|
|
52
|
+
├─ Receives product data from Server Component (base currency)
|
|
53
|
+
├─ Displays product with SSR data
|
|
54
|
+
└─ suppressHydrationWarning prevents mismatch
|
|
55
|
+
|
|
56
|
+
2. Currency Store Initialization
|
|
57
|
+
├─ CurrencyProvider initializes from Shop data
|
|
58
|
+
├─ Checks localStorage for saved currency
|
|
59
|
+
├─ Detects browser locale
|
|
60
|
+
└─ Sets preferred currency
|
|
61
|
+
|
|
62
|
+
3. Currency-Aware Refetch
|
|
63
|
+
├─ Compares preferred currency vs SSR currency
|
|
64
|
+
├─ If different, refetches product with new currency
|
|
65
|
+
├─ Updates prices dynamically
|
|
66
|
+
└─ Maintains selected variant
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Key Features
|
|
70
|
+
|
|
71
|
+
### 1. Metadata Generation (Requirement 13.1, 13.3)
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
export async function generateMetadata({ params }): Promise<Metadata> {
|
|
75
|
+
const data = await fetchProduct(params.slug);
|
|
76
|
+
const product = data?.product;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
title: product.title,
|
|
80
|
+
description: product.description,
|
|
81
|
+
openGraph: {
|
|
82
|
+
title: product.title,
|
|
83
|
+
description: product.description,
|
|
84
|
+
images: [product.images[0]],
|
|
85
|
+
},
|
|
86
|
+
twitter: {
|
|
87
|
+
card: "summary_large_image",
|
|
88
|
+
// ...
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Benefits:**
|
|
95
|
+
- Improved SEO with proper meta tags
|
|
96
|
+
- Better social media sharing with Open Graph
|
|
97
|
+
- Twitter Card support for rich previews
|
|
98
|
+
|
|
99
|
+
### 2. Structured Data (JSON-LD) (Requirement 13.3)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const jsonLd = {
|
|
103
|
+
"@context": "https://schema.org",
|
|
104
|
+
"@type": "Product",
|
|
105
|
+
name: product.title,
|
|
106
|
+
description: product.description,
|
|
107
|
+
image: product.images[0].url,
|
|
108
|
+
brand: { "@type": "Brand", name: product.vendor },
|
|
109
|
+
offers: {
|
|
110
|
+
"@type": "Offer",
|
|
111
|
+
price: product.priceRange.minVariantPrice.amount,
|
|
112
|
+
priceCurrency: product.priceRange.minVariantPrice.currencyCode,
|
|
113
|
+
availability: "https://schema.org/InStock",
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Benefits:**
|
|
119
|
+
- Rich snippets in search results
|
|
120
|
+
- Better product visibility in Google Shopping
|
|
121
|
+
- Improved search engine understanding
|
|
122
|
+
|
|
123
|
+
### 3. Static Params Generation (Requirement 2.2, 6.4)
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
export async function generateStaticParams() {
|
|
127
|
+
const { products } = await fetchProducts({
|
|
128
|
+
first: 100,
|
|
129
|
+
sortKey: "BEST_SELLING",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
return products.map((product) => ({
|
|
133
|
+
slug: product.handle,
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Benefits:**
|
|
139
|
+
- Pre-renders top 100 products at build time
|
|
140
|
+
- Instant page loads for popular products
|
|
141
|
+
- Reduced server load
|
|
142
|
+
- Better Core Web Vitals scores
|
|
143
|
+
|
|
144
|
+
### 4. SSR with Client Hydration (Requirement 2.2, 3.2, 6.4)
|
|
145
|
+
|
|
146
|
+
**Server Component:**
|
|
147
|
+
```typescript
|
|
148
|
+
export default async function ProductPage({ params }) {
|
|
149
|
+
const data = await fetchProduct(params.slug);
|
|
150
|
+
return <ProductClient product={data.product} />;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Client Component:**
|
|
155
|
+
```typescript
|
|
156
|
+
export function ProductClient({ product: initialProduct }) {
|
|
157
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
158
|
+
const needsRefetch = currency !== initialProduct.priceRange.minVariantPrice.currencyCode;
|
|
159
|
+
|
|
160
|
+
const { data } = useProduct(initialProduct.handle, {
|
|
161
|
+
initialData: { product: initialProduct },
|
|
162
|
+
enabled: needsRefetch,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const product = data?.product || initialProduct;
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<div suppressHydrationWarning>
|
|
169
|
+
<ProductPrice price={product.priceRange.minVariantPrice} />
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Benefits:**
|
|
176
|
+
- Fast initial render with SSR
|
|
177
|
+
- Dynamic currency switching without page reload
|
|
178
|
+
- No hydration mismatches
|
|
179
|
+
- Optimal user experience
|
|
180
|
+
|
|
181
|
+
### 5. ISR Configuration
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
export const revalidate = 60;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Benefits:**
|
|
188
|
+
- Pages stay fresh with 60-second revalidation
|
|
189
|
+
- Maintains static generation benefits
|
|
190
|
+
- Automatic updates when products change
|
|
191
|
+
- No manual cache invalidation needed
|
|
192
|
+
|
|
193
|
+
## Requirements Validation
|
|
194
|
+
|
|
195
|
+
✅ **Requirement 2.2**: Server Component renders prices in base currency for SSG
|
|
196
|
+
✅ **Requirement 3.2**: Client Component renders prices in preferred currency
|
|
197
|
+
✅ **Requirement 6.4**: Clear separation between server and client data fetching
|
|
198
|
+
✅ **Requirement 13.1**: Metadata generation with title, description, Open Graph
|
|
199
|
+
✅ **Requirement 13.3**: Structured data (JSON-LD) with Product schema
|
|
200
|
+
|
|
201
|
+
## Testing Recommendations
|
|
202
|
+
|
|
203
|
+
### Manual Testing
|
|
204
|
+
|
|
205
|
+
1. **SSG Verification**
|
|
206
|
+
- Build the project: `npm run build`
|
|
207
|
+
- Check `.next/server/app/products/[slug]` for pre-rendered pages
|
|
208
|
+
- Verify top 100 products are statically generated
|
|
209
|
+
|
|
210
|
+
2. **Metadata Verification**
|
|
211
|
+
- View page source in browser
|
|
212
|
+
- Check `<head>` for meta tags
|
|
213
|
+
- Verify Open Graph tags
|
|
214
|
+
- Test social media sharing
|
|
215
|
+
|
|
216
|
+
3. **Structured Data Verification**
|
|
217
|
+
- View page source
|
|
218
|
+
- Find `<script type="application/ld+json">`
|
|
219
|
+
- Validate with Google's Rich Results Test
|
|
220
|
+
- Check schema.org compliance
|
|
221
|
+
|
|
222
|
+
4. **Currency Switching**
|
|
223
|
+
- Load product page (should show base currency)
|
|
224
|
+
- Change currency in selector
|
|
225
|
+
- Verify prices update without page reload
|
|
226
|
+
- Check no hydration warnings in console
|
|
227
|
+
|
|
228
|
+
5. **ISR Verification**
|
|
229
|
+
- Update product in backend
|
|
230
|
+
- Wait 60 seconds
|
|
231
|
+
- Refresh page
|
|
232
|
+
- Verify changes appear
|
|
233
|
+
|
|
234
|
+
### Automated Testing
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// Example test for metadata generation
|
|
238
|
+
describe('Product Page Metadata', () => {
|
|
239
|
+
it('should generate correct metadata', async () => {
|
|
240
|
+
const metadata = await generateMetadata({ params: { slug: 'test-product' } });
|
|
241
|
+
expect(metadata.title).toBeDefined();
|
|
242
|
+
expect(metadata.description).toBeDefined();
|
|
243
|
+
expect(metadata.openGraph).toBeDefined();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Example test for static params
|
|
248
|
+
describe('Static Params Generation', () => {
|
|
249
|
+
it('should generate params for top products', async () => {
|
|
250
|
+
const params = await generateStaticParams();
|
|
251
|
+
expect(params.length).toBeGreaterThan(0);
|
|
252
|
+
expect(params[0]).toHaveProperty('slug');
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Performance Considerations
|
|
258
|
+
|
|
259
|
+
1. **Static Generation**: Top 100 products are pre-rendered at build time
|
|
260
|
+
2. **ISR**: Pages revalidate every 60 seconds for fresh data
|
|
261
|
+
3. **React Cache**: Server-side requests are deduplicated within a render
|
|
262
|
+
4. **Client-side Caching**: React Query caches product data with currency in key
|
|
263
|
+
5. **Image Optimization**: Next.js Image component handles optimization
|
|
264
|
+
|
|
265
|
+
## Future Enhancements
|
|
266
|
+
|
|
267
|
+
1. **Related Products**: Add similar products section based on tags/category
|
|
268
|
+
2. **Product Reviews**: Integrate review system with structured data
|
|
269
|
+
3. **Variant Images**: Show variant-specific images when variant changes
|
|
270
|
+
4. **Breadcrumbs**: Add dynamic breadcrumbs based on product category
|
|
271
|
+
5. **Share Buttons**: Add social media share buttons
|
|
272
|
+
6. **Recently Viewed**: Track and display recently viewed products
|
|
273
|
+
|
|
274
|
+
## Troubleshooting
|
|
275
|
+
|
|
276
|
+
### Hydration Mismatch Errors
|
|
277
|
+
|
|
278
|
+
**Problem**: Console shows hydration mismatch warnings
|
|
279
|
+
**Solution**: Ensure `suppressHydrationWarning` is on price elements
|
|
280
|
+
|
|
281
|
+
### Currency Not Switching
|
|
282
|
+
|
|
283
|
+
**Problem**: Prices don't update when currency changes
|
|
284
|
+
**Solution**: Check currency store initialization and query key includes currency
|
|
285
|
+
|
|
286
|
+
### 404 Errors
|
|
287
|
+
|
|
288
|
+
**Problem**: Product pages return 404
|
|
289
|
+
**Solution**: Verify product handle matches exactly, check generateStaticParams
|
|
290
|
+
|
|
291
|
+
### Metadata Not Showing
|
|
292
|
+
|
|
293
|
+
**Problem**: Meta tags not appearing in page source
|
|
294
|
+
**Solution**: Ensure generateMetadata is async and returns Metadata object
|
|
295
|
+
|
|
296
|
+
## Conclusion
|
|
297
|
+
|
|
298
|
+
The product detail page implementation follows Next.js 15+ best practices with:
|
|
299
|
+
- Server Components for optimal performance
|
|
300
|
+
- Client Components for interactivity
|
|
301
|
+
- Proper metadata for SEO
|
|
302
|
+
- Structured data for search engines
|
|
303
|
+
- Static generation for popular products
|
|
304
|
+
- ISR for fresh data
|
|
305
|
+
- Currency-aware price display
|
|
306
|
+
|
|
307
|
+
This implementation satisfies all requirements (2.2, 3.2, 6.4, 13.1, 13.3) and provides a solid foundation for a production-ready e-commerce storefront.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# DoSwiftly Storefront - shadcn/ui Template
|
|
2
|
+
|
|
3
|
+
This is a Next.js 15+ storefront template with shadcn/ui components, optimized for DoSwiftly Commerce.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Next.js 15+** with App Router
|
|
8
|
+
- ✅ **shadcn/ui** components pre-configured
|
|
9
|
+
- ✅ **Tailwind CSS v4** for styling
|
|
10
|
+
- ✅ **TypeScript** for type safety
|
|
11
|
+
- ✅ **GraphQL Codegen** for type-safe API calls
|
|
12
|
+
- ✅ **React Query** for data fetching
|
|
13
|
+
- ✅ **Zustand** for state management
|
|
14
|
+
- ✅ **Currency conversion** with client-side switching
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
### 1. Install Dependencies
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Configure Environment
|
|
25
|
+
|
|
26
|
+
Copy `.env.example` to `.env.local` and update:
|
|
27
|
+
|
|
28
|
+
```env
|
|
29
|
+
NEXT_PUBLIC_SHOP_SLUG=your-shop-slug
|
|
30
|
+
NEXT_PUBLIC_API_URL=https://api.doswiftly.pl
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Run GraphQL Codegen
|
|
34
|
+
|
|
35
|
+
Generate TypeScript types from your GraphQL schema:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm run codegen
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 4. Start Development Server
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pnpm run dev
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Open [http://localhost:3000](http://localhost:3000) in your browser.
|
|
48
|
+
|
|
49
|
+
## Adding shadcn/ui Components
|
|
50
|
+
|
|
51
|
+
This template is pre-configured with shadcn/ui. Add components using the shadcn CLI:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Add a button component
|
|
55
|
+
npx shadcn@latest add button
|
|
56
|
+
|
|
57
|
+
# Add a dialog component
|
|
58
|
+
npx shadcn@latest add dialog
|
|
59
|
+
|
|
60
|
+
# Add a dropdown menu
|
|
61
|
+
npx shadcn@latest add dropdown-menu
|
|
62
|
+
|
|
63
|
+
# See all available components
|
|
64
|
+
npx shadcn@latest add
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Components will be added to `components/ui/` directory.
|
|
68
|
+
|
|
69
|
+
## Project Structure
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
├── app/ # Next.js App Router pages
|
|
73
|
+
│ ├── layout.tsx # Root layout with providers
|
|
74
|
+
│ └── page.tsx # Homepage
|
|
75
|
+
├── components/
|
|
76
|
+
│ ├── ui/ # shadcn/ui components (auto-generated)
|
|
77
|
+
│ ├── layout/ # Layout components (Header, Footer)
|
|
78
|
+
│ └── providers/ # React providers (Query, Currency)
|
|
79
|
+
├── lib/
|
|
80
|
+
│ ├── graphql/
|
|
81
|
+
│ │ ├── server.ts # Server-side GraphQL client
|
|
82
|
+
│ │ ├── client.ts # Client-side GraphQL client
|
|
83
|
+
│ │ └── hooks.ts # React Query hooks
|
|
84
|
+
│ └── utils.ts # Utility functions (cn helper)
|
|
85
|
+
├── stores/
|
|
86
|
+
│ └── currency-store.ts # Zustand currency store
|
|
87
|
+
├── generated/
|
|
88
|
+
│ └── graphql.ts # Auto-generated GraphQL types
|
|
89
|
+
├── doswiftly.config.ts # DoSwiftly configuration
|
|
90
|
+
├── components.json # shadcn/ui configuration
|
|
91
|
+
└── codegen.ts # GraphQL Codegen configuration
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## GraphQL Codegen
|
|
95
|
+
|
|
96
|
+
This template uses GraphQL Codegen to generate TypeScript types from your GraphQL schema.
|
|
97
|
+
|
|
98
|
+
### Configuration
|
|
99
|
+
|
|
100
|
+
See `codegen.ts` for configuration. It reads:
|
|
101
|
+
- **Schema**: From your DoSwiftly API
|
|
102
|
+
- **Operations**: From `@doswiftly/storefront-operations` package
|
|
103
|
+
- **Custom queries**: From `src/graphql/**/*.{ts,tsx}`
|
|
104
|
+
|
|
105
|
+
### Running Codegen
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Generate types
|
|
109
|
+
pnpm run codegen
|
|
110
|
+
|
|
111
|
+
# Watch mode (auto-regenerate on changes)
|
|
112
|
+
pnpm run codegen:watch
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Currency Management
|
|
116
|
+
|
|
117
|
+
This template includes built-in currency conversion:
|
|
118
|
+
|
|
119
|
+
1. **Server Components**: Render prices in base currency (SSG-compatible)
|
|
120
|
+
2. **Client Components**: Switch to user's preferred currency dynamically
|
|
121
|
+
3. **Currency Store**: Persists user preference in localStorage
|
|
122
|
+
|
|
123
|
+
### Usage
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
// Server Component
|
|
127
|
+
import { fetchProduct } from '@/lib/graphql/server';
|
|
128
|
+
|
|
129
|
+
export default async function ProductPage({ params }) {
|
|
130
|
+
const { product } = await fetchProduct(params.handle);
|
|
131
|
+
// Prices in base currency
|
|
132
|
+
return <div>{product.priceRange.minVariantPrice.amount}</div>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Client Component
|
|
136
|
+
'use client';
|
|
137
|
+
import { useProduct } from '@/lib/graphql/hooks';
|
|
138
|
+
import { useCurrencyStore } from '@/stores/currency-store';
|
|
139
|
+
|
|
140
|
+
export function ProductPrice({ handle }) {
|
|
141
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
142
|
+
const { data } = useProduct(handle);
|
|
143
|
+
// Prices in user's preferred currency
|
|
144
|
+
return <div>{data.product.priceRange.minVariantPrice.amount} {currency}</div>;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Styling
|
|
149
|
+
|
|
150
|
+
This template uses Tailwind CSS v4 with shadcn/ui.
|
|
151
|
+
|
|
152
|
+
### Customizing Theme
|
|
153
|
+
|
|
154
|
+
Edit `app/globals.css` to customize colors:
|
|
155
|
+
|
|
156
|
+
```css
|
|
157
|
+
@layer base {
|
|
158
|
+
:root {
|
|
159
|
+
--background: 0 0% 100%;
|
|
160
|
+
--foreground: 222.2 84% 4.9%;
|
|
161
|
+
/* ... more variables */
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Using cn() Helper
|
|
167
|
+
|
|
168
|
+
The `cn()` helper combines Tailwind classes with proper precedence:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { cn } from '@/lib/utils';
|
|
172
|
+
|
|
173
|
+
<div className={cn('text-base', isActive && 'text-primary')} />
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Building for Production
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Build
|
|
180
|
+
pnpm run build
|
|
181
|
+
|
|
182
|
+
# Start production server
|
|
183
|
+
pnpm run start
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Learn More
|
|
187
|
+
|
|
188
|
+
- [DoSwiftly Documentation](https://docs.doswiftly.pl)
|
|
189
|
+
- [shadcn/ui Documentation](https://ui.shadcn.com)
|
|
190
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
191
|
+
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
UNLICENSED - Internal DoSwiftly template
|