├── .env.example ├── .eslintrc.js ├── .github ├── dependabot.yml └── workflows │ └── test.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .vscode ├── launch.json └── settings.json ├── README.md ├── app ├── [page] │ ├── layout.tsx │ ├── opengraph-image.tsx │ └── page.tsx ├── api │ └── revalidate │ │ └── route.ts ├── error.tsx ├── favicon.ico ├── globals.css ├── layout.tsx ├── opengraph-image.tsx ├── page.tsx ├── product │ └── [handle] │ │ └── page.tsx ├── robots.ts ├── search │ ├── [collection] │ │ ├── opengraph-image.tsx │ │ └── page.tsx │ ├── layout.tsx │ ├── loading.tsx │ └── page.tsx └── sitemap.ts ├── components ├── carousel.tsx ├── cart │ ├── actions.ts │ ├── add-to-cart.tsx │ ├── close-cart.tsx │ ├── delete-item-button.tsx │ ├── edit-item-quantity-button.tsx │ ├── index.tsx │ ├── modal.tsx │ └── open-cart.tsx ├── grid │ ├── index.tsx │ ├── three-items.tsx │ └── tile.tsx ├── icons │ └── logo.tsx ├── label.tsx ├── layout │ ├── footer-menu.tsx │ ├── footer.tsx │ ├── navbar │ │ ├── index.tsx │ │ ├── mobile-menu.tsx │ │ ├── search.tsx │ │ └── useOutsideClick.ts │ ├── product-grid-items.tsx │ └── search │ │ ├── collections.tsx │ │ └── filter │ │ ├── dropdown.tsx │ │ ├── index.tsx │ │ └── item.tsx ├── loading-dots.tsx ├── logo-square.tsx ├── opengraph-image.tsx ├── price.tsx ├── product │ ├── gallery.tsx │ ├── product-description.tsx │ └── variant-selector.tsx └── prose.tsx ├── fonts └── Inter-Bold.ttf ├── lib ├── constants.ts ├── orama │ └── index.ts ├── shopify │ ├── fragments │ │ ├── cart.ts │ │ ├── image.ts │ │ ├── product.ts │ │ └── seo.ts │ ├── index.ts │ ├── mutations │ │ └── cart.ts │ ├── queries │ │ ├── cart.ts │ │ ├── collection.ts │ │ ├── menu.ts │ │ ├── page.ts │ │ └── product.ts │ └── types.ts ├── type-guards.ts └── utils.ts ├── license.md ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── prettier.config.js ├── tailwind.config.js └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | COMPANY_NAME="Vercel Inc." 2 | TWITTER_CREATOR="@vercel" 3 | TWITTER_SITE="https://nextjs.org/commerce" 4 | SITE_NAME="Next.js Commerce" 5 | SHOPIFY_REVALIDATION_SECRET="" 6 | SHOPIFY_STOREFRONT_ACCESS_TOKEN="" 7 | SHOPIFY_STORE_DOMAIN="[your-shopify-store-subdomain].myshopify.com" 8 | NEXT_PUBLIC_ORAMA_API_KEY="" 9 | NEXT_PUBLIC_ORAMA_ENDPOINT="" 10 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['next', 'prettier'], 3 | plugins: ['unicorn'], 4 | rules: { 5 | 'no-unused-vars': [ 6 | 'error', 7 | { 8 | args: 'after-used', 9 | caughtErrors: 'none', 10 | ignoreRestSiblings: true, 11 | vars: 'all' 12 | } 13 | ], 14 | 'prefer-const': 'error', 15 | 'react-hooks/exhaustive-deps': 'error', 16 | 'unicorn/filename-case': [ 17 | 'error', 18 | { 19 | case: 'kebabCase' 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'github-actions' 4 | directory: '/' 5 | schedule: 6 | interval: 'weekly' 7 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: pull_request 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Cancel running workflows 8 | uses: styfle/cancel-workflow-action@0.11.0 9 | with: 10 | access_token: ${{ github.token }} 11 | - name: Checkout repo 12 | uses: actions/checkout@v4 13 | - name: Set node version 14 | uses: actions/setup-node@v3 15 | with: 16 | node-version-file: '.nvmrc' 17 | - name: Set pnpm version 18 | uses: pnpm/action-setup@v2 19 | with: 20 | run_install: false 21 | version: 7 22 | - name: Cache node_modules 23 | id: node-modules-cache 24 | uses: actions/cache@v3 25 | with: 26 | path: '**/node_modules' 27 | key: node-modules-cache-${{ hashFiles('**/pnpm-lock.yaml') }} 28 | - name: Install dependencies 29 | if: steps.node-modules-cache.outputs.cache-hit != 'true' 30 | run: pnpm install 31 | - name: Run tests 32 | run: pnpm test 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | .playwright 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files 30 | .env* 31 | !.env.example 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | next-env.d.ts 39 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | .next 3 | pnpm-lock.yaml 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Next.js: debug server-side", 6 | "type": "node-terminal", 7 | "request": "launch", 8 | "command": "pnpm dev" 9 | }, 10 | { 11 | "name": "Next.js: debug client-side", 12 | "type": "chrome", 13 | "request": "launch", 14 | "url": "http://localhost:3000" 15 | }, 16 | { 17 | "name": "Next.js: debug full stack", 18 | "type": "node-terminal", 19 | "request": "launch", 20 | "command": "pnpm dev", 21 | "serverReadyAction": { 22 | "pattern": "started server on .+, url: (https?://.+)", 23 | "uriFormat": "%s", 24 | "action": "debugWithChrome" 25 | } 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll": true, 6 | "source.organizeImports": true, 7 | "source.sortMembers": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fcommerce&project-name=commerce&repo-name=commerce&demo-title=Next.js%20Commerce&demo-url=https%3A%2F%2Fdemo.vercel.store&demo-image=https%3A%2F%2Fbigcommerce-demo-asset-ksvtgfvnd.vercel.app%2Fbigcommerce.png&env=COMPANY_NAME,SHOPIFY_REVALIDATION_SECRET,SHOPIFY_STORE_DOMAIN,SHOPIFY_STOREFRONT_ACCESS_TOKEN,SITE_NAME,TWITTER_CREATOR,TWITTER_SITE) 2 | 3 | # Next.js Commerce 4 | 5 | A Next.js 13 and App Router-ready ecommerce template featuring: 6 | 7 | - Next.js App Router 8 | - Optimized for SEO using Next.js's Metadata 9 | - React Server Components (RSCs) and Suspense 10 | - Server Actions for mutations 11 | - Edge Runtime 12 | - New fetching and caching paradigms 13 | - Dynamic OG images 14 | - Styling with Tailwind CSS 15 | - Checkout and payments with Shopify 16 | - Automatic light/dark mode based on system settings 17 | 18 |

19 | 20 | > Note: Looking for Next.js Commerce v1? View the [code](https://github.com/vercel/commerce/tree/v1), [demo](https://commerce-v1.vercel.store), and [release notes](https://github.com/vercel/commerce/releases/tag/v1). 21 | 22 | ## Providers 23 | 24 | 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). 25 | 26 | 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. 27 | 28 | - Shopify (this repository) 29 | - [BigCommerce](https://github.com/bigcommerce/nextjs-commerce) ([Demo](https://next-commerce-v2.vercel.app/)) 30 | - [Medusa](https://github.com/medusajs/vercel-commerce) ([Demo](https://medusa-nextjs-commerce.vercel.app/)) 31 | - [Saleor](https://github.com/saleor/nextjs-commerce) ([Demo](https://saleor-commerce.vercel.app/)) 32 | - [Shopware](https://github.com/shopwareLabs/vercel-commerce) ([Demo](https://shopware-vercel-commerce-react.vercel.app/)) 33 | - [Swell](https://github.com/swellstores/verswell-commerce) ([Demo](https://verswell-commerce.vercel.app/)) 34 | - [Umbraco](https://github.com/umbraco/Umbraco.VercelCommerce.Demo) ([Demo](https://vercel-commerce-demo.umbraco.com/)) 35 | - [Wix](https://github.com/wix/nextjs-commerce) ([Demo](https://wix-nextjs-commerce.vercel.app/)) 36 | 37 | > 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). 38 | 39 | ## Integrations 40 | 41 | Integrations enable upgraded or additional functionality for Next.js Commerce 42 | 43 | - [Orama](https://github.com/oramasearch/nextjs-commerce) ([Demo](https://vercel-commerce.oramasearch.com/)) 44 | - Upgrades search to include typeahead with dynamic re-rendering, vector-based similarity search, and JS-based configuration. 45 | - Search runs entirely in the browser for smaller catalogs or on a CDN for larger. 46 | 47 | ## Running locally 48 | 49 | 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. 50 | 51 | > Note: You should not commit your `.env` file or it will expose secrets that will allow others to control your Shopify store. 52 | 53 | 1. Install Vercel CLI: `npm i -g vercel` 54 | 2. Link local instance with Vercel and GitHub accounts (creates `.vercel` directory): `vercel link` 55 | 3. Download your environment variables: `vercel env pull` 56 | 57 | ```bash 58 | pnpm install 59 | pnpm dev 60 | ``` 61 | 62 | Your app should now be running on [localhost:3000](http://localhost:3000/). 63 | 64 |
65 | Expand if you work at Vercel and want to run locally and / or contribute 66 | 67 | 1. Run `vc link`. 68 | 1. Select the `Vercel Solutions` scope. 69 | 1. Connect to the existing `commerce-shopify` project. 70 | 1. Run `vc env pull` to get environment variables. 71 | 1. Run `pmpm dev` to ensure everything is working correctly. 72 |
73 | 74 | ## Vercel, Next.js Commerce, and Shopify Integration Guide 75 | 76 | 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. 77 | -------------------------------------------------------------------------------- /app/[page]/layout.tsx: -------------------------------------------------------------------------------- 1 | import Footer from 'components/layout/footer'; 2 | import { Suspense } from 'react'; 3 | 4 | export default function Layout({ children }: { children: React.ReactNode }) { 5 | return ( 6 | 7 |
8 |
9 | {children} 10 |
11 |
12 |