Integrating WordPress with Next.js for a Modern Web ExperienceIntegrating WordPress with Next.js for a Modern Web Experience
Updated at Apr 17, 2024
13 Views

Goal

Configure WordPress with GraphQL to serve as the backend for the Next.js frontend. Additionally, establish a custom “Project” feature to enhance the blog’s functionality.

Setup Customize Theme in WordPress

1. Open the “/wp-content/themes” directory and create a new folder named “redirects”.

2. Navigate to the “wp-content/themes/redirects” folder and generate the following two files.

<?php
	header( "Location: YOUR_NEXTJS_URL" );
?>

3. Style.css

/*
Theme Name: turn off frontend
Description: Redirects to my next.js blog
Theme URI: 
Author: Vincent Wang
Version: 1.0.0
License: GNU
License URI:
Tags:
*/

Setup GraphQL for WordPress

1. Install the wpgraphql plugin.

2. Here is an example of how to retrieve first 100 data from all posts in GraphQL.

{
  posts(first: 100, where: {orderby: {field: DATE, order: DESC}}) {
    nodes {
      title
      date
      slug
      featuredImage {
        node {
          sourceUrl
        }
      }
      categories(first: 1) {
        edges {
          node {
            name
          }
        }
      }
    }
  }
}

Register Custom Post Types (Optional)

I have a project within my portfolio that requires me to establish Custom Post Types within the `functions.php` file. Additionally, I intend to configure GraphQL in the same file.

<?php
add_theme_support('post-thumbnails');

// Register Custom Post Type
function custom_project_post_type()
{
    $labels = array(
        'name'                  => _x('Projects', 'Post Type General Name', 'text_domain'),
        'singular_name'         => _x('Project', 'Post Type Singular Name', 'text_domain'),
        'menu_name'             => __('Projects', 'text_domain'),
        'name_admin_bar'        => __('Project', 'text_domain'),
        'archives'              => __('Project Archives', 'text_domain'),
        'attributes'            => __('Project Attributes', 'text_domain'),
        'parent_item_colon'     => __('Parent Project:', 'text_domain'),
        'all_items'             => __('All Projects', 'text_domain'),
        'add_new_item'          => __('Add New Project', 'text_domain'),
        'add_new'               => __('Add New', 'text_domain'),
        'new_item'              => __('New Project', 'text_domain'),
        'edit_item'             => __('Edit Project', 'text_domain'),
        'update_item'           => __('Update Project', 'text_domain'),
        'view_item'             => __('View Project', 'text_domain'),
        'view_items'            => __('View Projects', 'text_domain'),
        'search_items'          => __('Search Project', 'text_domain'),
        'not_found'             => __('Not found', 'text_domain'),
        'not_found_in_trash'    => __('Not found in Trash', 'text_domain'),
        'featured_image'        => __('Featured Image', 'text_domain'),
        'set_featured_image'    => __('Set featured image', 'text_domain'),
        'remove_featured_image' => __('Remove featured image', 'text_domain'),
        'use_featured_image'    => __('Use as featured image', 'text_domain'),
        'insert_into_item'      => __('Insert into project', 'text_domain'),
        'uploaded_to_this_item' => __('Uploaded to this project', 'text_domain'),
        'items_list'            => __('Projects list', 'text_domain'),
        'items_list_navigation' => __('Projects list navigation', 'text_domain'),
        'filter_items_list'     => __('Filter projects list', 'text_domain'),
    );
    $args = array(
        'label'                 => __('Project', 'text_domain'),
        'description'           => __('Custom post type for projects', 'text_domain'),
        'labels'                => $labels,
        'supports'              => array('title', 'editor', 'thumbnail', 'custom-fields'),
        'taxonomies'            => array('project_category'),
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-portfolio',
        'show_in_admin_bar'     => true,
        'show_in_nav_menus'     => true,
        'can_export'            => true,
        'has_archive'           => true,
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'capability_type'       => 'post',
        'show_in_graphql' => true,
        'graphql_single_name' => 'project',
        'graphql_plural_name' => 'projects',
    );
    register_post_type('project', $args);
}
add_action('init', 'custom_project_post_type', 0);

// Register Custom Taxonomy
function custom_project_taxonomy()
{
    $labels = array(
        'name'                       => _x('Project Categories', 'Taxonomy General Name', 'text_domain'),
        'singular_name'              => _x('Project Category', 'Taxonomy Singular Name', 'text_domain'),
        'menu_name'                  => __('Project Categories', 'text_domain'),
        'all_items'                  => __('All Categories', 'text_domain'),
        'parent_item'                => __('Parent Category', 'text_domain'),
        'parent_item_colon'          => __('Parent Category:', 'text_domain'),
        'new_item_name'              => __('New Category Name', 'text_domain'),
        'add_new_item'               => __('Add New Category', 'text_domain'),
        'edit_item'                  => __('Edit Category', 'text_domain'),
        'update_item'                => __('Update Category', 'text_domain'),
        'view_item'                  => __('View Category', 'text_domain'),
        'separate_items_with_commas' => __('Separate categories with commas', 'text_domain'),
        'add_or_remove_items'        => __('Add or remove categories', 'text_domain'),
        'choose_from_most_used'      => __('Choose from the most used', 'text_domain'),
        'popular_items'              => __('Popular Categories', 'text_domain'),
        'search_items'               => __('Search Categories', 'text_domain'),
        'not_found'                  => __('Not Found', 'text_domain'),
        'no_terms'                   => __('No categories', 'text_domain'),
        'items_list'                 => __('Categories list', 'text_domain'),
        'items_list_navigation'      => __('Categories list navigation', 'text_domain'),
    );
    $args = array(
        'labels'                     => $labels,
        'hierarchical'               => true,
        'public'                     => true,
        'show_ui'                    => true,
        'show_admin_column'          => true,
        'show_in_nav_menus'          => true,
        'show_tagcloud'              => true,
        'show_in_graphql'            => true,
        'graphql_single_name' => 'projectCategory',
        'graphql_plural_name' => 'projectCategories',
    );
    register_taxonomy('project_category', array('project'), $args);
}
add_action('init', 'custom_project_taxonomy', 0);

Keep Reading