@shopify/create-hydrogen 1.0.9 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/commands/init.js +133 -62
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +12 -8
- package/templates/template-hydrogen-default/.devcontainer/devcontainer.json +0 -18
- package/templates/template-hydrogen-default/.eslintrc.js +0 -3
- package/templates/template-hydrogen-default/.gitignore +0 -7
- package/templates/template-hydrogen-default/.stylelintrc.js +0 -17
- package/templates/template-hydrogen-default/.vscode/extensions.json +0 -8
- package/templates/template-hydrogen-default/README.md +0 -40
- package/templates/template-hydrogen-default/_gitignore +0 -80
- package/templates/template-hydrogen-default/index.html +0 -20
- package/templates/template-hydrogen-default/package.json.liquid +0 -48
- package/templates/template-hydrogen-default/postcss.config.js +0 -6
- package/templates/template-hydrogen-default/public/favicon.ico +0 -0
- package/templates/template-hydrogen-default/shopify.config.js +0 -5
- package/templates/template-hydrogen-default/src/App.server.jsx +0 -27
- package/templates/template-hydrogen-default/src/components/Button.client.jsx +0 -65
- package/templates/template-hydrogen-default/src/components/Cart.client.jsx +0 -265
- package/templates/template-hydrogen-default/src/components/CartIcon.jsx +0 -33
- package/templates/template-hydrogen-default/src/components/CartIconWithItems.client.jsx +0 -28
- package/templates/template-hydrogen-default/src/components/CartProvider.client.jsx +0 -35
- package/templates/template-hydrogen-default/src/components/CartToggle.client.jsx +0 -30
- package/templates/template-hydrogen-default/src/components/CartUIProvider.client.jsx +0 -45
- package/templates/template-hydrogen-default/src/components/CountrySelector.client.jsx +0 -116
- package/templates/template-hydrogen-default/src/components/DefaultSeo.server.jsx +0 -36
- package/templates/template-hydrogen-default/src/components/FeaturedCollection.jsx +0 -26
- package/templates/template-hydrogen-default/src/components/Footer.server.jsx +0 -103
- package/templates/template-hydrogen-default/src/components/Gallery.client.jsx +0 -66
- package/templates/template-hydrogen-default/src/components/Header.client.jsx +0 -62
- package/templates/template-hydrogen-default/src/components/Layout.server.jsx +0 -86
- package/templates/template-hydrogen-default/src/components/LoadMoreProducts.client.jsx +0 -56
- package/templates/template-hydrogen-default/src/components/LoadingFallback.jsx +0 -26
- package/templates/template-hydrogen-default/src/components/MobileCountrySelector.client.jsx +0 -64
- package/templates/template-hydrogen-default/src/components/MobileNavigation.client.jsx +0 -98
- package/templates/template-hydrogen-default/src/components/MoneyCompareAtPrice.client.jsx +0 -14
- package/templates/template-hydrogen-default/src/components/MoneyPrice.client.jsx +0 -15
- package/templates/template-hydrogen-default/src/components/Navigation.client.jsx +0 -23
- package/templates/template-hydrogen-default/src/components/NotFound.server.jsx +0 -93
- package/templates/template-hydrogen-default/src/components/OpenIcon.jsx +0 -33
- package/templates/template-hydrogen-default/src/components/ProductCard.jsx +0 -50
- package/templates/template-hydrogen-default/src/components/ProductDetails.client.jsx +0 -233
- package/templates/template-hydrogen-default/src/components/ProductOptions.client.jsx +0 -49
- package/templates/template-hydrogen-default/src/components/Welcome.server.jsx +0 -188
- package/templates/template-hydrogen-default/src/index.css +0 -68
- package/templates/template-hydrogen-default/src/pages/collections/[handle].server.jsx +0 -105
- package/templates/template-hydrogen-default/src/pages/index.server.jsx +0 -241
- package/templates/template-hydrogen-default/src/pages/pages/[handle].server.jsx +0 -37
- package/templates/template-hydrogen-default/src/pages/products/[handle].server.jsx +0 -66
- package/templates/template-hydrogen-default/src/pages/redirect.server.jsx +0 -4
- package/templates/template-hydrogen-default/src/pages/robots.txt.server.js +0 -40
- package/templates/template-hydrogen-default/src/pages/sitemap.xml.server.jsx +0 -151
- package/templates/template-hydrogen-default/src/routes/collections/[handle].server.jsx +0 -105
- package/templates/template-hydrogen-default/src/routes/index.server.jsx +0 -241
- package/templates/template-hydrogen-default/src/routes/pages/[handle].server.jsx +0 -37
- package/templates/template-hydrogen-default/src/routes/products/[handle].server.jsx +0 -66
- package/templates/template-hydrogen-default/src/routes/redirect.server.jsx +0 -4
- package/templates/template-hydrogen-default/src/routes/robots.txt.server.js +0 -40
- package/templates/template-hydrogen-default/src/routes/sitemap.xml.server.jsx +0 -151
- package/templates/template-hydrogen-default/tailwind.config.js +0 -26
- package/templates/template-hydrogen-default/vite.config.js +0 -10
- package/templates/template-hydrogen-minimal/README.md +0 -8
- package/templates/template-hydrogen-minimal/package.json +0 -14
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This API endpoint generates a robots.txt file. Use this to control
|
|
3
|
-
* access to your resources from SEO crawlers.
|
|
4
|
-
* Learn more: https://developers.google.com/search/docs/advanced/robots/create-robots-txt
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export default function RobotsTxt({request, response}) {
|
|
8
|
-
response.doNotStream();
|
|
9
|
-
response.headers.set('content-type', 'text/plain');
|
|
10
|
-
|
|
11
|
-
const url = new URL(request.url);
|
|
12
|
-
|
|
13
|
-
return response.send(robotsTxtData({url: url.origin}));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function robotsTxtData({url}) {
|
|
17
|
-
const sitemapUrl = url ? `${url}/sitemap.xml` : undefined;
|
|
18
|
-
|
|
19
|
-
return `
|
|
20
|
-
User-agent: *
|
|
21
|
-
Disallow: /admin
|
|
22
|
-
Disallow: /cart
|
|
23
|
-
Disallow: /orders
|
|
24
|
-
Disallow: /checkouts/
|
|
25
|
-
Disallow: /checkout
|
|
26
|
-
Disallow: /carts
|
|
27
|
-
Disallow: /account
|
|
28
|
-
${sitemapUrl ? `Sitemap: ${sitemapUrl}` : ''}
|
|
29
|
-
|
|
30
|
-
# Google adsbot ignores robots.txt unless specifically named!
|
|
31
|
-
User-agent: adsbot-google
|
|
32
|
-
Disallow: /checkouts/
|
|
33
|
-
Disallow: /checkout
|
|
34
|
-
Disallow: /carts
|
|
35
|
-
Disallow: /orders
|
|
36
|
-
|
|
37
|
-
User-agent: Pinterest
|
|
38
|
-
Crawl-delay: 1
|
|
39
|
-
`;
|
|
40
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import {flattenConnection, useShopQuery} from '@shopify/hydrogen';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
|
|
4
|
-
const MAX_URLS = 250; // the google limit is 50K, however, SF API only allow querying for 250 resources each time
|
|
5
|
-
|
|
6
|
-
export default function Sitemap({request, response}) {
|
|
7
|
-
response.doNotStream();
|
|
8
|
-
|
|
9
|
-
const {data} = useShopQuery({
|
|
10
|
-
query: QUERY,
|
|
11
|
-
variables: {
|
|
12
|
-
urlLimits: MAX_URLS,
|
|
13
|
-
},
|
|
14
|
-
// Cache the page for 24 hours
|
|
15
|
-
cache: {maxAge: 60 * 60 * 24},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
response.headers.set('content-type', 'application/xml');
|
|
19
|
-
|
|
20
|
-
return response.send(shopSitemap(data, request.url));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function shopSitemap(data, baseUrl) {
|
|
24
|
-
const productsData = flattenConnection(data.products).map((product) => {
|
|
25
|
-
const url = product.onlineStoreUrl
|
|
26
|
-
? product.onlineStoreUrl
|
|
27
|
-
: `${baseUrl}/products/${product.handle}`;
|
|
28
|
-
|
|
29
|
-
const finalObject = {
|
|
30
|
-
url,
|
|
31
|
-
lastMod: product.updatedAt,
|
|
32
|
-
changeFreq: 'daily',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
if (product.featuredImage.url) {
|
|
36
|
-
finalObject.image = {
|
|
37
|
-
url: product.featuredImage.url,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (product.title) {
|
|
41
|
-
finalObject.image.title = product.title;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (product.featuredImage.altText) {
|
|
45
|
-
finalObject.image.caption = product.featuredImage.altText;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return finalObject;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const collectionsData = flattenConnection(data.collections).map(
|
|
53
|
-
(collection) => {
|
|
54
|
-
const url = collection.onlineStoreUrl
|
|
55
|
-
? collection.onlineStoreUrl
|
|
56
|
-
: `${baseUrl}/collections/${collection.handle}`;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
url,
|
|
60
|
-
lastMod: collection.updatedAt,
|
|
61
|
-
changeFreq: 'daily',
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const pagesData = flattenConnection(data.pages).map((page) => {
|
|
67
|
-
const url = page.onlineStoreUrl
|
|
68
|
-
? page.onlineStoreUrl
|
|
69
|
-
: `${baseUrl}/pages/${page.handle}`;
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
url,
|
|
73
|
-
lastMod: page.updatedAt,
|
|
74
|
-
changeFreq: 'weekly',
|
|
75
|
-
};
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const urlsDatas = [...productsData, ...collectionsData, ...pagesData];
|
|
79
|
-
|
|
80
|
-
return `
|
|
81
|
-
<urlset
|
|
82
|
-
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
83
|
-
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
|
|
84
|
-
>
|
|
85
|
-
${urlsDatas.map((url) => renderUrlTag(url)).join('')}
|
|
86
|
-
</urlset>`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function renderUrlTag({url, lastMod, changeFreq, image}) {
|
|
90
|
-
return `
|
|
91
|
-
<url>
|
|
92
|
-
<loc>${url}</loc>
|
|
93
|
-
<lastmod>${lastMod}</lastmod>
|
|
94
|
-
<changefreq>${changeFreq}</changefreq>
|
|
95
|
-
${
|
|
96
|
-
image
|
|
97
|
-
? `
|
|
98
|
-
<image:image>
|
|
99
|
-
<image:loc>${image.url}</image:loc>
|
|
100
|
-
<image:title>${image.title ?? ''}</image:title>
|
|
101
|
-
<image:caption>${image.caption ?? ''}</image:caption>
|
|
102
|
-
</image:image>`
|
|
103
|
-
: ''
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
</url>
|
|
107
|
-
`;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const QUERY = gql`
|
|
111
|
-
query sitemaps($urlLimits: Int) {
|
|
112
|
-
products(
|
|
113
|
-
first: $urlLimits
|
|
114
|
-
query: "published_status:'online_store:visible'"
|
|
115
|
-
) {
|
|
116
|
-
edges {
|
|
117
|
-
node {
|
|
118
|
-
updatedAt
|
|
119
|
-
handle
|
|
120
|
-
onlineStoreUrl
|
|
121
|
-
title
|
|
122
|
-
featuredImage {
|
|
123
|
-
url
|
|
124
|
-
altText
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
collections(
|
|
130
|
-
first: $urlLimits
|
|
131
|
-
query: "published_status:'online_store:visible'"
|
|
132
|
-
) {
|
|
133
|
-
edges {
|
|
134
|
-
node {
|
|
135
|
-
updatedAt
|
|
136
|
-
handle
|
|
137
|
-
onlineStoreUrl
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
pages(first: $urlLimits, query: "published_status:'published'") {
|
|
142
|
-
edges {
|
|
143
|
-
node {
|
|
144
|
-
updatedAt
|
|
145
|
-
handle
|
|
146
|
-
onlineStoreUrl
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
`;
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MediaFileFragment,
|
|
3
|
-
ProductProviderFragment,
|
|
4
|
-
useShopQuery,
|
|
5
|
-
flattenConnection,
|
|
6
|
-
RawHtml,
|
|
7
|
-
Seo,
|
|
8
|
-
} from '@shopify/hydrogen';
|
|
9
|
-
import gql from 'graphql-tag';
|
|
10
|
-
|
|
11
|
-
import LoadMoreProducts from '../../components/LoadMoreProducts.client';
|
|
12
|
-
import Layout from '../../components/Layout.server';
|
|
13
|
-
import ProductCard from '../../components/ProductCard';
|
|
14
|
-
import NotFound from '../../components/NotFound.server';
|
|
15
|
-
|
|
16
|
-
export default function Collection({
|
|
17
|
-
country = {isoCode: 'US'},
|
|
18
|
-
collectionProductCount = 24,
|
|
19
|
-
params,
|
|
20
|
-
}) {
|
|
21
|
-
const {handle} = params;
|
|
22
|
-
const {data} = useShopQuery({
|
|
23
|
-
query: QUERY,
|
|
24
|
-
variables: {
|
|
25
|
-
handle,
|
|
26
|
-
country: country.isoCode,
|
|
27
|
-
numProducts: collectionProductCount,
|
|
28
|
-
},
|
|
29
|
-
preload: true,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
if (data?.collection == null) {
|
|
33
|
-
return <NotFound />;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const collection = data.collection;
|
|
37
|
-
const products = flattenConnection(collection.products);
|
|
38
|
-
const hasNextPage = data.collection.products.pageInfo.hasNextPage;
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Layout>
|
|
42
|
-
{/* the seo object will be expose in API version 2022-04 or later */}
|
|
43
|
-
<Seo type="collection" data={{seo: {}, ...collection}} />
|
|
44
|
-
<h1 className="font-bold text-4xl md:text-5xl text-gray-900 mb-6 mt-6">
|
|
45
|
-
{collection.title}
|
|
46
|
-
</h1>
|
|
47
|
-
<RawHtml string={collection.descriptionHtml} className="text-lg" />
|
|
48
|
-
<p className="text-sm text-gray-500 mt-5 mb-5">
|
|
49
|
-
{products.length} {products.length > 1 ? 'products' : 'product'}
|
|
50
|
-
</p>
|
|
51
|
-
<ul className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
|
52
|
-
{products.map((product) => (
|
|
53
|
-
<li key={product.id}>
|
|
54
|
-
<ProductCard product={product} />
|
|
55
|
-
</li>
|
|
56
|
-
))}
|
|
57
|
-
</ul>
|
|
58
|
-
{hasNextPage && (
|
|
59
|
-
<LoadMoreProducts startingCount={collectionProductCount} />
|
|
60
|
-
)}
|
|
61
|
-
</Layout>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const QUERY = gql`
|
|
66
|
-
query CollectionDetails(
|
|
67
|
-
$handle: String!
|
|
68
|
-
$country: CountryCode
|
|
69
|
-
$numProducts: Int!
|
|
70
|
-
$includeReferenceMetafieldDetails: Boolean = false
|
|
71
|
-
$numProductMetafields: Int = 0
|
|
72
|
-
$numProductVariants: Int = 250
|
|
73
|
-
$numProductMedia: Int = 6
|
|
74
|
-
$numProductVariantMetafields: Int = 0
|
|
75
|
-
$numProductVariantSellingPlanAllocations: Int = 0
|
|
76
|
-
$numProductSellingPlanGroups: Int = 0
|
|
77
|
-
$numProductSellingPlans: Int = 0
|
|
78
|
-
) @inContext(country: $country) {
|
|
79
|
-
collection(handle: $handle) {
|
|
80
|
-
id
|
|
81
|
-
title
|
|
82
|
-
description
|
|
83
|
-
descriptionHtml
|
|
84
|
-
image {
|
|
85
|
-
url
|
|
86
|
-
width
|
|
87
|
-
height
|
|
88
|
-
}
|
|
89
|
-
products(first: $numProducts) {
|
|
90
|
-
edges {
|
|
91
|
-
node {
|
|
92
|
-
vendor
|
|
93
|
-
...ProductProviderFragment
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
pageInfo {
|
|
97
|
-
hasNextPage
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
${MediaFileFragment}
|
|
104
|
-
${ProductProviderFragment}
|
|
105
|
-
`;
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useShopQuery,
|
|
3
|
-
flattenConnection,
|
|
4
|
-
ProductProviderFragment,
|
|
5
|
-
Image,
|
|
6
|
-
Link,
|
|
7
|
-
Seo,
|
|
8
|
-
CacheDays,
|
|
9
|
-
} from '@shopify/hydrogen';
|
|
10
|
-
import gql from 'graphql-tag';
|
|
11
|
-
|
|
12
|
-
import Layout from '../components/Layout.server';
|
|
13
|
-
import FeaturedCollection from '../components/FeaturedCollection';
|
|
14
|
-
import ProductCard from '../components/ProductCard';
|
|
15
|
-
import Welcome from '../components/Welcome.server';
|
|
16
|
-
import {Suspense} from 'react';
|
|
17
|
-
|
|
18
|
-
export default function Index({country = {isoCode: 'US'}}) {
|
|
19
|
-
return (
|
|
20
|
-
<Layout hero={<GradientBackground />}>
|
|
21
|
-
<Suspense fallback={null}>
|
|
22
|
-
<SeoForHomepage />
|
|
23
|
-
</Suspense>
|
|
24
|
-
<div className="relative mb-12">
|
|
25
|
-
<Welcome />
|
|
26
|
-
<Suspense fallback={<BoxFallback />}>
|
|
27
|
-
<FeaturedProductsBox country={country} />
|
|
28
|
-
</Suspense>
|
|
29
|
-
<Suspense fallback={<BoxFallback />}>
|
|
30
|
-
<FeaturedCollectionBox country={country} />
|
|
31
|
-
</Suspense>
|
|
32
|
-
</div>
|
|
33
|
-
</Layout>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function SeoForHomepage() {
|
|
38
|
-
const {
|
|
39
|
-
data: {
|
|
40
|
-
shop: {
|
|
41
|
-
name: shopName,
|
|
42
|
-
primaryDomain: {url: shopUrl},
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
} = useShopQuery({
|
|
46
|
-
query: SEO_QUERY,
|
|
47
|
-
cache: CacheDays(),
|
|
48
|
-
preload: true,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<Seo
|
|
53
|
-
type="homepage"
|
|
54
|
-
data={{
|
|
55
|
-
title: shopName,
|
|
56
|
-
url: shopUrl,
|
|
57
|
-
}}
|
|
58
|
-
/>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function BoxFallback() {
|
|
63
|
-
return <div className="bg-white p-12 shadow-xl rounded-xl mb-10 h-40"></div>;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function FeaturedProductsBox({country}) {
|
|
67
|
-
const {data} = useShopQuery({
|
|
68
|
-
query: QUERY,
|
|
69
|
-
variables: {
|
|
70
|
-
country: country.isoCode,
|
|
71
|
-
},
|
|
72
|
-
preload: true,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const collections = data ? flattenConnection(data.collections) : [];
|
|
76
|
-
const featuredProductsCollection = collections[0];
|
|
77
|
-
const featuredProducts = featuredProductsCollection
|
|
78
|
-
? flattenConnection(featuredProductsCollection.products)
|
|
79
|
-
: null;
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<div className="bg-white p-12 shadow-xl rounded-xl mb-10">
|
|
83
|
-
{featuredProductsCollection ? (
|
|
84
|
-
<>
|
|
85
|
-
<div className="flex justify-between items-center mb-8 text-md font-medium">
|
|
86
|
-
<span className="text-black uppercase">
|
|
87
|
-
{featuredProductsCollection.title}
|
|
88
|
-
</span>
|
|
89
|
-
<span className="hidden md:inline-flex">
|
|
90
|
-
<Link
|
|
91
|
-
to={`/collections/${featuredProductsCollection.handle}`}
|
|
92
|
-
className="text-blue-600 hover:underline"
|
|
93
|
-
>
|
|
94
|
-
Shop all
|
|
95
|
-
</Link>
|
|
96
|
-
</span>
|
|
97
|
-
</div>
|
|
98
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-8">
|
|
99
|
-
{featuredProducts.map((product) => (
|
|
100
|
-
<div key={product.id}>
|
|
101
|
-
<ProductCard product={product} />
|
|
102
|
-
</div>
|
|
103
|
-
))}
|
|
104
|
-
</div>
|
|
105
|
-
<div className="md:hidden text-center">
|
|
106
|
-
<Link
|
|
107
|
-
to={`/collections/${featuredProductsCollection.handle}`}
|
|
108
|
-
className="text-blue-600"
|
|
109
|
-
>
|
|
110
|
-
Shop all
|
|
111
|
-
</Link>
|
|
112
|
-
</div>
|
|
113
|
-
</>
|
|
114
|
-
) : null}
|
|
115
|
-
</div>
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function FeaturedCollectionBox({country}) {
|
|
120
|
-
const {data} = useShopQuery({
|
|
121
|
-
query: QUERY,
|
|
122
|
-
variables: {
|
|
123
|
-
country: country.isoCode,
|
|
124
|
-
},
|
|
125
|
-
preload: true,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
const collections = data ? flattenConnection(data.collections) : [];
|
|
129
|
-
const featuredCollection =
|
|
130
|
-
collections && collections.length > 1 ? collections[1] : collections[0];
|
|
131
|
-
|
|
132
|
-
return <FeaturedCollection collection={featuredCollection} />;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function GradientBackground() {
|
|
136
|
-
return (
|
|
137
|
-
<div className="fixed top-0 w-full h-3/5 overflow-hidden">
|
|
138
|
-
<div className="absolute w-full h-full bg-gradient-to-t from-gray-50 z-10" />
|
|
139
|
-
|
|
140
|
-
<svg
|
|
141
|
-
viewBox="0 0 960 743"
|
|
142
|
-
fill="none"
|
|
143
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
144
|
-
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
145
|
-
className="filter blur-[30px]"
|
|
146
|
-
aria-hidden="true"
|
|
147
|
-
>
|
|
148
|
-
<defs>
|
|
149
|
-
<path fill="#fff" d="M0 0h960v540H0z" id="reuse-0" />
|
|
150
|
-
</defs>
|
|
151
|
-
<g clipPath="url(#a)">
|
|
152
|
-
<use xlinkHref="#reuse-0" />
|
|
153
|
-
<path d="M960 0H0v743h960V0Z" fill="#7CFBEE" />
|
|
154
|
-
<path
|
|
155
|
-
d="M831 380c200.48 0 363-162.521 363-363s-162.52-363-363-363c-200.479 0-363 162.521-363 363s162.521 363 363 363Z"
|
|
156
|
-
fill="#4F98D0"
|
|
157
|
-
/>
|
|
158
|
-
<path
|
|
159
|
-
d="M579 759c200.479 0 363-162.521 363-363S779.479 33 579 33 216 195.521 216 396s162.521 363 363 363Z"
|
|
160
|
-
fill="#7CFBEE"
|
|
161
|
-
/>
|
|
162
|
-
<path
|
|
163
|
-
d="M178 691c200.479 0 363-162.521 363-363S378.479-35 178-35c-200.4794 0-363 162.521-363 363s162.5206 363 363 363Z"
|
|
164
|
-
fill="#4F98D0"
|
|
165
|
-
/>
|
|
166
|
-
<path
|
|
167
|
-
d="M490 414c200.479 0 363-162.521 363-363S690.479-312 490-312 127-149.479 127 51s162.521 363 363 363Z"
|
|
168
|
-
fill="#4F98D0"
|
|
169
|
-
/>
|
|
170
|
-
<path
|
|
171
|
-
d="M354 569c200.479 0 363-162.521 363-363 0-200.47937-162.521-363-363-363S-9 5.52063-9 206c0 200.479 162.521 363 363 363Z"
|
|
172
|
-
fill="#7CFBEE"
|
|
173
|
-
/>
|
|
174
|
-
<path
|
|
175
|
-
d="M630 532c200.479 0 363-162.521 363-363 0-200.4794-162.521-363-363-363S267-31.4794 267 169c0 200.479 162.521 363 363 363Z"
|
|
176
|
-
fill="#4F98D0"
|
|
177
|
-
/>
|
|
178
|
-
</g>
|
|
179
|
-
<path fill="#fff" d="M0 540h960v203H0z" />
|
|
180
|
-
<defs>
|
|
181
|
-
<clipPath id="a">
|
|
182
|
-
<use xlinkHref="#reuse-0" />
|
|
183
|
-
</clipPath>
|
|
184
|
-
</defs>
|
|
185
|
-
</svg>
|
|
186
|
-
</div>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const SEO_QUERY = gql`
|
|
191
|
-
query homeShopInfo {
|
|
192
|
-
shop {
|
|
193
|
-
name
|
|
194
|
-
description
|
|
195
|
-
primaryDomain {
|
|
196
|
-
url
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
`;
|
|
201
|
-
|
|
202
|
-
const QUERY = gql`
|
|
203
|
-
query indexContent(
|
|
204
|
-
$country: CountryCode
|
|
205
|
-
$numCollections: Int = 2
|
|
206
|
-
$numProducts: Int = 3
|
|
207
|
-
$includeReferenceMetafieldDetails: Boolean = false
|
|
208
|
-
$numProductMetafields: Int = 0
|
|
209
|
-
$numProductVariants: Int = 250
|
|
210
|
-
$numProductMedia: Int = 1
|
|
211
|
-
$numProductVariantMetafields: Int = 10
|
|
212
|
-
$numProductVariantSellingPlanAllocations: Int = 0
|
|
213
|
-
$numProductSellingPlanGroups: Int = 0
|
|
214
|
-
$numProductSellingPlans: Int = 0
|
|
215
|
-
) @inContext(country: $country) {
|
|
216
|
-
collections(first: $numCollections) {
|
|
217
|
-
edges {
|
|
218
|
-
node {
|
|
219
|
-
descriptionHtml
|
|
220
|
-
description
|
|
221
|
-
handle
|
|
222
|
-
id
|
|
223
|
-
title
|
|
224
|
-
image {
|
|
225
|
-
...ImageFragment
|
|
226
|
-
}
|
|
227
|
-
products(first: $numProducts) {
|
|
228
|
-
edges {
|
|
229
|
-
node {
|
|
230
|
-
...ProductProviderFragment
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
${ProductProviderFragment}
|
|
240
|
-
${Image.Fragment}
|
|
241
|
-
`;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {useShopQuery, RawHtml, Seo} from '@shopify/hydrogen';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
|
|
4
|
-
import Layout from '../../components/Layout.server';
|
|
5
|
-
import NotFound from '../../components/NotFound.server';
|
|
6
|
-
|
|
7
|
-
export default function Page({params}) {
|
|
8
|
-
const {handle} = params;
|
|
9
|
-
const {data} = useShopQuery({query: QUERY, variables: {handle}});
|
|
10
|
-
|
|
11
|
-
if (!data.pageByHandle) {
|
|
12
|
-
return <NotFound />;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const page = data.pageByHandle;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<Layout>
|
|
19
|
-
<Seo type="page" data={page} />
|
|
20
|
-
<h1 className="text-2xl font-bold">{page.title}</h1>
|
|
21
|
-
<RawHtml string={page.body} className="prose mt-8" />
|
|
22
|
-
</Layout>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const QUERY = gql`
|
|
27
|
-
query PageDetails($handle: String!) {
|
|
28
|
-
pageByHandle(handle: $handle) {
|
|
29
|
-
title
|
|
30
|
-
body
|
|
31
|
-
seo {
|
|
32
|
-
title
|
|
33
|
-
description
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {useShopQuery, ProductProviderFragment, Seo} from '@shopify/hydrogen';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
|
|
4
|
-
import ProductDetails from '../../components/ProductDetails.client';
|
|
5
|
-
import NotFound from '../../components/NotFound.server';
|
|
6
|
-
import Layout from '../../components/Layout.server';
|
|
7
|
-
|
|
8
|
-
export default function Product({country = {isoCode: 'US'}, params}) {
|
|
9
|
-
const {handle} = params;
|
|
10
|
-
|
|
11
|
-
const {
|
|
12
|
-
data: {product},
|
|
13
|
-
} = useShopQuery({
|
|
14
|
-
query: QUERY,
|
|
15
|
-
variables: {
|
|
16
|
-
country: country.isoCode,
|
|
17
|
-
handle,
|
|
18
|
-
},
|
|
19
|
-
preload: true,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (!product) {
|
|
23
|
-
return <NotFound />;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<Layout>
|
|
28
|
-
<Seo type="product" data={product} />
|
|
29
|
-
<ProductDetails product={product} />
|
|
30
|
-
</Layout>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const QUERY = gql`
|
|
35
|
-
query product(
|
|
36
|
-
$country: CountryCode
|
|
37
|
-
$handle: String!
|
|
38
|
-
$includeReferenceMetafieldDetails: Boolean = true
|
|
39
|
-
$numProductMetafields: Int = 20
|
|
40
|
-
$numProductVariants: Int = 250
|
|
41
|
-
$numProductMedia: Int = 6
|
|
42
|
-
$numProductVariantMetafields: Int = 10
|
|
43
|
-
$numProductVariantSellingPlanAllocations: Int = 0
|
|
44
|
-
$numProductSellingPlanGroups: Int = 0
|
|
45
|
-
$numProductSellingPlans: Int = 0
|
|
46
|
-
) @inContext(country: $country) {
|
|
47
|
-
product: product(handle: $handle) {
|
|
48
|
-
id
|
|
49
|
-
description
|
|
50
|
-
vendor
|
|
51
|
-
seo {
|
|
52
|
-
title
|
|
53
|
-
description
|
|
54
|
-
}
|
|
55
|
-
featuredImage {
|
|
56
|
-
url
|
|
57
|
-
height
|
|
58
|
-
width
|
|
59
|
-
altText
|
|
60
|
-
}
|
|
61
|
-
...ProductProviderFragment
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
${ProductProviderFragment}
|
|
66
|
-
`;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This API endpoint generates a robots.txt file. Use this to control
|
|
3
|
-
* access to your resources from SEO crawlers.
|
|
4
|
-
* Learn more: https://developers.google.com/search/docs/advanced/robots/create-robots-txt
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export default function RobotsTxt({request, response}) {
|
|
8
|
-
response.doNotStream();
|
|
9
|
-
response.headers.set('content-type', 'text/plain');
|
|
10
|
-
|
|
11
|
-
const url = new URL(request.url);
|
|
12
|
-
|
|
13
|
-
return response.send(robotsTxtData({url: url.origin}));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function robotsTxtData({url}) {
|
|
17
|
-
const sitemapUrl = url ? `${url}/sitemap.xml` : undefined;
|
|
18
|
-
|
|
19
|
-
return `
|
|
20
|
-
User-agent: *
|
|
21
|
-
Disallow: /admin
|
|
22
|
-
Disallow: /cart
|
|
23
|
-
Disallow: /orders
|
|
24
|
-
Disallow: /checkouts/
|
|
25
|
-
Disallow: /checkout
|
|
26
|
-
Disallow: /carts
|
|
27
|
-
Disallow: /account
|
|
28
|
-
${sitemapUrl ? `Sitemap: ${sitemapUrl}` : ''}
|
|
29
|
-
|
|
30
|
-
# Google adsbot ignores robots.txt unless specifically named!
|
|
31
|
-
User-agent: adsbot-google
|
|
32
|
-
Disallow: /checkouts/
|
|
33
|
-
Disallow: /checkout
|
|
34
|
-
Disallow: /carts
|
|
35
|
-
Disallow: /orders
|
|
36
|
-
|
|
37
|
-
User-agent: Pinterest
|
|
38
|
-
Crawl-delay: 1
|
|
39
|
-
`;
|
|
40
|
-
}
|