Giter Club home page Giter Club logo

faustjs's Introduction

Faust.js

Introduction

Faust.js is a framework for building front-end applications for headless WordPress sites. Faust.js provides tooling to reduce the pains of building a headless WordPress site (namely around data fetching, authentication, previews, and SSR/SSG) while offering a pleasant experience for both developers and publishers.

Getting Started

Faust.js aims to be framework agnostic, so it can be used with any front-end framework. Visit one of the guides below for a starting point:

As we work towards our first release, we will be introducing support for other frameworks.

System Requirements

  • Node.js v16.0.0 or newer (v16.8.0 when using Next.js 13 and v18.17 when using Next.js 14).
  • MacOS, Windows (including WSL), and Linux are supported.

Documentation

Visit https://faustjs.org/docs/getting-started to view the full documentation.

WordPress Plugin (FaustWP)

There are two key parts to Faust.js: the NPM packages and the WordPress plugin. To take full advantage of headless, you will need to install the plugin in addition to the npm packages.

You can download and install FaustWP from the WordPress Plugin Directory, or by using the zip linked below.

📥 Download Latest Version

Community

To chat with other Faust.js users and the headless community as a whole, you can join the WP Engine Developers Discord.

Additionally, if you have questions or ideas, please share them on GitHub Discussions.

Contributing

There are many ways to contribute to this project.

Contributor License Agreement

All external contributors to WP Engine products must have a signed Contributor License Agreement (CLA) in place before the contribution may be accepted into any WP Engine codebase.

  1. Submit your name and email
  2. 📝 Sign the CLA emailed to you
  3. 📥 Receive copy of signed CLA

❤️ Thank you for helping us fulfill our legal obligations in order to continue empowering builders through headless WordPress.

faustjs's People

Contributors

anthonyburchell avatar apmatthews avatar bdurette avatar blakewilson avatar chriswiegman avatar claygriffiths avatar dana-blackbean avatar dependabot[bot] avatar dgallardox avatar github-actions[bot] avatar jordanmaslyn avatar josephfusco avatar kellenmace avatar m1kit avatar markkelnar avatar matt-landers avatar matthewguywright avatar mindctrl avatar moonmeister avatar narcher7 avatar nickcernis avatar rfmeier avatar riderjensen avatar shaunsantacruz avatar swiftgaruda avatar teresagobble avatar theodesp avatar trevanhetzel avatar wjohnsto avatar wpe-jenkins-github-admin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

faustjs's Issues

Create tests for `next` package

We need a suite of tests for the basic functionality of the next package. This may include:

  • utils
  • Hooks
  • nextConfig
  • getNextStaticPaths

regression: Front page does not show latest posts if a static homepage is set

If a static homepage is set in Settings → Reading, the “latest posts” section of front-page.tsx shows no posts. You have to set “Your homepage displays” to “latest posts” before posts appear.

Current behaviour

Screenshot 2021-02-16 at 15 57 48

Screenshot 2021-02-16 at 15 58 37

Expected result

Latest Posts should display posts whether “latest posts” or a static page is selected in reading settings.

Screenshot 2021-02-16 at 15 58 29

To reproduce

  1. In WordPress at Settings → Reading, set “Your homepage displays” to “a static page” and choose any page.
  2. npm run bootstrap && npm run dev
  3. Visit http://localhost:3000

The Latest Posts section is empty.

More info

Introduced in d56a5e7. If I check out the previous commit (d513e0e) all is well.

Logging console.log(pageProps.__APOLLO_STATE__.ROOT_QUERY); in examples/getting-started/pages/_app.tsx shows that nodes are empty for the root query when a static page is set:

getting-started: [Object: null prototype] {
getting-started:   __typename: 'Query',
getting-started:   'nodeByUri({"uri":"/"})': { __ref: 'Page:cG9zdDo2' },
getting-started:   generalSettings: [Object: null prototype] {
getting-started:     __typename: 'GeneralSettings',
getting-started:     title: 'fresh install',
getting-started:     description: 'Just another WordPress site',
getting-started:     url: 'http://localhost:3000'
getting-started:   },
getting-started:   'contentNode({"asPreview":false,"id":"/","idType":"URI"})': { __ref: 'Page:cG9zdDo2' }
getting-started: }

There should be a nodes property like this:

getting-started: [Object: null prototype] {
getting-started:   __typename: 'Query',
getting-started:   'nodeByUri({"uri":"/"})': { __ref: 'ContentType:cG9zdF90eXBlOnBvc3Q=' },
getting-started:   generalSettings: [Object: null prototype] {
getting-started:     __typename: 'GeneralSettings',
getting-started:     title: 'fresh install',
getting-started:     description: 'Just another WordPress site',
getting-started:     url: 'http://localhost:3000'
getting-started:   },
getting-started:   'posts({})': [Object: null prototype] {
getting-started:     __typename: 'RootQueryToPostConnection',
getting-started:     pageInfo: [Object: null prototype] {
getting-started:       __typename: 'WPPageInfo',
getting-started:       endCursor: 'YXJyYXljb25uZWN0aW9uOjE=',
getting-started:       hasNextPage: false,
getting-started:       hasPreviousPage: false,
getting-started:       startCursor: 'YXJyYXljb25uZWN0aW9uOjEw'
getting-started:     },
getting-started:     nodes: [ [Object], [Object] ]
getting-started:   }

How to create archive, category pages

I really liked this framework and i would like to use this one for my next project.
I am struggling with handle archive, category pages.
So how i can use these template files inside theme directory and also if i want to custom-page-template then what to do here?

Breakout `core` Package

This issue is in response to @wjohnsto's comment on #194

We need to break the package up with the first package being core which should include (but not limited to):
The core package includes:

  • Authentication and authorization
    • OAuth handlers
    • JWT Auth
    • Preview support
  • Data fetching
    • Retrieve WP data based on the URL scheme
    • Fetch custom queries
    • Compose queries from fragments so that components can let the framework know the data it requires
    • Provide a mechanism for mutations
  • Gutenberg block processing
    • Communication between WP and the frontend
    • Shared styles
    • Configuration
    • Data changes

Ran into issues with .env.local settings

Hi @nickcernis,
I was going through the tutorial to spin up an example headless site and ran into an issue with configuring the .env.local file. It appears that the secret variable has recently been changed to WP_HEADLESS_SECRET but when I try to run the project, it complains saying that "Error: WPE_HEADLESS_SECRET environment variable is not set.". Changing the variable name to WPE_HEADLESS_SECRET seems to fix the problem.

To reproduce this issue, ran the following command to start the project:
npx create-next-app -e https://github.com/wpengine/headless-framework/tree/canary --example-path examples/getting-started --use-npm
I then changed into that directory, renamed .env.local.sample to .env.local and then updated my settings, then ran npm run dev to launch the project.

Kind regards
Anton

wpgraph-ql-jwt-authentication plugin prevents authentication of preview link URLs

To reproduce

  • wp plugin install --activate https://github.com/wp-graphql/wp-graphql-jwt-authentication/archive/refs/heads/develop.zip
  • Attempt to preview a post. You'll see a blank section where the post content should be.

Cause

Caused by this logic in the wp-graph-ql-jwt-authentication plugin (the validate_token() call returns an error because the passed headless framework auth key doesn't match wpgraph-ql-jwt-authentication's expected keys):

https://github.com/wp-graphql/wp-graphql-jwt-authentication/blob/6f4c18ada3382f51c8aa690aaec3bad994af13f3/wp-graphql-jwt-authentication.php#L191-L206

			add_action( 'init_graphql_request', function() {


				$jwt_secret = Auth::get_secret_key();
				if ( empty( $jwt_secret ) || 'graphql-jwt-auth' === $jwt_secret ) {
					throw new \Exception( __( 'You must define the GraphQL JWT Auth secret to use the WPGraphQL JWT Authentication plugin.', 'graphql-jwt-auth' ) );
				} else {
					$token = Auth::validate_token();
					if ( is_wp_error( $token ) ) {
						add_action( 'graphql_before_resolve_field', function() use ( $token ) {
							throw new \Exception( $token->get_error_code() . ' | ' . $token->get_error_message() );
						}, 1 );
					}
				}




			} );

Commenting that out allows previews to work again.

If we can't work around this in our plugin. wpgraph-ql-jwt-authentication may need to be adjusted.

cc @wjohnsto for visibility. This is a separate issue to #189 that came up while testing the fix in #190.

How should we expose other headless dependencies' modules?

Currently, in the next package, we are importing modules from @wpengine/headless-core and @wpengine/headless-react, then exporting them to be consumed in @wpengine/headless-next. This allows us to only have a dependency of @wpengine/headless-next when building Next.js applications:

import { authorizeHandler } from '@wpengine/headless-next'

However, as we add more functionality, this may start to pollute the named export.

We could use a submodule approach where we export our needed modules under a core or react submodule, then import them like so in Next.js:

import { authorizeHandler } from '@wpengine/headless-next/core'
import { HeadlessProvider } from '@wpengine/headless-next/react'

I think this approach helps delineate between modules better.

@matt-landers @wjohnsto Any thoughts on this?

[PROPOSAL] Authentication and authorization requirements

This is a reference to #198 which discusses:

  • Authentication and authorization
    • OAuth handlers
    • JWT Auth

Auth Implementation

There is currently a limited implementation of auth in core and the WordPress plugin. Here is how OAuth should work, including suggestions for how core should handle authorization and authentication:

NOTE: Some of these features may already exist

  • The WordPress plugin should publish a route where you can send a user to have them authenticate with WordPress
  • Upon successful login, the WordPress plugin will generate a short-lived Authorization Code and redirect the user to a specified redirect URL on the frontend
  • The frontend server should use the Authorization Code and the configured secret key to exchange the code for an access token and refresh token (and associated expirations)
  • The frontend server should store the access token and refresh token in a client-side cookie to be used with subsequent requests to WordPress
  • The WordPress plugin should provide a WPGraphQL mutation that allows exchanging an Access Token and Refresh Token for a new Access Token and Refresh Token
  • The WordPress plugin should provide a WPGraphQL mutation that allows exchanging a username and password for an Access Token and Refresh Token
  • core should handle access token expiration by automatically requesting a new set of tokens when the access token is soon to expire
  • core should provide functionality for:
    • logging in with username and password
    • exchanging refreshing tokens
    • exchanging authorization code and secret for tokens
    • logging out (clearing cookie)

Access Token and Refresh Token Generation

Currently the WordPress plugin only generates an access token with no expiration. We should move to generating both an access token and a refresh token. Here are my suggestions for default token expirations:

  • Access token expiration: 180 days
  • Refresh token expiration: 1 year

NOTE: These expirations should be configurable in the WordPress plugin

Secret Key Generation

Currently the WordPress plugin automatically generates a secret key using wp_generate_uuid4. You are also able to regenerate the key when needed. Should this functionality remain the same? Some plugins (such as WPGraphQL JWT Auth) seem to require a developer to define a secret, and provide no menu functionality to automatically generate one. The benefit of doing it the way JWT Auth does it is you don't run the risk of a publisher accessing the menu and accidentally regenerating the key.

Add root-level scripts for linting and testing

Since this is a monorepo we should support better instrumentation at the root level. Someone should not be required to scope their IDE to a particular directory in order to get the right level of tooling. We'll start by allowing linting and testing from the top level.

Publish `core`, `react`, and `next` to npm

These libraries are now split out, but need to be published to npm, and then react and next should be using the version of their local dependencies from NPM rather than through lerna. This will save us headache related to the multiple react versions, etc.

I suggest we have a canary dist-tag that each of the packages use when specifying internal dependencies.

@matt-landers: We also do not have a name for the framework as of yet, so should we publish under @wpengine/headless-<package> for now? i.e:

  • @wpengine/headless-core
  • @wpengine/headless-react
  • @wpengine/headless-next

Remove Cypress

We switched from Cypress to Codeception and still have some Cypress code in the repo. The Cypress code should be removed so as to not confuse newcomers to the repo.

Previewing drafts only works with a client-side request

Support for previewing drafts was merged in and works great. But only if you have the NEXT_PUBLIC_WORDPRESS_URL config variable set instead of WORDPRESS_URL. That means I have to have the whole site make client side requests in order to have draft previewing capabilities. It would be great if draft previewing worked without having to update the config variable.

Breakout `react` package

This issue is in response to @wjohnsto's comment on #194

In order to create a clear delineation of dependencies, a react package should be created with react specific features. Do not mix Next features in the react package. This package should include (but not limited to):

  • Hooks for data fetching (usePost, usePosts, etc.)
  • Gutenberg block processing for react components
  • Mechanism for registering components with the framework
    • Provide data requirements

[PROPOSAL] Data Fetching

NOTE: This is still a work in progress, I will add to it as more ideas come to mind

Questions unanswered:

  1. Should we be making API calls without the explicit direction of the application?
  2. How can we support a variety of URL schemes for things like pagination, etc?
    • Keep in mind that Next.js (and possible other SSG frameworks) does not support query params when using SSG, so we need to make sure we allow for URLs that might not be WP conventions. We also might need the WP plugin to coordinate this.
  3. How should we allow for components to declare fields needed from specific queries?
  4. How should we allow for addons to provide data fetching capabilities for specific queries?
  5. ...?

This is a reference to #198 which discusses:

  • Data fetching
    • Retrieve WP data based on the URL scheme
    • Fetch custom queries
    • Compose queries from fragments so that components can let the framework know the data it requires
    • Provide a mechanism for mutations

Retrieving WP Data

Currently @wpengine/headless has the following services:

  • getPosts: get a list of posts
  • getContentNode: get an individual post or page
  • getGeneralSettings: get the WP site settings
  • getUriInfo: get information about a URL using WPGraphQL's nodeByUri query

Improvements

getContentNode

Something that can get confusing is how getContentNode will work for posts or pages. We probably want two functions, one for getting a post and another for getting a page. This will simplify our queries and reduce some confusion:

  • getPost: gets a single post
  • getPage: gets a single page

Categories

We should provide functionality around the WPGraphQL categories query:

  • getCategories: get a list of categories
  • getCategory: get a single category
  • getPostsByCategory: gets a list of posts for a specific category
  • ...?

Tags

We should provide functionality around the WPGraphQL tags query:

  • getTags: get a list of tags
  • getTag: get a single tag
  • getPostsWithTags: gets a list of posts that contain specified tags

Menus

We should provide functionality around the WPGraphQL menus query:

  • getMenus: get a list of menus
  • getMenu: get a single menu

Move from Apollo to gqless

I came across this and think it might be useful for the framework to support a number of data fetching scenarios. Let's look into it and see how it works https://github.com/gqless/gqless

Pay specific attention to:

  1. How does it work outside of React/Next?
  2. How does it work with React/Next?
  3. How well is SSG (and SSR/ISR) supported?
  4. Is there opportunity for abstraction and additional functionality that packages/core, packages/react, and packages/next can provide specific to Headless WordPress?

Comment on this issue with any interesting findings. Try to include some sample code with your comments.

UPDATE: We're moving to gqless. Here is how it will work:

  1. core will ship with a default implementation of the gqless client and WPGraphQL schema.
  2. core will publish a function for creating the client that allows overwriting of the schema with a custom version (supports custom WPGraphQL queries)
  3. core will also allow intercepting fetch calls to handle the request, apply headers, etc.
  4. react will use @gqless/react and provide a similar level of configuration for the React gqless client as core
  5. The example apps will provide a standard way of creating the client and providing it to the framework for use in any helper functions.

Branch for this here: https://github.com/wpengine/headless-framework/tree/feature-gqless

[wpe-headless] Site URL conflict

Hey All, I just ran across a "bug" and I'm not sure who needs to know so thought I'd send it to both of you. So yesterday I changed the "Site Address (URL)" to point to my atlas front end. this fixed all the "View" buttons for posts and pages. It fixes an issue in wpgraphql I talked with Jason on the other day where the nodeByUri uses the site_url.

HOWEVER, once this is changed Gutenberg is broken. For some reason Gutenberg uses the frontend url and it breaks the ability to create/update posts. There are some solutions @ WordPress/gutenberg#1761 .

image

Plugin: preview link authentication logic breaks general use of Authorization headers for authentication

With the WPE headless plugin active, JWT authenticated requests give an authentication error.

To reproduce

  1. Install the wp-graphql-jwt-authentication plugin:

    wp plugin install --activate https://github.com/wp-graphql/wp-graphql-jwt-authentication/archive/refs/heads/develop.zip
    
  2. Edit your wp-config.php and add define( 'GRAPHQL_JWT_AUTH_SECRET_KEY', 'your-secret-token' );

  3. Obtain an auth token for your user by running this POST GraphQL request in Postman:

    mutation LoginUser {
      login( input: {
        clientMutationId: "uniqueId",
        username: "your_login",
        password: "your password"
      } ) {
        authToken
        user {
          id
          name
        }
      }
    }
    
  4. Copy the "authToken" value from the response (without the surrounding quotes).

  5. Make a new request in Postman for data that requires authentication, setting “Type” on the “Authentication” tab to “Bearer Token” and pasting your authToken into the token field.

     {
         generalSettings {
             email
         }
     }
    
    Screenshot 2021-04-27 at 11 41 58

    You will see an authentication error like this one:

{
    "errors": [
        {
            "debugMessage": "Authentication Error",
            "message": "Internal server error",
            "extensions": {
                "category": "internal"
            },
            "trace": [
                {
                    "file": "/Users/nick/Sites/dev/wp-content/plugins/wp-graphql/src/Request.php",
                    "line": 604,
                    "call": "WPGraphQL\\Request::after_execute(instance of GraphQL\\Executor\\ExecutionResult)"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-content/plugins/wp-graphql/src/Router.php",
                    "line": 465,
                    "call": "WPGraphQL\\Request::execute_http()"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-content/plugins/wp-graphql/src/Router.php",
                    "line": 270,
                    "call": "WPGraphQL\\Router::process_http_request()"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/class-wp-hook.php",
                    "line": 292,
                    "call": "WPGraphQL\\Router::resolve_http_request(instance of WP)"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/class-wp-hook.php",
                    "line": 316,
                    "call": "WP_Hook::apply_filters(null, array(1))"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/plugin.php",
                    "line": 551,
                    "call": "WP_Hook::do_action(array(1))"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/class-wp.php",
                    "line": 388,
                    "function": "do_action_ref_array('parse_request', array(1))"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/class-wp.php",
                    "line": 750,
                    "call": "WP::parse_request((empty string))"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-includes/functions.php",
                    "line": 1291,
                    "call": "WP::main((empty string))"
                },
                {
                    "file": "/Users/nick/Sites/dev/wp-blog-header.php",
                    "line": 16,
                    "function": "wp()"
                },
                {
                    "file": "/Users/nick/Sites/dev/index.php",
                    "line": 17,
                    "function": "require('/Users/nick/Sites/dev/wp-blog-header.php')"
                },
                {
                    "file": "/Users/nick/.composer/vendor/laravel/valet/server.php",
                    "line": 219,
                    "function": "require('/Users/nick/Sites/dev/index.php')"
                }
            ]
        }
    ]
}

Expected behaviour

After wp plugin deactivate wpe-headless, the same request yields:

{
    "data": {
        "generalSettings": {
            "email": "[email protected]"
        }
    },
    "extensions": {
        "debug": []
    }
}

Notes

The default authentication token expiry is 300 seconds (5 minutes). You can extend this with PHP for testing purposes (not recommended in production):

<?php
// Extend JWT token expiration from 300 seconds to 1 day.
function custom_jwt_expiration( $expiration ) {
    return 86400;
}

add_filter( 'graphql_jwt_auth_expire', 'custom_jwt_expiration' );

Breakup Framework Packages

In an effort to clearly delineate what dependencies are allowed at different levels of the framework (e.g. core, react, next), I propose that we break the framework into smaller npm packages that depend on each other. The foundational package (core) should not have a dependency on react or next. This part of the framework should be able to be used by any frontend framework including Vue, Angular, Svelte, etc.

The core package includes:

  • Authentication and authorization
    • OAuth handlers
    • JWT Auth
    • Preview support
  • Data fetching
    • Retrieve WP data based on the URL scheme
    • Fetch custom queries
    • Compose queries from fragments so that components can let the framework know the data it requires
    • Provide a mechanism for mutations
  • Gutenberg block processing
  • Communication between WP and the frontend
    • Shared styles
    • Configuration
    • Data changes

The react package includes:

  • Hooks for data fetching (usePost, usePosts, etc.)
  • Gutenberg block processing for react components
  • Mechanism for registering components with the framework
    • Provide data requirements

The next package includes:

  • Data cache sync on client and server (SSR)
  • Support for preview mode

This list is not exhaustive of what we should do, but it includes what is in the framework today with some future enhancements that we know we need to address.

Next.js app doesnt run after setup - Win 10 WSL 2

I have gone through the instructions and setup a local WP instance through WP local with an alias. I am stuck at Step 6 after running npm run dev

I am on Windows 10 using WSL 2 so I hope that's not the cause of this issue?

WP Local Setup

WP Local config

Next.js Error

Next Localhost

Apollo Error

Apollo Error

Local Environment File

Local Environment file

Remove lerna

We no longer need lerna now that we have moved to using canary dependencies. It can be removed and replaced with top-level scripts for cleaning and installing dependencies.

Migrate `examples/next/getting-started` to canary framework

Things to make sure are supported:

  1. All files/pages specified in #235
  2. 404s
  3. Previews
  4. Custom pages
  5. Pagination <-- this will require further feature support
  6. Use both SSR and SSG <-- validate in developer network tab

Let's log new issues for bugs as they come up.

Previewing only works for WP post links from site root, not from custom paths

Previews will only work if your post links are from the root of your site (e.g. mysite.local/hello-world) rather than at a separate path (e.g. mysite.local/blog/hello-world).

I believe this is an issue with the plugin. The plugin is aware of and creates direct URLs to where it assumes the frontend has the preview handler API router. So if your "Front-end site URL" in your headless settings is https://mysite.local/blog then the plugin will end up sending you to https://mysite.local/blog/api/auth/wpe-headless?redirect_url=blog%2Fhello-world%2Fpreview%2F21 if you are trying to preview an autosave, and https://mysite.local/blog/api/auth/wpe-headless?redirect_url=draft%2Fpreview%2F21 if you are trying to preview a draft post. There are a few things wrong with this,:

  1. The frontend site doesn't have its API route at /blog/api/.... In fact, in its current state the frontend is not able to specify a custom API route for the preview handler.
    • You can kind of get around this by specifying the following in your next.config.js
    rewrites() {
      return [
        {
          source: '/blog/api/:path*',
          destination: '/api/:path*',
        },
      ];
    },
    • While the code above works to rewrite the API route, it's a hack and should not be relied on
  2. Notice that for draft posts the redirect URL is draft/preview/21. This won't work, as the URL would need to be blog/draft/preview/21.

There are a couple ways you could deal with this issue, but before I get into that it is important to understand the reason the WP plugin is currently using direct URLs to the API route in the first place rather than rewriting to be the same URL WP would use. When using a WP site to preview drafts/autosaves the URL will contain preview information in the query string. In a Next app, you do not have access to query parameters in the GetStaticPropsContext (see an issue about it here). So in order to support previewing with Next and getStaticProps it is necessary to rewrite the URL query parameters to be part of the path.

With that being said, I think some day in the future Next may support query params in GetStaticPropsContext and when that day comes we should revert back to simply using the same WP frontend URLs for previewing, which would in-effect decouple the plugin from the framework. For now, we have to come up with some way to do it that supports custom frontend routes for blog posts. Here is my suggestion:

  1. We refactor the plugin to have 2 URL options
    • The first one is the root URL (e.g. https://mysite.local/)
    • The second one is the root list posts path (e.g. /blog/), which defaults to /
  2. When you are in wp-admin and want to preview a post, the URL will be rewritten to use the same schema that WP uses, only we will append /preview/ to the front of the path (e.g. https://mysite.local/preview/?p=21&preview=true or https://mysite.local/preview/hello-world/?preview_id=1&preview_nonce=ac879988a0&preview=true).
  3. On the frontend/framework side, we instruct people to create a specific /pages/preview/[[...page]].tsx that will serve as their page for previews.
    • This page could be fully client-side rendered or could use getServerSideProps, but shouldn't use getStaticProps
  4. Logic is added to the framework to handle redirecting for authentication based on frontend configuration only. This effectively prevents the WP plugin from having to know/direct anything about the frontend routes except for the configured preview route.

I think doing this or something similar makes the most sense for now and will decouple the plugin from the frontend as much as possible while we wait for Next to add support for query params in GetStaticPropsContext.

Thoughts?

Use ESLint ignorepatterns for files outside of `src` in packages

Our tsconfig.json's rootDir is src. Our ESLint config uses our tsconfig.json for a parser config, so all files outside of src are throwing an eslint warning in the ESLint VSC plugin.

We can add an ignore patterns for js/ts files outside of src to fix this.

[PROPOSAL] Next.js Templating

NOTE: This is still a work in progress, feedback welcome.

Currently, @wpengine/headless provides templating functionality for use in Next.js. This includes the templates in wp-templates/, getNextStaticProps(), getNextStaticPaths(), etc.

With the improvements in #232, it will become much easier to query and fetch data.

With these improvements, we may want to consider leveraging the native Next.js page routing system, where the user would implement the data fetching functionality and getStaticProps/getStaticPaths themselves.

An example Next.js app using this format will look like:

pages/
├─ preview/ <- All pages under here are CSR/SSR only
│  ├─ post/
│  │  ├─ [[...postPreviewUri]].tsx
│  ├─ page/
│  │  ├─ [[...pagePreviewUri]].tsx
├─ posts/
│  ├─ index.tsx
│  ├─ [postSlug].tsx <-- /posts/hello-world
│  ├─ page/
│  │  ├─ [paginationTerm]/
│  │  │  ├─ [postCursor].tsx <-- posts/page/[before|after]/tbsda==
├─ category/
│  ├─ [categorySlug].tsx <-- category/featured
│  ├─ page/
│  │  │  ├─ [paginationTerm]/
│  │  │  |  ├─[categoryCursor].tsx <-- category/featured/[before|after]/tbsda==
├─ _app.tsx
├─ 404.tsx
├─ index.tsx
├─ about.tsx
├─ [...pageUri].tsx

Breakout `next` package

This issue is in response to @wjohnsto's comment on #194

The react package should not have a dependency on next, so we need a next specific package that includes (but not limited to):

  • Data cache sync on client and server (SSR)
  • Support for preview mode

bad link to getting-started readme.md

The headless-framework readme has a bad link down in the Guides section which takes the user to https://github.com/wpengine/headless-framework/blob/canary/docs/getting-started/README.mid

Changing the url to README.md takes you to the correct page.

Ignore query strings in Next.js routing.

Hey guys!

Killer framework, love using it so far. I'm running into an issue using the headless-framework with Local.

Local will open URLs with a cache-buster query string to force browsers to load a fresh copy of the site. When Local opens the headless framework with that query string we get a 404. Removing the cache-buster query string allows the requested page to load.

I'm wondering if we can either whitelist the cache-buster query string, or ignore all query strings in the routing.

Thanks!

Plugin redirects are not factoring in the query string

When you have the Enable public route redirects flag enabled you are supposed to get 302 redirects for non-admin WP URLs to your specified frontend URL. This works and preserves the URL path (e.g. "http://mysite.local/foo/bar" will redirect to "http://localhost:3000/foo/bar"), but doesn't factor into the query string.

Steps to reproduce:

  1. Ensure Enable public route redirects is checked
  2. Navigate to your WP frontend with a query string (e.g. "http://mysite.local?foo=bar")
  3. Note that you are redirected to your frontend without the query string (e.g. "http://localhost:3000)

Create an example project using the `next` package

We need an example project that uses the new broken out packages. Let's create an /examples/next/getting-started directory and project. We can start with a simple blog site with SSG, previews, etc. It might make sense to copy the current getting-started and pair it down to only the features preserved in the new framework, but whoever owns this issue can make that decision.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.