@graphcommerce/docs 3.1.4

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.
Files changed (59) hide show
  1. package/.babelrc +4 -0
  2. package/CHANGELOG.md +160 -0
  3. package/components/Layout/LayoutFull.tsx +85 -0
  4. package/components/Layout/Logo.tsx +19 -0
  5. package/components/Layout/graphcommerce.svg +34 -0
  6. package/components/Search.tsx +37 -0
  7. package/components/SearchForm.tsx +110 -0
  8. package/components/SidebarMenu/index.tsx +101 -0
  9. package/components/prism.css +274 -0
  10. package/components/rehype-prism-plus.css +49 -0
  11. package/components/theme.ts +410 -0
  12. package/content/framework/deployment.md +56 -0
  13. package/content/framework/environment-variables.md +61 -0
  14. package/content/framework/favicon.md +38 -0
  15. package/content/framework/graphcms.md +66 -0
  16. package/content/framework/icons.md +255 -0
  17. package/content/framework/readme.md +79 -0
  18. package/content/framework/seo.md +64 -0
  19. package/content/framework/static-file-serving.md +44 -0
  20. package/content/framework/static-generation.md +221 -0
  21. package/content/framework/theming.md +258 -0
  22. package/content/framework/translations.md +112 -0
  23. package/content/framework/troubleshooting.md +67 -0
  24. package/content/framework/typography.md +143 -0
  25. package/content/getting-started/create.md +152 -0
  26. package/content/getting-started/graphcms-component.md +240 -0
  27. package/content/getting-started/header.md +224 -0
  28. package/content/getting-started/pages.md +290 -0
  29. package/content/getting-started/readme.md +294 -0
  30. package/content/getting-started/start-building.md +160 -0
  31. package/content/getting-started/vscode.md +48 -0
  32. package/content/readme.md +124 -0
  33. package/content/roadmap.md +31 -0
  34. package/lib/DocumentIndexer.ts +59 -0
  35. package/lib/files.ts +168 -0
  36. package/lib/instantSearch.ts +26 -0
  37. package/lib/typesense/IndexerHandler.ts +47 -0
  38. package/lib/typesense/Leaves.ts +37 -0
  39. package/lib/typesense/SearchIndexer.ts +64 -0
  40. package/lib/typesense/batchInterable.ts +13 -0
  41. package/lib/typesense/createInstantSearchProps.ts +36 -0
  42. package/lib/typesense/typesenseClientConf.ts +23 -0
  43. package/lib/typesense/typesenseIndexerHandler.ts +23 -0
  44. package/next-env.d.ts +5 -0
  45. package/next.config.js +21 -0
  46. package/package.json +56 -0
  47. package/pages/[[...url]].tsx +391 -0
  48. package/pages/_app.tsx +26 -0
  49. package/pages/_document.tsx +22 -0
  50. package/pages/api/reindex.ts +4 -0
  51. package/pages/menu/[[...url]].tsx +69 -0
  52. package/public/apple-touch-icon.png +0 -0
  53. package/public/favicon.ico +0 -0
  54. package/public/favicon.svg +12 -0
  55. package/public/link.svg +4 -0
  56. package/public/manifest/favicon-192.png +0 -0
  57. package/public/manifest/favicon-512.png +0 -0
  58. package/public/manifest.webmanifest +20 -0
  59. package/tsconfig.json +5 -0
@@ -0,0 +1,224 @@
1
+ ---
2
+ menu: 3. Build a custom header
3
+ metaTitle: Build a custom header
4
+ ---
5
+
6
+ > **Developer preview**
7
+ > This is a developer preview of GraphCommerce. The documentation will be
8
+ > updated as GraphCommerce introduces
9
+ > [new features and refines existing functionality](https://github.com/ho-nl/m2-pwa/releases).
10
+
11
+ # Build a custom header in GraphCommerce
12
+
13
+ Previously, you created a GraphCommerce app and started building your custom
14
+ storefront with GraphCommerce. You're now ready to build a custom header for
15
+ your app.
16
+
17
+ In this tutorial, you'll accomplish a series of tasks to add some specific
18
+ functionality to your app. Your final app will be simple, but you'll learn where
19
+ to find resources to build more complex features on your own.
20
+
21
+ ### After you've finished this tutorial, you'll have accomplished the following:
22
+
23
+ - Edited the layout component to remove components
24
+ - Add a simplified search Icon button
25
+ - Make a local copy of the MenuFab component and update its imports
26
+ - Change the Menu component's styling to a fullscreen overlay
27
+
28
+ ### Requirements
29
+
30
+ You've familiarized yourself with
31
+ [React ↗](https://reactjs.org/docs/getting-started.html),
32
+ [Next.js ↗](https://nextjs.org/docs/getting-started), and
33
+ [Mui ↗](https://mui.com/getting-started/installation/). GraphCommerce is a
34
+ frontend React framework that uses Next.js for server-side rendering.
35
+
36
+ ---
37
+
38
+ <figure>
39
+
40
+ https://user-images.githubusercontent.com/1251986/154978614-8d2eaee1-d64b-4bae-a7d7-cfee2e9175d3.mp4
41
+
42
+ <video width="100%" controls autoPlay loop muted>
43
+ <source src="https://user-images.githubusercontent.com/1251986/154978614-8d2eaee1-d64b-4bae-a7d7-cfee2e9175d3.mp4" type="video/mp4"/>
44
+ </video>
45
+
46
+ <figcaption>Before customization of the header</figcaption>
47
+ </figure>
48
+
49
+ <figure>
50
+
51
+ https://user-images.githubusercontent.com/1251986/154979091-89c72d68-c62f-451c-af49-6f36f3fa6609.mp4
52
+
53
+ <video width="100%" controls autoPlay loop muted>
54
+ <source src="https://user-images.githubusercontent.com/1251986/154979091-89c72d68-c62f-451c-af49-6f36f3fa6609.mp4" type="video/mp4"/>
55
+ </video>
56
+
57
+ <figcaption>After customization of the header</figcaption>
58
+ </figure>
59
+
60
+ ### Move and justify the logo
61
+
62
+ - In /components/Layout/LayoutFull.tsx, move `<Logo />` after
63
+ `<DesktopNavBar>...</DesktopNavBar>`
64
+ - Wrap the `<Logo />` component in a `<Box>` component:
65
+
66
+ ```tsx
67
+ <Box
68
+ sx={{
69
+ display: 'flex',
70
+ justifyContent: 'center',
71
+ flexGrow: 1,
72
+ pointerEvents: 'none',
73
+ }}
74
+ >
75
+ <Logo />
76
+ </Box>
77
+ ```
78
+
79
+ - Add the import of 'Box' to the list of the `'@mui/material'` imports at the
80
+ top of the file
81
+ - Save the file to see your changes updated in real-time
82
+
83
+ <figure>
84
+ <img src="https://cdn-std.droplr.net/files/acc_857465/v0jqud" />
85
+ <figcaption>Reorder components</figcaption>
86
+ </figure>
87
+
88
+ ### Remove DesktopNavBar
89
+
90
+ - In /components/Layout/LayoutFull.tsx, remove the
91
+ `<DesktopNavBar>...</DesktopNavBar>` component.
92
+
93
+ <figure>
94
+ <img src="https://cdn-std.droplr.net/files/acc_857465/S1BIyc" />
95
+ <figcaption>Remove navigation</figcaption>
96
+ </figure>
97
+
98
+ ### Replace Search input with Search Fab
99
+
100
+ - In /components/Layout/LayoutFull.tsx, replace
101
+ `<SearchButton onClick={onSearchStart} label=' ' />` with:
102
+
103
+ ```tsx
104
+ <PageLink href='/search' passHref>
105
+ <Fab aria-label={t`Search`} size='large' color='inherit'>
106
+ <IconSvg src={iconSearch} size='large' />
107
+ </Fab>
108
+ </PageLink>
109
+ ```
110
+
111
+ - Add `iconSearch` to the existing imports from `'@graphcommerce/next-ui'` at
112
+ the top of the file
113
+
114
+ ### Remove Customer Service Fab
115
+
116
+ - In /components/Layout/LayoutFull.tsx, remove the Customer Service floating
117
+ action button by removing it completely:
118
+
119
+ ```tsx
120
+ <PageLink href='/service' passHref>
121
+ <Fab aria-label={t`Account`} size='large' color='inherit'>
122
+ <IconSvg src={iconCustomerService} size='large' />
123
+ </Fab>
124
+ </PageLink>
125
+ ```
126
+
127
+ <figure>
128
+ <img src="https://cdn-std.droplr.net/files/acc_857465/7eadNI" />
129
+ <figcaption>Replace search input with Search Fab, remove Customer Service Fab</figcaption>
130
+ </figure>
131
+
132
+ ### Make a local copy of the MenuFab component
133
+
134
+ - In /components/Layout/LayoutFull.tsx, remove `MenuFab` from the
135
+ `'@graphcommerce/next-ui'` import
136
+ - Add `import { MenuFab } from './MenuFab'` to the list of imports at the top of
137
+ the file
138
+
139
+ - Make a copy of /node_modules/@graphcommerce/next-ui/LayoutParts/MenuFab.tsx
140
+ and move it to the directory /components/Layout/MenuFab.tsx
141
+ - In /components/Layout/MenuFab.tsx, change
142
+ `const MotionDiv = styled(m.div)({})` to:
143
+ ```ts
144
+ const MotionDiv = styled('div')({})
145
+ ```
146
+ - Remove the `style={{...}}` prop from both the `<MotionDiv>` components to
147
+ remove the Fab scroll animation
148
+ - Remove `const { opacity, scale, shadowOpacity } = useFabAnimation()`
149
+
150
+ - Update all imports:
151
+
152
+ ```tsx
153
+ import {
154
+ extendableComponent,
155
+ responsiveVal,
156
+ iconClose,
157
+ iconMenu,
158
+ IconSvg,
159
+ } from '@graphcommerce/next-ui'
160
+ import { styled, Box, Fab, Menu, ListItem, Divider, alpha } from '@mui/material'
161
+ import { useRouter } from 'next/router'
162
+ import React, { useEffect } from 'react'
163
+ ```
164
+
165
+ <figure>
166
+ <img src="https://cdn-std.droplr.net/files/acc_857465/O1iBQ4" />
167
+ <figcaption>Local copy of the MenuFab component with Fab scroll animation removed</figcaption>
168
+ </figure>
169
+
170
+ ### Change the Menu component's styling
171
+
172
+ - In /components/Layout/MenuFab.tsx, change the `<Menu>` component's PaperProps
173
+ prop to:
174
+
175
+ ```tsx
176
+ PaperProps={{
177
+ sx: (theme) => ({
178
+ width: '100vw',
179
+ height: '100vh',
180
+ maxWidth: '100vw',
181
+ maxHeight: '100vh',
182
+ backgroundColor: alpha(theme.palette.text.primary, 0.95),
183
+ color: theme.palette.background.paper,
184
+ display: 'flex',
185
+ justifyContent: 'center',
186
+ alignItems: 'center',
187
+ borderRadius: 0,
188
+ '& svg': {
189
+ color: theme.palette.background.paper,
190
+ },
191
+ }),
192
+ }}
193
+ ```
194
+
195
+ - Remove the `<Menu>` component's prop 'disableScrollLock`
196
+ - Add a two props to the `<Menu>` component:
197
+
198
+ ```tsx
199
+ marginThreshold={0}
200
+ TransitionComponent={Fade}
201
+ ```
202
+
203
+ - Add the import of 'Fade' to the list of the `'@mui/material'` imports at the
204
+ top of the file
205
+ - Remove the search component by removing:
206
+
207
+ ```tsx
208
+ search ? (
209
+ <ListItem key='search' dense sx={{ mb: '6px', borderColor: 'red' }}>
210
+ {search}
211
+ </ListItem>
212
+ ) : null,
213
+ ```
214
+
215
+ <figure>
216
+ <img src="https://cdn-std.droplr.net/files/acc_857465/RyXlBV" />
217
+ <figcaption>Menu component with custom styling</figcaption>
218
+ </figure>
219
+
220
+ ## Next steps
221
+
222
+ - Learn how to [build pages](../getting-started/pages.md) in GraphCommerce
223
+ - Learn more about creating
224
+ [styled components with the styled() utility](../framework/theming.md)
@@ -0,0 +1,290 @@
1
+ ---
2
+ menu: 4. Build pages
3
+ metaTitle: Build pages
4
+ ---
5
+
6
+ > **Developer preview**
7
+ > This is a developer preview of GraphCommerce. The documentation will be
8
+ > updated as GraphCommerce introduces
9
+ > [new features and refines existing functionality](https://github.com/ho-nl/m2-pwa/releases).
10
+
11
+ # Build pages in GraphCommerce
12
+
13
+ Previously, you created a custom storefront and started customizing your
14
+ storefront in GraphCommerce. You're now ready to build pages in your
15
+ GraphCommerce app.
16
+
17
+ In this tutorial, you'll accomplish a series of tasks to add some specific
18
+ functionality to your custom storefront. The result will be simple, but you'll
19
+ learn where to find resources to build more complex features on your own.
20
+
21
+ ## What you'll learn
22
+
23
+ - Create a new route
24
+ - Add the page GraphQL queries required to render the layout (header, footer)
25
+ - Use getStaticProps to fetch GraphCMS data
26
+ - Use getStaticPaths to provide a list of all URLs to pre-render
27
+
28
+ ### Requirements
29
+
30
+ You've familiarized yourself with
31
+ [React ↗](https://reactjs.org/docs/getting-started.html),
32
+ [Next.js ↗](https://nextjs.org/docs/getting-started), and
33
+ [Mui ↗](https://mui.com/getting-started/installation/). GraphCommerce is a
34
+ frontend React framework that uses Next.js for server-side rendering.
35
+
36
+ ---
37
+
38
+ ### Create the route
39
+
40
+ - Create a new file, /about/about-us.tsx:
41
+
42
+ ```tsx
43
+ export default function AboutUs() {
44
+ return <>About Us</>
45
+ }
46
+ ```
47
+
48
+ - Visit the page: http://localhost:3000/about/about-us
49
+
50
+ ### Add GraphQL query
51
+
52
+ - In /about/about-us.tsx, replace the previous code with the following:
53
+
54
+ ```tsx
55
+ import { PageOptions } from '@graphcommerce/framer-next-pages'
56
+ import { StoreConfigDocument } from '@graphcommerce/magento-store'
57
+ import { GetStaticProps } from '@graphcommerce/next-ui'
58
+ import { Container } from '@mui/material'
59
+ import { GetStaticPaths } from 'next'
60
+ import { LayoutFull, LayoutFullProps } from '../../components'
61
+ import {
62
+ DefaultPageDocument,
63
+ DefaultPageQuery,
64
+ } from '../../graphql/DefaultPage.gql'
65
+ import { PagesStaticPathsDocument } from '../../graphql/PagesStaticPaths.gql'
66
+ import {
67
+ graphqlSsrClient,
68
+ graphqlSharedClient,
69
+ } from '../../lib/graphql/graphqlSsrClient'
70
+
71
+ type Props = DefaultPageQuery
72
+ type RouteProps = { url: string }
73
+ type GetPageStaticPaths = GetStaticPaths<RouteProps>
74
+ type GetPageStaticProps = GetStaticProps<LayoutFullProps, Props, RouteProps>
75
+
76
+ function AboutUs() {
77
+ return <Container>About Us</Container>
78
+ }
79
+
80
+ AboutUs.pageOptions = {
81
+ Layout: LayoutFull,
82
+ } as PageOptions
83
+
84
+ export default AboutUs
85
+
86
+ export const getStaticProps: GetPageStaticProps = async (context) => {
87
+ const { locale } = context
88
+ const client = graphqlSharedClient(locale)
89
+ const staticClient = graphqlSsrClient(locale)
90
+
91
+ const conf = client.query({ query: StoreConfigDocument })
92
+ const page = staticClient.query({
93
+ query: DefaultPageDocument,
94
+ variables: {
95
+ url: '',
96
+ rootCategory: (await conf).data.storeConfig?.root_category_uid ?? '',
97
+ },
98
+ })
99
+ // if (!(await page).data.pages?.[0]) return { notFound: true }
100
+ return {
101
+ props: {
102
+ ...(await page).data,
103
+ apolloState: await conf.then(() => client.cache.extract()),
104
+ },
105
+ revalidate: 60 * 20,
106
+ }
107
+ }
108
+ ```
109
+
110
+ - Visiting http://localhost:3000/about/about-us will output:
111
+
112
+ <figure>
113
+ <img src="https://cdn-std.droplr.net/files/acc_857465/xdI9be" />
114
+ <figcaption>Page with page layout (header, footer)</figcaption>
115
+ </figure>
116
+
117
+ ```tsx
118
+ // Example from /graphql/DefaultPage.graphql (DefaultPageDocument)
119
+
120
+ query DefaultPage($url: String!, $rootCategory: String!) {
121
+ ...MenuQueryFragment
122
+ ...FooterQueryFragment
123
+ ...PageContentQueryFragment
124
+ }
125
+ ```
126
+
127
+ In the `getStaticProps` function, the query `StoreConfigDocument` is used to
128
+ fetch information about the Magento storeview. Then, the query
129
+ `DefaultPageDocument` is used to fetch the data required to render the menu,
130
+ footer and page content.
131
+
132
+ In this example, the URL variable is empty. As a result, the
133
+ `...PageContentQueryFragment` will have no result when trying to fetch a
134
+ GraphCMS page with URL `''`.
135
+
136
+ The function `getStaticProps` is used to fetch data, meaning content is rendered
137
+ on the server. Review the page's source code and search for `About Us` to
138
+ validate that this string (currently hard-coded) is part of the source code.
139
+
140
+ ### Add GraphCMS content to the page
141
+
142
+ - Login to GraphCMS, navigate to Content and add a new Page entry with URL:
143
+ about/about-us
144
+ - In /about/about-us.tsx, make the following change to `getStaticProps`:
145
+
146
+ ```tsx
147
+ const page = staticClient.query({
148
+ query: DefaultPageDocument,
149
+ variables: {
150
+ url: 'about/about-us',
151
+ rootCategory: (await conf).data.storeConfig?.root_category_uid ?? '',
152
+ },
153
+ })
154
+ ```
155
+
156
+ And replace the previous AboutUs function with the following:
157
+
158
+ ```tsx
159
+ function AboutUs({ pages }: Props) {
160
+ const title = pages?.[0].title ?? ''
161
+
162
+ return <Container>{title}</Container>
163
+ }
164
+ ```
165
+
166
+ <figure>
167
+ <img src="https://cdn-std.droplr.net/files/acc_857465/PIOjzB" />
168
+ <figcaption>Fetch page content from GraphCMS</figcaption>
169
+ </figure>
170
+
171
+ <figure>
172
+ <img src="https://cdn-std.droplr.net/files/acc_857465/XKo4ut" />
173
+ <figcaption>GraphCMS entry</figcaption>
174
+ </figure>
175
+
176
+ ### Add pre-rendering with getStaticPaths
177
+
178
+ - Rename `/about/about-us.tsx` to `/about/[url].tsx`
179
+ - In /about/[url].tsx, replace the getStaticProps function with the following:
180
+
181
+ ```tsx
182
+ export const getStaticPaths: GetPageStaticPaths = (context) => ({
183
+ paths: [],
184
+ fallback: 'blocking',
185
+ })
186
+
187
+ export const getStaticProps: GetPageStaticProps = async (context) => {
188
+ const { locale, params } = context
189
+ const client = graphqlSharedClient(locale)
190
+ const staticClient = graphqlSsrClient(locale)
191
+
192
+ const conf = client.query({ query: StoreConfigDocument })
193
+ const page = staticClient.query({
194
+ query: DefaultPageDocument,
195
+ variables: {
196
+ url: `about/${params?.url}`,
197
+ rootCategory: (await conf).data.storeConfig?.root_category_uid ?? '',
198
+ },
199
+ })
200
+ // if (!(await page).data.pages?.[0]) return { notFound: true }
201
+ return {
202
+ props: {
203
+ ...(await page).data,
204
+ apolloState: await conf.then(() => client.cache.extract()),
205
+ },
206
+ revalidate: 60 * 20,
207
+ }
208
+ }
209
+ ```
210
+
211
+ By renaming the file to `/about/[url].tsx`, all routes starting with /about/
212
+ will be handled by the file (dynamic routing). Pages that have dynamic routes
213
+ need a list of paths to be statically generated.
214
+
215
+ All paths specified by a function called `getStaticPaths` will be statically
216
+ pre-rendered at build-time.
217
+
218
+ In the example above, the array with paths is empty. The required getStaticPaths
219
+ function is there, but no URLs are pre-rendered. Because getStaticPaths has the
220
+ option `fallback: 'blocking'`, the paths that have not been pre-rendered at
221
+ built-time will not result in a 404:
222
+
223
+ > From the
224
+ > [getStaticPaths API reference ↗](https://nextjs.org/docs/api-reference/data-fetching/get-static-paths):
225
+ > If fallback is 'blocking', new paths not returned by getStaticPaths will wait
226
+ > for the HTML to be generated, identical to SSR (hence why blocking), and then
227
+ > be cached for future requests so it only happens once per path.
228
+
229
+ ### Pre-render all /about/ pages from GraphCMS
230
+
231
+ - In /about/[url].tsx, replace the getStaticPaths function with the following:
232
+
233
+ ```tsx
234
+ export const getStaticPaths: GetPageStaticPaths = async (context) => {
235
+ const { locales = [] } = context
236
+ // if (process.env.NODE_ENV === 'development') return { paths: [], fallback: 'blocking' }
237
+
238
+ const path = async (locale: string) => {
239
+ const client = graphqlSharedClient(locale)
240
+ const { data } = await client.query({
241
+ query: PagesStaticPathsDocument,
242
+ variables: {
243
+ first: 10,
244
+ urlStartsWith: 'about',
245
+ },
246
+ })
247
+ return data.pages.map((page) => ({
248
+ params: { url: page.url.split('/').slice(1)[0] },
249
+ locale,
250
+ }))
251
+ }
252
+ const paths = (await Promise.all(locales.map(path))).flat(1)
253
+ // console.log(paths)
254
+ return { paths, fallback: 'blocking' }
255
+ }
256
+ ```
257
+
258
+ The PagesStaticPathsDocument query is used to fetch all pages from GraphCMS that
259
+ have a URL starting with 'about'. The locale options from the context object are
260
+ used to create an array:
261
+
262
+ ```txt
263
+ // Terminal output for console.log(paths), upon refreshing the page
264
+
265
+ [
266
+ { params: { url: 'about-us' }, locale: 'en-us' },
267
+ { params: { url: 'about-us' }, locale: 'nl' },
268
+ { params: { url: 'about-us' }, locale: 'fr-be' },
269
+ { params: { url: 'about-us' }, locale: 'nl-be' },
270
+ { params: { url: 'about-us' }, locale: 'en-gb' },
271
+ { params: { url: 'about-us' }, locale: 'en-ca' },
272
+ ]
273
+ ```
274
+
275
+ ## Build your local environment
276
+
277
+ You can test the static build process by running it locally:
278
+
279
+ - `cd /examples/magento-graphcms/` Navigate to the project directory
280
+ - `yarn build` Start static build process
281
+
282
+ <figure>
283
+ <img src="https://cdn-std.droplr.net/files/acc_857465/AAOnX2" />
284
+ <figcaption>Successful pre-render of the about/about-us page</figcaption>
285
+ </figure>
286
+
287
+ ## Next steps
288
+
289
+ - Learn how to
290
+ [build a custom GraphCMS component](../getting-started/graphcms-component.md)