Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"typescript.tsdk": "node_modules/.pnpm/typescript@4.9.5/node_modules/typescript/lib",
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
Expand Down
1 change: 0 additions & 1 deletion app/[page]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<Suspense>{children}</Suspense>
</div>
</div>
{/* @ts-expect-error Server Component */}
<Footer />
</Suspense>
);
Expand Down
11 changes: 11 additions & 0 deletions app/[page]/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import OpengraphImage from 'components/opengraph-image';
import { getPage } from 'lib/bigcommerce';

export const runtime = 'edge';

export default async function Image({ params }: { params: { page: string } }) {
const page = await getPage(params.page);
const title = page.seo?.title || page.title;

return await OpengraphImage({ title });
}
Binary file removed app/api/og/Inter-Regular.ttf
Binary file not shown.
67 changes: 0 additions & 67 deletions app/api/og/route.tsx

This file was deleted.

37 changes: 37 additions & 0 deletions app/api/revalidate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TAGS } from 'lib/constants';
import { revalidateTag } from 'next/cache';
import { headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export const runtime = 'edge';

// We always need to respond with a 200 status code to Shopify,
// otherwise it will continue to retry the request.
export async function POST(req: NextRequest): Promise<Response> {
const collectionWebhooks = ['collections/create', 'collections/delete', 'collections/update'];
const productWebhooks = ['products/create', 'products/delete', 'products/update'];
const topic = headers().get('x-shopify-topic') || 'unknown';
const secret = req.nextUrl.searchParams.get('secret');
const isCollectionUpdate = collectionWebhooks.includes(topic);
const isProductUpdate = productWebhooks.includes(topic);

if (!secret || secret !== process.env.SHOPIFY_REVALIDATION_SECRET) {
console.error('Invalid revalidation secret.');
return NextResponse.json({ status: 200 });
}

if (!isCollectionUpdate && !isProductUpdate) {
// We don't need to revalidate anything for any other topics.
return NextResponse.json({ status: 200 });
}

if (isCollectionUpdate) {
revalidateTag(TAGS.collections);
}

if (isProductUpdate) {
revalidateTag(TAGS.products);
}

return NextResponse.json({ status: 200, revalidated: true, now: Date.now() });
}
1 change: 0 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export default async function RootLayout({ children }: { children: ReactNode })
return (
<html lang="en" className={inter.variable}>
<body className="bg-white text-black selection:bg-teal-300 dark:bg-black dark:text-white dark:selection:bg-fuchsia-600 dark:selection:text-white">
{/* @ts-expect-error Server Component */}
<Navbar />
<Suspense>
<main>{children}</main>
Expand Down
7 changes: 7 additions & 0 deletions app/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import OpengraphImage from 'components/opengraph-image';

export const runtime = 'edge';

export default async function Image() {
return await OpengraphImage();
}
3 changes: 0 additions & 3 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ export const metadata = {
export default async function HomePage() {
return (
<>
{/* @ts-expect-error Server Component */}
<ThreeItemGrid />
<Suspense>
{/* @ts-expect-error Server Component */}
<Carousel />
<Suspense>
{/* @ts-expect-error Server Component */}
<Footer />
</Suspense>
</Suspense>
Expand Down
3 changes: 0 additions & 3 deletions app/product/[handle]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export default async function ProductPage({ params }: { params: { handle: string
</div>

<div className="p-6 lg:col-span-2">
{/* @ts-expect-error Server Component */}
<VariantSelector options={product.options} variants={product.variants} />

{product.descriptionHtml ? (
Expand All @@ -108,10 +107,8 @@ export default async function ProductPage({ params }: { params: { handle: string
</div>
</div>
<Suspense>
{/* @ts-expect-error Server Component */}
<RelatedProducts id={product.id} />
<Suspense>
{/* @ts-expect-error Server Component */}
<Footer />
</Suspense>
</Suspense>
Expand Down
11 changes: 11 additions & 0 deletions app/search/[collection]/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import OpengraphImage from 'components/opengraph-image';
import { getCollection } from 'lib/bigcommerce';

export const runtime = 'edge';

export default async function Image({ params }: { params: { collection: string } }) {
const collection = await getCollection(params.collection);
const title = collection?.seo?.title || collection?.title;

return await OpengraphImage({ title });
}
11 changes: 1 addition & 10 deletions app/search/[collection]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,7 @@ export async function generateMetadata({
return {
title: collection.seo?.title || collection.title,
description:
collection.seo?.description || collection.description || `${collection.title} products`,
openGraph: {
images: [
{
url: `/api/og?title=${encodeURIComponent(collection.title)}`,
width: 1200,
height: 630
}
]
}
collection.seo?.description || collection.description || `${collection.title} products`
};
}

Expand Down
1 change: 0 additions & 1 deletion app/search/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default function SearchLayout({ children }: { children: React.ReactNode }
<FilterList list={sorting} title="Sort by" />
</div>
</div>
{/* @ts-expect-error Server Component */}
<Footer />
</Suspense>
);
Expand Down
1 change: 0 additions & 1 deletion components/layout/navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export default async function Navbar() {

<div className="flex w-1/3 justify-end">
<Suspense fallback={<CartIcon className="h-6" />}>
{/* @ts-expect-error Server Component */}
<Cart />
</Suspense>
</div>
Expand Down
1 change: 0 additions & 1 deletion components/layout/search/collections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export default function Collections() {
</div>
}
>
{/* @ts-expect-error Server Component */}
<CollectionList />
</Suspense>
);
Expand Down
45 changes: 45 additions & 0 deletions components/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ImageResponse } from '@vercel/og';

export type Props = {
title?: string;
};

export default async function OpengraphImage(props?: Props): Promise<ImageResponse> {
const { title } = {
...{
title: process.env.SITE_NAME
},
...props
};

return new ImageResponse(
(
<div tw="flex h-full w-full flex-col items-center justify-center bg-black">
<svg viewBox="0 0 32 32" width="140">
<rect width="100%" height="100%" rx="16" fill="white" />
<path
fillRule="evenodd"
clipRule="evenodd"
fill="black"
d="M17.6482 10.1305L15.8785 7.02583L7.02979 22.5499H10.5278L17.6482 10.1305ZM19.8798 14.0457L18.11 17.1983L19.394 19.4511H16.8453L15.1056 22.5499H24.7272L19.8798 14.0457Z"
/>
</svg>
<p tw="mt-12 text-6xl font-bold text-white">{title}</p>
</div>
),
{
width: 1200,
height: 630,
fonts: [
{
name: 'Inter',
data: await fetch(new URL('../fonts/Inter-Bold.ttf', import.meta.url)).then((res) =>
res.arrayBuffer()
),
style: 'normal',
weight: 700
}
]
}
);
}
File renamed without changes.
5 changes: 5 additions & 0 deletions lib/constants.tsx → lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ export const sorting: SortFilterItem[] = [
{ title: 'Price: High to low', slug: 'price-desc', sortKey: 'PRICE', reverse: true }
];

export const TAGS = {
collections: 'collections',
products: 'products'
};

export const HIDDEN_PRODUCT_TAG = 'nextjs-frontend-hidden';
export const DEFAULT_OPTION = 'Default Title';
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,33 @@
"*": "prettier --write --ignore-unknown"
},
"dependencies": {
"@headlessui/react": "^1.7.14",
"@vercel/og": "^0.5.4",
"@headlessui/react": "^1.7.15",
"@vercel/og": "^0.5.6",
"clsx": "^1.2.1",
"framer-motion": "^10.12.8",
"framer-motion": "^10.12.16",
"is-empty-iterable": "^3.0.0",
"next": "13.4.1",
"next": "13.4.4",
"react": "18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "18.2.0"
},
"devDependencies": {
"@playwright/test": "^1.33.0",
"@playwright/test": "^1.34.3",
"@tailwindcss/typography": "^0.5.9",
"@types/node": "20.1.0",
"@types/react": "18.2.6",
"@types/node": "20.2.5",
"@types/react": "18.2.8",
"@types/react-dom": "18.2.4",
"@vercel/git-hooks": "^1.0.0",
"autoprefixer": "^10.4.14",
"eslint": "^8.40.0",
"eslint-config-next": "^13.4.1",
"eslint": "^8.42.0",
"eslint-config-next": "^13.4.4",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-unicorn": "^47.0.0",
"lint-staged": "^13.2.2",
"postcss": "^8.4.23",
"postcss": "^8.4.24",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.2.8",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2",
"typescript": "5.0.4"
"typescript": "5.1.3"
}
}
Loading