wpengine / faustjs

Faust.js™ - The Headless WordPress Framework
https://faustjs.org
Other
1.44k stars 131 forks source link

Support for querying data from multiple WordPress endpoints #1937

Open jasonbahl opened 2 months ago

jasonbahl commented 2 months ago

As a developer building a Faust website, I would like to be able to get data from multiple WordPress installs and render the data in the same Faust front-end.

Problem

Currently Faust.js is centered around a singular WPGraphQL endpoint, enabling the Faust front-end to get data from 1 WordPress install.

Organizations that use multiple WordPress installs to split up content creation responsibilities have reported wanting to use Faust to pull in data from multiple different WordPress and render the data in a single front-end.

Proposal

My proposal is to create a "Client Registry" within Faust that allows multiple clients to be configured. Then different dynamic templates could be created and the <WordPressTemplate /> and getWordPressProps functions could pass an argument to specify which client to interact with.

Client Registry

Users would configure multiple clients in their faust.config.js, like so (pseudo):

import { setConfig } from '@faustwp/core'

export default setConfig({
  ...existingFaustSettings,
  clients: {
    {
      id:  "default",
      uri: "https://site-a.com",
      otherConfigFieldHere: "other config value here"
    },
    {
      id:  "site-b",
      uri: "https://site-b.com",
      otherConfigFieldHere: "other config value here"
    },
    {
      id:  "site-c",
      uri: "https://site-c.com",
      otherConfigFieldHere: "other config value here"
    }
  }
})

Template Usage

Multiple NextJS Dynamic Routes could be created, each specifying which client should be used:

Default Client

In this example, any url that did not match another dynamic route would fall back to this template and communicate to the "default" client (i.e. site-a.com)

/pages/[...WordPressNode].js

import { getWordPressProps, WordPressTemplate } from '@faustwp/core'

export default function Page(props) {
  return <WordPressTemplate {...props} />
}

export async function getStaticProps(ctx) {
  return { ...(await getWordPressProps({ ctx })), revalidate: 5 }
}

export async function getStaticPaths() {
  return {
    paths: [],
    fallback: 'blocking',
  }
}

Additional Clients

In this example, any url visited under the /news/** directory would attempt to resolve by communicating with "site-b"

/pages/news/[...WordPressNode].js

import { getWordPressProps, WordPressTemplate } from '@faustwp/core'

export default function Page(props) {
  return <WordPressTemplate {...props} client="site-b" />
}

export async function getStaticProps(ctx) {
  return { ...(await getWordPressProps({ ctx, client: "site-b" })), revalidate: 5 }
}

export async function getStaticPaths() {
  return {
    paths: [],
    fallback: 'blocking',
  }
}

Helper functions, etc

We'd likely need to introduce various helper functions and utilities for fetching from a specific client directly.

const siteBClient = getApolloClient( id: "site-b" )
const { data } = siteBClient.query( {  query: ..., variables: { ... } } );
SRIIAKHILLESSH commented 2 months ago

Hi there, Since I finished these tasks for my project previously, I'm willing to assist. I have emailed you through the Google form because I am interested in helping you resolve this issue. I look forward to working with you on it.