-
-> 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).
-
-## Providers
-
-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 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/))
-- [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/))
-- [Umbraco](https://github.com/umbraco/Umbraco.VercelCommerce.Demo) ([Demo](https://vercel-commerce-demo.umbraco.com/))
-- [Wix](https://github.com/wix/nextjs-commerce) ([Demo](https://wix-nextjs-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).
-
-## Integrations
-
-Integrations enable upgraded or additional functionality for Next.js Commerce
-
-- [Orama](https://github.com/oramasearch/nextjs-commerce) ([Demo](https://vercel-commerce.oramasearch.com/))
- - Upgrades search to include typeahead with dynamic re-rendering, vector-based similarity search, and JS-based configuration.
- - Search runs entirely in the browser for smaller catalogs or on a CDN for larger.
-
## 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.
@@ -55,22 +23,10 @@ You will need to use the environment variables [defined in `.env.example`](.env.
3. Download your environment variables: `vercel env pull`
```bash
-pnpm install
-pnpm dev
+yarn install
+yarn dev
```
+> For `windows users`: A symlink error may occur during the initial installation with `yarn`. To fix this you have to open an administrator console and run `yarn`.
+
Your app should now be running on [localhost:3000](http://localhost:3000/).
-
-
- Expand if you work at Vercel and want to run locally and / or contribute
-
-1. Run `vc link`.
-1. Select the `Vercel Solutions` scope.
-1. Connect to the existing `commerce-shopify` project.
-1. Run `vc env pull` to get environment variables.
-1. Run `pnpm dev` to ensure everything is working correctly.
-
-
-## Vercel, Next.js Commerce, and Shopify Integration Guide
-
-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.
diff --git a/app/[page]/layout.tsx b/app/[page]/layout.tsx
index 453253dca..12fc6ba62 100644
--- a/app/[page]/layout.tsx
+++ b/app/[page]/layout.tsx
@@ -1,5 +1,5 @@
-import Footer from 'components/layout/footer';
-import { Suspense } from 'react';
+import Footer from "components/layout/footer";
+import { Suspense } from "react";
export default function Layout({ children }: { children: React.ReactNode }) {
return (
diff --git a/app/[page]/opengraph-image.tsx b/app/[page]/opengraph-image.tsx
index 2fd59281e..31639796f 100644
--- a/app/[page]/opengraph-image.tsx
+++ b/app/[page]/opengraph-image.tsx
@@ -1,7 +1,7 @@
-import OpengraphImage from 'components/opengraph-image';
-import { getPage } from 'lib/shopify';
+import OpengraphImage from "components/opengraph-image";
+import { getPage } from "lib/shopify";
-export const runtime = 'edge';
+export const runtime = "edge";
export default async function Image({ params }: { params: { page: string } }) {
const page = await getPage(params.page);
diff --git a/app/[page]/page.tsx b/app/[page]/page.tsx
index 3dfde9f92..69c5af037 100644
--- a/app/[page]/page.tsx
+++ b/app/[page]/page.tsx
@@ -1,10 +1,10 @@
-import type { Metadata } from 'next';
+import type { Metadata } from "next";
-import Prose from 'components/prose';
-import { getPage } from 'lib/shopify';
-import { notFound } from 'next/navigation';
+import Prose from "components/prose";
+import { getPage } from "lib/shopify";
+import { notFound } from "next/navigation";
-export const runtime = 'edge';
+export const runtime = "edge";
export const revalidate = 43200; // 12 hours in seconds
@@ -23,7 +23,7 @@ export async function generateMetadata({
openGraph: {
publishedTime: page.createdAt,
modifiedTime: page.updatedAt,
- type: 'article'
+ type: "article"
}
};
}
@@ -39,9 +39,9 @@ export default async function Page({ params }: { params: { page: string } }) {
{`This document was last updated on ${new Intl.DateTimeFormat(undefined, {
- year: 'numeric',
- month: 'long',
- day: 'numeric'
+ year: "numeric",
+ month: "long",
+ day: "numeric"
}).format(new Date(page.updatedAt))}.`}
>
diff --git a/app/api/revalidate/route.ts b/app/api/revalidate/route.ts
index 47af2a4a4..03c3c7ece 100644
--- a/app/api/revalidate/route.ts
+++ b/app/api/revalidate/route.ts
@@ -1,7 +1,7 @@
-import { revalidate } from 'lib/shopify';
-import { NextRequest, NextResponse } from 'next/server';
+import { revalidate } from "lib/shopify";
+import { NextRequest, NextResponse } from "next/server";
-export const runtime = 'edge';
+export const runtime = "edge";
export async function POST(req: NextRequest): Promise {
return revalidate(req);
diff --git a/app/error.tsx b/app/error.tsx
index e0a7416a3..9d3343fef 100644
--- a/app/error.tsx
+++ b/app/error.tsx
@@ -1,4 +1,4 @@
-'use client';
+"use client";
export default function Error({ reset }: { reset: () => void }) {
return (
diff --git a/app/globals.css b/app/globals.css
index 0a6d36768..69bc4a590 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -9,7 +9,7 @@
}
@supports (font: -apple-system-body) and (-webkit-appearance: none) {
- img[loading='lazy'] {
+ img[loading="lazy"] {
clip-path: inset(0.6px);
}
}
diff --git a/app/layout.tsx b/app/layout.tsx
index 58f5a9708..4c70047ea 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,15 +1,15 @@
-import Navbar from 'components/layout/navbar';
-import { GeistSans } from 'geist/font';
-import { ensureStartsWith } from 'lib/utils';
-import { ReactNode, Suspense } from 'react';
-import './globals.css';
+import Navbar from "components/layout/navbar";
+import { GeistSans } from "geist/font";
+import { ensureStartsWith } from "lib/utils";
+import { ReactNode, Suspense } from "react";
+import "./globals.css";
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;
+ : "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),
@@ -24,7 +24,7 @@ export const metadata = {
...(twitterCreator &&
twitterSite && {
twitter: {
- card: 'summary_large_image',
+ card: "summary_large_image",
creator: twitterCreator,
site: twitterSite
}
diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx
index 23762cbdd..6e7878a23 100644
--- a/app/opengraph-image.tsx
+++ b/app/opengraph-image.tsx
@@ -1,6 +1,6 @@
-import OpengraphImage from 'components/opengraph-image';
+import OpengraphImage from "components/opengraph-image";
-export const runtime = 'edge';
+export const runtime = "edge";
export default async function Image() {
return await OpengraphImage();
diff --git a/app/page.tsx b/app/page.tsx
index aefd19396..2ad0a4f71 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,14 +1,14 @@
-import { Carousel } from 'components/carousel';
-import { ThreeItemGrid } from 'components/grid/three-items';
-import Footer from 'components/layout/footer';
-import { Suspense } from 'react';
+import { Carousel } from "components/carousel";
+import { ThreeItemGrid } from "components/grid/three-items";
+import Footer from "components/layout/footer";
+import { Suspense } from "react";
-export const runtime = 'edge';
+export const runtime = "edge";
export const metadata = {
- description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopify.',
+ description: "High-performance ecommerce store built with Next.js, Vercel, and Shopify.",
openGraph: {
- type: 'website'
+ type: "website"
}
};
diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx
index cf31f0021..6c3d4ee91 100644
--- a/app/product/[handle]/page.tsx
+++ b/app/product/[handle]/page.tsx
@@ -1,17 +1,17 @@
-import type { Metadata } from 'next';
-import { notFound } from 'next/navigation';
-import { Suspense } from 'react';
+import type { Metadata } from "next";
+import { notFound } from "next/navigation";
+import { Suspense } from "react";
-import { GridTileImage } from 'components/grid/tile';
-import Footer from 'components/layout/footer';
-import { Gallery } from 'components/product/gallery';
-import { ProductDescription } from 'components/product/product-description';
-import { HIDDEN_PRODUCT_TAG } from 'lib/constants';
-import { getProduct, getProductRecommendations } from 'lib/shopify';
-import { Image } from 'lib/shopify/types';
-import Link from 'next/link';
+import { GridTileImage } from "components/grid/tile";
+import Footer from "components/layout/footer";
+import { Gallery } from "components/product/gallery";
+import { ProductDescription } from "components/product/product-description";
+import { HIDDEN_PRODUCT_TAG } from "lib/constants";
+import { getProduct, getProductRecommendations } from "lib/shopify";
+import { Image } from "lib/shopify/types";
+import Link from "next/link";
-export const runtime = 'edge';
+export const runtime = "edge";
export async function generateMetadata({
params
@@ -57,16 +57,16 @@ export default async function ProductPage({ params }: { params: { handle: string
if (!product) return notFound();
const productJsonLd = {
- '@context': 'https://schema.org',
- '@type': 'Product',
+ "@context": "https://schema.org",
+ "@type": "Product",
name: product.title,
description: product.description,
image: product.featuredImage.url,
offers: {
- '@type': 'AggregateOffer',
+ "@type": "AggregateOffer",
availability: product.availableForSale
- ? 'https://schema.org/InStock'
- : 'https://schema.org/OutOfStock',
+ ? "https://schema.org/InStock"
+ : "https://schema.org/OutOfStock",
priceCurrency: product.priceRange.minVariantPrice.currencyCode,
highPrice: product.priceRange.maxVariantPrice.amount,
lowPrice: product.priceRange.minVariantPrice.amount
diff --git a/app/robots.ts b/app/robots.ts
index c9849a276..0c124008c 100644
--- a/app/robots.ts
+++ b/app/robots.ts
@@ -1,12 +1,12 @@
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
- : 'http://localhost:3000';
+ : "http://localhost:3000";
export default function robots() {
return {
rules: [
{
- userAgent: '*'
+ userAgent: "*"
}
],
sitemap: `${baseUrl}/sitemap.xml`,
diff --git a/app/search/[collection]/opengraph-image.tsx b/app/search/[collection]/opengraph-image.tsx
index 9eb9c47f7..09472dcef 100644
--- a/app/search/[collection]/opengraph-image.tsx
+++ b/app/search/[collection]/opengraph-image.tsx
@@ -1,7 +1,7 @@
-import OpengraphImage from 'components/opengraph-image';
-import { getCollection } from 'lib/shopify';
+import OpengraphImage from "components/opengraph-image";
+import { getCollection } from "lib/shopify";
-export const runtime = 'edge';
+export const runtime = "edge";
export default async function Image({ params }: { params: { collection: string } }) {
const collection = await getCollection(params.collection);
diff --git a/app/search/[collection]/page.tsx b/app/search/[collection]/page.tsx
index 25416d544..1caf3bc58 100644
--- a/app/search/[collection]/page.tsx
+++ b/app/search/[collection]/page.tsx
@@ -1,12 +1,12 @@
-import { getCollection, getCollectionProducts } from 'lib/shopify';
-import { Metadata } from 'next';
-import { notFound } from 'next/navigation';
+import { getCollection, getCollectionProducts } from "lib/shopify";
+import { Metadata } from "next";
+import { notFound } from "next/navigation";
-import Grid from 'components/grid';
-import ProductGridItems from 'components/layout/product-grid-items';
-import { defaultSort, sorting } from 'lib/constants';
+import Grid from "components/grid";
+import ProductGridItems from "components/layout/product-grid-items";
+import { defaultSort, sorting } from "lib/constants";
-export const runtime = 'edge';
+export const runtime = "edge";
export async function generateMetadata({
params
diff --git a/app/search/layout.tsx b/app/search/layout.tsx
index 24d1480d3..4c1915735 100644
--- a/app/search/layout.tsx
+++ b/app/search/layout.tsx
@@ -1,8 +1,8 @@
-import Footer from 'components/layout/footer';
-import Collections from 'components/layout/search/collections';
-import FilterList from 'components/layout/search/filter';
-import { sorting } from 'lib/constants';
-import { Suspense } from 'react';
+import Footer from "components/layout/footer";
+import Collections from "components/layout/search/collections";
+import FilterList from "components/layout/search/filter";
+import { sorting } from "lib/constants";
+import { Suspense } from "react";
export default function SearchLayout({ children }: { children: React.ReactNode }) {
return (
diff --git a/app/search/loading.tsx b/app/search/loading.tsx
index 855c371bc..193e6b459 100644
--- a/app/search/loading.tsx
+++ b/app/search/loading.tsx
@@ -1,4 +1,4 @@
-import Grid from 'components/grid';
+import Grid from "components/grid";
export default function Loading() {
return (
diff --git a/app/search/page.tsx b/app/search/page.tsx
index 2f7a53bd4..1fe8c9628 100644
--- a/app/search/page.tsx
+++ b/app/search/page.tsx
@@ -1,13 +1,13 @@
-import Grid from 'components/grid';
-import ProductGridItems from 'components/layout/product-grid-items';
-import { defaultSort, sorting } from 'lib/constants';
-import { getProducts } from 'lib/shopify';
+import Grid from "components/grid";
+import ProductGridItems from "components/layout/product-grid-items";
+import { defaultSort, sorting } from "lib/constants";
+import { getProducts } from "lib/shopify";
-export const runtime = 'edge';
+export const runtime = "edge";
export const metadata = {
- title: 'Search',
- description: 'Search for products in the store.'
+ title: "Search",
+ description: "Search for products in the store."
};
export default async function SearchPage({
@@ -19,14 +19,14 @@ export default async function SearchPage({
const { sortKey, reverse } = sorting.find((item) => item.slug === sort) || defaultSort;
const products = await getProducts({ sortKey, reverse, query: searchValue });
- const resultsText = products.length > 1 ? 'results' : 'result';
+ const resultsText = products.length > 1 ? "results" : "result";
return (
<>
{searchValue ? (
{products.length === 0
- ? 'There are no products that match '
+ ? "There are no products that match "
: `Showing ${products.length} ${resultsText} for `}
"{searchValue}"
diff --git a/app/sitemap.ts b/app/sitemap.ts
index fe8ed96ac..01ab20b34 100644
--- a/app/sitemap.ts
+++ b/app/sitemap.ts
@@ -1,6 +1,6 @@
-import { getCollections, getPages, getProducts } from 'lib/shopify';
-import { validateEnvironmentVariables } from 'lib/utils';
-import { MetadataRoute } from 'next';
+import { getCollections, getPages, getProducts } from "lib/shopify";
+import { validateEnvironmentVariables } from "lib/utils";
+import { MetadataRoute } from "next";
type Route = {
url: string;
@@ -9,12 +9,12 @@ type Route = {
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
- : 'http://localhost:3000';
+ : "http://localhost:3000";
export default async function sitemap(): Promise {
validateEnvironmentVariables();
- const routesMap = [''].map((route) => ({
+ const routesMap = [""].map((route) => ({
url: `${baseUrl}${route}`,
lastModified: new Date().toISOString()
}));
diff --git a/components/carousel.tsx b/components/carousel.tsx
index 286d4dfea..9dc3d40fe 100644
--- a/components/carousel.tsx
+++ b/components/carousel.tsx
@@ -1,10 +1,10 @@
-import { getCollectionProducts } from 'lib/shopify';
-import Link from 'next/link';
-import { GridTileImage } from './grid/tile';
+import { getCollectionProducts } from "lib/shopify";
+import Link from "next/link";
+import { GridTileImage } from "./grid/tile";
export async function Carousel() {
// Collections that start with `hidden-*` are hidden from the search page.
- const products = await getCollectionProducts({ collection: 'hidden-homepage-carousel' });
+ const products = await getCollectionProducts({ collection: "hidden-homepage-carousel" });
if (!products?.length) return null;
diff --git a/components/cart/actions.ts b/components/cart/actions.ts
index fa2c34d37..187ede5a4 100644
--- a/components/cart/actions.ts
+++ b/components/cart/actions.ts
@@ -1,12 +1,12 @@
-'use server';
+"use server";
-import { TAGS } from 'lib/constants';
-import { addToCart, createCart, getCart, removeFromCart, updateCart } from 'lib/shopify';
-import { revalidateTag } from 'next/cache';
-import { cookies } from 'next/headers';
+import { TAGS } from "lib/constants";
+import { addToCart, createCart, getCart, removeFromCart, updateCart } from "lib/shopify";
+import { revalidateTag } from "next/cache";
+import { cookies } from "next/headers";
export async function addItem(prevState: any, selectedVariantId: string | undefined) {
- let cartId = cookies().get('cartId')?.value;
+ let cartId = cookies().get("cartId")?.value;
let cart;
if (cartId) {
@@ -16,33 +16,33 @@ export async function addItem(prevState: any, selectedVariantId: string | undefi
if (!cartId || !cart) {
cart = await createCart();
cartId = cart.id;
- cookies().set('cartId', cartId);
+ cookies().set("cartId", cartId);
}
if (!selectedVariantId) {
- return 'Missing product variant ID';
+ return "Missing product variant ID";
}
try {
await addToCart(cartId, [{ merchandiseId: selectedVariantId, quantity: 1 }]);
revalidateTag(TAGS.cart);
} catch (e) {
- return 'Error adding item to cart';
+ return "Error adding item to cart";
}
}
export async function removeItem(prevState: any, lineId: string) {
- const cartId = cookies().get('cartId')?.value;
+ const cartId = cookies().get("cartId")?.value;
if (!cartId) {
- return 'Missing cart ID';
+ return "Missing cart ID";
}
try {
await removeFromCart(cartId, [lineId]);
revalidateTag(TAGS.cart);
} catch (e) {
- return 'Error removing item from cart';
+ return "Error removing item from cart";
}
}
@@ -54,10 +54,10 @@ export async function updateItemQuantity(
quantity: number;
}
) {
- const cartId = cookies().get('cartId')?.value;
+ const cartId = cookies().get("cartId")?.value;
if (!cartId) {
- return 'Missing cart ID';
+ return "Missing cart ID";
}
const { lineId, variantId, quantity } = payload;
@@ -78,6 +78,6 @@ export async function updateItemQuantity(
]);
revalidateTag(TAGS.cart);
} catch (e) {
- return 'Error updating item quantity';
+ return "Error updating item quantity";
}
}
diff --git a/components/cart/add-to-cart.tsx b/components/cart/add-to-cart.tsx
index 5e7afbff9..77b5196b3 100644
--- a/components/cart/add-to-cart.tsx
+++ b/components/cart/add-to-cart.tsx
@@ -1,12 +1,12 @@
-'use client';
+"use client";
-import { PlusIcon } from '@heroicons/react/24/outline';
-import clsx from 'clsx';
-import { addItem } from 'components/cart/actions';
-import LoadingDots from 'components/loading-dots';
-import { ProductVariant } from 'lib/shopify/types';
-import { useSearchParams } from 'next/navigation';
-import { useFormState, useFormStatus } from 'react-dom';
+import { PlusIcon } from "@heroicons/react/24/outline";
+import clsx from "clsx";
+import { addItem } from "components/cart/actions";
+import LoadingDots from "components/loading-dots";
+import { ProductVariant } from "lib/shopify/types";
+import { useSearchParams } from "next/navigation";
+import { useFormState, useFormStatus } from "react-dom";
function SubmitButton({
availableForSale,
@@ -17,8 +17,8 @@ function SubmitButton({
}) {
const { pending } = useFormStatus();
const buttonClasses =
- 'relative flex w-full items-center justify-center rounded-full bg-blue-600 p-4 tracking-wide text-white';
- const disabledClasses = 'cursor-not-allowed opacity-60 hover:opacity-60';
+ "relative flex w-full items-center justify-center rounded-full bg-blue-600 p-4 tracking-wide text-white";
+ const disabledClasses = "cursor-not-allowed opacity-60 hover:opacity-60";
if (!availableForSale) {
return (
@@ -51,7 +51,7 @@ function SubmitButton({
aria-label="Add to cart"
aria-disabled={pending}
className={clsx(buttonClasses, {
- 'hover:opacity-90': true,
+ "hover:opacity-90": true,
disabledClasses: pending
})}
>
diff --git a/components/cart/close-cart.tsx b/components/cart/close-cart.tsx
index 515b94843..6e313f37b 100644
--- a/components/cart/close-cart.tsx
+++ b/components/cart/close-cart.tsx
@@ -1,10 +1,10 @@
-import { XMarkIcon } from '@heroicons/react/24/outline';
-import clsx from 'clsx';
+import { XMarkIcon } from "@heroicons/react/24/outline";
+import clsx from "clsx";
export default function CloseCart({ className }: { className?: string }) {
return (
-
+
);
}
diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx
index 814e1f389..451765256 100644
--- a/components/cart/delete-item-button.tsx
+++ b/components/cart/delete-item-button.tsx
@@ -1,11 +1,11 @@
-'use client';
+"use client";
-import { XMarkIcon } from '@heroicons/react/24/outline';
-import clsx from 'clsx';
-import { removeItem } from 'components/cart/actions';
-import LoadingDots from 'components/loading-dots';
-import type { CartItem } from 'lib/shopify/types';
-import { useFormState, useFormStatus } from 'react-dom';
+import { XMarkIcon } from "@heroicons/react/24/outline";
+import clsx from "clsx";
+import { removeItem } from "components/cart/actions";
+import LoadingDots from "components/loading-dots";
+import type { CartItem } from "lib/shopify/types";
+import { useFormState, useFormStatus } from "react-dom";
function SubmitButton() {
const { pending } = useFormStatus();
@@ -19,9 +19,9 @@ function SubmitButton() {
aria-label="Remove cart item"
aria-disabled={pending}
className={clsx(
- 'ease flex h-[17px] w-[17px] items-center justify-center rounded-full bg-neutral-500 transition-all duration-200',
+ "ease flex h-[17px] w-[17px] items-center justify-center rounded-full bg-neutral-500 transition-all duration-200",
{
- 'cursor-not-allowed px-0': pending
+ "cursor-not-allowed px-0": pending
}
)}
>
diff --git a/components/cart/edit-item-quantity-button.tsx b/components/cart/edit-item-quantity-button.tsx
index b743ab704..7828bd330 100644
--- a/components/cart/edit-item-quantity-button.tsx
+++ b/components/cart/edit-item-quantity-button.tsx
@@ -1,13 +1,13 @@
-'use client';
+"use client";
-import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
-import clsx from 'clsx';
-import { updateItemQuantity } from 'components/cart/actions';
-import LoadingDots from 'components/loading-dots';
-import type { CartItem } from 'lib/shopify/types';
-import { useFormState, useFormStatus } from 'react-dom';
+import { MinusIcon, PlusIcon } from "@heroicons/react/24/outline";
+import clsx from "clsx";
+import { updateItemQuantity } from "components/cart/actions";
+import LoadingDots from "components/loading-dots";
+import type { CartItem } from "lib/shopify/types";
+import { useFormState, useFormStatus } from "react-dom";
-function SubmitButton({ type }: { type: 'plus' | 'minus' }) {
+function SubmitButton({ type }: { type: "plus" | "minus" }) {
const { pending } = useFormStatus();
return (
@@ -16,19 +16,19 @@ function SubmitButton({ type }: { type: 'plus' | 'minus' }) {
onClick={(e: React.FormEvent) => {
if (pending) e.preventDefault();
}}
- aria-label={type === 'plus' ? 'Increase item quantity' : 'Reduce item quantity'}
+ aria-label={type === "plus" ? "Increase item quantity" : "Reduce item quantity"}
aria-disabled={pending}
className={clsx(
- 'ease flex h-full min-w-[36px] max-w-[36px] flex-none items-center justify-center rounded-full px-2 transition-all duration-200 hover:border-neutral-800 hover:opacity-80',
+ "ease flex h-full min-w-[36px] max-w-[36px] flex-none items-center justify-center rounded-full px-2 transition-all duration-200 hover:border-neutral-800 hover:opacity-80",
{
- 'cursor-not-allowed': pending,
- 'ml-auto': type === 'minus'
+ "cursor-not-allowed": pending,
+ "ml-auto": type === "minus"
}
)}
>
{pending ? (
- ) : type === 'plus' ? (
+ ) : type === "plus" ? (
) : (
@@ -37,12 +37,12 @@ function SubmitButton({ type }: { type: 'plus' | 'minus' }) {
);
}
-export function EditItemQuantityButton({ item, type }: { item: CartItem; type: 'plus' | 'minus' }) {
+export function EditItemQuantityButton({ item, type }: { item: CartItem; type: "plus" | "minus" }) {
const [message, formAction] = useFormState(updateItemQuantity, null);
const payload = {
lineId: item.id,
variantId: item.merchandise.id,
- quantity: type === 'plus' ? item.quantity + 1 : item.quantity - 1
+ quantity: type === "plus" ? item.quantity + 1 : item.quantity - 1
};
const actionWithVariant = formAction.bind(null, payload);
diff --git a/components/cart/index.tsx b/components/cart/index.tsx
index 3e250ba93..eeb6e983a 100644
--- a/components/cart/index.tsx
+++ b/components/cart/index.tsx
@@ -1,9 +1,9 @@
-import { getCart } from 'lib/shopify';
-import { cookies } from 'next/headers';
-import CartModal from './modal';
+import { getCart } from "lib/shopify";
+import { cookies } from "next/headers";
+import CartModal from "./modal";
export default async function Cart() {
- const cartId = cookies().get('cartId')?.value;
+ const cartId = cookies().get("cartId")?.value;
let cart;
if (cartId) {
diff --git a/components/cart/modal.tsx b/components/cart/modal.tsx
index aee2f7a47..56c600eaa 100644
--- a/components/cart/modal.tsx
+++ b/components/cart/modal.tsx
@@ -1,18 +1,18 @@
-'use client';
+"use client";
-import { Dialog, Transition } from '@headlessui/react';
-import { ShoppingCartIcon } from '@heroicons/react/24/outline';
-import Price from 'components/price';
-import { DEFAULT_OPTION } from 'lib/constants';
-import type { Cart } from 'lib/shopify/types';
-import { createUrl } from 'lib/utils';
-import Image from 'next/image';
-import Link from 'next/link';
-import { Fragment, useEffect, useRef, useState } from 'react';
-import CloseCart from './close-cart';
-import { DeleteItemButton } from './delete-item-button';
-import { EditItemQuantityButton } from './edit-item-quantity-button';
-import OpenCart from './open-cart';
+import { Dialog, Transition } from "@headlessui/react";
+import { ShoppingCartIcon } from "@heroicons/react/24/outline";
+import Price from "components/price";
+import { DEFAULT_OPTION } from "lib/constants";
+import type { Cart } from "lib/shopify/types";
+import { createUrl } from "lib/utils";
+import Image from "next/image";
+import Link from "next/link";
+import { Fragment, useEffect, useRef, useState } from "react";
+import CloseCart from "./close-cart";
+import { DeleteItemButton } from "./delete-item-button";
+import { EditItemQuantityButton } from "./edit-item-quantity-button";
+import OpenCart from "./open-cart";
type MerchandiseSearchParams = {
[key: string]: string;
diff --git a/components/cart/open-cart.tsx b/components/cart/open-cart.tsx
index fa8226ab5..03a1c28c8 100644
--- a/components/cart/open-cart.tsx
+++ b/components/cart/open-cart.tsx
@@ -1,5 +1,5 @@
-import { ShoppingCartIcon } from '@heroicons/react/24/outline';
-import clsx from 'clsx';
+import { ShoppingCartIcon } from "@heroicons/react/24/outline";
+import clsx from "clsx";
export default function OpenCart({
className,
@@ -11,7 +11,7 @@ export default function OpenCart({
return (
);
diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx
index 23b3f8991..06d8e7424 100644
--- a/components/grid/three-items.tsx
+++ b/components/grid/three-items.tsx
@@ -1,7 +1,7 @@
-import { GridTileImage } from 'components/grid/tile';
-import { getCollectionProducts } from 'lib/shopify';
-import type { Product } from 'lib/shopify/types';
-import Link from 'next/link';
+import { GridTileImage } from "components/grid/tile";
+import { getCollectionProducts } from "lib/shopify";
+import type { Product } from "lib/shopify/types";
+import Link from "next/link";
function ThreeItemGridItem({
item,
@@ -9,24 +9,24 @@ function ThreeItemGridItem({
priority
}: {
item: Product;
- size: 'full' | 'half';
+ size: "full" | "half";
priority?: boolean;
}) {
return (
) {
return (
{props.src ? (
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
diff --git a/components/icons/logo.tsx b/components/icons/logo.tsx
index 46fa02464..e190d2c12 100644
--- a/components/icons/logo.tsx
+++ b/components/icons/logo.tsx
@@ -1,13 +1,13 @@
-import clsx from 'clsx';
+import clsx from "clsx";
-export default function LogoIcon(props: React.ComponentProps<'svg'>) {
+export default function LogoIcon(props: React.ComponentProps<"svg">) {
return (