Skip to content

DopamineDriven/headless-wp-next-directory

Repository files navigation

headless-wp-next-directory

Use for get post preview

export async function getPreviewPost(id, idType = 'DATABASE_ID') {
	const data = await fetchAPI(
		`
    query PreviewPost($id: ID!, $idType: PostIdType!) {
      post(id: $id, idType: $idType) {
        databaseId
        slug
        status
      }
    }`,
		{
			variables: { id, idType }
		}
	);
	return data.post;
}

Apollo Client Codegen options

USAGE
\$ apollo client:codegen [OUTPUT]

ARGUMENTS
OUTPUT
Directory to which generated files will be written. - For TypeScript/Flow generators, this specifies a directory relative
to each source file by default. - For TypeScript/Flow generators with the "outputFlat" flag is set,
and for the Swift generator, this specifies a file or directory
(absolute or relative to the current working directory) to which: - a file will be written for each query (if "output" is a
directory) - all generated types will be written - For all other types, this defines a file (absolute or relative to
the current working directory) to which all generated types are
written.

OPTIONS
-c, --config=config
Path to your Apollo config file

-g, --graph=graph
The ID for the graph in Apollo to operate client commands with.
Overrides config file if set.

-v, --variant=variant
The variant of the graph in Apollo to associate this client to

--[no-]addTypename
[default: true] Automatically add \_\_typename to your queries, can be
unset with --no-addTypename

--clientName=clientName
Name of the client that the queries will be attached to

--clientReferenceId=clientReferenceId
Reference id for the client which will match ids from client traces,
will use clientName if not provided

--clientVersion=clientVersion
The version of the client that the queries will be attached to

--customScalarsPrefix=customScalarsPrefix
Include a prefix when using provided types for custom scalars

--endpoint=endpoint
The URL for the CLI use to introspect your service

--excludes=excludes
Glob of files to exclude for GraphQL operations. Caveat: this doesn't
currently work in watch mode

--globalTypesFile=globalTypesFile
By default, TypeScript will put a file named "globalTypes.ts" inside
the "output" directory. Set "globalTypesFile" to specify a different
path. Alternatively, set "tsFileExtension" to modify the extension of
the file, for example "d.ts" will output "globalTypes.d.ts"

--header=header
Additional header to send during introspection. May be used multiple
times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
if using the `--header` flag.

--includes=includes
Glob of files to search for GraphQL operations. This should be used to
find queries _and_ any client schema extensions

--key=key
The API key to use for authentication to Apollo

--localSchemaFile=localSchemaFile
Path to one or more local GraphQL schema file(s), as introspection
result or SDL. Supports comma-separated list of paths (ex.
`--localSchemaFile=schema.graphql,extensions.graphql`)

--mergeInFieldsFromFragmentSpreads
Merge fragment fields onto its enclosing type

--namespace=namespace
The namespace to emit generated code into.

--omitDeprecatedEnumCases
Omit deprecated enum cases from generated code [Swift only]

--only=only
Parse all input files, but only output generated code for the
specified file [Swift only]

--operationIdsPath=operationIdsPath
Path to an operation id JSON map file. If specified, also stores the
operation ids (hashes) as properties on operation types [currently
Swift-only]

--outputFlat
By default, TypeScript/Flow will put each generated file in a
directory next to its source file using the value of the "output" as
the directory name. Set "outputFlat" to put all generated files in the
directory relative to the current working directory defined by
"output".

--passthroughCustomScalars
Use your own types for custom scalars

--queries=queries
Deprecated in favor of the includes flag

--suppressSwiftMultilineStringLiterals
Prevents operations from being rendered as multiline strings [Swift
only]

--tagName=tagName
Name of the template literal tag used to identify template literals
containing GraphQL queries in Javascript/Typescript code

--target=target
(required) Type of code generator to use (swift | typescript | flow |
scala | json | json-modern (exposes raw json types))

--tsFileExtension=tsFileExtension
By default, TypeScript will output "ts" files. Set "tsFileExtension"
to specify a different file extension, for example "d.ts"

--useFlowExactObjects
Use Flow exact objects for generated types [flow only]

--useFlowReadOnlyTypes
Use read only types for generated types [flow only]. **Deprecated in
favor of `useReadOnlyTypes`.**

--useReadOnlyTypes
Use read only types for generated types [flow | typescript]

--watch
Watch for file changes and reload codegen

ALIASES
\$ apollo codegen:generate

Code Review - Advanced Apollo TS

Make Links "Crawlable"

Try adding undefined

AWS Amplify

GraphQL.js + CodeGen

PostOrderByType

import { GraphQLEnumType } from 'graphql';
export declare type PostOrderBy =
	| 'date'
	| 'id'
	| 'include'
	| 'relevance'
	| 'slug'
	| 'title';
declare const postOrderByType: GraphQLEnumType;
export default postOrderByType;

GraphQL-let codegen (vercel/next example repo)

9-28-20

wpapi and @types/wpapi packages

Wp-GraphQL-WooCommerce Plugin

Better REST Api Featured Images plugin

IMPORTANT @jlovejo2

ALSO IMPORANT

  • Check out the getServerSideProps method used by the author here
  • passing query and resolving props types in that way for getServerSideProps
  • When attempting this approach (see my revisions in andrew-james-notes.md) the following error was returned
$ yarn dev
yarn run v1.22.5
$ next
info  - Loaded env from C:\Users\Anthr\headless-wp-next-directory\.env.local
ready - started server on http://localhost:3000
event - compiled successfully
event - build page: /next/dist/pages/_error
wait  - compiling...
event - compiled successfully
event - build page: /
wait  - compiling...
event - compiled successfully
[
  {
    message: 'Field "posts" argument "where" requires type PostObjectsConnectionOrderbyEnum, found undefined.',
    extensions: { category: 'graphql' },
    locations: [ [Object] ]
  },
  {
    message: 'Field "posts" argument "where" requires type OrderEnum, found undefined.',
    extensions: { category: 'graphql' },
    locations: [ [Object] ]
  }
]
Error: Failed to fetch API
    at fetchAPI (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:3204:11)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async getAllPostsForHomeAlphabetical (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:3249:16)
    at async getServerSideProps (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:6530:20)
    at async renderToHTML (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\render.js:38:185)
    at async C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:76:329
    at async C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:75:142
    at async DevServer.renderToHTMLWithComponents (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:99:364)
    at async DevServer.renderToHTML (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:100:255)
[
  {
    message: 'Field "posts" argument "where" requires type PostObjectsConnectionOrderbyEnum, found undefined.',
    locations: [ [Object] ]
  },
  {
    message: 'Field "posts" argument "where" requires type OrderEnum, found undefined.',
    extensions: { category: 'graphql' },
    locations: [ [Object] ]
  }
]
Error: Failed to fetch API
    at fetchAPI (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:3204:11)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async getAllPostsForHomeAlphabetical (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:3249:16)
    at async getServerSideProps (C:\Users\Anthr\headless-wp-next-directory\.next\server\pages\index.js:6530:20)
    at async renderToHTML (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\render.js:38:185)
    at async C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:76:329
    at async C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:75:142
    at async DevServer.renderToHTMLWithComponents (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:99:364)
    at async DevServer.renderToHTML (C:\Users\Anthr\headless-wp-next-directory\node_modules\next\dist\next-server\server\next-server.js:100:255)

TypeRoots && TypePlugins && TSLint/ESLint config (.eslintrc.json)

{
	"parser": "@typescript-eslint/parser",
	"extends": [
		"eslint:recommended",
		"plugin:@typescript-eslint/recommended",
		"plugin:react/recommended"
	],
	"parserOptions": {
		"ecmaVersion": 2020,
		"sourceType": "module",
		"ecmaFeatures": {
			"jsx": true
		}
	},
	"plugins": ["@typescript-eslint"],
	"env": {
		"node": true,
		"es6": true,
		"browser": true
	},
	"rules": {
		// could set "indent": [true, "tabs", 1]
		"indent": "off",
		"@typescript-eslint/indent": "off",
		"@typescript-eslint/explicit-function-return-type": "off",
		"@typescript-eslint/explicit-module-boundary-types": "off",
		"react/prop-types": "off"
	},
	"settings": {
		"react": {
			"version": "detect"
		}
	}
}

Prettier format script

  • Resolve
		"prettier-format": "prettier --config .prettierrc 'components/**/*.tsx' --write"

TailwindCSS Tips and Tricks

WP-GQL/WP-GQL-ACF

ReactElement vs ReactNode vs JSX.Element

interface ReactElement<
	P = any,
	T extends string | JSXElementConstructor<any> =
		| string
		| JSXElementConstructor<any>
> {
	type: T;
	props: P;
	key: Key | null;
}
interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;
type ReactNode =
	| ReactChild
	| ReactFragment
	| ReactPortal
	| boolean
	| null
	| undefined;

InferGetStaticPropsType, GetStaticPropsResult, GetStaticPropsContext...

getInitialProps

Incremental Static Regeneration (ISR)

node_modules/wp-graphql/lib/lib/abstract-types

Headless WP, NextJS, React, TypeScript, Node, Tailwindcss, Vercel

8/26/20

Patching node_modules

npx patch-package @fortawesome/fontawesome-common-types
  • however, if you were to edit the core css in fontawesome-svg-core, for example, then target that module
npx patch-package @fortawesome/fontawesome-svg-core
  • see my post for more details on custom icon incorporation

Multilingual Support

Responsive Navbar ideas

Thread Vercel with WPEngine in Production

  • Goal: link new/updated posts in the headless CMS with a deployed build on Vercel in real time
    • First steps:
      • determine how WP Engine communicates with local env under the hood
      • configure communication between Vercel and WP Engine clouds in real time

WPGQL Custom Post Types

WPGQL Typings

add_action( 'graphql_register_types', function() {
  register_graphql_field( 'Post', 'color', [
     'type' => 'String',
     'description' => __( 'The color of the post', 'wp-graphql' ),
     'resolve' => function( $post ) {
       $color = get_post_meta( $post->ID, 'color', true );
       return ! empty( $color ) ? $color : 'blue';
     }
  ] );
} );

Simple Social Icons Plugin

query MyQuery {
  plugins {
    edges {
      node {
        name
        path
        pluginUri
        id
        description
        author
        authorUri
      }
    }
  }
}
  • returns
{
	"node": {
		"name": "Simple Social Icons",
		"path": "simple-social-icons/simple-social-icons.php",
		"pluginUri": "https://wordpress.org/plugins/simple-social-icons/",
		"id": "cGx1Z2luOnNpbXBsZS1zb2NpYWwtaWNvbnMvc2ltcGxlLXNvY2lhbC1pY29ucy5waHA=",
		"description": "A simple CSS and SVG driven social icons widget.",
		"author": "StudioPress",
		"authorUri": "https://www.studiopress.com/"
	}
}
  • plugins are independent of posts and authors
  • plugin component made
  • plugin in index and slug.tsx

WP-GraphQL-Composer Plugin

Search Bar Configuration

WP Decoupled with Nextjs

ServerSideProps and Cookies in NextJS

WP Developer Blog

Generate a random secret

  • open the terminal, type "node", hit enter
  • next, input the following:
require('crypto').randomBytes(64).toString('hex')
  • this returns a 122-character hexadecimal string

Generating a public/private keypair for WP Engine SFTP access

  • enter the following into a bash terminal
ssh-keygen -t rsa -b 4096 -f ~/.ssh/wpengine_rsa
  • then, to connect with WP Engine site of interest
ssh -i ~/.ssh/wpengine_rsa -o IdentitiesOnly=yes nextjsheadless@nextjsheadless.ssh.wpengine.net
  • this connects you with WP Engine and a figlet-mediated animation appears
  • cd into the correct directory and execute ls to ensure wp-config.php is located here
cd sites/nextjsheadless && ls
  • then enter the following to insert a new key value pair under the WP Engine Settings # tag of the wp-config file
wp config set GRAPHQL_JWT_AUTH_SECRET_KEY <secret generated using node terminal> --placement=after --anchor=Settings
  • double check the placement of the insertion by running
wp config edit vim
  • if changes need to be made, enter
:vim wp config edit
  • then enter
i
  • this enables -- INSERT -- mode in Vim
  • proceed with editing; once finished, save your changes with
:x
  • this successfully saves and exits the Vim editor
  • if no changes are required after opening the Vim editor, then
:qa!

Enable WPGraphQL JWT Authentication Plugin via WP Engine GraphiQL plugin

  • after enabling, open GraphiQL interface
mutation Login {
	login(
		input: {
			clientMutationId: "uniqueId"
			password: "insert password"
			username: "nextjsheadless"
		}
	) {
		refreshToken
	}
}
  • this returns a refresh token value for the WORDPRESS_AUTH_REFRESH_TOKEN key in .env.local
  • set the value of the WORDPRESS_PREVIEW_SECRET key to any url-friendly string
href={`localhost:3000/api/preview?secret=${process.env.WORDPRESS_PREVIEW_SECRET}&id=${draft.id}`}

View drafts locally or on the deployed site

  • append the following relative path on the landing page url
  • /api/preview?secret=secret-path&id=target-id
  • where - secret-path = /preview-mode - target-id = id of the unpublished post (determined via phpmyadmin)
  • this will load the corresponding post
  • for example, try
https://headless-wp-next-directory.vercel.app/api/preview?secret=/preview-mode&id=22
  • (08-04-20)

Favicon

HWP+Next

JAMstack

Lazy-Loading Images with Next

Configure GraphQL JWT w/ WPEngine

Tailwind Starter Kits

Using @fortawesome/react-fontawesome with nextjs

Customizable Background Patterns -- SVGs

Useful Supplemental Resources

HTML Symbols

About

Headless WP, NextJS, GraphQL, React, TypeScript, Node, Tailwindcss, Vercel

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published