From c6eb7a30f9a50a9ab1a81b4006b208752551af10 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Tue, 8 Aug 2023 10:00:08 -0500 Subject: [PATCH 01/26] Changes variants to use router replace (#1157) --- components/product/variant-selector.tsx | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/components/product/variant-selector.tsx b/components/product/variant-selector.tsx index 89f2a322c..9d47eb5c8 100644 --- a/components/product/variant-selector.tsx +++ b/components/product/variant-selector.tsx @@ -3,8 +3,7 @@ import clsx from 'clsx'; import { ProductOption, ProductVariant } from 'lib/shopify/types'; import { createUrl } from 'lib/utils'; -import Link from 'next/link'; -import { usePathname, useSearchParams } from 'next/navigation'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; type Combination = { id: string; @@ -19,6 +18,7 @@ export function VariantSelector({ options: ProductOption[]; variants: ProductVariant[]; }) { + const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const hasNoOptionsOrJustOneOption = @@ -76,17 +76,14 @@ export function VariantSelector({ // The option is active if it's in the url params. const isActive = searchParams.get(optionNameLowerCase) === value; - // You can't disable a link, so we need to render something that isn't clickable. - const DynamicTag = isAvailableForSale ? Link : 'p'; - const dynamicProps = { - ...(isAvailableForSale && { scroll: false }) - }; - return ( - { + router.replace(optionUrl, { scroll: false }); + }} title={`${option.name} ${value}${!isAvailableForSale ? ' (Out of Stock)' : ''}`} className={clsx( 'flex min-w-[48px] items-center justify-center rounded-full border bg-neutral-100 px-2 py-1 text-sm dark:border-neutral-800 dark:bg-neutral-900', @@ -98,10 +95,9 @@ export function VariantSelector({ !isAvailableForSale } )} - {...dynamicProps} > {value} - + ); })} From 3f1a4f65aed78f0181f7e7ce1922038ce0c539a0 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Tue, 8 Aug 2023 10:05:38 -0500 Subject: [PATCH 02/26] Fixes product detail spacing (#1158) --- app/product/[handle]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx index d59423364..cf31f0021 100644 --- a/app/product/[handle]/page.tsx +++ b/app/product/[handle]/page.tsx @@ -82,7 +82,7 @@ export default async function ProductPage({ params }: { params: { handle: string }} />
-
+
({ From 857a1df0f65fc3ec2bf21262ed212bae9d64ec9f Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Tue, 8 Aug 2023 10:19:23 -0500 Subject: [PATCH 03/26] Changes product detail gallery thumbnails to always be square (#1160) --- components/product/gallery.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/product/gallery.tsx b/components/product/gallery.tsx index eabc500e3..0b03557a5 100644 --- a/components/product/gallery.tsx +++ b/components/product/gallery.tsx @@ -74,7 +74,7 @@ export function Gallery({ images }: { images: { src: string; altText: string }[] imageSearchParams.set('image', index.toString()); return ( -
  • +
  • Date: Tue, 8 Aug 2023 17:00:43 -0300 Subject: [PATCH 04/26] Fixes footer deploy button on mobile (#1161) --- components/layout/footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index 918345bda..ca568e77f 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -39,7 +39,7 @@ export default async function Footer() {
    From 5f2348d89d7314d05e901b511a18f20384583921 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Tue, 8 Aug 2023 15:55:15 -0500 Subject: [PATCH 05/26] Adds redirect for `/password` (#1162) --- next.config.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/next.config.js b/next.config.js index 7a65540b1..53a8515e2 100644 --- a/next.config.js +++ b/next.config.js @@ -16,5 +16,14 @@ module.exports = { pathname: '/s/files/**' } ] + }, + async redirects() { + return [ + { + source: '/password', + destination: '/', + permanent: true + } + ]; } }; From ec838fd4e62d5d52240b04f3040f3967ba992554 Mon Sep 17 00:00:00 2001 From: Rein van Haaren Date: Tue, 8 Aug 2023 23:12:51 +0200 Subject: [PATCH 06/26] Adds group hover on grid tile image + labels (#1163) --- components/grid/tile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/grid/tile.tsx b/components/grid/tile.tsx index cf9aa49a9..f79a459f4 100644 --- a/components/grid/tile.tsx +++ b/components/grid/tile.tsx @@ -20,7 +20,7 @@ export function GridTileImage({ return (
    From e8c0ee04fce690349116ba929b27f8a1acb858b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Wed, 9 Aug 2023 15:33:15 +0200 Subject: [PATCH 07/26] Adds Shopware provider (#1156) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9f1a06883..26bb48616 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Vercel is more than happy to partner and work with any commerce provider to help - [BigCommerce](https://github.com/bigcommerce/nextjs-commerce) ([Demo](https://next-commerce-v2.vercel.app/)) - [Medusa](https://github.com/medusajs/vercel-commerce) ([Demo](https://medusa-nextjs-commerce.vercel.app/)) - [Saleor](https://github.com/saleor/nextjs-commerce) ([Demo](https://saleor-commerce.vercel.app/)) +- [Shopware](https://github.com/shopwareLabs/vercel-commerce) ([Demo](https://shopware-vercel-commerce-react.vercel.app/)) - [Swell](https://github.com/swellstores/verswell-commerce) ([Demo](https://verswell-commerce.vercel.app/)) ## Running locally From fc92f70c00ae8be70675b5818a5cb23d2b7ec4e2 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 11 Aug 2023 08:54:04 -0500 Subject: [PATCH 08/26] Fixes accessibility issue with home page link (#1171) --- components/layout/navbar/index.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/layout/navbar/index.tsx b/components/layout/navbar/index.tsx index 2683942c9..0058d5ec8 100644 --- a/components/layout/navbar/index.tsx +++ b/components/layout/navbar/index.tsx @@ -19,11 +19,7 @@ export default async function Navbar() {
    - +
    {SITE_NAME} From 528ad9b8ce67f2406c8117ee4e8dc2f1964db9f0 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 11 Aug 2023 20:19:49 -0500 Subject: [PATCH 09/26] Adds better error messages and environment variable fault tolerance (#1172) * Adds better error messages and environment variable fault tolerance * No hidden undefined --- .env.example | 6 +++--- app/layout.tsx | 11 +++++++---- lib/shopify/index.ts | 6 +++++- lib/type-guards.ts | 1 + lib/utils.ts | 3 +++ 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index 75213ad42..9ff0463db 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,6 @@ COMPANY_NAME="Vercel Inc." TWITTER_CREATOR="@vercel" TWITTER_SITE="https://nextjs.org/commerce" SITE_NAME="Next.js Commerce" -SHOPIFY_REVALIDATION_SECRET= -SHOPIFY_STOREFRONT_ACCESS_TOKEN= -SHOPIFY_STORE_DOMAIN= +SHOPIFY_REVALIDATION_SECRET="" +SHOPIFY_STOREFRONT_ACCESS_TOKEN="" +SHOPIFY_STORE_DOMAIN="[your-shopify-store-subdomain].myshopify.com" diff --git a/app/layout.tsx b/app/layout.tsx index 7256fb488..6dc05ea08 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,5 @@ import Navbar from 'components/layout/navbar'; +import { ensureStartsWith } from 'lib/utils'; import { Inter } from 'next/font/google'; import { ReactNode, Suspense } from 'react'; import './globals.css'; @@ -7,6 +8,8 @@ const { TWITTER_CREATOR, TWITTER_SITE, SITE_NAME } = process.env; const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}` : 'http://localhost:3000'; +const twitterCreator = TWITTER_CREATOR ? ensureStartsWith(TWITTER_CREATOR, '@') : undefined; +const twitterSite = TWITTER_SITE ? ensureStartsWith(TWITTER_SITE, 'https://') : undefined; export const metadata = { metadataBase: new URL(baseUrl), @@ -18,12 +21,12 @@ export const metadata = { follow: true, index: true }, - ...(TWITTER_CREATOR && - TWITTER_SITE && { + ...(twitterCreator && + twitterSite && { twitter: { card: 'summary_large_image', - creator: TWITTER_CREATOR, - site: TWITTER_SITE + creator: twitterCreator, + site: twitterSite } }) }; diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts index a8804d045..0b14212d2 100644 --- a/lib/shopify/index.ts +++ b/lib/shopify/index.ts @@ -1,5 +1,6 @@ import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants'; import { isShopifyError } from 'lib/type-guards'; +import { ensureStartsWith } from 'lib/utils'; import { revalidateTag } from 'next/cache'; import { headers } from 'next/headers'; import { NextRequest, NextResponse } from 'next/server'; @@ -49,7 +50,9 @@ import { ShopifyUpdateCartOperation } from './types'; -const domain = `https://${process.env.SHOPIFY_STORE_DOMAIN!}`; +const domain = process.env.SHOPIFY_STORE_DOMAIN + ? ensureStartsWith(process.env.SHOPIFY_STORE_DOMAIN, 'https://') + : ''; const endpoint = `${domain}${SHOPIFY_GRAPHQL_API_ENDPOINT}`; const key = process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN!; @@ -97,6 +100,7 @@ export async function shopifyFetch({ } catch (e) { if (isShopifyError(e)) { throw { + cause: e.cause?.toString() || 'unknown', status: e.status || 500, message: e.message, query diff --git a/lib/type-guards.ts b/lib/type-guards.ts index 1b7e7af5a..6f920d1f6 100644 --- a/lib/type-guards.ts +++ b/lib/type-guards.ts @@ -1,6 +1,7 @@ export interface ShopifyErrorLike { status: number; message: Error; + cause?: Error; } export const isObject = (object: unknown): object is Record => { diff --git a/lib/utils.ts b/lib/utils.ts index 3fa32280b..02ff6fe1b 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -6,3 +6,6 @@ export const createUrl = (pathname: string, params: URLSearchParams | ReadonlyUR return `${pathname}${queryString}`; }; + +export const ensureStartsWith = (stringToCheck: string, startsWith: string) => + stringToCheck.startsWith(startsWith) ? stringToCheck : `${startsWith}${stringToCheck}`; From 6a153b627c746302b94969d74e730dda37f54476 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Mon, 14 Aug 2023 16:14:37 -0500 Subject: [PATCH 10/26] Replaces README configuration guide with Vercel and Shopify integration guide (#1174) --- README.md | 218 +----------------------------------------------------- 1 file changed, 2 insertions(+), 216 deletions(-) diff --git a/README.md b/README.md index 26bb48616..c8f3da272 100644 --- a/README.md +++ b/README.md @@ -59,220 +59,6 @@ Your app should now be running on [localhost:3000](http://localhost:3000/). 1. Run `pmpm dev` to ensure everything is working correctly. -## How to configure your Shopify store for Next.js Commerce +## Vercel, Next.js Commerce, and Shopify Integration Guide -Next.js Commerce requires a [paid Shopify plan](https://www.shopify.com/pricing). - -> Note: Next.js Commerce will not work with a Shopify Starter plan as it does not allow installation of custom themes, which is required to run as a headless storefront. - -### Add Shopify domain to an environment variable - -Create a `SHOPIFY_STORE_DOMAIN` environment variable and use your Shopify domain as the the value (ie. `[your-shopify-store-subdomain].myshopify.com`). - -> Note: Do not include the `https://`. - -### Accessing the Shopify Storefront API - -Next.js Commerce utilizes [Shopify's Storefront API](https://shopify.dev/docs/api/storefront) to create unique customer experiences. The API offers a full range of commerce options making it possible for customers to control products, collections, menus, pages, cart, checkout, and more. - -In order to use the Shopify's Storefront API, you need to install the [Headless app](https://apps.shopify.com/headless) in your Shopify store. - -Once installed, you'll need to create a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable and use the public access token as the value. - -> Note: Shopify does offer a Node.js Storefront API SDK. We use the Storefront API via GraphQL directly instead of the Node.js SDK so we have more control over fetching and caching. - -
    - Expand to view detailed walkthrough - -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/apps`. -1. Click the green `Shopify App Store` button. - ![Shopify App Store](https://user-images.githubusercontent.com/446260/233220545-cb4c1461-ebc5-424e-a421-bf0d32044027.jpg) -1. Search for `Headless` and click on the `Headless` app. - ![Headless](https://user-images.githubusercontent.com/446260/233220547-6d93b5ef-16c7-45db-99e7-13ae7e18eb39.jpg) -1. Click the black `Add app` button. - ![Add app](https://user-images.githubusercontent.com/446260/233220550-a34c8bda-75a8-437a-9673-125f3794ff35.jpg) -1. Click the green `Add sales channel` button. - ![Add sales channel](https://user-images.githubusercontent.com/446260/233220553-42d94a74-421d-4f8a-99ab-a95936b707a3.jpg) -1. Click the green `Create storefront` button. - ![Create storefront](https://user-images.githubusercontent.com/446260/233220556-1eee15c4-a45d-446e-9f73-2e7c9f56b29c.jpg) -1. Copy and paste the public access token and assign it to a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable. - ![Pubic access token](https://user-images.githubusercontent.com/446260/233220558-5db04ff9-b894-40fe-bfba-0e92f26b8e1f.jpg) -1. If you ever need to reference the public access token again, you can navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/headless_storefronts`. -
    - -### Install a headless theme - -When using a headless Shopify setup, you normally don't want customers to access any of the theme pages except for checkout. However, you can't totally disable the theme and a lot of links will still point to the theme (e.g. links in emails, order details, plugins, checkout, etc.). - -To enable a seamless flow between your headless site and Shopify, you can install the [Shopify Headless Theme](https://github.com/instantcommerce/shopify-headless-theme). - -Follow the installation instructions and configure the theme with your headless site's values. - -
    - Expand to view detailed walkthrough - -1. Download [Shopify Headless Theme](https://github.com/instantcommerce/shopify-headless-theme). - ![Download Shoify Headless Theme](https://user-images.githubusercontent.com/446260/233220560-9f3f5ab0-ffb4-4305-b4ee-2c9d33eea90f.jpg) -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`. -1. Click `Add theme`, then `Upload zip file`. - ![Upload zip file](https://user-images.githubusercontent.com/446260/233220561-7a53809e-0d95-45eb-b52f-3a52e3663a9c.jpg) -1. Select the downloaded zip file from above, and click the green `Upload file` button. - ![Select and upload file](https://user-images.githubusercontent.com/446260/233220563-135fb9f7-2921-4189-8f17-3b1cc15c0ea6.jpg) -1. Click `Customize`. - ![Customize theme](https://user-images.githubusercontent.com/446260/233220565-24b9c954-c18a-46f1-9db5-3d2a00040e48.jpg) -1. Click `Theme settings` (ie. the paintbrush icon), expand the `STOREFRONT` section, enter your headless store domain, click the gray `Publish` button. - ![Set headless domain in theme settings](https://user-images.githubusercontent.com/446260/233220566-acaee14d-03f8-400d-a2a2-28e85eb5ecdc.jpg) -1. Confirm the theme change by clicking the green `Save and publish` button. - ![Confirm save and publish](https://user-images.githubusercontent.com/446260/233220567-504d5bde-cfb9-426d-a264-f9a12d02af13.jpg) -1. The headless theme should now be your current active theme. -![Headless theme is current and active](https://user-images.githubusercontent.com/446260/233220569-63cab2b4-241b-4bf1-9b5b-451daaeceb91.jpg) -
    - -### Branding & Design - -Since you're creating a headless Shopify store, you'll be in full control of your brand and design. However, there are still a few aspects we're leaving within Shopify's control. - -- Checkout -- Emails -- Order status -- Order history -- Favicon (for any Shopify controlled pages) - -You can use Shopify's admin to customize these pages to match your brand and design. - -
    - Expand to view detailed walkthrough - -#### Checkout, order status, and order history - -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/checkout`. -1. Click the green `Customize` button. - ![Customize](https://user-images.githubusercontent.com/446260/233220530-9beda4b4-5008-440a-b923-9d196b722539.jpg) -1. Click `Branding` (ie. the paintbrush icon) and customize your brand. Please note, there are three steps / pages to the checkout flow. Use the dropdown to change pages and adjust branding as needed on each page. Click `Save` when you are done. - ![Branding](https://user-images.githubusercontent.com/446260/233220534-e884d9fd-1a39-4f4d-9d09-163dde47c2e8.jpg) -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/branding`. -1. Customize settings to match your brand. - ![Branding](https://user-images.githubusercontent.com/446260/233220536-452b8802-9a1e-40f0-9a12-52b3dace84a5.jpg) - -#### Emails - -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/email_settings`. -1. Customize settings to match your brand. - ![Branding](https://user-images.githubusercontent.com/446260/233220538-13c83a9e-55f8-41e6-9b34-a39ee0848a8a.jpg) - -#### Favicon - -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`. -1. Click the green `Customize` button. - ![Customize theme](https://user-images.githubusercontent.com/446260/233220539-4869a6cd-f59f-4de6-8091-95ed81d2302d.jpg) -1. Click `Theme settings` (ie. the paintbrush icon), expand the `FAVICON` section, upload favicon, then click the `Save` button. - ![Favicon](https://user-images.githubusercontent.com/446260/233220542-ac81b674-d86e-4172-ab38-c79d1ad1ff36.jpg) - -
    - -### Configure webhooks for on-demand incremental static regeneration (ISR) - -Utilizing [Shopify's webhooks](https://shopify.dev/docs/apps/webhooks), and listening for select [Shopify webhook event topics](https://shopify.dev/docs/api/admin-rest/2022-04/resources/webhook#event-topics), we can use [Next'js on-demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#using-on-demand-revalidation) to keep data fetches indefinitely cached until certain events in the Shopify store occur. - -Next.js is pre-configured to listen for the following Shopify webhook events and automatically revalidate fetches. - -- `collections/create` -- `collections/delete` -- `collections/update` -- `products/create` -- `products/delete` -- `products/update` (this also includes when variants are added, updated, and removed as well as when products are purchased so inventory and out of stocks can be updated) - -
    - Expand to view detailed walkthrough - -#### Setup secret for secure revalidation - -1. Create your own secret or [generate a random UUID](https://www.uuidgenerator.net/guid). -1. Create a [Vercel Environment Variable](https://vercel.com/docs/concepts/projects/environment-variables) named `SHOPIFY_REVALIDATION_SECRET` and use the value from above. - -#### Configure Shopify webhooks - -1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/notifications`. -1. Add webhooks for all six event topics listed above. You can add more sets for other preview urls, environments, or local development. Append `?secret=[SECRET]` to each url, where `[SECRET]` is the secret you created above. - ![Shopify store webhooks](https://github.com/vercel/commerce/assets/446260/3d713fd7-b642-46e2-b2ce-f2b695ff6d2b) - ![Shopify store add webhook](https://github.com/vercel/commerce/assets/446260/f0240a22-be07-42bc-bf6c-b97873868677) - -#### Testing webhooks during local development - -The easiest way to test webhooks while developing locally is to use [ngrok](https://ngrok.com). - -1. [Install and configure ngrok](https://ngrok.com/download) (you will need to create an account). -1. Run your app locally, `npm run dev`. -1. In a separate terminal session, run `ngrok http 3000`. -1. Use the url generated by ngrok and add or update your webhook urls in Shopify. - ![ngrok](https://github.com/vercel/commerce/assets/446260/5dc09c5d-0e48-479c-ab64-de8dc9a2c4b1) - ![Shopify store edit webhook](https://github.com/vercel/commerce/assets/446260/13fd397d-4666-4e8d-b25f-4adc674345c0) -1. You can now make changes to your store and your local app should receive updates. You can also use the `Send test notification` button to trigger a generic webhook test. - ![Shopify store webhook send test notification](https://github.com/vercel/commerce/assets/446260/e872e233-1663-446d-961f-8c9455358530) - -
    - -### Using Shopify as a CMS - -Next.js Commerce is fully powered by Shopify in a truly headless and data driven way. - -#### Products - -`https://[your-shopify-store-subdomain].myshopify.com/admin/products` - -Only `Active` products are shown. `Draft` products will not be shown until they are marked as `Active`. - -`Active` products can still be hidden and not seen by navigating the site, by adding a `nextjs-frontend-hidden` tag on the product. This tag will also tell search engines to not index or crawl the product. The product is still directly accessible via url. This feature is great for "secret" products you only want to people you share the url with. - -Product options and option combinations are driven from Shopify options and variants. When selecting options on the product detail page, other option and variant combinations will be visually validated and verified for availability, like Amazon does. - -Products that are active and "out of stock" are still shown on the site, but the ability to add the product to the cart is disabled. - -#### Collections - -`https://[your-shopify-store-subdomain].myshopify.com/admin/collections` - -Create whatever collections you want and configure them however you want. All available collections will show on the search page as filters on the left, with one exception... - -Any collection names that start with the word "hidden" will not show up on the headless front end. The Next.js Commerce theme comes pre-configured to look for two hidden collections. Collections were chosen for this over tags so that order of products could be controlled (collections allow for manual ordering). - -Create the following collections: - -- `Hidden: Homepage Featured Items` -- Products in this collection are displayed in the three featured blocks on the homepage. -- `Hidden: Homepage Carousel` -- Products in this collection are displayed in the auto-scrolling carousel section on the homepage. - -![Shopify collections](https://user-images.githubusercontent.com/446260/233220543-81896a2b-7085-4abc-a4f1-ce321e08b953.jpg) - -![Shopify collection detail](https://user-images.githubusercontent.com/446260/233220544-ecd4c069-49fc-4a0b-8378-aa5e1b4b5257.jpg) - -#### Pages - -`https://[your-shopify-store-subdomain].myshopify.com/admin/pages` - -Next.js Commerce contains a dynamic `[page]` route. It will use the value to look for a corresponding page in Shopify. If a page is found, it will display its rich content using Tailwind's prose. If a page is not found, a 404 page is displayed. - -![Shopify pages](https://user-images.githubusercontent.com/446260/233221142-4dc3fa56-5256-4d84-b0a3-331ffb7d79b2.jpg) - -![Shopify page detail](https://user-images.githubusercontent.com/446260/233247700-cbeaf917-fb67-49e9-b9b9-5ee8cb188639.jpg) - -#### Navigation menus - -`https://[your-shopify-store-subdomain].myshopify.com/admin/menus` - -Next.js Commerce's header and footer navigation is pre-configured to be controlled by Shopify navigation menus. This means you have full control over what links go here. They can be to collections, pages, external links, and more. - -Create the following navigation menus: - -- `Next.js Frontend Header Menu` -- Menu items to be shown in the headless frontend header. -- `Next.js Frontend Footer Menu` -- Menu items to be shown in the headless frontend footer. - -![Shopify navigation menus](https://user-images.githubusercontent.com/446260/233220571-33f9d5a8-1206-4ab4-ad79-83b4ca954331.jpg) - -![Shopify navigation menu detail](https://user-images.githubusercontent.com/446260/233220573-5f03a51f-4100-461f-a696-f085856e391b.jpg) - -#### SEO - -Shopify's products, collections, pages, etc. allow you to create custom SEO titles and descriptions. Next.js Commerce is pre-configured to display these custom values, but also comes with sensible default fallbacks if they are not provided. - -![Shopify SEO](https://user-images.githubusercontent.com/446260/233247701-0ff2a560-7949-4e6c-b3a8-8168ed6341f8.jpg) +You can use this comprehensive [integration guide](http://vercel.com/docs/integrations/shopify) with step-by-step instructions on how to configure Shopify as a headless CMS using Next.js Commerce as your headless Shopify storefront on Vercel. From e9643a546e0e24842e7304acf417db53aa3b5a4e Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Sat, 19 Aug 2023 11:01:10 -0500 Subject: [PATCH 11/26] Adds download link for product assets (#1179) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c8f3da272..a0e5076ad 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ A Next.js 13 and App Router-ready ecommerce template featuring: Vercel will only be actively maintaining a Shopify version [as outlined in our vision and strategy for Next.js Commerce](https://github.com/vercel/commerce/pull/966). -Vercel is more than happy to partner and work with any commerce provider to help them get a similar template up and running and listed below. Alternative providers should be able to fork this repository and swap out the `lib/shopify` file with their own implementation while leaving the rest of the template mostly unchanged. +Vercel is happy to partner and work with any commerce provider to help them get a similar template up and running and listed below. Alternative providers should be able to fork this repository and swap out the `lib/shopify` file with their own implementation while leaving the rest of the template mostly unchanged. - Shopify (this repository) - [BigCommerce](https://github.com/bigcommerce/nextjs-commerce) ([Demo](https://next-commerce-v2.vercel.app/)) @@ -32,6 +32,8 @@ Vercel is more than happy to partner and work with any commerce provider to help - [Shopware](https://github.com/shopwareLabs/vercel-commerce) ([Demo](https://shopware-vercel-commerce-react.vercel.app/)) - [Swell](https://github.com/swellstores/verswell-commerce) ([Demo](https://verswell-commerce.vercel.app/)) +> Note: Providers, if you are looking to use similar products for your demo, you can [download these assets](https://drive.google.com/file/d/1q_bKerjrwZgHwCw0ovfUMW6He9VtepO_/view?usp=sharing). + ## Running locally You will need to use the environment variables [defined in `.env.example`](.env.example) to run Next.js Commerce. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables) for this, but a `.env` file is all that is necessary. From 4993fca3565a11a44bc07d39f1eb7f43c9fa5b89 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Wed, 23 Aug 2023 10:00:31 -0500 Subject: [PATCH 12/26] Fixes squished footer (#1184) --- components/layout/footer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index ca568e77f..8627ca28b 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -16,7 +16,7 @@ export default async function Footer() { return (