eddev 0.2.20 → 0.2.23

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 (103) hide show
  1. package/build/serverless/create-next-app.js +1 -0
  2. package/config/config-schema.d.ts +5 -0
  3. package/config/config-schema.js +1 -0
  4. package/config/get-config.d.ts +3 -0
  5. package/config/parse-config.d.ts +2 -0
  6. package/dev-ui/theme.d.ts +4 -5
  7. package/docs_old/README.md +33 -0
  8. package/docs_old/babel.config.js +3 -0
  9. package/docs_old/blog/2019-05-28-first-blog-post.md +12 -0
  10. package/docs_old/blog/2019-05-29-long-blog-post.md +44 -0
  11. package/docs_old/blog/2021-08-01-mdx-blog-post.mdx +20 -0
  12. package/docs_old/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  13. package/docs_old/blog/2021-08-26-welcome/index.md +25 -0
  14. package/docs_old/blog/authors.yml +17 -0
  15. package/docs_old/docs/graphql/1.graphql-overview.md +62 -0
  16. package/docs_old/docs/graphql/2.query-hooks.md +238 -0
  17. package/docs_old/docs/graphql/3.extending-wpgraphql.md +3 -0
  18. package/docs_old/docs/graphql/_category_.json +4 -0
  19. package/docs_old/docs/graphql/img/graphql-ide.png +0 -0
  20. package/docs_old/docs/graphql/img/infinite-example.gif +0 -0
  21. package/docs_old/docs/graphql/img/mutation-example.gif +0 -0
  22. package/docs_old/docs/gutenberg/1.overview.md +25 -0
  23. package/docs_old/docs/gutenberg/2.block-definition.md +37 -0
  24. package/docs_old/docs/gutenberg/3.block-acf.md +13 -0
  25. package/docs_old/docs/gutenberg/4.block-graphql.md +63 -0
  26. package/docs_old/docs/gutenberg/5.inline-editing.md +33 -0
  27. package/docs_old/docs/gutenberg/6.nested-blocks.md +80 -0
  28. package/docs_old/docs/gutenberg/7.restricting-to-post-types.md +38 -0
  29. package/docs_old/docs/gutenberg/8.restricting-to-page-templates.md +26 -0
  30. package/docs_old/docs/gutenberg/9.dynamic-blocks.md +21 -0
  31. package/docs_old/docs/gutenberg/_category_.json +4 -0
  32. package/docs_old/docs/gutenberg/img/create-acf-fields-for-block.png +0 -0
  33. package/docs_old/docs/gutenberg/img/example-acf-single-project-tile.png +0 -0
  34. package/docs_old/docs/how-to/1.new-site.md +36 -0
  35. package/docs_old/docs/how-to/2.deployment.md +31 -0
  36. package/docs_old/docs/how-to/3.menus.md +72 -0
  37. package/docs_old/docs/how-to/4.options-pages.md +41 -0
  38. package/docs_old/docs/how-to/5.bundle-size.md +177 -0
  39. package/docs_old/docs/how-to/6.favicons.md +82 -0
  40. package/docs_old/docs/how-to/_category_.json +4 -0
  41. package/docs_old/docs/how-to/img/bundle-analysis-after.png +0 -0
  42. package/docs_old/docs/how-to/img/bundle-analysis-before.png +0 -0
  43. package/docs_old/docs/how-to/img/bundle-webpack-after.png +0 -0
  44. package/docs_old/docs/how-to/img/bundle-webpack-before.png +0 -0
  45. package/docs_old/docs/how-to/img/favicon-codebase.png +0 -0
  46. package/docs_old/docs/how-to/img/favicon-figma-export.png +0 -0
  47. package/docs_old/docs/how-to/img/favicon-figma.png +0 -0
  48. package/docs_old/docs/intro.md +7 -0
  49. package/docs_old/docs/known-issues.md +8 -0
  50. package/docs_old/docs/serverless/1.overview.md +1 -0
  51. package/docs_old/docs/serverless/2.config.md +1 -0
  52. package/docs_old/docs/serverless/3.wordpress-vercel.md +8 -0
  53. package/docs_old/docs/serverless/4.apis.md +1 -0
  54. package/docs_old/docs/serverless/5.rpc.md +1 -0
  55. package/docs_old/docs/serverless/_category_.json +4 -0
  56. package/docs_old/docs/stack/1-WordPress.md +18 -0
  57. package/docs_old/docs/stack/2-Flywheel.md +15 -0
  58. package/docs_old/docs/stack/3-React.md +12 -0
  59. package/docs_old/docs/stack/4-TypeScript.md +13 -0
  60. package/docs_old/docs/stack/5-WPGraphQL.md +21 -0
  61. package/docs_old/docs/stack/6-eddev.md +9 -0
  62. package/docs_old/docs/stack/_category_.json +4 -0
  63. package/docs_old/docs/tooling/1.scripts.md +25 -0
  64. package/docs_old/docs/tooling/2.aliases.md +13 -0
  65. package/docs_old/docs/tooling/3.defines.md +13 -0
  66. package/docs_old/docs/tooling/4.config-file.md +14 -0
  67. package/docs_old/docs/tooling/_category_.json +4 -0
  68. package/docs_old/docs/views/1.overview.md +31 -0
  69. package/docs_old/docs/views/2.queries.md +18 -0
  70. package/docs_old/docs/views/3.content-blocks.md +36 -0
  71. package/docs_old/docs/views/4.app-view.md +35 -0
  72. package/docs_old/docs/views/5.page-templates.md +20 -0
  73. package/docs_old/docs/views/_category_.json +4 -0
  74. package/docs_old/docusaurus.config.js +119 -0
  75. package/docs_old/package.json +40 -0
  76. package/docs_old/sidebars.js +26 -0
  77. package/docs_old/src/components/HomepageFeatures.js +64 -0
  78. package/docs_old/src/components/HomepageFeatures.module.css +11 -0
  79. package/docs_old/src/css/custom.css +28 -0
  80. package/docs_old/src/pages/index.js +36 -0
  81. package/docs_old/src/pages/index.module.css +23 -0
  82. package/docs_old/src/pages/markdown-page.md +7 -0
  83. package/{components/ServerlessRouter.d.ts → docs_old/static/.nojekyll} +0 -0
  84. package/docs_old/static/img/docusaurus.png +0 -0
  85. package/docs_old/static/img/favicon.ico +0 -0
  86. package/docs_old/static/img/logo-black.svg +4 -0
  87. package/docs_old/static/img/logo-white.svg +4 -0
  88. package/docs_old/static/img/tutorial/docsVersionDropdown.png +0 -0
  89. package/docs_old/static/img/tutorial/localeDropdown.png +0 -0
  90. package/docs_old/static/img/undraw_docusaurus_mountain.svg +170 -0
  91. package/docs_old/static/img/undraw_docusaurus_react.svg +169 -0
  92. package/docs_old/static/img/undraw_docusaurus_tree.svg +1 -0
  93. package/docs_old/yarn.lock +8814 -0
  94. package/dynamic/dynamic-component.d.ts +0 -1
  95. package/entry/Root.d.ts +1 -1
  96. package/gravityforms/useGravityForm.js +0 -2
  97. package/package.json +1 -1
  98. package/serverless/define-rpc-router.d.ts +1 -1
  99. package/serverless-template/package.json +1 -1
  100. package/serverless-template/pages/_document.tsx +20 -1
  101. package/style/createStitches.d.ts +4 -5
  102. package/utils/getRepoName.js +7 -1
  103. package/components/ServerlessRouter.js +0 -1
@@ -0,0 +1,177 @@
1
+ # Bundle Size Tips
2
+
3
+ ## Inspecting Bundle Size
4
+
5
+ You can quite easily see the production size of your app by running:
6
+
7
+ ```bash
8
+ yarn build
9
+ ```
10
+
11
+ ![Webpack Result](./img/bundle-webpack-before.png)
12
+
13
+ Above, we can see that the bundle size is 1.34mb, which is quite large. The note from Webpack says that we should aim for 244kb, which is really quite small. When we eventually move to serverless (via Vercel) for production frontends, we'll certainly aim for this smaller size. For now, with WordPress hosting, 600-700kb is fine. React itself takes up a bit of space on it's own.
14
+
15
+ Let's dig deeper into why the bundle is so large.
16
+
17
+ Our compile system includes the official [Webpack Bundle Analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer) plugin. You can get a detailed analysis of the bundle size using the following:
18
+
19
+ ```bash
20
+ yarn build
21
+ open dist/frontend/bundle-report.html
22
+ ```
23
+
24
+ Your browser will launch the bundle report, which will look something like this.
25
+
26
+ ![Bundle Size Output](./img/bundle-analysis-before.png)
27
+
28
+ You can see in the example above, that `hls.js` and `moment` + `moment-timezone` are taking up _a lot_ of the bundle size.
29
+
30
+ What can we do about this?
31
+
32
+ ## Choosing better libraries
33
+
34
+ In the example above, `moment` is taking up SO much space, for something that is so simple. There are much simpler and smaller libraries that can be used instead.
35
+
36
+ - If all you want is date formatting, check out `date-fns` — which provides a nifty date formatting function. The library is tree-shakable, meaning only the functions from that library you actually use in your code will be included in the bundle. [date-fns →](https://date-fns.org/)
37
+ - If you need something a little more powerful, or if you need something related to timezones, check out `luxon`, which is made by the same team that created `moment`. It's a much lighter alternative, because even though it supports timezones, it uses native browser APIs, instead of bundling info on every timezone/locale. [Luxon →](https://moment.github.io/luxon/index.html#/?id=luxon)
38
+ - (ps. Luxon doesn't come with TypeScript types, but you can install them using `yarn add --dev @types/luxon`)
39
+
40
+ It's always worth reconsidering the libraries we choose, looking for the most modern libraries for certain functions.
41
+
42
+ ## Dynamic imports
43
+
44
+ Next up is `hls.js`. It's a library that provides a simple way to load and play HLS streams. It's not huge, but we probably don't need to include it in the main bundle.
45
+
46
+ Say we have the following code:
47
+
48
+ ```tsx
49
+ import Hls from "hls.js"
50
+
51
+ // ...
52
+
53
+ useEffect(() => {
54
+ const video = ref.current!
55
+ if (src) {
56
+ if (video.canPlayType("application/vnd.apple.mpegurl")) {
57
+ // HLS is already supported natively by this browser
58
+ video.src = props.url
59
+ } else {
60
+ // HLS is not supported by the browser. Use Hls.js instead!
61
+ const hls = new Hls()
62
+ hls.loadSource(props.url!)
63
+ hls.attachMedia(video)
64
+ return () => {
65
+ hls.destroy()
66
+ }
67
+ }
68
+ }
69
+ }, [src])
70
+ ```
71
+
72
+ We can quite easily refactor this code to use dynamic imports, which will automatically split that library into it's own file, which will be imported separately only if/when it's needed. If we still need TypeScript types for the module, we can also use `import type` syntax, which will only import the types for TypeScript's sake, and not the module itself.
73
+
74
+ ```tsx
75
+ import type Hls from "hls.js"
76
+
77
+ // ...
78
+
79
+ useEffect(() => {
80
+ const video = ref.current!
81
+ if (props.url) {
82
+ if (video.canPlayType("application/vnd.apple.mpegurl")) {
83
+ // HLS is already supported natively by this browser
84
+ video.src = props.url
85
+ } else {
86
+ // HLS is not supported by the browser. Use Hls.js instead!
87
+ // Declare a reference to the object, so we can can still destroy it when the component transitions out
88
+ let hls: Hls
89
+ import("hls.js").then(({ default: Hls }) => {
90
+ // hls.js has been successfully dynamically imported.
91
+ // Assign to the `hls` variable, so that it can be destroyed properly
92
+ hls = new Hls()
93
+ hls.loadSource(props.url!)
94
+ hls.attachMedia(video)
95
+ })
96
+ return () => {
97
+ // Destroy the hls video, as long as it was created in the first place
98
+ if (hls) {
99
+ hls.destroy()
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }, [props.url])
105
+ ```
106
+
107
+ ## Dynamicly imported components
108
+
109
+ Similar to Next's `next/dynamic` [(link)](https://nextjs.org/docs/advanced-features/dynamic-import), we have our own `eddev/dynamic` function. This allows you dynamically load components from the `components/*` directory using dynamic imports.
110
+
111
+ ```tsx title="blocks/homepage/some-block.tsx"
112
+ import { dynamic } from "eddev/dynamic"
113
+
114
+ const MyDynamicComponent = dynamic(() => import("@components/something/my-dynamic-component"))
115
+
116
+ export default defineBlock("homepage/some-block", () => {
117
+ return (
118
+ <div>
119
+ <p>I appear instantly</p>
120
+ <MyDynamicComponent fallback={<div>Loading...</div>} />
121
+ </div>
122
+ )
123
+ })
124
+ ```
125
+
126
+ All the same props from `MyDynamicComponent` are available, and the fallback (which is optional) is added as a prop by the `dynamic` function. It'll show the fallback while the component is loading.
127
+
128
+ When using this feature, you may notice a flash while the component is being loaded, since your page will actually render without the dynamic component first. This means that it may not always be suitable if the component is typically "above the fold". You may want to consider showing a placeholder div, and/or fading in the component using an animation once it's loaded.
129
+
130
+ It's also important to note that the dynamic function expects (by default), a `default` export. Normally, we prefer to export named components, but in this case, `default` is good.
131
+
132
+ ```tsx title="components/something/my-dynamic-component.tsx"
133
+ // BAD: export function MyDynamicComponent() {}
134
+ // GOOD:
135
+ export default function MyDynamicComponent() {
136
+ return <div>I'm a dynamic component!</div>
137
+ }
138
+ ```
139
+
140
+ Internally, we use `@loadable/components` — you can see other options for `dynamic` via their [docs](https://loadable-components.com/). Next also uses this library!
141
+
142
+ ## Dynamically imported blocks
143
+
144
+ The `eddev/dynamic` function requires a tiny bit of boilerplate to get going. If you'd like to make a whole _block_ load dynamically, it's even easier. Note though that you wont be able to show a loading fallback.
145
+
146
+ Just add `Dynamic: true` to your block header comment — the compiler will spot this, and automatically turn it into a dynamic component. That's it!
147
+
148
+ ```tsx title="blocks/homepage/some-block.tsx"
149
+ /**
150
+ * Title: Some Block
151
+ * Description: A block that does something cool
152
+ * Category: common
153
+ * Icon: book-alt
154
+ * Keywords: post
155
+ * Templates: default
156
+ * Types: page
157
+ * Mode: preview
158
+ * Supports multiple: true
159
+ * Tags: root
160
+ * Child Tags: none
161
+ * Dynamic: true
162
+ */
163
+ ```
164
+
165
+ ^ The last line is the important part. You can read more about dynamic blocks [here](../gutenberg/dynamic-blocks).
166
+
167
+ ## Validating the changes
168
+
169
+ In the top sections above, we swapped from `moment` to `luxon`, and we also made `hls.js` a dynamic import.
170
+
171
+ After running `yarn build` again, and checking out the visualizer, we can see that these two small changes have reduced our main bundle size by **HALF**.
172
+
173
+ ![Webpack Result](./img/bundle-webpack-after.png)
174
+
175
+ ![Bundle Size Output](./img/bundle-analysis-after.png)
176
+
177
+ We could take this even further if we wanted, by making any blocks which use Swiper dynamic blocks, as discussed above.
@@ -0,0 +1,82 @@
1
+ # Favicons
2
+
3
+ Since `eddev@0.2.0`, favicons are automatically included in every page, in both serverless and WordPress. All you need to do is export the icons straight from Figma!
4
+
5
+ ## Exporting the icons
6
+
7
+ 1. Navigate to the **🍒 oGraph & Icons** page in Figma
8
+ 2. Select all the icons on the right
9
+ 3. Activate the **Export** tab in the sidebar
10
+ 4. Export with default settings to the `assets` folder in your theme.
11
+ 5. Run `yarn dev` to regenerate the `favicon.ico` file, which is used as a fallback. The `<head>` is published automatically.
12
+
13
+ :::tip
14
+ See the bottom of this page for screenshots!
15
+ :::
16
+
17
+ ## `favicon.ico`
18
+
19
+ When you run `yarn dev` or `yarn build`, a `favicon.ico` is automatically generated for you!
20
+
21
+ It uses the uses the pattern `assets/favicon/favicon-*.png`, which usually means it'll be composed using `favicon-16x16.png`, `favicon-32x32.png` and `favicon-96x96.png`.
22
+
23
+ ## Light & Dark Mode Icons
24
+
25
+ Not all browsers support SVG favicons, but they're a great way to optionally support light/dark mode. You can right-click and 'Copy as SVG', and then add appropriate styling. Save to `assets/favicon/favicon.svg`, and it'll automatically be added to the `<head>` tag.
26
+
27
+ See below for an example:
28
+
29
+ ```svg title="assets/favicon/favicon.svg"
30
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
31
+ xmlns="http://www.w3.org/2000/svg">
32
+ <style>
33
+ path {
34
+ fill: #000000;
35
+ }
36
+ @media (prefers-color-scheme: dark) {
37
+ path {
38
+ fill: #ffffff;
39
+ }
40
+ }
41
+ </style>
42
+ <path d="..." />
43
+ </svg>
44
+ ```
45
+
46
+ ## Meta Tags
47
+
48
+ The appropriate `<link />` tags are automatically added to your `<head>` tag, so you don't need to worry about it. Note that these tags only appear if they're found in the correct folder (`assets/favicon/`).
49
+
50
+ ## Filenames
51
+
52
+ The following files are expected to be found. Note that if they are missing, there are no errors!
53
+
54
+ ```
55
+ /assets/favicons/favicon.svg
56
+ /assets/favicons/120x120.png
57
+ /assets/favicons/128x128.png
58
+ /assets/favicons/196x196.png
59
+ /assets/favicons/apple-touch-icon-120x120.png
60
+ /assets/favicons/apple-touch-icon-152x152.png
61
+ /assets/favicons/apple-touch-icon-167x167.png
62
+ /assets/favicons/apple-touch-icon-180x180.png
63
+ /assets/favicons/favicon-16x16.png
64
+ /assets/favicons/favicon-32x32.png
65
+ /assets/favicons/favicon-96x96.png
66
+ /assets/favicons/windows-270x270.png
67
+ /assets/favicons/windows-70x70.png
68
+ ```
69
+
70
+ ## Screenshots of export steps
71
+
72
+ Select all the icons, skipping the labels:
73
+
74
+ ![Figure A. Select all icons](./img/favicon-figma.png)
75
+
76
+ Export your selection:
77
+
78
+ ![Figure B. Export them](./img/favicon-figma-export.png)
79
+
80
+ Your codebase should look like this after you've exported them. Note that if you instead see an `App icon` folder, you should rename this to `favicon` and ensure that it matches as below:
81
+
82
+ ![Figure C. You should now have a 'favicons' folder](./img/favicon-codebase.png)
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "🧐 How To",
3
+ "position": 20
4
+ }
@@ -0,0 +1,7 @@
1
+ ---
2
+ sidebar_position: 1
3
+ ---
4
+
5
+ # 👋 Intro
6
+
7
+ Welcome! Use the sidebar on the left to find what you're looking for.
@@ -0,0 +1,8 @@
1
+ ---
2
+ sidebar_position: 100
3
+ ---
4
+
5
+ # Known Issues
6
+
7
+ - Fragments from `/queries/fragments` don't run in GraphiQL IDE
8
+ - Block ACF fields cannot be queried in the GraphiQL IDE
@@ -0,0 +1 @@
1
+ # Overview
@@ -0,0 +1 @@
1
+ # Config
@@ -0,0 +1,8 @@
1
+ # WordPress + Vercel
2
+
3
+ WIP
4
+
5
+ - `SITE_URL` environment variable in Vercel
6
+ - `serverless.endpoints` option in `ed.config.json` — so that:
7
+ - Frontend code executed in WordPress can access API endpoints hosted on Vercel
8
+ - WordPress can redirect to the Vercel URL if WordPress is being used completely headless
@@ -0,0 +1 @@
1
+ # APIs
@@ -0,0 +1 @@
1
+ # RPC API
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "☀️ Serverless",
3
+ "position": 5
4
+ }
@@ -0,0 +1,18 @@
1
+ ---
2
+ sidebar_position: 1
3
+ ---
4
+
5
+ # WordPress
6
+
7
+ There are several CMS' out there, and while WordPress may not be the most modern, it's very well known (both to clients and developers) and is easy to work with and host.
8
+
9
+ ## Why not a cloud-based headless CMS + Next.js?
10
+
11
+ We use WordPress as a semi-headless CMS. While there are plenty of cloud-based headless CMS' out there, there are several issues with using them:
12
+
13
+ - They can be quite expensive!
14
+ - They often lack features we require, such as versioning, translation, ecommerce, user registration, user-submitted data, live preview and block-based content editing. These features are also often hidden behind an expensive 'Enterprise' plan.
15
+ - The lack of specific features often leads to the requirement of additional third-party platforms, which adds a great deal of complexity to our projects.
16
+ - Integrating them with frameworks like Next.js require lots of boilerplate code, which becomes hard to maintain.
17
+ - Next.js' file-based routing is great for web apps, but imposes limitations on URL customisation which are hard to overcome.
18
+ - We love our elegant page transitions, and these are harder to achive with Next.js.
@@ -0,0 +1,15 @@
1
+ ---
2
+ sidebar_position: 2
3
+ ---
4
+
5
+ # Flywheel + Local
6
+
7
+ Our primary WordPress hosting provider is [Flywheel](https://getflywheel.com/). We have an organisation plan which allows us to host hundreds of WordPress sites, managed in an easy-to-use [dashboard](https://app.getflywheel.com/).
8
+
9
+ [Local](https://localwp.com/) is a desktop app which provides a development environment for WordPress sites, and was developed by Flywheel. It has useful 'sync' functionality, allowing you to push/pull files and the database between Local and a Flywheel site.
10
+
11
+ ## Local Sync
12
+
13
+ Feel free to use Local Sync to deploy your WordPress site to Flywheel during the initial stages of development, however it's recommended that you use Github Actions to automate code deployment.
14
+
15
+ Pulling from Flywheel to Local is also a great way to pull down a site to work on it locally — just don't forget to re-clone the theme folder so that it's correctly linked to Git.
@@ -0,0 +1,12 @@
1
+ ---
2
+ sidebar_position: 3
3
+ ---
4
+
5
+ # React
6
+
7
+ There's not much to say! React is great. It's particularly great for complex UI.
8
+
9
+ Be sure you're across React, hooks and how to use TypeScript with React. You should also probably know how Context works
10
+
11
+ - [React Hooks Guide on Smashing Magazine](https://www.smashingmagazine.com/2020/04/react-hooks-api-guide/) — goes over all the core hooks, as well as how to create custom hooks.
12
+ - [React & TypeScript: how to type hooks (a complete guide)](https://devtrium.com/posts/react-typescript-how-to-type-hooks) — learn by looking! Lots of examples and tips on how to correctly use hooks with TypeScript.
@@ -0,0 +1,13 @@
1
+ ---
2
+ sidebar_position: 4
3
+ ---
4
+
5
+ # TypeScript
6
+
7
+ TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. We use TypeScript to write code that is easier to read and understand, although it is not as fast as JavaScript.
8
+
9
+ Some resources:
10
+
11
+ - [TypeScript — The Basics](https://www.youtube.com/watch?v=ahCwqrYpIuM) (video)
12
+ - [TypeScript with React](https://www.notion.so/ed-studio/ED-Stack-2021-Tour-7f50bc455d95403ebdff9a4503a78aee#b15ee6c11d40449e8f18b9ff19301901) (Udemy course)
13
+ - [React & TypeScript: how to type hooks (a complete guide)](https://devtrium.com/posts/react-typescript-how-to-type-hooks) — learn by looking! Lots of examples and tips on how to correctly use hooks with TypeScript.
@@ -0,0 +1,21 @@
1
+ # (WP)GraphQL
2
+
3
+ "GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools." (from the [GraphQL Website](https://graphql.org/)).
4
+
5
+ The [WPGraphQL](https://www.wpgraphql.com/) plugin (which is actually installed in the theme with Composer, rather than a plugin), provides a GraphQL API for WordPress.
6
+
7
+ ## Schemas
8
+
9
+ GraphQL requires a server to be running to serve the queries. The WPGraphQL plugin provides a server that can be accessed at the URL `/graphql`, or via the `graphql()` PHP function.
10
+
11
+ The schema is automatically generated for you by the plugin, and makes all WordPress data available to you via queries.
12
+
13
+ You can define your own types and fields on the schema using the PHP functions documented on the [WPGraphQL website](https://www.wpgraphql.com/functions/).
14
+
15
+ ## Queries
16
+
17
+ Queries are written in `.graphql` files, which can be stored in three locations in your code.
18
+
19
+ - `blocks/*/*.graphql`, alongside a block's `.tsx` file. Queries in these files will be run automatically by the server when the page is visited, and the data is passed as props to the block component. This allows blocks to query any other data on the site. Blocks can also query ACF fields defined on the block, via the global `block` field, which represents the current block being executed.
20
+ - `views/*.graphql`, alongside any View `.tsx` file. Just like blocks, the data is passed to the view's component. They can also use special variables to refer to the current post, or some querystring value.
21
+ - `queries/*.graphql`— these queries will have React hooks automatically generated for them, allowing the queries or mutations to be executed on demand by your React code. This is useful for components which need to perform searching/filtering/pagination, handle user data submissions, trigger server-side code etc.
@@ -0,0 +1,9 @@
1
+ # `eddev` Library
2
+
3
+ ## Purpose
4
+
5
+ TBA
6
+
7
+ ## Features
8
+
9
+ TBA
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "📚 The Stack",
3
+ "position": 1
4
+ }
@@ -0,0 +1,25 @@
1
+ # Scripts
2
+
3
+ ## `yarn dev`
4
+
5
+ The 'dev' command provides hot-reloading for multiple bundles — like frontend, admin and (eventually) serverless.
6
+
7
+ It's custom built, and made to be as clean as possible by showing issues relevant to the most recent attempt at a rebuild.
8
+
9
+ ### Webpack
10
+
11
+ Internally, the system uses [Webpack](https://webpack.js.org/) and [webpack-dev-server](https://webpack.js.org/configuration/dev-server/), along with [react-refresh](https://github.com/pmmmwh/react-refresh-webpack-plugin). Webpack configuration is _not editable_, and is auto-generated by the tool itself. We may swap Webpack out for another tool such as `swc` or `esbuild` at some point in the future for an additional speed boost, and so allowing access to Webpack config could result in compatibility issues.
12
+
13
+ For speed, each Webpack bundle runs in a separate worker thread, so that each bundle can compile concurrently, taking advantage of multiple CPU cores.
14
+
15
+ ### GraphQL Codegen
16
+
17
+ The dev tool also provides realtime GraphQL -> TypeScript generation, by monitoring your project for changes and rebuilding when appropriate. For this, we're using [GraphQL Code Generator](https://www.graphql-code-generator.com/) with a host of custom plugins.
18
+
19
+ These files are _only_ generated by the dev tool, and not be the `yarn build` tooling. This only really matters for dynamic queries in the `queries/` folder. To be safe, you should always make sure `yarn dev` runs after editing a `.graphql` file in your project.
20
+
21
+ ## `yarn build`
22
+
23
+ This produces production builds of the frontend and admin bundles, with tree shaking, minification and code-splitting.
24
+
25
+ It also produces a bundle sizing report, in `/dist/frontnend/bundle-report.html` — which you can use to see which dependencies are bloating up your bundle files. If a dependency is too large, consider dynamically importing it instead.
@@ -0,0 +1,13 @@
1
+ # Aliases
2
+
3
+ There are a few import aliases predefined for you.
4
+
5
+ ```
6
+ @components/* -> ./components/*
7
+ @hooks/* -> ./hooks/*
8
+ @utils/* -> ./utils/*
9
+ @theme -> ./theme.css.tsx
10
+ @queries -> ./hooks/queries.ts
11
+ ```
12
+
13
+ This just means that you can use absolute paths to import your components and hooks etc, rather than having to use relative paths — making copy/pasting of import statements around your codebase a little bit easier.
@@ -0,0 +1,13 @@
1
+ # Defines
2
+
3
+ There are a few globally accessible variables which you can access, which are defined via Webpack's `DefinePlugin`
4
+
5
+ From [Webpack configuration docs](https://webpack.js.org/plugins/define-plugin/):
6
+
7
+ > The `DefinePlugin` replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds. If you perform logging in your development build but not in the production build you might use a global constant to determine whether logging takes place. That's where DefinePlugin shines, set it and forget it rules for development and production builds.
8
+
9
+ The following variables are available:
10
+
11
+ - `process.dev` — `true` or `false`, depending on whether this bundle is targetting at dev mode or not.
12
+ - `process.admin` - `true` or `false`, depending on whether this bundle is used for the admin editor (Gutenberg) or on the frontend. Useful for rendering blocks for better editing experience.
13
+ - `process.themePath` - The relative URI pointing to the theme directory. Useful for calculating the location of assets. Note that there is NO trailing slash.
@@ -0,0 +1,14 @@
1
+ # Config File
2
+
3
+ You'll find a `ed.config.json` file in the root of your theme folder. This file is read by both the `eddev` dev and build tool, along with the supporting `eddev-php` library.
4
+
5
+ Here are the options:
6
+
7
+ - `serverless` — An optional object.
8
+ - `enabled` — `true` or `false` — Controls whether serverless node is enabled for this project.
9
+ - `uploads` — `"proxy"` or `"remote"`
10
+ - `plugins` — `"proxy"` or `"remote"`
11
+ - `theme` — `"proxy"`, `"remote"` or `"copy"`
12
+ - `devAssets` — an optional array of glob paths or file names, relative to the theme folder, which are necessary for the frontend — this includes `assets/**` by default.
13
+
14
+ You can also find the original schema file [here](https://github.com/ed-digital/eddev/blob/main/src/config/config-schema.ts).
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "🛠 Tooling",
3
+ "position": 2
4
+ }
@@ -0,0 +1,31 @@
1
+ # Views Overview
2
+
3
+ Views represent the different page types of the site. WordPress will choose which view to use based on the URL of the page. If for example, it identifies that the url `/blog/my-first-post` is a "post" object, it'll first look for `views/single-post.tsx`, followed by `views/single.tsx`. If it doesn't find either of those, it'll use `views/_404.tsx`. The naming of view files follows WordPress' [Template Hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/).
4
+
5
+ Views exist within the `views` directory as `.tsx` files, often with a paired `.graphql` file.
6
+
7
+ The standard `views/page.tsx` looks like this:
8
+
9
+ ```tsx title="views/page.tsx"
10
+ import { Heading } from "@components/atoms/Heading"
11
+ import { Container } from "@components/layout/Grid"
12
+ import { defineView } from "eddev/views"
13
+ import { ContentBlocks } from "eddev"
14
+
15
+ export default defineView("page", (props) => {
16
+ return (
17
+ <Container>
18
+ <Heading variant="h1" css={{ pb: "$6" }}>
19
+ {props.page?.title}
20
+ </Heading>
21
+ <ContentBlocks blocks={props.page?.contentBlocks} />
22
+ </Container>
23
+ )
24
+ })
25
+ ```
26
+
27
+ You'll notice above the following:
28
+
29
+ - The file exports a view defined with the `defineView` function, and the first argument passed to it is the name of the view. This MUST be consistent with the name of the file. The general rule is `views/{name}.tsx`. We just care about the name part!
30
+ - We're getting some data from props — `props.page.title` and `props.page.contentBlocks`. These are coming from the linked query file (see the next section)
31
+ - The code itself is quite lean. It wouldn't be strange to have a more complex file, but in general it's better to move as much code as possible into separate component files. This encourages reusability and makes it easier to maintain.
@@ -0,0 +1,18 @@
1
+ # View Queries
2
+
3
+ Views typically need to access data about the current page or object, as well as other arbitrary content from the CMS. To do so, create a `.graphql` file with the same name as the `.tsx` file. The GraphQL query will be executed every request, and the data is automatically passed to the view when it is rendered. You never need to handle the loading process yourself!
4
+
5
+ To query the current page or post being viewed, use `$postId` as an input variable.
6
+
7
+ ```graphql title="views/page.graphql"
8
+ query Page($postId: ID!) {
9
+ page(id: $postId, idType: DATABASE_ID) {
10
+ title
11
+ slug
12
+ template {
13
+ templateName
14
+ }
15
+ contentBlocks
16
+ }
17
+ }
18
+ ```
@@ -0,0 +1,36 @@
1
+ # Content Blocks
2
+
3
+ To allow Gutenberg blocks on your page, you'll need to do two things:
4
+
5
+ 1. Ensure you've got a `.graphql` file which selects the `contentBlocks` field from the your post type.
6
+ 2. Pass the `contentBlocks` field to the `blocks` prop of the `<ContentBlocks />` component.
7
+
8
+ The `ContentBlocks` component is much like `InnerBlocks`, except that blocks are passed in as an array, rather than implictly.
9
+
10
+ ```graphql title="views/page.graphql"
11
+ query Page($postId: ID!) {
12
+ page(id: $postId, idType: DATABASE_ID) {
13
+ title
14
+ slug
15
+ template {
16
+ templateName
17
+ }
18
+ contentBlocks
19
+ }
20
+ }
21
+ ```
22
+
23
+ ```tsx title="views/page.jsx"
24
+ import { Container } from "@components/layout/Grid"
25
+ import { defineView } from "eddev/views"
26
+ import { ContentBlocks } from "eddev"
27
+
28
+ export default defineView("page", (props) => {
29
+ return (
30
+ <Container>
31
+ <h1>{props.title!}</h1>
32
+ <ContentBlocks blocks={props.page?.contentBlocks} />
33
+ </Container>
34
+ )
35
+ })
36
+ ```
@@ -0,0 +1,35 @@
1
+ # 'App' View
2
+
3
+ The `views/_app.tsx` view is a special kind of view. It's always rendered, as the wrapper around your entire frontend. It's usually where you'd put your header/footer and other global elements, as well as where you'll load global styles.
4
+
5
+ ```tsx
6
+ import { PageLoadIndicator } from "@components/generic/PageLoadIndicator"
7
+ import { AdminBar } from "eddev"
8
+ import { Header } from "@components/site/Header"
9
+ import { defineView } from "eddev/views"
10
+ import { fontFaceGlobalStyles, frontendGlobalStyles } from "@theme"
11
+ import { Footer } from "@components/site/Footer"
12
+
13
+ fontFaceGlobalStyles()
14
+ frontendGlobalStyles()
15
+
16
+ export default defineView("_app", ({ children }) => {
17
+ return (
18
+ <>
19
+ <PageLoadIndicator />
20
+ <AdminBar />
21
+ <Header />
22
+ {children}
23
+ <Footer />
24
+ </>
25
+ )
26
+ })
27
+ ```
28
+
29
+ ## App Query
30
+
31
+ You can write an `views/_app.graphql` file, and the result will be available on every page, via the `useAppData()` hook. The result _wont_ be passed in as props, so be sure to use the hook if you need to access it.
32
+
33
+ Note that the `_app.graphql` query only runs _once_ — when the user first loads the page.
34
+
35
+ This is especially useful for things like menus, which are often used on every page, and should be accessible from anywhere on the first render of the page.