Skip to content

Commit 59fc2bc

Browse files
authored
Update to new design. (#1103)
1 parent d918fcc commit 59fc2bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1000
-1245
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
COMPANY_NAME="Vercel Inc."
12
TWITTER_CREATOR="@vercel"
23
TWITTER_SITE="https://nextjs.org/commerce"
34
SITE_NAME="Next.js Commerce"

.github/workflows/e2e.yml

Lines changed: 0 additions & 49 deletions
This file was deleted.

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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=SHOPIFY_REVALIDATION_SECRET,SHOPIFY_STOREFRONT_ACCESS_TOKEN,SHOPIFY_STORE_DOMAIN,SITE_NAME,TWITTER_CREATOR,TWITTER_SITE)
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)
22

33
# Next.js Commerce
44

@@ -64,7 +64,7 @@ Next.js Commerce requires a [paid Shopify plan](https://www.shopify.com/pricing)
6464
6565
### Add Shopify domain to an environment variable
6666

67-
Create a `SHOPIFY_STORE_DOMAIN` environment variable and use your Shopify domain as the the value (ie. `SHOPIFY_STORE_SUBDOMAIN.myshopify.com`).
67+
Create a `SHOPIFY_STORE_DOMAIN` environment variable and use your Shopify domain as the the value (ie. `[your-shopify-store-subdomain].myshopify.com`).
6868

6969
> Note: Do not include the `https://`.
7070
@@ -74,14 +74,14 @@ Next.js Commerce utilizes [Shopify's Storefront API](https://shopify.dev/docs/ap
7474

7575
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.
7676

77-
Once installed, you'll need to create a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable and use the public access token as the value
77+
Once installed, you'll need to create a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable and use the public access token as the value.
7878

7979
> 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.
8080
8181
<details>
8282
<summary>Expand to view detailed walkthrough</summary>
8383

84-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/settings/apps`.
84+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/apps`.
8585
1. Click the green `Shopify App Store` button.
8686
![Shopify App Store](https://user-images.githubusercontent.com/446260/233220545-cb4c1461-ebc5-424e-a421-bf0d32044027.jpg)
8787
1. Search for `Headless` and click on the `Headless` app.
@@ -94,7 +94,7 @@ Once installed, you'll need to create a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` enviro
9494
![Create storefront](https://user-images.githubusercontent.com/446260/233220556-1eee15c4-a45d-446e-9f73-2e7c9f56b29c.jpg)
9595
1. Copy and paste the public access token and assign it to a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable.
9696
![Pubic access token](https://user-images.githubusercontent.com/446260/233220558-5db04ff9-b894-40fe-bfba-0e92f26b8e1f.jpg)
97-
1. If you ever need to reference the public access token again, you can navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/headless_storefronts`.
97+
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`.
9898
</details>
9999

100100
### Install a headless theme
@@ -110,7 +110,7 @@ Follow the installation instructions and configure the theme with your headless
110110

111111
1. Download [Shopify Headless Theme](https://github.com/instantcommerce/shopify-headless-theme).
112112
![Download Shoify Headless Theme](https://user-images.githubusercontent.com/446260/233220560-9f3f5ab0-ffb4-4305-b4ee-2c9d33eea90f.jpg)
113-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/themes`.
113+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`.
114114
1. Click `Add theme`, then `Upload zip file`.
115115
![Upload zip file](https://user-images.githubusercontent.com/446260/233220561-7a53809e-0d95-45eb-b52f-3a52e3663a9c.jpg)
116116
1. Select the downloaded zip file from above, and click the green `Upload file` button.
@@ -142,24 +142,24 @@ You can use Shopify's admin to customize these pages to match your brand and des
142142

143143
#### Checkout, order status, and order history
144144

145-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/settings/checkout`.
145+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/checkout`.
146146
1. Click the green `Customize` button.
147147
![Customize](https://user-images.githubusercontent.com/446260/233220530-9beda4b4-5008-440a-b923-9d196b722539.jpg)
148148
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.
149149
![Branding](https://user-images.githubusercontent.com/446260/233220534-e884d9fd-1a39-4f4d-9d09-163dde47c2e8.jpg)
150-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/settings/branding`.
150+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/branding`.
151151
1. Customize settings to match your brand.
152152
![Branding](https://user-images.githubusercontent.com/446260/233220536-452b8802-9a1e-40f0-9a12-52b3dace84a5.jpg)
153153

154154
#### Emails
155155

156-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/settings/email_settings`.
156+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/email_settings`.
157157
1. Customize settings to match your brand.
158158
![Branding](https://user-images.githubusercontent.com/446260/233220538-13c83a9e-55f8-41e6-9b34-a39ee0848a8a.jpg)
159159

160160
#### Favicon
161161

162-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/themes`.
162+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`.
163163
1. Click the green `Customize` button.
164164
![Customize theme](https://user-images.githubusercontent.com/446260/233220539-4869a6cd-f59f-4de6-8091-95ed81d2302d.jpg)
165165
1. Click `Theme settings` (ie. the paintbrush icon), expand the `FAVICON` section, upload favicon, then click the `Save` button.
@@ -190,7 +190,7 @@ Next.js is pre-configured to listen for the following Shopify webhook events and
190190

191191
#### Configure Shopify webhooks
192192

193-
1. Navigate to `https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/settings/notifications`.
193+
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/notifications`.
194194
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.
195195
![Shopify store webhooks](https://github.com/vercel/commerce/assets/446260/3d713fd7-b642-46e2-b2ce-f2b695ff6d2b)
196196
![Shopify store add webhook](https://github.com/vercel/commerce/assets/446260/f0240a22-be07-42bc-bf6c-b97873868677)
@@ -216,7 +216,7 @@ Next.js Commerce is fully powered by Shopify in a truly headless and data driven
216216

217217
#### Products
218218

219-
`https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/products`
219+
`https://[your-shopify-store-subdomain].myshopify.com/admin/products`
220220

221221
Only `Active` products are shown. `Draft` products will not be shown until they are marked as `Active`.
222222

@@ -228,7 +228,7 @@ Products that are active and "out of stock" are still shown on the site, but the
228228

229229
#### Collections
230230

231-
`https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/collections`
231+
`https://[your-shopify-store-subdomain].myshopify.com/admin/collections`
232232

233233
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...
234234

@@ -245,7 +245,7 @@ Create the following collections:
245245

246246
#### Pages
247247

248-
`https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/pages`
248+
`https://[your-shopify-store-subdomain].myshopify.com/admin/pages`
249249

250250
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.
251251

@@ -255,7 +255,7 @@ Next.js Commerce contains a dynamic `[page]` route. It will use the value to loo
255255

256256
#### Navigation menus
257257

258-
`https://SHOPIFY_STORE_SUBDOMAIN.myshopify.com/admin/menus`
258+
`https://[your-shopify-store-subdomain].myshopify.com/admin/menus`
259259

260260
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.
261261

app/[page]/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Suspense } from 'react';
44
export default function Layout({ children }: { children: React.ReactNode }) {
55
return (
66
<Suspense>
7-
<div className="w-full bg-white dark:bg-black">
7+
<div className="w-full">
88
<div className="mx-8 max-w-2xl py-20 sm:mx-auto">
99
<Suspense>{children}</Suspense>
1010
</div>

app/[page]/page.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ export async function generateMetadata({
2121
title: page.seo?.title || page.title,
2222
description: page.seo?.description || page.bodySummary,
2323
openGraph: {
24-
images: [
25-
{
26-
url: `/api/og?title=${encodeURIComponent(page.title)}`,
27-
width: 1200,
28-
height: 630
29-
}
30-
],
3124
publishedTime: page.createdAt,
3225
modifiedTime: page.updatedAt,
3326
type: 'article'

app/globals.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@
77
clip-path: inset(0.6px);
88
}
99
}
10+
11+
a,
12+
input,
13+
button {
14+
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-400 focus-visible:ring-offset-2 focus-visible:ring-offset-neutral-50 dark:focus-visible:ring-neutral-600 dark:focus-visible:ring-offset-neutral-900;
15+
}

app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const inter = Inter({
3333
export default async function RootLayout({ children }: { children: ReactNode }) {
3434
return (
3535
<html lang="en" className={inter.variable}>
36-
<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">
36+
<body className="bg-neutral-50 text-black selection:bg-teal-300 dark:bg-neutral-900 dark:text-white dark:selection:bg-pink-500 dark:selection:text-white">
3737
<Navbar />
3838
<Suspense>
3939
<main>{children}</main>

app/page.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ export const runtime = 'edge';
88
export const metadata = {
99
description: 'High-performance ecommerce store built with Next.js, Vercel, and Shopify.',
1010
openGraph: {
11-
images: [
12-
{
13-
url: `/api/og?title=${encodeURIComponent(process.env.SITE_NAME || '')}`,
14-
width: 1200,
15-
height: 630
16-
}
17-
],
1811
type: 'website'
1912
}
2013
};

app/product/[handle]/page.tsx

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ import type { Metadata } from 'next';
22
import { notFound } from 'next/navigation';
33
import { Suspense } from 'react';
44

5-
import Grid from 'components/grid';
5+
import { GridTileImage } from 'components/grid/tile';
66
import Footer from 'components/layout/footer';
7-
import ProductGridItems from 'components/layout/product-grid-items';
8-
import { AddToCart } from 'components/cart/add-to-cart';
97
import { Gallery } from 'components/product/gallery';
10-
import { VariantSelector } from 'components/product/variant-selector';
11-
import Prose from 'components/prose';
8+
import { ProductDescription } from 'components/product/product-description';
129
import { HIDDEN_PRODUCT_TAG } from 'lib/constants';
1310
import { getProduct, getProductRecommendations } from 'lib/shopify';
1411
import { Image } from 'lib/shopify/types';
12+
import Link from 'next/link';
1513

1614
export const runtime = 'edge';
1715

@@ -76,43 +74,36 @@ export default async function ProductPage({ params }: { params: { handle: string
7674
};
7775

7876
return (
79-
<div>
77+
<>
8078
<script
8179
type="application/ld+json"
8280
dangerouslySetInnerHTML={{
8381
__html: JSON.stringify(productJsonLd)
8482
}}
8583
/>
86-
<div className="lg:grid lg:grid-cols-6">
87-
<div className="lg:col-span-4">
88-
<Gallery
89-
title={product.title}
90-
amount={product.priceRange.maxVariantPrice.amount}
91-
currencyCode={product.priceRange.maxVariantPrice.currencyCode}
92-
images={product.images.map((image: Image) => ({
93-
src: image.url,
94-
altText: image.altText
95-
}))}
96-
/>
84+
<div className="mx-auto max-w-screen-2xl px-4">
85+
<div className="rounded-lg border border-neutral-200 bg-white p-8 px-4 dark:border-neutral-800 dark:bg-black md:p-12 lg:grid lg:grid-cols-6">
86+
<div className="lg:col-span-4">
87+
<Gallery
88+
images={product.images.map((image: Image) => ({
89+
src: image.url,
90+
altText: image.altText
91+
}))}
92+
/>
93+
</div>
94+
95+
<div className="py-6 pr-8 md:pr-12 lg:col-span-2">
96+
<ProductDescription product={product} />
97+
</div>
9798
</div>
98-
99-
<div className="p-6 lg:col-span-2">
100-
<VariantSelector options={product.options} variants={product.variants} />
101-
102-
{product.descriptionHtml ? (
103-
<Prose className="mb-6 text-sm leading-tight" html={product.descriptionHtml} />
104-
) : null}
105-
106-
<AddToCart variants={product.variants} availableForSale={product.availableForSale} />
107-
</div>
108-
</div>
109-
<Suspense>
110-
<RelatedProducts id={product.id} />
11199
<Suspense>
112-
<Footer />
100+
<RelatedProducts id={product.id} />
113101
</Suspense>
102+
</div>
103+
<Suspense>
104+
<Footer />
114105
</Suspense>
115-
</div>
106+
</>
116107
);
117108
}
118109

@@ -122,11 +113,31 @@ async function RelatedProducts({ id }: { id: string }) {
122113
if (!relatedProducts.length) return null;
123114

124115
return (
125-
<div className="px-4 py-8">
126-
<div className="mb-4 text-3xl font-bold">Related Products</div>
127-
<Grid className="grid-cols-2 lg:grid-cols-5">
128-
<ProductGridItems products={relatedProducts} />
129-
</Grid>
116+
<div className="py-8">
117+
<h2 className="mb-4 text-2xl font-bold">Related Products</h2>
118+
<div className="flex w-full gap-4 overflow-x-auto pt-1">
119+
{relatedProducts.map((product, i) => {
120+
return (
121+
<Link
122+
key={i}
123+
className="w-full flex-none min-[475px]:w-1/2 sm:w-1/3 md:w-1/4 lg:w-1/5"
124+
href={`/product/${product.handle}`}
125+
>
126+
<GridTileImage
127+
alt={product.title}
128+
label={{
129+
title: product.title,
130+
amount: product.priceRange.maxVariantPrice.amount,
131+
currencyCode: product.priceRange.maxVariantPrice.currencyCode
132+
}}
133+
src={product.featuredImage?.url}
134+
width={600}
135+
height={600}
136+
/>
137+
</Link>
138+
);
139+
})}
140+
</div>
130141
</div>
131142
);
132143
}

app/search/[collection]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default async function CategoryPage({
4040
{products.length === 0 ? (
4141
<p className="py-3 text-lg">{`No products found in this collection`}</p>
4242
) : (
43-
<Grid className="grid-cols-2 lg:grid-cols-3">
43+
<Grid className="grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
4444
<ProductGridItems products={products} />
4545
</Grid>
4646
)}

app/search/layout.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import { Suspense } from 'react';
77
export default function SearchLayout({ children }: { children: React.ReactNode }) {
88
return (
99
<Suspense>
10-
<div className="mx-auto flex max-w-7xl flex-col bg-white py-6 text-black dark:bg-black dark:text-white md:flex-row">
11-
<div className="order-first flex-none md:w-1/6">
10+
<div className="mx-auto flex max-w-screen-2xl flex-col gap-8 px-4 pb-4 text-black dark:text-white md:flex-row">
11+
<div className="order-first w-full flex-none md:max-w-[125px]">
1212
<Collections />
1313
</div>
1414
<div className="order-last min-h-screen w-full md:order-none">{children}</div>
15-
<div className="order-none md:order-last md:w-1/6 md:flex-none">
15+
<div className="order-none flex-none md:order-last md:w-[125px]">
1616
<FilterList list={sorting} title="Sort by" />
1717
</div>
1818
</div>

app/search/loading.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export default function Loading() {
66
{Array(12)
77
.fill(0)
88
.map((_, index) => {
9-
return <Grid.Item key={index} className="animate-pulse bg-gray-100 dark:bg-gray-900" />;
9+
return (
10+
<Grid.Item key={index} className="animate-pulse bg-neutral-100 dark:bg-neutral-900" />
11+
);
1012
})}
1113
</Grid>
1214
);

0 commit comments

Comments
 (0)