diff --git a/src/pages/docs/explanation/apollo-client-basics/index.mdx b/src/pages/docs/explanation/apollo-client-basics/index.mdx index cb3c8656..2a3dcaa0 100644 --- a/src/pages/docs/explanation/apollo-client-basics/index.mdx +++ b/src/pages/docs/explanation/apollo-client-basics/index.mdx @@ -1,7 +1,8 @@ export const metadata = { - title: "Apollo Client Basics", - -} + title: "Apollo Client Basics", + description: + "Learn about core Apollo Client concepts like queries, fragments, mutations, and caching as they relate to Faust.js and WordPress.", +}; Faust.js uses `@apollo/client` under the hood to perform GraphQL operations against your WordPress backend. Having a solid understanding of Apollo Client queries, fragments, and mutations will help you get the most out of Faust.js. diff --git a/src/pages/docs/explanation/example/index.mdx b/src/pages/docs/explanation/example/index.mdx index 4b40f298..31297ff1 100644 --- a/src/pages/docs/explanation/example/index.mdx +++ b/src/pages/docs/explanation/example/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Example", + description: + "Example documentation page demonstrating various content elements and formatting styles.", }; Welcome to the Faust.js docs! diff --git a/src/pages/docs/explanation/index.mdx b/src/pages/docs/explanation/index.mdx index 79dd44f9..680d3db1 100644 --- a/src/pages/docs/explanation/index.mdx +++ b/src/pages/docs/explanation/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Explanation", + description: + "High-level conceptual guides that provide background information and understanding of Headless WordPress development.", }; I see you found the root of the Explanatory guides! Explanatory guides are a place where we step away from code and talk high-level concepts and import background information. If you are looking to grow your understanding of Headless WordPress, you are in the right place. diff --git a/src/pages/docs/explanation/migrating-to-typescript/index.mdx b/src/pages/docs/explanation/migrating-to-typescript/index.mdx index 100236ba..013e034c 100644 --- a/src/pages/docs/explanation/migrating-to-typescript/index.mdx +++ b/src/pages/docs/explanation/migrating-to-typescript/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Migrating to TypeScript", + description: + "Guide for migrating existing Next.js pages to TypeScript in a Faust.js project with resources and references.", }; If you have existing Next.js pages that you want to migrate to TypeScript, you can follow the [official TypeScript Docs](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html) for general TypeScript migration tips. diff --git a/src/pages/docs/explanation/telemetry/index.mdx b/src/pages/docs/explanation/telemetry/index.mdx index dde21906..6d4ce6c6 100644 --- a/src/pages/docs/explanation/telemetry/index.mdx +++ b/src/pages/docs/explanation/telemetry/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Telemetry", + description: + "Information about Faust's anonymous telemetry data collection, what data is collected, and how to opt out.", }; Faust collects completely anonymous telemetry data about general usage. Participation in this anonymous program is optional. For more information on how we handle this data, please read our [Privacy Policy](/privacy-policy). diff --git a/src/pages/docs/how-to/authentication/index.mdx b/src/pages/docs/how-to/authentication/index.mdx index e2f1ca91..f616b71e 100644 --- a/src/pages/docs/how-to/authentication/index.mdx +++ b/src/pages/docs/how-to/authentication/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Auth", + description: + "Guide to implementing authentication in your Next.js app using Faust.js toolkit features.", }; Understanding authentication is crucial for protecting your application's data. This page will guide you through implementing features from the Faust.js toolkit into your Next.js app. diff --git a/src/pages/docs/how-to/basic-setup/index.mdx b/src/pages/docs/how-to/basic-setup/index.mdx index d67a78d3..1156ba60 100644 --- a/src/pages/docs/how-to/basic-setup/index.mdx +++ b/src/pages/docs/how-to/basic-setup/index.mdx @@ -1,5 +1,7 @@ export const metadata = { - title: "Basic Setup with Template Hierarchy", + title: "Basic Setup", + description: + "Step-by-step guide for setting up a WordPress backend and Next.js frontend to use Faust.js toolkit features.", }; In order to leverage any of the tools in the Faust.js toolkit, some preliminary setup needs to be done. Follow the steps below to get started. @@ -16,6 +18,10 @@ Likewise, if you don't have a Next.js project yet, [create one](https://nextjs.o Install and activate the [FaustWP](https://wordpress.org/plugins/faustwp/) and [WPGraphQL](https://wordpress.org/plugins/wp-graphql/) plugins on your WordPress backend site. +### Set permalinks + +In the WordPress admin sidebar, go to `Settings` > `Permalinks`. Check the radio button next to `Custom Structure`, type `/blog/%postname%/` into the box next to it, then click the button to save your changes. This will result in Posts having URIs like `/blog/hello-world`, whereas Pages will still exist on the root domain, such as `/about`. + ### Set environment variables Create a `.env.local` file in the root of your Next.js project that contains these environment variables: @@ -32,7 +38,7 @@ Replace `https://faustexample.wpengine.com` with the URL for your WordPress back Replace `YOUR_PLUGIN_SECRET` with the Secret Key found in `Settings → Faust` in your WordPress admin area. -![](./images/headless-admin-secret-1024x743.png) +![Faust.js secret key](./images/headless-admin-secret-1024x743.png) Save your `.env.local` file. @@ -46,7 +52,7 @@ npm install @apollo/client @faustwp/core graphql @faustwp/cli ## Create Faust config file -Create a `faust.config` file in the root of your project with this code: +Create a `faust.config.js` file in the root of your project with this code: ```js title="faust.config.js" import { setConfig } from "@faustwp/core"; @@ -54,31 +60,32 @@ import { setConfig } from "@faustwp/core"; /** * @type {import('@faustwp/core').FaustConfig} **/ -export default setConfig({ - plugins: [], -}); +export default setConfig({}); ``` ### Create Faust API route -Create an API route for Faust.js to use. You can do this by creating a file in `pages/api/faust/[[...route]].js`, with the following code: +Create an API route for Faust.js to use. You can do this by creating a file in `src/pages/api/faust/[[...route]].js`, with the following code: -```js title="pages/api/faust/[[...route]].js" -import "../../../faust.config"; +```js title="src/pages/api/faust/[[...route]].js" +import "../../faust.config"; // Adjust path as necessary export { apiRouter as default } from "@faustwp/core"; ``` +> [!IMPORTANT] Important +> If you're not using a `/src` folder in your project, you can omit "/src" from the file path above. And the same applies for other file paths mentioned throughout this doc. + ### Update `_app.js` file -Once the API router is set up, head to `pages/_app.js` and add this code to the file: +Once the API router is set up, head to `src/pages/_app.js`. Add the `import` statements, wrap your app in the `FaustProvider`, and pass `key={router.asPath}` to `Component`, as shown below. -```js title="pages/_app.js" +```js title="src/pages/_app.js" import { useRouter } from "next/router"; import { FaustProvider } from "@faustwp/core"; import "../faust.config"; -export default function MyApp({ Component, pageProps }) { +export default function App({ Component, pageProps }) { const router = useRouter(); return ( @@ -95,6 +102,8 @@ export default function MyApp({ Component, pageProps }) { In order for Faust.js to run the GraphQL queries it needs to determine the correct template to use, it needs to have a list of all the types available in the GraphQL schema. We'll generate this list of types now. +In your WordPress admin sidebar, go to `GraphQL` > `Settings`. Check the `Enable Public Introspection` box if it's not checked already and save your changes. Enabling introspection is required for the `npm run generate` command below to work. + Add the following generate script to your Next.js project's `package.json` file, in the scripts block: ```json title="package.json" @@ -109,12 +118,9 @@ Add the following generate script to your Next.js project's `package.json` file, Run `npm run generate` on the command line. Confirm that a possibleTypes.json has been generated in the root of your project. -> [!IMPORTANT] Important -> Be sure to enable WPGraphQL introspection before running the `npm run generate` command since it is [disabled by default](https://www.wpgraphql.com/docs/security#introspection-disabled-by-default). - ### Add a template -Create a new `wp-templates` folder in the root of your project. This is where your template files will be stored. We'll start by adding a template for rendering single blog posts. +Create a new `src/wp-templates` folder (or add the `/wp-templates` folder in the root project folder if you don't use a `/src` folder). This is where your template files will be stored. We'll start by adding a template for rendering single blog posts. Inside the `wp-templates` folder, create a `single.js` file that contains the following code. @@ -157,10 +163,10 @@ In the `SingleTemplate` component, we receive the props, destructure the `title` Finally, we have to make Faust.js aware that this template exists. To do that, create an `index.js` file inside the `wp-templates` folder with this code inside: ```js title="wp-templates/index.js" -import single from "./single"; +import SingleTemplate from "./single"; const templates = { - single, + single: SingleTemplate, }; export default templates; @@ -168,19 +174,19 @@ export default templates; ### Pass in Templates and Types in Faust.js config -Put the following code inside your Faust.js config: +Put the following code inside your `faust.config.js` file: ```js title="faust.config.js" import { setConfig } from "@faustwp/core"; -import templates from "./wp-templates/index.js"; -import possibleTypes from "./possibleTypes.json"; +import templates from "./src/wp-templates/index.js"; // Adjust path as necessary // [!code ++] +import possibleTypes from "./possibleTypes.json"; // [!code ++] /** * @type {import('@faustwp/core').FaustConfig} **/ export default setConfig({ - templates, - possibleTypes, + templates, // [!code ++] + possibleTypes, // [!code ++] }); ``` @@ -190,7 +196,7 @@ Here, we call the `setConfig()` function that Faust.js provides, passing in our Create a `[...wordpressNode].js` file inside your `pages` folder. Add the following code to it. -```js title="pages/[...wordpressNode].js" +```js title="src/pages/[...wordpressNode].js" import { getWordPressProps, WordPressTemplate } from "@faustwp/core"; export default function Page(props) { @@ -211,7 +217,7 @@ export async function getStaticPaths() { This catch-all route tells Next.js to use the templates to render pages. -Note that it is still possible to override this with hardcoded pages. For example, if you have a page in your WordPress site with a URI of `/about`, Faust.js will render that page using the relevant template in your project's `wp-templates` folder. However, if you add a `pages/about.js` file to your project, Next.js will render the `/about` path in your app using that file instead. +Note that it is still possible to override this with hardcoded pages. For example, if you have a page in your WordPress site with a URI of `/about`, Faust.js will render that page using the relevant template in your project's `wp-templates` folder. However, if you add a `src/pages/about.js` file to your project, Next.js will render the `/about` path in your app using that file instead. ## Test your template diff --git a/src/pages/docs/how-to/create-a-plugin/index.mdx b/src/pages/docs/how-to/create-a-plugin/index.mdx index 4b275e24..afd75ef3 100644 --- a/src/pages/docs/how-to/create-a-plugin/index.mdx +++ b/src/pages/docs/how-to/create-a-plugin/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Create A Plugin", + description: + "Learn how to create Faust.js plugins to extend or alter the framework's behavior using JavaScript/TypeScript actions and filters.", }; Faust plugins are a structured way to extend or alter the framework's behavior, very much like WordPress plugins do in a traditional WordPress environment. Instead of `PHP`, however, Faust's plugins are written in JavaScript/TypeScript, leveraging actions and filters to deliver similar flexibility in a headless architecture. diff --git a/src/pages/docs/how-to/generate-types-with-graphql-codegen/index.mdx b/src/pages/docs/how-to/generate-types-with-graphql-codegen/index.mdx index d0a25915..85a52d0b 100644 --- a/src/pages/docs/how-to/generate-types-with-graphql-codegen/index.mdx +++ b/src/pages/docs/how-to/generate-types-with-graphql-codegen/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Generate types with GraphQL Codegen", + description: + "Guide to generating TypeScript definitions for your custom GraphQL queries and fragments using GraphQL Code Generator.", }; Faust.js provides built-in TypeScript support, including types for Templates, Blocks, and more. This guide will show you how to generate fully typed definitions for your custom GraphQL queries and fragments using [GraphQL Code Generator](https://the-guild.dev/graphql/codegen). diff --git a/src/pages/docs/how-to/index.mdx b/src/pages/docs/how-to/index.mdx index 5f4dfc13..d5bcb771 100644 --- a/src/pages/docs/how-to/index.mdx +++ b/src/pages/docs/how-to/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "How-to Guides", + description: + "Step-by-step guides for implementing specific features and achieving practical goals with Faust.js.", }; I see you found the root of the How-to guides! How-to guides are a place where we walk you through implementing specific features of Faust.js®. If you are looking to achieve a specific goal with Faust.js®, you are in the right place. diff --git a/src/pages/docs/how-to/post-previews/index.mdx b/src/pages/docs/how-to/post-previews/index.mdx index 07e86fce..0a3cdf5e 100644 --- a/src/pages/docs/how-to/post-previews/index.mdx +++ b/src/pages/docs/how-to/post-previews/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Post Previews", + description: + "Learn how to implement post preview functionality in your headless WordPress app using Faust.js.", }; When editing content in the [WordPress editor](https://wordpress.com/support/wordpress-editor/), content creators can click the **Preview** link to preview what the content will look like on the frontend before the post has been published. This docs page outlines how to set up post previews in a headless WordPress app. diff --git a/src/pages/docs/how-to/query-data-in-nextjs-routes/index.mdx b/src/pages/docs/how-to/query-data-in-nextjs-routes/index.mdx index 46a47d73..f010194c 100644 --- a/src/pages/docs/how-to/query-data-in-nextjs-routes/index.mdx +++ b/src/pages/docs/how-to/query-data-in-nextjs-routes/index.mdx @@ -1,6 +1,7 @@ export const metadata = { - title: "Query Data in Next.js Routes", - + title: "Query Data in Next.js Routes", + description: + "Guide to pre-fetching WordPress data in Next.js routes using getNextServerSideProps and getNextStaticProps helper functions.", }; When you want to pre-fetch WordPress data and render your pages outside of the Faust.js template hierarchy and instead use Next.js routes, either at **build time** or **on every request**, Faust provides two helper functions: diff --git a/src/pages/docs/how-to/query-data-in-the-browser/index.mdx b/src/pages/docs/how-to/query-data-in-the-browser/index.mdx index bf19e59e..d4f7db34 100644 --- a/src/pages/docs/how-to/query-data-in-the-browser/index.mdx +++ b/src/pages/docs/how-to/query-data-in-the-browser/index.mdx @@ -1,7 +1,8 @@ export const metadata = { - title: "Query Data in the Browser", - -} + title: "Query Data in the Browser", + description: + "Learn how to perform client-side data fetching using Apollo's useQuery hook in your React components.", +}; When you query data in the browser, you're leveraging Apollo's `useQuery` hook within your React components. diff --git a/src/pages/docs/how-to/rendering-blocks-with-the-template-hierarchy/index.mdx b/src/pages/docs/how-to/rendering-blocks-with-the-template-hierarchy/index.mdx index e763a3d8..30d9917b 100644 --- a/src/pages/docs/how-to/rendering-blocks-with-the-template-hierarchy/index.mdx +++ b/src/pages/docs/how-to/rendering-blocks-with-the-template-hierarchy/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Rendering Blocks with the Template Hierarchy", + description: + "Learn how to use Faust.js template router to dynamically map and render WordPress blocks as React components.", }; In headless WordPress with Faust.js, the template router offers a powerful way to dynamically map WordPress pages and posts to specific templates, streamlining how content is fetched and rendered. When working with WordPress block data, the template router allows you to efficiently map block types to React components, giving you greater control over how individual blocks are rendered within each template. diff --git a/src/pages/docs/how-to/rendering-blocks/index.mdx b/src/pages/docs/how-to/rendering-blocks/index.mdx index cfc935c1..c58b4cbf 100644 --- a/src/pages/docs/how-to/rendering-blocks/index.mdx +++ b/src/pages/docs/how-to/rendering-blocks/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Rendering Blocks", + description: + "Guide to mapping WordPress blocks to React components in your front-end app for customized block rendering.", }; In headless WordPress, it's possible to take the HTML for an entire page and insert it into the DOM in your decoupled front-end app. On most sites, though, it becomes necessary to map WordPress blocks to React components in your front-end app so you can control how individual blocks are rendered. This document details how to do just that. diff --git a/src/pages/docs/how-to/sitemaps/index.mdx b/src/pages/docs/how-to/sitemaps/index.mdx index 7084e97e..57404f97 100644 --- a/src/pages/docs/how-to/sitemaps/index.mdx +++ b/src/pages/docs/how-to/sitemaps/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Sitemaps", + description: + "Guide to implementing XML sitemaps in your headless WordPress site using Faust.js built-in sitemap functionality.", }; Sitemaps can be a complicated process when using WordPress in a headless environment. Thankfully, Faust takes care of all your sitemap needs through creation of a file within the pages directory. diff --git a/src/pages/docs/how-to/use-wpgraphql-smart-cache/index.mdx b/src/pages/docs/how-to/use-wpgraphql-smart-cache/index.mdx index bebae94f..25320cea 100644 --- a/src/pages/docs/how-to/use-wpgraphql-smart-cache/index.mdx +++ b/src/pages/docs/how-to/use-wpgraphql-smart-cache/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Using WPGraphQL Smart Cache Network Caching", + description: + "Guide to optimizing GraphQL queries using WPGraphQL Smart Cache with Faust.js built-in network caching support.", }; WPGraphQL Smart Cache optimizes GraphQL queries by caching the results of your requests and automatically evicting outdated data whenever your WordPress content changes. Faust.js provides built-in support for [Network Caching](https://github.com/wp-graphql/wp-graphql-smart-cache/blob/main/docs/network-cache.md). This guide walks you through enabling Automatic Persisted Queries, using GET methods for network requests, and making one-off requests that override your default settings. diff --git a/src/pages/docs/index.mdx b/src/pages/docs/index.mdx index a9c00473..8657f486 100644 --- a/src/pages/docs/index.mdx +++ b/src/pages/docs/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Introduction", + description: + "Introduction to Faust.js, a toolkit for building headless WordPress applications with Next.js.", }; ## What is Faust.js®? diff --git a/src/pages/docs/nav.json b/src/pages/docs/nav.json index 7665476a..569c1051 100644 --- a/src/pages/docs/nav.json +++ b/src/pages/docs/nav.json @@ -3,6 +3,16 @@ "title": "Getting Started", "route": "/docs/" }, + { + "title": "Tutorials", + "route": "/docs/tutorial/", + "children": [ + { + "title": "Learn Faust.js", + "route": "/docs/tutorial/learn-faust/" + } + ] + }, { "title": "How-To Guides", "route": "/docs/how-to/", diff --git a/src/pages/docs/reference/from-theme-json/index.mdx b/src/pages/docs/reference/from-theme-json/index.mdx index 0684e5f7..9fabac99 100644 --- a/src/pages/docs/reference/from-theme-json/index.mdx +++ b/src/pages/docs/reference/from-theme-json/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "fromThemeJson", + description: + "Reference for the fromThemeJson helper function that converts WordPress theme.json objects into compatible BlocksTheme objects.", }; The `fromThemeJson` is a helper function that is used to convert a WordPress theme's `theme.json` object into a compatible `BlocksTheme` object. diff --git a/src/pages/docs/reference/get-next-server-side-props/index.mdx b/src/pages/docs/reference/get-next-server-side-props/index.mdx index 0df92664..d5325d6e 100644 --- a/src/pages/docs/reference/get-next-server-side-props/index.mdx +++ b/src/pages/docs/reference/get-next-server-side-props/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "getNextServerSideProps", + description: + "Reference for the getNextServerSideProps function used to enable server-side rendering with WordPress data outside the template hierarchy.", }; The `getNextServerSideProps` function lets you server side render your page with WordPress data outside of the template hierarchy using Next.js file-based pages. The function should be returned from `getServerSideProps` which is required by Next.js to perform server-side rendering (SSR). diff --git a/src/pages/docs/reference/get-next-static-props/index.mdx b/src/pages/docs/reference/get-next-static-props/index.mdx index acc3d75b..f9700776 100644 --- a/src/pages/docs/reference/get-next-static-props/index.mdx +++ b/src/pages/docs/reference/get-next-static-props/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "getNextStaticProps", + description: + "Reference for the getNextStaticProps function used to build static sites with WordPress data outside the template hierarchy.", }; The `getNextStaticProps` function lets you build a static site with your WordPress data outside of the template hierarchy using Next.js file based pages. The function should be returned from `getStaticProps`. diff --git a/src/pages/docs/reference/get-site-map-props/index.mdx b/src/pages/docs/reference/get-site-map-props/index.mdx index e577a70f..76e083ad 100644 --- a/src/pages/docs/reference/get-site-map-props/index.mdx +++ b/src/pages/docs/reference/get-site-map-props/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "getSiteMapProps", + description: + "Reference for the getSitemapProps helper function used to proxy sitemaps from WordPress to your Faust frontend.", }; `getSitemapProps` is a server side helper function that facilitates the proxying of sitemaps from your WordPress site to your Faust frontend. It is a function that is returned from inside of a [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props) Next.js function. diff --git a/src/pages/docs/reference/get-styles/index.mdx b/src/pages/docs/reference/get-styles/index.mdx index f82003db..91d2e7d2 100644 --- a/src/pages/docs/reference/get-styles/index.mdx +++ b/src/pages/docs/reference/get-styles/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "getStyles", + description: + "Reference for the getStyles helper function used to calculate inline styles for WordPress blocks based on theme and block properties.", }; The `getStyles` is a helper function that is used to calculate the inline styles of a block given the current theme and block properties. This is mainly useful when developing blocks taken from the [core WordPress blocks list](https://developer.wordpress.org/block-editor/reference-guides/core-blocks/). diff --git a/src/pages/docs/reference/get-wordpress-props/index.mdx b/src/pages/docs/reference/get-wordpress-props/index.mdx index cae2f513..3e7cfd4a 100644 --- a/src/pages/docs/reference/get-wordpress-props/index.mdx +++ b/src/pages/docs/reference/get-wordpress-props/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "getWordPressProps", + description: + "Reference for the getWordPressProps function used to set up the Faust Template Hierarchy system in Next.js applications.", }; `getWordPressProps` is a function that should be returned within Next.js' `getStaticProps` or `getServerSideProps` to properly setup the Faust Template Hierarchy system. diff --git a/src/pages/docs/reference/index.mdx b/src/pages/docs/reference/index.mdx index 7edd735d..05aa9f44 100644 --- a/src/pages/docs/reference/index.mdx +++ b/src/pages/docs/reference/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Reference Guides", + description: + "API specifications and detailed documentation for Faust.js functions, components, and features.", }; I see you found the root of the Reference guides! Reference guides are a place where we provide API specs. If you are looking for information on specific APIs, you are in the right place. diff --git a/src/pages/docs/reference/set-config/index.mdx b/src/pages/docs/reference/set-config/index.mdx index 2b90285b..5f970566 100644 --- a/src/pages/docs/reference/set-config/index.mdx +++ b/src/pages/docs/reference/set-config/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "setConfig", + description: + "Reference for the setConfig function used to configure Faust.js settings in the faust.config.js file.", }; The `setConfig` function is used to set the configuration for Faust. It is used in the `faust.config.js` file to set the configuration options for Faust. diff --git a/src/pages/docs/reference/typescript/index.mdx b/src/pages/docs/reference/typescript/index.mdx index 4d5dfd4f..ce2b3113 100644 --- a/src/pages/docs/reference/typescript/index.mdx +++ b/src/pages/docs/reference/typescript/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "TypeScript", + description: + "Guide to using TypeScript with Faust.js components, hooks, and plugins, including common patterns and type definitions.", }; Faust has built-in TypeScript support, which means you can use TypeScript to type your Faust components, hooks, and plugins. This may not be exhaustive but should show you common patterns for typing your Faust code. diff --git a/src/pages/docs/reference/use-auth/index.mdx b/src/pages/docs/reference/use-auth/index.mdx index 194cf9af..a470f425 100644 --- a/src/pages/docs/reference/use-auth/index.mdx +++ b/src/pages/docs/reference/use-auth/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "useAuth", + description: + "Reference for the useAuth hook that provides authentication configuration and functionality in Faust.js applications.", }; ## Configuration diff --git a/src/pages/docs/reference/use-blocks-theme/index.mdx b/src/pages/docs/reference/use-blocks-theme/index.mdx index a38d8dc7..c0ed2502 100644 --- a/src/pages/docs/reference/use-blocks-theme/index.mdx +++ b/src/pages/docs/reference/use-blocks-theme/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "useBlocksTheme", + description: + "Reference for the useBlocksTheme hook that provides theme values from WordPressBlocksProvider for block rendering.", }; `useBlocksTheme` is a React hook that provides the theme value when passed in the `WordPressBlocksProvider` component. The theme value is sourced by a theme.json file when using the [fromThemeJson](/docs/reference/from-theme-json) helper function. diff --git a/src/pages/docs/reference/use-login/index.mdx b/src/pages/docs/reference/use-login/index.mdx index c85136ed..34e35643 100644 --- a/src/pages/docs/reference/use-login/index.mdx +++ b/src/pages/docs/reference/use-login/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "useLogin", + description: + "Reference for the useLogin hook that enables in-app authentication with WordPress without leaving your Faust.js application.", }; `useLogin` is a React hook that facilitates login to your headless WordPress site without having to leave your Faust app. @@ -94,4 +96,4 @@ export default function Login() { } ``` -It create some state values to keep track of the user email and password fields. It then uses the `useLogin` hook and extracts the return values. Based on the return values, it will either disable some fields when `loading=true` or return an error message when `data.generateAuthorizationCode.error` is not empty. +It creates some state values to keep track of the user email and password fields. It then uses the `useLogin` hook and extracts the return values. Based on the return values, it will either disable some fields when `loading=true` or return an error message when `data.generateAuthorizationCode.error` is not empty. diff --git a/src/pages/docs/reference/use-logout/index.mdx b/src/pages/docs/reference/use-logout/index.mdx index cd0d007f..552c295b 100644 --- a/src/pages/docs/reference/use-logout/index.mdx +++ b/src/pages/docs/reference/use-logout/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "useLogout", + description: + "Reference for the useLogout hook that provides functionality to log out users from your Faust.js application.", }; `useLogout` is a React hook that facilitates logging out from your Faust app. diff --git a/src/pages/docs/reference/with-faust/index.mdx b/src/pages/docs/reference/with-faust/index.mdx index d2b3e506..e1010ebb 100644 --- a/src/pages/docs/reference/with-faust/index.mdx +++ b/src/pages/docs/reference/with-faust/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "withFaust", + description: + "Reference for the withFaust helper function used to merge Next.js configuration with required Faust.js settings.", }; The `withFaust` helper function is used to merge your `next.config.js` config with necessary Faust.js configuration. diff --git a/src/pages/docs/reference/wordpress-blocks-provider/index.mdx b/src/pages/docs/reference/wordpress-blocks-provider/index.mdx index 138a58cb..6a3bc448 100644 --- a/src/pages/docs/reference/wordpress-blocks-provider/index.mdx +++ b/src/pages/docs/reference/wordpress-blocks-provider/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "WordPressBlocksProvider", + description: + "Reference for the WordPressBlocksProvider component that provides block data and configuration for WordPress block rendering.", }; `WordPressBlocksProvider` is a React [Context Provider](https://react.dev/reference/react/createContext#provider) that exposes the data that `WordPressBlocksViewer` needs to render WordPress blocks, namely which blocks have been defined as a part of your Faust app. diff --git a/src/pages/docs/reference/wordpress-blocks-viewer/index.mdx b/src/pages/docs/reference/wordpress-blocks-viewer/index.mdx index aabf2740..d7421e39 100644 --- a/src/pages/docs/reference/wordpress-blocks-viewer/index.mdx +++ b/src/pages/docs/reference/wordpress-blocks-viewer/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "WordPressBlocksViewer", + description: + "Reference for the WordPressBlocksViewer component that renders WordPress blocks using React components defined in WordPressBlocksProvider.", }; `WordPressBlocksViewer` is a component used to render blocks received from WordPress. It uses the React components passed to the `WordPressBlocksProvider` and matches them to the appropriate blocks received in the `editorBlocks` prop. diff --git a/src/pages/docs/tutorial/index.mdx b/src/pages/docs/tutorial/index.mdx index 0d90c6cb..404f3908 100644 --- a/src/pages/docs/tutorial/index.mdx +++ b/src/pages/docs/tutorial/index.mdx @@ -1,5 +1,7 @@ export const metadata = { title: "Tutorials", + description: + "Step-by-step tutorials for learning the basics and core features of Faust.js through hands-on examples.", }; I see you found the root of the Tutorial! Tutorials are a place where we walk you through learning the basics of Faust.js®. If you are looking to learn about what Faust.js® offers, you are in the right place. diff --git a/src/pages/docs/tutorial/learn-faust/images/faust-front-end-site-url.png b/src/pages/docs/tutorial/learn-faust/images/faust-front-end-site-url.png new file mode 100644 index 00000000..3ee5931b Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/faust-front-end-site-url.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/faust-secret-key-setting.png b/src/pages/docs/tutorial/learn-faust/images/faust-secret-key-setting.png new file mode 100644 index 00000000..81841ebd Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/faust-secret-key-setting.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/install-content-blocks-plugin.png b/src/pages/docs/tutorial/learn-faust/images/install-content-blocks-plugin.png new file mode 100644 index 00000000..36c74cd2 Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/install-content-blocks-plugin.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/permalink-settings.png b/src/pages/docs/tutorial/learn-faust/images/permalink-settings.png new file mode 100644 index 00000000..f016d800 Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/permalink-settings.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/preview-link.png b/src/pages/docs/tutorial/learn-faust/images/preview-link.png new file mode 100644 index 00000000..57dbeefe Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/preview-link.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/template-hierarchy.png b/src/pages/docs/tutorial/learn-faust/images/template-hierarchy.png new file mode 100644 index 00000000..2092b74a Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/template-hierarchy.png differ diff --git a/src/pages/docs/tutorial/learn-faust/images/wpgraphql-introspection.png b/src/pages/docs/tutorial/learn-faust/images/wpgraphql-introspection.png new file mode 100644 index 00000000..4e54b233 Binary files /dev/null and b/src/pages/docs/tutorial/learn-faust/images/wpgraphql-introspection.png differ diff --git a/src/pages/docs/tutorial/learn-faust/index.mdx b/src/pages/docs/tutorial/learn-faust/index.mdx new file mode 100644 index 00000000..bfe1d226 --- /dev/null +++ b/src/pages/docs/tutorial/learn-faust/index.mdx @@ -0,0 +1,427 @@ +export const metadata = { + title: "Learn Faust.js", + description: + "Comprehensive tutorial covering core Faust.js features including template hierarchy, authentication, post previews, and block handling.", +}; + +This tutorial will familiarize you with the core features of Faust.js. You'll start with a Next.js project that has been configured to work with Faust.js, then learn how to leverage these features yourself: + +- Template hierarchy +- Authentication & Post previews +- Blocks + +After going through this tutorial, you'll be able to [configure your Next.js app]('/docs/how-to-basic-setup'), then use the knowledge you gained to implement Faust.js' features in your own apps. + +## Prerequisites + +In order to complete this tutorial, you should: + +- Be familiar with HTML, CSS, JavaScript, [WordPress](https://wordpress.org/), [React](https://react.dev/), and [Next.js](https://nextjs.org/) +- Be familiar with [cloning a repository from GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) +- Be comfortable running commands on the [command line](https://en.wikipedia.org/wiki/Command-line_interface) +- Have [Node.js and NPM](https://nodejs.org/) installed on your computer + +You should also not have any other projects running on port `3000` or `8881`, since the links in this tutorial point to pages on those ports. + +## Set up + +The steps below will get you up-and-running with the pre-built app you will use for the tutorial. + +### 1. Install the Next.js app + +Run the command below to set up the example Next.js app we will use for the tutorial. + +```sh +npx create-next-app \ + -e https://github.com/wpengine/faustjs/tree/canary \ + --example-path examples/next/tutorial \ + --use-npm +``` + +When asked if it's okay to install the `create-next-app` package, answer `y` to confirm. + +### 2. Set up headless WordPress backend + +`cd` into the project directory. + +Run `npx @wp-now/wp-now start --blueprint faust-tutorial-blueprint.json`. This command uses the [`wp-now`](https://www.npmjs.com/package/@wp-now/wp-now) NPM package and the included `faust-tutorial-blueprint.json` blueprint file to set up a local WordPress environment. + +When asked if it's okay to install the `@wp-now/wp-now` package, answer `y` to confirm. + +After a moment, you should have a WordPress site up-and-running. + +By navigating to http://localhost:8881/wp-admin/plugins.php, You can see that the required [Faust.js](https://wordpress.org/plugins/faustwp/) and [WPGraphQL](https://wordpress.org/plugins/wp-graphql/) plugins have already been installed and activated for you. + +In the WordPress admin sidebar, go to `Settings` > `Permalinks`. Check the radio button for `Custom Structure`, enter `/blog/%postname%/` in the text field, and save your changes. With this setting, our blog posts will have URLs such as http://localhost:3000/blog/hello-world/. + +![Permalink settings](./images/permalink-settings.png) + +Next, head to `GraphQL` > `Settings`. Check the box for `Enable Public Introspection` and click the save button. This allows Faust.js to run an "introspection query" on your WordPress backend to get a list of the available GraphQL types and fields. + +![WPGraphQL introspection setting](./images/wpgraphql-introspection.png) + +Finally, head to to `Settings` > `Faust` to access the Faust.js settings page. Set the `Front-end site URL` setting to `http://localhost:3000` and save your changes. This lets Faust know the URL for your decoupled frontend app, which we'll set up next. + +![Faust Front-end site URL setting](./images/faust-front-end-site-url.png) + +### 3. Set up Faust.js frontend + +Run `npm run dev` to install the project's NPM packages + +Run `npm run generate` on the command line. Confirm that a `possibleTypes.json` has been generated in the root of your project. + +Create a `.env.local` file in the root project folder and populate it with the environment variables shown below. + +```env +# Your WordPress site URL +NEXT_PUBLIC_WORDPRESS_URL=http://localhost:8881 + +# Plugin secret found in WordPress Settings->Faust +FAUST_SECRET_KEY= +``` + +Once again, in the WordPress admin sidebar, go to `Settings` > `Faust` to access the Faust.js settings page. Copy the value you see for the `Secret Key` and paste that in as the value of `FAUST_SECRET_KEY` in your `.env.local` file and save it. Faust.js uses this secret key to send authenticated request to WordPress. + +![Faust Secret Key setting](./images/faust-secret-key-setting.png) + +In a separate terminal window from the one running your WordPress backend, run `npm run dev` to start up your frontend app. You should now be able to visit http://localhost:3000 and see your frontend app running. + +### 4. Template Hierarchy + +WordPress is well-known for its [template hierarchy](https://developer.wordpress.org/themes/basics/template-hierarchy/) feature. It allows WordPress to determine which page template to use to render a page depending on the type of content the page contains. Faust.js allows you to leverage the template hierarchy in your frontend app. + +The following image is helpful for visualizing how WordPress' template hierarchy feature works. The logic starts on the left side of this flowchart and progresses to the right. A series of conditionals are run to determine the appropriate page template to use. Just disregard the ".php" file extensions you see, since templates in our headless WP project will be ".js" files instead. + +![WordPress template hierarchy](./images/template-hierarchy.png) + +Open the project in a code editor and find the `wp-templates` folder. This is the folder where you can place page template files you'd like to use. We've provided a `single.js` file for you. As you can see in the template hierarchy flowchart, the "single" page template is used to render single blog post pages. You can see this page template in action by viewing http://localhost:3000/blog/hello-world/. That page should display the contents for the "Hello world" blog post. + +#### Add a template + +Next, you'll learn how to create your own template. Let's add one for rendering single pages (the "Page" post type in WordPress). + +By referencing the template hierarchy image above, you can see that we can target pages by adding a template named `page`. Inside of the `wp-templates` folder, add a new `page.js` file for our new template. + +Copy the `gql` import and the `SingleTemplate` component from `wp-templates/single.js` and paste them into `wp-templates/page.js`. Rename the `SingleTemplate` component to `PageTemplate`. Our new page template should now look like this: + +```jsx +import { gql } from "@apollo/client"; + +export default function PageTemplate(props) { + const { title, content } = props.data.page; + + return ( + <> +

{title}

+
+ + ); +} +``` + +You can see that the `PageTemplate` component receives the props passed into it, destructures the `title` and `content` for the page, then renders them inside of the JSX the component returns. + +Next, copy the `SingleTemplate.query` and `SingleTemplate.variables` assignments from `wp-templates/single.js` and paste them into `wp-templates/page.js`. rename them to `PageTemplate.query` and `PageTemplate.variables`. The new page template should now look like this: + +```jsx +import { gql } from "@apollo/client"; + +export default function PageTemplate(props) { + const { title, content } = props.data.page; + + return ( + <> +

{title}

+
+ + ); +} + +PageTemplate.query = gql` + query GetPage($uri: ID!) { + page(id: $uri, idType: URI) { + title + content + } + } +`; + +PageTemplate.variables = (seedQuery, ctx) => { + return { + uri: seedQuery?.uri, + }; +}; +``` + +The `PageTemplate.variables` function takes the `uri` for the current page and makes that available as a variable that can be used in queries for the component's data. + +`PageTemplate.query` is a `gql` [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) literal that specifies the data the component requires. In plain English, this query essentially says "hey WordPress: find the Page with this URI and give me back the title and post content for it". Once fetched, this data gets passed into the component inside of `props.data.page`. + +The last step is to make Faust aware of our new template. Do to this, open `wp-templates/index.js` and add these lines: + +```js +import SingleTemplate from "./single"; +import PageTemplate from "./page"; // [!code ++] + +const templates = { + single: SingleTemplate, + page: PageTemplate, // [!code ++] +}; + +export default templates; +``` + +This tells Faust to use the `PageTemplate` component as the template to render pages that match `page`, according to the template hierarchy. + +Save your changes and visit [http://localhost:3000/sample-page/](http://localhost:3000/sample-page/) in a browser. You should be able to see the title and content for the [Sample Page page in WordPress](http://localhost:8881/wp-admin/post.php?post=2&action=edit). + +Now that you understand how to leverage the template hierarchy, you can follow this pattern to add additional page templates: + +1. Create the template file inside of `/wp-templates` +2. Add the new template to the list of page templates in `/wp-templates/index.js` + +You can reference the template hierarchy image above to determine which key to use for the `templates` object in `src/wp-templates/index.js`. This will result in Faust mapping the correct page template to the correct component. + +## Authentication & Post previews + +You now have page templates rendering your published WordPress Posts and Pages, which is cool! What about unpublished, _draft_ posts that content creators want to preview, though? Thankfully, Faust has you covered there, too! + +In this section, we'll leverage Faust's built-in Authentication and Post Preview features to allow content creators to preview their draft blog posts. By authenticating the user, we'll know whether they have the permissions necessary to view a particular draft post. If they do, we'll handle rendering the draft blog post for them to preview. + +The app is set up so that when Faust renders a page, it includes an additional `asPreview` prop that is set to `true` if a draft post is being rendered, else `false`. Let's learn how we can make use of that prop to render draft posts. + +### 1. Update `single` template + +Open your `wp-templates/single.js` template. Above the existing `return` statement, add the code below. + +```jsx title="src/wp-templates/single.js" +if (props.loading) { + return

Loading...

; +} +``` + +This tells React to render a "Loading" message if the component is still loading. This momentary data fetching delay occurs because draft blog posts are client-side rendered (CSR) rather than server-side rendered (SSR). + +Update the `Component.variables` function to return a new `asPreview` variable that is set to the value of `ctx?.asPreview`: + +```jsx title="src/wp-templates/single.js" +SingleTemplate.variables = ({ databaseId }, ctx) => { + return { + databaseId, + asPreview: ctx?.asPreview, // [!code ++] + }; +}; +``` + +Inside of the `GetPost` GraphQL query, accept a new `$asPreview: Boolean = false` argument. Pass that value into the `post` query by adding `asPreview: $asPreview`, as shown below. + +```jsx title="src/wp-templates/single.js" +SingleTemplate.query = gql` + query GetPost($uri: ID!, $asPreview: Boolean = false) { + post(id: $uri, idType: URI, asPreview: $asPreview) { + title + content + } + } +`; +``` + +Your `single` template file should now look like this: + +```jsx title="src/wp-templates/single.js" +import { gql } from "@apollo/client"; + +export default function SingleTemplate(props) { + const { title, content } = props.data.post; + + if (props.loading) { + return

Loading...

; + } + + return ( + <> +

{title}

+
+ + ); +} + +SingleTemplate.query = gql` + query GetPost($uri: ID!, $asPreview: Boolean = false) { + post(id: $uri, idType: URI, asPreview: $asPreview) { + title + content + } + } +`; + +SingleTemplate.variables = (seedQuery, ctx) => { + return { + uri: seedQuery?.uri, + asPreview: ctx?.asPreview, + }; +}; +``` + +### 2. Preview a draft post + +Let's try out our new post previews feature! In the WordPress admin sidebar, click the `Posts` link. Find the `Hello world!` blog post on the list and click it to edit that post. Make a small change to it, such as modifying the title or content. + +Click the `View` icon, then click `Preview in new tab`. + +![Preview in new tab link](./images/preview-link.png) + +This should send you to `http://localhost:3000/blog/hello-world` with a number of query string parameters attached. When this request is made, Faust authenticates you, confirms that you have the permissions necessary to preview the post, then finally renders the draft blog post. + +// TODO: This doesn't work! 😬 + +After you complete the tutorial, you can read our how-to guides on [Authentication](/docs/how-to/authentication/) and [Post Previews](/docs/how-to/post-previews/) to learn more about these features. + +## Blocks + +Content creators use the Block Editor to write posts and pages in WordPress using blocks. In headless WordPress, it's possible to take the HTML for the entire page and insert it into the DOM in your decoupled front-end app. On most sites, though, it becomes necessary to map WordPress blocks to React components in your front-end app so you can control how individual blocks are rendered. Fortunately, we can leverage the [WPGraphQL Content Blocks](https://github.com/wpengine/wp-graphql-content-blocks) extension and the blocks functionality that comes with Faust.js to do just that. Let's learn how. + +### 1. Install the WPGraphQL Content Blocks plugin + +Head to the [Releases page of the WPGraphQL Content Blocks](https://github.com/wpengine/wp-graphql-content-blocks/releases) GitHub repository. Download the `wp-graphql-content-blocks.zip` file from the latest release. + +In the WordPress admin, navigate to `Plugins` > `Add New` > `Upload`. Select the `wp-graphql-content-blocks.zip` file to install the plugin, then activate it. + +![Install WPGraphQL Content Blocks plugin](./images/install-content-blocks-plugin.png) + +This plugin exposes WordPress blocks data in the GraphQL schema so that we can query for it. + +### 2. Query for blocks data + +Next, we'll update our `single` blog post template to query for and render blocks. Currently, the `single` template does this: + +1. Includes `content` in its GraphQL query to get the post content. +2. Uses `
` to render the content as a string of HTML. + +Inside of the `SingleTemplate.query` GraphQL query, remove `content` and replace it with an `editorBlocks` section, as shown below. + +```jsx title="src/wp-templates/single.js" +query GetPost($uri: ID!, $asPreview: Boolean = false) { + post(id: $uri, idType: URI, asPreview: $asPreview) { + title + editorBlocks { + __typename + name + renderedHtml + ... on CoreParagraph { + attributes { + className + } + } + } + } +} +``` + +Next we'll update the component to use this new data. Within the `SingleTemplate` component, remove `content` from the destructured post props and replace it with `editorBlocks`: + +```jsx title="src/wp-templates/single.js" +const { title, editorBlocks } = post; +``` + +Finally, replace the `
` line with the code below. + +```jsx title="src/wp-templates/single.js" +
+ {editorBlocks.map((block, index) => { + console.log(block); + if (block.name === "core/paragraph") { + return ( +
+ ); + } + return ( +
+ ); + })} +
+``` + +Your updated `SingleTemplate` component should now look like this: + +```jsx title="src/wp-templates/single.js" +export default function SingleTemplate(props) { + const { title, editorBlocks } = props.data.post; + + if (props.loading) { + return

Loading...

; + } + + return ( + <> +

{title}

+
+ {editorBlocks.map((block, index) => { + console.log(block); + if (block.name === "core/paragraph") { + return ( +
+ ); + } + return ( +
+ ); + })} +
+ + ); +} +``` + +You should now be able to visit the URL for a post such as http://localhost:3000/blog/hello-world/ and see the blocks content being rendered. + +Inspect the blog post content in the browser dev tools and notice that each block is being rendered and that only the paragraph blocks are wrapped in a `div` with a class name of `paragraph-block-wrapper`. Currently, we're not leveraging the `paragraph-block-wrapper` class in any way, but you can see the potential here. By being able to query for and render blocks individually, you have the ability to wrap specific blocks in arbitrary markup, override specific blocks with custom implementations, and more. + +Now [edit the Hello World! blog post](http://localhost:8881/wp-admin/post.php?post=1&action=edit). Make several changes to it in terms of font size, padding, margin, a border, an HTML anchor, and additional CSS classes, then save your changes. + +Reload the http://localhost:3000/blog/hello-world/ page in your frontend app and see that all the changes you applied are now being reflected. Inspect the paragraph block in DevTools to see markup similar to the example below. You can see that Faust has taken care of rendering the paragraph tag to include these attributes, and even loaded the CSS required to apply the correct styles. + +```html +
+

+ Welcome to WordPress. This is your first post. Edit or delete it, then start + writing! +

+
+``` + +More information about using Faust to render blocks, override WordPress core blocks with your own implementation, and even add support for custom blocks can be found in these how-to guides: + +- [Rendering Blocks](/docs/how-to/rendering-blocks/) +- [Override Blocks](/docs/how-to/override-blocks/) +- [Custom Blocks](/docs/how-to/custom-blocks/) + +## Next steps + +Thanks for completing this tutorial to learn about the core features of Faust.js! You should now have a basic understanding of the Template hierarchy, Authentication & Post previews, and Blocks functionality that it provides. + +You can review the rest of our documentation to learn how to add Faust to your headless WordPress + Next.js project and learn about Faust's features in more depth.