diff --git a/.yarn/cache/@headlessui-react-npm-1.7.16-039d64d731-85844c96c7.zip b/.yarn/cache/@headlessui-react-npm-1.7.16-039d64d731-85844c96c7.zip
deleted file mode 100644
index e727fb718..000000000
Binary files a/.yarn/cache/@headlessui-react-npm-1.7.16-039d64d731-85844c96c7.zip and /dev/null differ
diff --git a/.yarn/cache/@headlessui-react-npm-1.7.17-c3f120aed0-0cdb67747e.zip b/.yarn/cache/@headlessui-react-npm-1.7.17-c3f120aed0-0cdb67747e.zip
new file mode 100644
index 000000000..a38510bfa
Binary files /dev/null and b/.yarn/cache/@headlessui-react-npm-1.7.17-c3f120aed0-0cdb67747e.zip differ
diff --git a/app/[locale]/about/layout.tsx b/app/[locale]/about/layout.tsx
index 16fd7989e..790272de1 100644
--- a/app/[locale]/about/layout.tsx
+++ b/app/[locale]/about/layout.tsx
@@ -1,5 +1,3 @@
-import { Suspense } from 'react';
-
export default function Layout({ children }: { children: React.ReactNode }) {
- return {children};
+ return <>{children}>;
}
diff --git a/app/[locale]/about/page.tsx b/app/[locale]/about/page.tsx
index 1fcfbe8b1..46cd14681 100644
--- a/app/[locale]/about/page.tsx
+++ b/app/[locale]/about/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getPage, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import AboutNaraiDetail from './about-narai-detail';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -43,9 +39,7 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
-
-
-
+
);
}
diff --git a/app/[locale]/add-to-cart-ppr.tsx b/app/[locale]/add-to-cart-ppr.tsx
new file mode 100644
index 000000000..b342336f4
--- /dev/null
+++ b/app/[locale]/add-to-cart-ppr.tsx
@@ -0,0 +1,93 @@
+'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 React from 'react';
+import { useFormState, useFormStatus } from 'react-dom';
+
+function SubmitButton({
+ availableForSale,
+ selectedVariantId
+}: {
+ availableForSale: boolean;
+ selectedVariantId: string | undefined;
+}) {
+ 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';
+
+ if (!availableForSale) {
+ return (
+
+ );
+ }
+
+ if (!selectedVariantId) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
+
+export function AddToCart({
+ variants,
+ availableForSale
+}: {
+ variants: ProductVariant[];
+ availableForSale: boolean;
+}) {
+ const [message, formAction] = useFormState(addItem, null);
+ const searchParams = useSearchParams();
+ const defaultVariantId = variants.length === 1 ? variants[0]?.id : undefined;
+ const variant = variants.find((variant: ProductVariant) =>
+ variant.selectedOptions.every(
+ (option) => option.value === searchParams.get(option.name.toLowerCase())
+ )
+ );
+ const selectedVariantId = variant?.id || defaultVariantId;
+ const actionWithVariant = formAction.bind(null, selectedVariantId);
+
+ return (
+
+ );
+}
diff --git a/app/[locale]/bar/layout.tsx b/app/[locale]/bar/layout.tsx
index 16fd7989e..790272de1 100644
--- a/app/[locale]/bar/layout.tsx
+++ b/app/[locale]/bar/layout.tsx
@@ -1,5 +1,3 @@
-import { Suspense } from 'react';
-
export default function Layout({ children }: { children: React.ReactNode }) {
- return {children};
+ return <>{children}>;
}
diff --git a/app/[locale]/bar/page.tsx b/app/[locale]/bar/page.tsx
index c5f496db0..24101dcb7 100644
--- a/app/[locale]/bar/page.tsx
+++ b/app/[locale]/bar/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import SagyobarDetail from './sagyobar-detail';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -41,9 +37,7 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
-
-
-
+
);
}
diff --git a/app/[locale]/company/layout.tsx b/app/[locale]/company/layout.tsx
index 16fd7989e..790272de1 100644
--- a/app/[locale]/company/layout.tsx
+++ b/app/[locale]/company/layout.tsx
@@ -1,5 +1,3 @@
-import { Suspense } from 'react';
-
export default function Layout({ children }: { children: React.ReactNode }) {
- return {children};
+ return <>{children}>;
}
diff --git a/app/[locale]/company/page.tsx b/app/[locale]/company/page.tsx
index fe6ca923c..d5a19255c 100644
--- a/app/[locale]/company/page.tsx
+++ b/app/[locale]/company/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import CompanyDetail from './company-detail';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -41,9 +37,7 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
-
-
-
+
);
}
diff --git a/app/[locale]/concept/layout.tsx b/app/[locale]/concept/layout.tsx
index 16fd7989e..790272de1 100644
--- a/app/[locale]/concept/layout.tsx
+++ b/app/[locale]/concept/layout.tsx
@@ -1,5 +1,3 @@
-import { Suspense } from 'react';
-
export default function Layout({ children }: { children: React.ReactNode }) {
- return {children};
+ return <>{children}>;
}
diff --git a/app/[locale]/concept/page.tsx b/app/[locale]/concept/page.tsx
index ea6fc481e..534ab26fd 100644
--- a/app/[locale]/concept/page.tsx
+++ b/app/[locale]/concept/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import ConceptDetail from './concept-detail';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -41,9 +37,7 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
-
-
-
+
);
}
diff --git a/app/[locale]/disclosures/page.tsx b/app/[locale]/disclosures/page.tsx
index 8654d2192..6719cdcd5 100644
--- a/app/[locale]/disclosures/page.tsx
+++ b/app/[locale]/disclosures/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import Disclosures from './disclosures';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -45,9 +41,7 @@ export default async function DisclosuresPage({
-
-
-
+
);
}
diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx
deleted file mode 100644
index 43ccc6d15..000000000
--- a/app/[locale]/layout.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import { Lato, Noto_Serif_JP } from 'next/font/google';
-import localFont from 'next/font/local';
-import { ReactNode, Suspense } from 'react';
-
-import { SupportedLocale } from 'components/layout/navbar/language-control';
-import { NextIntlClientProvider } from 'next-intl';
-import { notFound } from 'next/navigation';
-import Analytics from './analytics';
-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';
-
-export const metadata = {
- metadataBase: new URL(baseUrl),
- title: {
- default: SITE_NAME!,
- template: `%s | ${SITE_NAME}`
- },
- robots: {
- follow: true,
- index: true
- },
- ...(TWITTER_CREATOR &&
- TWITTER_SITE && {
- twitter: {
- card: 'summary_large_image',
- creator: TWITTER_CREATOR,
- site: TWITTER_SITE
- }
- })
-};
-
-// Font files can be colocated inside of `app`
-const cinzel = localFont({
- src: '../fonts/Cinzel-Regular.ttf',
- display: 'swap',
- variable: '--font-cinzel'
-});
-
-const alpina = localFont({
- src: [
- {
- path: '../fonts/GT-Alpina-Regular-Trial.woff2',
- weight: '400',
- style: 'normal'
- },
- {
- path: '../fonts/GT-Alpina-Bold-Trial.woff2',
- weight: '700',
- style: 'normal'
- }
- ],
- variable: '--font-alpina'
-});
-
-const lato = Lato({
- subsets: ['latin'],
- display: 'swap',
- weight: ['300'],
- variable: '--font-lato'
-});
-
-const noto = Noto_Serif_JP({
- subsets: ['latin'],
- display: 'swap',
- weight: ['200', '400', '600'],
- variable: '--font-noto'
-});
-
-export function generateStaticParams() {
- return [{ locale: 'ja' }, { locale: 'en' }];
-}
-
-export default async function RootLayout({
- children,
- params
-}: {
- children: ReactNode;
- params: { locale?: SupportedLocale };
-}) {
- let messages;
- try {
- messages = (await import(`../../messages/${params?.locale}.json`)).default;
- } catch (error) {
- notFound();
- }
-
- return (
-
-
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/app/[locale]/opengraph-image.tsx b/app/[locale]/opengraph-image.tsx
index 434a936b8..23762cbdd 100644
--- a/app/[locale]/opengraph-image.tsx
+++ b/app/[locale]/opengraph-image.tsx
@@ -1,7 +1,6 @@
import OpengraphImage from 'components/opengraph-image';
export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
export default async function Image() {
return await OpengraphImage();
diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx
index d351d6034..bc06f68f9 100644
--- a/app/[locale]/page.tsx
+++ b/app/[locale]/page.tsx
@@ -24,10 +24,6 @@ import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import Image from 'next/image';
-import { Suspense } from 'react';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
const { SITE_NAME } = process.env;
@@ -152,9 +148,7 @@ export default async function HomePage({
/>
-
-
-
+
);
}
diff --git a/app/[locale]/privacy/page.tsx b/app/[locale]/privacy/page.tsx
index c63355d2e..a45f3c815 100644
--- a/app/[locale]/privacy/page.tsx
+++ b/app/[locale]/privacy/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import PrivacyPolicy from './privacy-policy';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -45,9 +41,7 @@ export default async function PrivacyPage({
-
-
-
+
);
}
diff --git a/app/[locale]/product/[handle]/layout.tsx b/app/[locale]/product/[handle]/layout.tsx
index 9d1928993..f561435f3 100644
--- a/app/[locale]/product/[handle]/layout.tsx
+++ b/app/[locale]/product/[handle]/layout.tsx
@@ -4,10 +4,7 @@ import { SupportedLocale } from 'components/layout/navbar/language-control';
import Navbar from 'components/layout/navbar';
import { getCart } from 'lib/shopify';
import { cookies } from 'next/headers';
-import { ReactNode, Suspense } from 'react';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
+import { ReactNode } from 'react';
const { SITE_NAME } = process.env;
@@ -37,9 +34,7 @@ export default async function ProductLayout({
{children}
-
-
-
+
);
}
diff --git a/app/[locale]/product/[handle]/page.tsx b/app/[locale]/product/[handle]/page.tsx
index 01b6330bb..d14214840 100644
--- a/app/[locale]/product/[handle]/page.tsx
+++ b/app/[locale]/product/[handle]/page.tsx
@@ -1,6 +1,5 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
-import { Suspense } from 'react';
import { ChevronDoubleRightIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx';
@@ -17,9 +16,7 @@ import { getProduct, getProductRecommendations } from 'lib/shopify';
import { Image as MediaImage, Product } from 'lib/shopify/types';
import Image from 'next/image';
import Link from 'next/link';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
+import { Suspense } from 'react';
export async function generateMetadata({
params
@@ -136,13 +133,17 @@ export default async function ProductPage({
@@ -165,30 +166,32 @@ export default async function ProductPage({
)}
- {!!otherImages &&
- otherImages?.length > 0 &&
- otherImages.map((image, index) => {
- const isOdd = otherImages.length % 2 != 0;
- const isLast = index === otherImages.length - 1;
- const isOddAndLast = isOdd && isLast;
- return (
-
-
-
- );
- })}
+
+ {!!otherImages &&
+ otherImages?.length > 0 &&
+ otherImages.map((image, index) => {
+ const isOdd = otherImages.length % 2 != 0;
+ const isLast = index === otherImages.length - 1;
+ const isOddAndLast = isOdd && isLast;
+ return (
+
+
+
+ );
+ })}
+
{!!product?.lower?.value && (
@@ -197,9 +200,7 @@ export default async function ProductPage({
)}
-
-
-
+
>
diff --git a/app/[locale]/products/page.tsx b/app/[locale]/products/page.tsx
index 3993cfa35..44fff7efd 100644
--- a/app/[locale]/products/page.tsx
+++ b/app/[locale]/products/page.tsx
@@ -6,10 +6,6 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
const { SITE_NAME } = process.env;
@@ -45,9 +41,7 @@ export default async function ProductPage({
-
-
-
+
);
}
diff --git a/app/[locale]/shop-list/layout.tsx b/app/[locale]/shop-list/layout.tsx
index 8ec725c55..790272de1 100644
--- a/app/[locale]/shop-list/layout.tsx
+++ b/app/[locale]/shop-list/layout.tsx
@@ -1,7 +1,3 @@
-import { Suspense } from 'react';
-
-export const revalidate = 300; // 5 minutes in seconds
-
export default function Layout({ children }: { children: React.ReactNode }) {
- return {children};
+ return <>{children}>;
}
diff --git a/app/[locale]/shop-list/opengraph-image.tsx b/app/[locale]/shop-list/opengraph-image.tsx
index df924a4a3..e1723449e 100644
--- a/app/[locale]/shop-list/opengraph-image.tsx
+++ b/app/[locale]/shop-list/opengraph-image.tsx
@@ -1,9 +1,6 @@
import OpengraphImage from 'components/opengraph-image';
import { getPage } from 'lib/shopify';
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
-
export default async function Image({ params }: { params: { page: string } }) {
const page = await getPage({ handle: params.page });
const title = page.seo?.title || page.title;
diff --git a/app/[locale]/shop-list/page.tsx b/app/[locale]/shop-list/page.tsx
index 8ef045f72..445f70dc3 100644
--- a/app/[locale]/shop-list/page.tsx
+++ b/app/[locale]/shop-list/page.tsx
@@ -8,11 +8,8 @@ import { getCart, getPage, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
import { notFound } from 'next/navigation';
-import { Suspense } from 'react';
import ShopsNav from './shops-nav';
-export const revalidate = 300; // 5 minutes in seconds
-
export async function generateMetadata({
params
}: {
@@ -61,9 +58,7 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
-
-
-
+
);
}
diff --git a/app/[locale]/stories/[handle]/layout.tsx b/app/[locale]/stories/[handle]/layout.tsx
index 747ed671a..cc23b3e4e 100644
--- a/app/[locale]/stories/[handle]/layout.tsx
+++ b/app/[locale]/stories/[handle]/layout.tsx
@@ -5,10 +5,7 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { ReactNode, Suspense } from 'react';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
+import { ReactNode } from 'react';
const { SITE_NAME } = process.env;
@@ -43,9 +40,7 @@ export default async function BlogLayout({
{children}
-
-
-
+
);
}
diff --git a/app/[locale]/stories/[handle]/page.tsx b/app/[locale]/stories/[handle]/page.tsx
index 0dc20e721..1c89d5fea 100644
--- a/app/[locale]/stories/[handle]/page.tsx
+++ b/app/[locale]/stories/[handle]/page.tsx
@@ -8,9 +8,6 @@ import { getBlogArticle } from 'lib/shopify';
import { BlogArticle } from 'lib/shopify/types';
import Image from 'next/image';
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
-
export async function generateMetadata({
params
}: {
diff --git a/app/[locale]/stories/page.tsx b/app/[locale]/stories/page.tsx
index 316d20c0a..172de199f 100644
--- a/app/[locale]/stories/page.tsx
+++ b/app/[locale]/stories/page.tsx
@@ -7,10 +7,6 @@ import { BLOG_HANDLE } from 'lib/constants';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
const { SITE_NAME } = process.env;
@@ -46,9 +42,7 @@ export default async function StoriesPage({
-
-
-
+
);
}
diff --git a/app/[locale]/terms/page.tsx b/app/[locale]/terms/page.tsx
index fcd3b8647..a339f88be 100644
--- a/app/[locale]/terms/page.tsx
+++ b/app/[locale]/terms/page.tsx
@@ -5,12 +5,8 @@ import Navbar from 'components/layout/navbar';
import { getCart, getProduct } from 'lib/shopify';
import { Product } from 'lib/shopify/types';
import { cookies } from 'next/headers';
-import { Suspense } from 'react';
import TermsOfUse from './terms-of-use';
-export const runtime = 'edge';
-export const revalidate = 43200; // 12 hours in seconds
-
const { SITE_NAME } = process.env;
export const metadata = {
@@ -45,9 +41,7 @@ export default async function TermsPage({
-
-
-
+
);
}
diff --git a/app/layout.tsx b/app/layout.tsx
index 1e17f31d3..f89f061dc 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,15 +1,17 @@
-import Navbar from 'components/layout/navbar';
-import { GeistSans } from 'geist/font/sans';
-import { ensureStartsWith } from 'lib/utils';
+import { Lato, Noto_Serif_JP } from 'next/font/google';
+import localFont from 'next/font/local';
import { ReactNode } from 'react';
+
+import { SupportedLocale } from 'components/layout/navbar/language-control';
+import { NextIntlClientProvider } from 'next-intl';
+import { notFound } from 'next/navigation';
+import Analytics from './[locale]/analytics';
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;
export const metadata = {
metadataBase: new URL(baseUrl),
@@ -21,22 +23,81 @@ export const metadata = {
follow: true,
index: true
},
- ...(twitterCreator &&
- twitterSite && {
+ ...(TWITTER_CREATOR &&
+ TWITTER_SITE && {
twitter: {
card: 'summary_large_image',
- creator: twitterCreator,
- site: twitterSite
+ creator: TWITTER_CREATOR,
+ site: TWITTER_SITE
}
})
};
-export default async function RootLayout({ children }: { children: ReactNode }) {
+// Font files can be colocated inside of `app`
+const cinzel = localFont({
+ src: '../fonts/Cinzel-Regular.ttf',
+ display: 'swap',
+ variable: '--font-cinzel'
+});
+
+const alpina = localFont({
+ src: [
+ {
+ path: '../fonts/GT-Alpina-Regular-Trial.woff2',
+ weight: '400',
+ style: 'normal'
+ },
+ {
+ path: '../fonts/GT-Alpina-Bold-Trial.woff2',
+ weight: '700',
+ style: 'normal'
+ }
+ ],
+ variable: '--font-alpina'
+});
+
+const lato = Lato({
+ subsets: ['latin'],
+ display: 'swap',
+ weight: ['300'],
+ variable: '--font-lato'
+});
+
+const noto = Noto_Serif_JP({
+ subsets: ['latin'],
+ display: 'swap',
+ weight: ['200', '400', '600'],
+ variable: '--font-noto'
+});
+
+export function generateStaticParams() {
+ return [{ locale: 'ja' }, { locale: 'en' }];
+}
+
+export default async function RootLayout({
+ children,
+ params
+}: {
+ children: ReactNode;
+ params: { locale?: SupportedLocale };
+}) {
+ let messages;
+ try {
+ messages = (await import(`../../messages/${params?.locale}.json`)).default;
+ } catch (error) {
+ notFound();
+ }
+
return (
-
-
-
- {children}
+
+
+
+
+ {children}
+
);
diff --git a/app/page.tsx b/app/page.tsx
deleted file mode 100644
index 0fad0ac28..000000000
--- a/app/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Carousel } from 'components/carousel';
-import { ThreeItemGrid } from 'components/grid/three-items';
-import Footer from 'components/layout/footer';
-
-export const metadata = {
- description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopify.',
- openGraph: {
- type: 'website'
- }
-};
-
-export default async function HomePage() {
- return (
- <>
-
-
-
- >
- );
-}
diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx
deleted file mode 100644
index c7b759841..000000000
--- a/app/product/[handle]/page.tsx
+++ /dev/null
@@ -1,138 +0,0 @@
-import type { Metadata } from 'next';
-import { notFound } from 'next/navigation';
-
-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 { Suspense } from 'react';
-
-export async function generateMetadata({
- params
-}: {
- params: { handle: string };
-}): Promise {
- const product = await getProduct(params.handle);
-
- if (!product) return notFound();
-
- const { url, width, height, altText: alt } = product.featuredImage || {};
- const indexable = !product.tags.includes(HIDDEN_PRODUCT_TAG);
-
- return {
- title: product.seo.title || product.title,
- description: product.seo.description || product.description,
- robots: {
- index: indexable,
- follow: indexable,
- googleBot: {
- index: indexable,
- follow: indexable
- }
- },
- openGraph: url
- ? {
- images: [
- {
- url,
- width,
- height,
- alt
- }
- ]
- }
- : null
- };
-}
-
-export default async function ProductPage({ params }: { params: { handle: string } }) {
- const product = await getProduct(params.handle);
-
- if (!product) return notFound();
-
- const productJsonLd = {
- '@context': 'https://schema.org',
- '@type': 'Product',
- name: product.title,
- description: product.description,
- image: product.featuredImage.url,
- offers: {
- '@type': 'AggregateOffer',
- availability: product.availableForSale
- ? 'https://schema.org/InStock'
- : 'https://schema.org/OutOfStock',
- priceCurrency: product.priceRange.minVariantPrice.currencyCode,
- highPrice: product.priceRange.maxVariantPrice.amount,
- lowPrice: product.priceRange.minVariantPrice.amount
- }
- };
-
- return (
- <>
-
-
-
-
-
- ({
- src: image.url,
- altText: image.altText
- }))}
- />
-
-
-
-
-
-
-
-
- >
- );
-}
-
-async function RelatedProducts({ id }: { id: string }) {
- const relatedProducts = await getProductRecommendations(id);
-
- if (!relatedProducts.length) return null;
-
- return (
-
-
Related Products
-
- {relatedProducts.map((product) => (
- -
-
-
-
-
- ))}
-
-
- );
-}
diff --git a/components/grid/homepage-products.tsx b/components/grid/homepage-products.tsx
index f3c518d18..1e1d2e6c1 100644
--- a/components/grid/homepage-products.tsx
+++ b/components/grid/homepage-products.tsx
@@ -8,9 +8,6 @@ import Link from 'next/link';
import Label from '../label';
import { GridTileImage } from './tile';
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
-
function HomepageProductsItem({ item, priority }: { item: Product; priority?: boolean }) {
const size = item?.variants?.[0]?.selectedOptions?.find((option) => option.name === 'Size');
const image = item?.variants?.[0]?.image;
diff --git a/components/layout/menu/modal.tsx b/components/layout/menu/modal.tsx
index ed5550cbe..a13d60860 100644
--- a/components/layout/menu/modal.tsx
+++ b/components/layout/menu/modal.tsx
@@ -7,7 +7,7 @@ import Logo from 'components/icons/logo';
import MenuIcon from 'components/icons/menu';
import { useLocale, useTranslations } from 'next-intl';
import Link from 'next/link';
-import { Fragment, useRef, useState } from 'react';
+import { Fragment, Suspense, useRef, useState } from 'react';
import { LanguageControl, SupportedLocale } from '../navbar/language-control';
export function MenuModal({ scrolled }: { scrolled: boolean }) {
@@ -72,55 +72,56 @@ export function MenuModal({ scrolled }: { scrolled: boolean }) {
-
-
-
diff --git a/components/layout/navbar/index.tsx b/components/layout/navbar/index.tsx
index fcb39c24b..772808c9a 100644
--- a/components/layout/navbar/index.tsx
+++ b/components/layout/navbar/index.tsx
@@ -7,6 +7,7 @@ import CartModal from 'components/cart/modal';
import LogoNamemark from 'components/icons/namemark';
import { Cart, Product } from 'lib/shopify/types';
import Link from 'next/link';
+import { Suspense } from 'react';
import { useInView } from 'react-intersection-observer';
import { MenuModal } from '../menu/modal';
import { LanguageControl, SupportedLocale } from './language-control';
@@ -84,13 +85,15 @@ export default function Navbar({
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/deprecated/[page]/layout.tsx b/deprecated/[page]/layout.tsx
deleted file mode 100644
index 50614b5b1..000000000
--- a/deprecated/[page]/layout.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Footer from 'components/layout/footer';
-
-export default function Layout({ children }: { children: React.ReactNode }) {
- return (
- <>
-
-
- >
- );
-}
diff --git a/deprecated/[page]/opengraph-image.tsx b/deprecated/[page]/opengraph-image.tsx
deleted file mode 100644
index df924a4a3..000000000
--- a/deprecated/[page]/opengraph-image.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import OpengraphImage from 'components/opengraph-image';
-import { getPage } from 'lib/shopify';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
-
-export default async function Image({ params }: { params: { page: string } }) {
- const page = await getPage({ handle: params.page });
- const title = page.seo?.title || page.title;
-
- return await OpengraphImage({ title });
-}
diff --git a/deprecated/[page]/page.tsx b/deprecated/[page]/page.tsx
deleted file mode 100644
index 46804a6ff..000000000
--- a/deprecated/[page]/page.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { Metadata } from 'next';
-
-import { SupportedLocale } from 'components/layout/navbar/language-control';
-import Prose from 'components/prose';
-import { getPage } from 'lib/shopify';
-import { notFound } from 'next/navigation';
-
-export async function generateMetadata({
- params
-}: {
- params: { page: string; locale?: SupportedLocale };
-}): Promise {
- const page = await getPage({ handle: params.page, language: params?.locale?.toUpperCase() });
-
- if (!page) return notFound();
-
- return {
- title: page.seo?.title || page.title,
- description: page.seo?.description || page.bodySummary,
- openGraph: {
- publishedTime: page.createdAt,
- modifiedTime: page.updatedAt,
- type: 'article'
- }
- };
-}
-
-export default async function Page({
- params
-}: {
- params: { page: string; locale?: SupportedLocale };
-}) {
- const page = await getPage({ handle: params.page, language: params?.locale?.toUpperCase() });
-
- if (!page) return notFound();
-
- return (
-
-
{page.title}
-
-
- {`This document was last updated on ${new Intl.DateTimeFormat(undefined, {
- year: 'numeric',
- month: 'long',
- day: 'numeric'
- }).format(new Date(page.updatedAt))}.`}
-
-
- );
-}
diff --git a/deprecated/search/[collection]/opengraph-image.tsx b/deprecated/search/[collection]/opengraph-image.tsx
deleted file mode 100644
index bdeb12cc8..000000000
--- a/deprecated/search/[collection]/opengraph-image.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import OpengraphImage from 'components/opengraph-image';
-import { getCollection } from 'lib/shopify';
-
-export const runtime = 'edge';
-export const revalidate = 300; // 5 minutes in seconds
-
-export default async function Image({ params }: { params: { collection: string } }) {
- const collection = await getCollection({ handle: params.collection });
- const title = collection?.seo?.title || collection?.title;
-
- return await OpengraphImage({ title });
-}
diff --git a/deprecated/search/[collection]/page.tsx b/deprecated/search/[collection]/page.tsx
deleted file mode 100644
index f1f133f6b..000000000
--- a/deprecated/search/[collection]/page.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-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';
-
-export async function generateMetadata({
- params
-}: {
- params: { collection: string };
-}): Promise {
- const collection = await getCollection({ handle: params.collection });
-
- if (!collection) return notFound();
-
- return {
- title: collection.seo?.title || collection.title,
- description:
- collection.seo?.description || collection.description || `${collection.title} products`
- };
-}
-
-export default async function CategoryPage({
- params,
- searchParams
-}: {
- params: { collection: string };
- searchParams?: { [key: string]: string | string[] | undefined };
-}) {
- const { sort } = searchParams as { [key: string]: string };
- const { sortKey, reverse } = sorting.find((item) => item.slug === sort) || defaultSort;
- const products = await getCollectionProducts({ collection: params.collection, sortKey, reverse });
-
- return (
-
- {products.length === 0 ? (
- {`No products found in this collection`}
- ) : (
-
-
-
- )}
-
- );
-}
diff --git a/deprecated/search/layout.tsx b/deprecated/search/layout.tsx
deleted file mode 100644
index 53f9c28b5..000000000
--- a/deprecated/search/layout.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-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';
-
-export default function SearchLayout({ children }: { children: React.ReactNode }) {
- return (
- <>
-
-
-
-
-
{children}
-
-
-
-
-
- >
- );
-}
diff --git a/deprecated/search/loading.tsx b/deprecated/search/loading.tsx
deleted file mode 100644
index 855c371bc..000000000
--- a/deprecated/search/loading.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import Grid from 'components/grid';
-
-export default function Loading() {
- return (
-
- {Array(12)
- .fill(0)
- .map((_, index) => {
- return (
-
- );
- })}
-
- );
-}
diff --git a/deprecated/search/page.tsx b/deprecated/search/page.tsx
deleted file mode 100644
index 60f11b189..000000000
--- a/deprecated/search/page.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-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 metadata = {
- title: 'Search',
- description: 'Search for products in the store.'
-};
-
-export default async function SearchPage({
- searchParams
-}: {
- searchParams?: { [key: string]: string | string[] | undefined };
-}) {
- const { sort, q: searchValue } = searchParams as { [key: string]: string };
- 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';
-
- return (
- <>
- {searchValue ? (
-
- {products.length === 0
- ? 'There are no products that match '
- : `Showing ${products.length} ${resultsText} for `}
- "{searchValue}"
-
- ) : null}
- {products.length > 0 ? (
-
-
-
- ) : null}
- >
- );
-}
diff --git a/deprecated/sitemap.ts b/deprecated/sitemap.ts
deleted file mode 100644
index 523413b22..000000000
--- a/deprecated/sitemap.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { getCollections, getPages, getProducts } from 'lib/shopify';
-import { validateEnvironmentVariables } from 'lib/utils';
-import { MetadataRoute } from 'next';
-
-type Route = {
- url: string;
- lastModified: string;
-};
-
-const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
- ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
- : 'http://localhost:3000';
-
-export default async function sitemap(): Promise {
- validateEnvironmentVariables();
-
- const routesMap = [''].map((route) => ({
- url: `${baseUrl}${route}`,
- lastModified: new Date().toISOString()
- }));
-
- const collectionsPromise = getCollections().then((collections) =>
- collections.map((collection) => ({
- url: `${baseUrl}${collection.path}`,
- lastModified: collection.updatedAt
- }))
- );
-
- const productsPromise = getProducts({}).then((products) =>
- products.map((product) => ({
- url: `${baseUrl}/product/${product.handle}`,
- lastModified: product.updatedAt
- }))
- );
-
- const pagesPromise = getPages({}).then((pages) =>
- pages.map((page) => ({
- url: `${baseUrl}/${page.handle}`,
- lastModified: page.updatedAt
- }))
- );
-
- let fetchedRoutes: Route[] = [];
-
- try {
- fetchedRoutes = (await Promise.all([collectionsPromise, productsPromise, pagesPromise])).flat();
- } catch (error) {
- throw JSON.stringify(error, null, 2);
- }
-
- return [...routesMap, ...fetchedRoutes];
-}
diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts
index 57e3627da..8a53bc039 100644
--- a/lib/shopify/index.ts
+++ b/lib/shopify/index.ts
@@ -400,6 +400,7 @@ export async function getPage({
}): Promise {
const res = await shopifyFetch({
query: getPageQuery,
+ cache: 'no-store',
variables: { handle, language, country }
});
@@ -415,6 +416,7 @@ export async function getPages({
}): Promise {
const res = await shopifyFetch({
query: getPagesQuery,
+ cache: 'no-store',
variables: { language, country }
});
diff --git a/yarn.lock b/yarn.lock
index 4590e3b1d..b42eb6ef3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -183,15 +183,15 @@ __metadata:
languageName: node
linkType: hard
-"@headlessui/react@npm:^1.7.15":
- version: 1.7.16
- resolution: "@headlessui/react@npm:1.7.16"
+"@headlessui/react@npm:^1.7.17":
+ version: 1.7.17
+ resolution: "@headlessui/react@npm:1.7.17"
dependencies:
client-only: ^0.0.1
peerDependencies:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
- checksum: 85844c96c79796236fa7dec2f1c2f0332d7554d9b785d7b37d9762bb4133088a0cf1334653d6f91c1fe4619960eb569f14ba5f6a962c3305e03f7b362acbabbe
+ checksum: 0cdb67747e7f606f78214dac0b48573247779e70534b4471515c094b74addda173dc6a9847d33aea9c6e6bc151016c034125328953077e32aa7947ebabed91f7
languageName: node
linkType: hard
@@ -1352,7 +1352,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "commerce@workspace:."
dependencies:
- "@headlessui/react": ^1.7.15
+ "@headlessui/react": ^1.7.17
"@heroicons/react": ^2.0.18
"@tailwindcss/container-queries": ^0.1.1
"@tailwindcss/typography": ^0.5.9