{"id":13902785,"url":"https://github.com/gregrickaby/nextjs-wordpress","last_synced_at":"2025-04-09T14:13:38.503Z","repository":{"id":42456002,"uuid":"342459015","full_name":"gregrickaby/nextjs-wordpress","owner":"gregrickaby","description":"💀 It's headless WordPress!","archived":false,"fork":false,"pushed_at":"2024-05-01T19:15:45.000Z","size":3462,"stargazers_count":205,"open_issues_count":1,"forks_count":40,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-05-02T03:19:56.154Z","etag":null,"topics":["graphql","headless","headless-cms","headless-wordpress","nextjs","tailwindcss","typescript","vercel","wordpress","wpgraphql"],"latest_commit_sha":null,"homepage":"https://nextjswp.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gregrickaby.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"gregrickaby"}},"created_at":"2021-02-26T04:07:16.000Z","updated_at":"2024-05-14T13:36:25.598Z","dependencies_parsed_at":"2023-02-19T08:00:53.563Z","dependency_job_id":"1e4c73a1-6d41-4fbb-a541-2c28b0827e6d","html_url":"https://github.com/gregrickaby/nextjs-wordpress","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregrickaby%2Fnextjs-wordpress","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregrickaby%2Fnextjs-wordpress/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregrickaby%2Fnextjs-wordpress/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregrickaby%2Fnextjs-wordpress/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gregrickaby","download_url":"https://codeload.github.com/gregrickaby/nextjs-wordpress/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054193,"owners_count":21039952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","headless","headless-cms","headless-wordpress","nextjs","tailwindcss","typescript","vercel","wordpress","wpgraphql"],"created_at":"2024-08-06T22:01:24.169Z","updated_at":"2025-04-09T14:13:38.486Z","avatar_url":"https://github.com/gregrickaby.png","language":"TypeScript","readme":"# Next.js + WordPress\n\nIt's headless WordPress! 💀 - \u003chttps://nextjswp.com\u003e\n\nThis is a bare-bones Next.js app, which fetches data from WordPress via WPGraphQL and styles it with TailwindCSS.\n\nPlease consider it a starting point for your next headless WordPress project.\n\n---\n\n## Supported Features\n\n- Category and Tag Archives\n- Comments\n- Custom Fields\n- Custom Post Types\n- On-demand Revalidation\n- Post/Page Previews\n- RSS Feed\n- Robots.txt\n- Search\n- Sitemap.xml\n- Static Site Generation (SSG)\n- TypeScript, ESLint, and Prettier\n- WordPress Menus\n- Yoast SEO\n\nPlus it's really, really fast! 🚀\n\n![screenshot](https://dl.dropbox.com/s/xh6uq9mblx8rqm1/Screenshot%202023-10-21%20at%2009.58.44.png?dl=0)\n\n---\n\n## Setup\n\n### 1. Clone the repo\n\n```bash\ngit clone git@github.com:gregrickaby/nextjs-wordpress.git\n```\n\n### 2. Install dependencies\n\n```bash\nnpm i\n```\n\n### 3. Create a `.env.local` file\n\n```bash\ncp .env.example .env.local\n```\n\nCustomize the URLs in `.env.local` to match your WordPress setup:\n\n```txt\n# WordPress GraphQL API URL. No trailing slash.\nNEXT_PUBLIC_WORDPRESS_GRAPHQL_URL=\"https://blog.nextjswp.com/graphql\"\n\n# WordPress REST API URL. No trailing slash.\nNEXT_PUBLIC_WORDPRESS_REST_API_URL=\"https://blog.nextjswp.com/wp-json/wp/v2\"\n\n# Optional. JWT auth refresh token.\n#NEXTJS_AUTH_REFRESH_TOKEN=\"\"\n\n# Preview Secret. Must match the constant in wp-config.php.\nNEXTJS_PREVIEW_SECRET=\"preview\"\n\n# Revalidation Secret. Must match the constant in wp-config.php.\nNEXTJS_REVALIDATION_SECRET=\"revalidate\"\n```\n\n### 4. Configure `next.config.js`\n\nUpdate the URL in `next.config.js` to match your WordPress site:\n\n```ts\nconst nextConfig = {\n  images: {\n    remotePatterns: [\n      {\n        protocol: 'https',\n        hostname: '*.nextjswp.**' // \u003c-- Change this to your WordPress site\n      }\n    ]\n  }\n}\n```\n\n### 5. Configure `/lib/config.ts`\n\nOpen `/lib/config.ts` and update the content to match your WordPress site:\n\n```ts\nconst config = {\n  siteName: 'Next.js WordPress',\n  siteDescription: \"It's headless WordPress!\",\n  siteUrl: 'https://nextjswp.com',\n  revalidation: 3600\n}\n```\n\n### 6. Configure WordPress\n\n#### Plugins\n\nYou'll need either a local or public WordPress site with the following plugins:\n\n- [Advanced Custom Fields](https://wordpress.org/plugins/advanced-custom-fields/) (free version is fine)\n- [Next.js WordPress Plugin](https://github.com/gregrickaby/nextjs-wordpress-plugin)\n- [Next.js WordPress Theme](https://github.com/gregrickaby/nextjs-wordpress-theme)\n- [WPGraphQL Yoast SEO](https://wordpress.org/plugins/add-wpgraphql-seo/)\n- [WPGraphQL for Advanced Custom Fields](https://wordpress.org/plugins/wpgraphql-acf/)\n- [WPGraphQL JWT Authentication](https://github.com/wp-graphql/wp-graphql-jwt-authentication) (optional)\n- [WPGraphQL](https://www.wpgraphql.com/)\n- [Yoast SEO](https://wordpress.org/plugins/wordpress-seo/)\n\n#### WP-Config\n\nAfter installing all the plugins mentioned above, you'll need to add some constants to your `wp-config.php` file:\n\n```php\n// The URL of your Next.js frontend. Include the trailing slash.\ndefine( 'NEXTJS_FRONTEND_URL', 'https://nextjswp.com/' );\n\n// Optional. JWT auth refresh token.\n//define( 'GRAPHQL_JWT_AUTH_SECRET_KEY', '' );\n\n// Any random string. This must match the .env variable in the Next.js frontend.\ndefine( 'NEXTJS_PREVIEW_SECRET', 'preview' );\n\n// Any random string. This must match the .env variable in the Next.js frontend.\ndefine( 'NEXTJS_REVALIDATION_SECRET', 'revalidate' );\n```\n\n#### Permalinks\n\nFinally, set your permalink structure to `/blog/%postname%/` in **Settings -\u003e Permalinks**.\n\n### 7. Optional. Authentication for Previews\n\nIn order to query draft posts for Previews, you'll need to authenticate with WordPress. The following is a one-time step:\n\n- Install and activate the [WPGraphQL JWT Authentication](https://github.com/wp-graphql/wp-graphql-jwt-authentication) plugin\n- Generate any random string. I recommend using the [WordPress salt generator](https://api.wordpress.org/secret-key/1.1/salt/)\n- Copy the string\n- Open your `wp-config.php` file, and paste the string into the `GRAPHQL_JWT_AUTH_SECRET_KEY` constant\n\n```php\n// Optional. JWT auth refresh token.\ndefine( 'GRAPHQL_JWT_AUTH_SECRET_KEY', 'the-random-string-generated-by-wp-salt' );\n```\n\n- Go to **GraphQL -\u003e GraphiQL IDE** in your WordPress admin\n- Copy the following and paste into GraphiQL IDE (replace `your_username` and `your_password` with your WordPress credentials)\n\n```graphql\nmutation Login {\n  login(\n    input: {\n      clientMutationId: \"uniqueId\"\n      password: \"your_password\"\n      username: \"your_username\"\n    }\n  ) {\n    refreshToken\n  }\n}\n```\n\n- Click the **Play** button in GraphiQL to run the mutation\n- Copy the `refreshToken` returned by the mutation\n- Open the Next.js `.env.local` file, and paste the `refreshToken` into the `NEXTJS_AUTH_REFRESH_TOKEN` variable\n\n```txt\n# Optional. JWT auth refresh token.\nNEXTJS_AUTH_REFRESH_TOKEN=\"refresh-token-generated-by-grapqh-query\"\n```\n\nYou should now be able to preview draft posts in your Next.js app by clicking the **Preview** button in your WordPress admin.\n\n### 8. Start the dev server\n\n```bash\nnpm run dev\n```\n\nOnce the dev server has started, you can view the front-end: \u003chttp://localhost:3000\u003e\n\n---\n\n## Querying WordPress data with GraphQL\n\nGraphQL is efficient because we can query multiple endpoints in a single request. If we were to use the WordPress REST-API, we would need to make multiple round trips to each respective endpoint.\n\nWe can build our queries in GraphiQL (or your favorite REST client) and let `JSON.stringify()` format it. Because this is all standard JavaScript, we can even pass variables to our queries-- no need for a 3rd party package!\n\nHere is a query to fetch a single post (based on the slug), the featured image, author meta, categories, tags, SEO, and post comments:\n\n```ts\nimport {Post} from '@/lib/types'\n\n/**\n * Fetch a single post by slug.\n */\nexport async function getPostBySlug(slug: string) {\n  // Define our query.\n  const query = `\n    query GetPost($slug: ID!) {\n      post(id: $slug, idType: SLUG) {\n        databaseId\n        content(format: RENDERED)\n        title(format: RENDERED)\n        featuredImage {\n          node {\n            altText\n            mediaDetails {\n              sizes(include: MEDIUM) {\n                height\n                width\n                sourceUrl\n              }\n            }\n          }\n        }\n        author {\n          node {\n            avatar {\n              url\n            }\n            name\n          }\n        }\n        date\n        tags {\n          nodes {\n            databaseId\n            name\n          }\n        }\n        categories {\n          nodes {\n            databaseId\n            name\n          }\n        }\n        seo {\n          metaDesc\n          title\n        }\n        comments(first: 30, where: {order: ASC}) {\n          nodes {\n            content(format: RENDERED)\n            databaseId\n            date\n            status\n            author {\n              node {\n                avatar {\n                  url\n                }\n                email\n                name\n                url\n              }\n            }\n          }\n        }\n      }\n    }\n  `\n\n  // Define our variables.\n  const variables = {\n    slug: slug\n  }\n\n  // Fetch the data using a reusable fetch function. Next.js\n  // automatically memoizes and caches these requests.\n  const response = await fetchGraphQL(query, variables)\n\n  // Return the post.\n  return response.data.post as Post\n}\n```\n\nThis repo does not use a 3rd party GraphQL package, because Next.js automatically memoizes the `fetch()` requests in our custom fetch function. This means that if we fetch the same data twice, Next.js will only make one request to WordPress.\n\n\u003e If you prefer use a 3rd party GraphQL package, simply swap out the custom `fetchGraphQL()` function with the package of your choosing.\n\n---\n\n### Going To Production\n\nRemember to add all the environment variables from `.env.local` to your production environment on [Vercel](https://vercel.com) or [Netlify](https://netlify.com).\n\n---\n\n### Other\n\n#### RSS Feed, Sitemap, Robots.txt\n\n- \u003chttps://nextjswp.com/feed.xml\u003e\n- \u003chttps://nextjswp.com/sitemap.xml\u003e\n- \u003chttps://nextjswp.com/robots.txt\u003e\n\n#### Previews\n\n- \u003chttps://nextjswp.com/preview/120?secret=preview\u003e\n\n---\n\n## Contributing\n\nThis is a hobby project and my time is limited, so your contributions are welcome! Please see the [contributing guidelines](./CONTRIBUTING.md) to get started.\n\n---\n","funding_links":["https://github.com/sponsors/gregrickaby"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregrickaby%2Fnextjs-wordpress","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgregrickaby%2Fnextjs-wordpress","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregrickaby%2Fnextjs-wordpress/lists"}