Skip to content

WordPress with Pods and WPGraphQL

Set up a WordPress backend for Silex with custom content types and GraphQL API.

Overview

WordPress is the primary CMS backend for Silex. Using two plugins, you can define custom content types, custom fields, and expose them via GraphQL:

  1. Pods — Create custom post types and custom fields (100% open source, GPL)
  2. WPGraphQL — GraphQL API for WordPress

Why Pods?

We recommend Pods because it is 100% open source (GPL), consistent with Silex's free/libre philosophy. Pods handles custom post types, custom fields, and custom taxonomies — all in one plugin, no extras needed.

The popular alternative, ACF (Advanced Custom Fields), has a free version with limited features and a commercial Pro version (~$99/year). Since Silex is a free and open-source project, we prefer to recommend tools that share the same values. See Using ACF instead if you already use it.

This approach lets designers bind Silex components to WordPress data without coding.

Prerequisites

  • WordPress 5.9 or later
  • PHP 7.4 or later
  • WordPress admin access
  • Silex instance with CMS enabled (default)

Installation

1. Install and activate plugins

In your WordPress admin:

  1. Go to PluginsAdd New
  2. Search for and install:
  3. Pods (free, open-source)
  4. WPGraphQL (free)
  5. Activate both

Or via WP-CLI:

wp plugin install pods --activate
wp plugin install wp-graphql --activate

2. Install WPGraphQL for Pods (if needed)

Pods fields may not appear in GraphQL by default. Add the integration plugin:

wp plugin install wpgraphql-for-pods --activate

Or search for "WPGraphQL for Pods" in the plugin directory.

Defining content types

Create a custom post type

Using Pods:

  1. Go to Pods AdminEdit Pods
  2. Click Add New
  3. Select Custom Post Type and configure:
  4. Pod Name: blog_post (no spaces, lowercase)
  5. Plural Label: Blog Posts
  6. Singular Label: Blog Post
  7. Description: Blog posts and articles
  8. Check: Show in REST API and Show in GraphQL
  9. Click Save Pod

Create custom fields with Pods

Custom fields are managed inside the Pod definition itself:

  1. Go to Pods AdminEdit Pods
  2. Select the pod you want to add fields to (e.g., Blog Post)
  3. Click Add Field and configure each field:
  4. Featured Image (File / Image field)
  5. Author Name (Plain Text field)
  6. Excerpt (Paragraph Text field)
  7. Categories (Relationship field, linked to category)
  8. For each field, make sure Show in GraphQL is enabled in the field settings
  9. Click Save Pod

Map fields to GraphQL

With WPGraphQL + Pods (and the WPGraphQL for Pods plugin if needed), fields are exposed automatically. In the GraphQL explorer, they appear directly under the post type's fields:

{
  blogPosts {
    edges {
      node {
        id
        title
        content
        featuredImage {
          sourceUrl
        }
        authorName
        excerpt
        categories {
          edges {
            node {
              name
            }
          }
        }
      }
    }
  }
}

Data contracts

A data contract defines the shape of data your Silex site expects. Document contracts before building the site.

Example: Blog post contract

// Data contract: Blog Post
{
  type: "BlogPost",
  fields: {
    id: { type: "string", description: "Post ID" },
    title: { type: "string", description: "Post title" },
    slug: { type: "string", description: "Post slug (URL)" },
    content: { type: "string", description: "Post content (HTML)" },
    excerpt: { type: "string", description: "Short description" },
    date: { type: "date", description: "Publication date" },
    author: {
      type: "object",
      fields: {
        name: { type: "string" },
        avatar: { type: "string" },
      }
    },
    featuredImage: {
      type: "object",
      fields: {
        sourceUrl: { type: "string", description: "Image URL" },
        altText: { type: "string", description: "Alt text" },
      }
    },
    categories: {
      type: "array",
      items: {
        type: "object",
        fields: {
          name: { type: "string" },
          slug: { type: "string" },
        }
      }
    }
  }
}

Creating Pods fields to match contract

In Pods, create fields matching your contract by going to Pods AdminEdit Pods → select your pod:

Field Name Field Type Pods Settings
Excerpt Paragraph Text Max length 200
Featured Image File / Image Single file
Author Name Plain Text Required
Categories Relationship Related to: Category

Querying WordPress via GraphQL

Accessing the GraphQL API

After enabling WPGraphQL, access the GraphQL endpoint:

https://your-wordpress.com/graphql

Or use GraphiQL explorer:

https://your-wordpress.com/graphql?enable=true

Example queries

Query all blog posts:

query GetBlogPosts {
  blogPosts(first: 10) {
    edges {
      node {
        id
        title
        slug
        excerpt
        date
        featuredImage {
          sourceUrl
          altText
        }
        authorName
      }
    }
  }
}

Query by category:

query GetPostsByCategory {
  blogPosts(
    first: 10
    where: {
      categoryName: "news"
    }
  ) {
    edges {
      node {
        id
        title
        slug
      }
    }
  }
}

Query a single post:

query GetPost {
  blogPostBy(slug: "my-first-post") {
    id
    title
    content
    authorName
    featuredImage {
      sourceUrl
    }
  }
}

Configuring Silex to use WordPress

In Silex editor

  1. Go to SettingsPageCMS
  2. Click Add Data Source
  3. Configure:
  4. Name: WordPress
  5. Type: GraphQL
  6. URL: https://your-wordpress.com/graphql
  7. Backend: wordpress
  8. Click Save

In client config

Or set up in your client config file:

// client-config.js
export default async function (config) {
  config.cmsConfig.dataSources = [
    {
      id: 'wordpress',
      type: 'graphql',
      url: 'https://my-wordpress.com/graphql',
      backend: 'wordpress',
    },
  ]
}

Server-side config (optional)

If you need to add custom logic on the server:

// .silex.js
module.exports = async function (config) {
  // WordPress is built-in, no special config needed
  // But you can customize if needed
}

Binding data in Silex

In the editor, create states that bind to WordPress data:

Loop over posts

  1. Add a Div component (will repeat for each post)
  2. Right panel → DataAdd State
  3. Configure:
  4. Name: posts
  5. Type: Query (GraphQL)
  6. Expression:
    query GetPosts {
      blogPosts(first: 10) {
        edges {
          node {
            id
            title
            slug
            authorName
          }
        }
      }
    }
    
  7. Set Loop Over: posts.edges

The component repeats for each post.

Bind text to post title

  1. Add a Text component inside the repeating div
  2. Right panel → DataAdd State
  3. innerHTML state:
  4. Expression: node.title

The text displays the post title.

  1. Add an Image component
  2. Right panel → DataAdd State
  3. src state:
  4. Expression: node.featuredImage.sourceUrl

Authentication and permissions

Public access (no auth)

By default, WPGraphQL allows public queries. This is fine for reading public posts.

Restrict to authenticated users

To limit queries to logged-in users, in WordPress:

  1. Install WPGraphQL Smart Cache (optional)
  2. Add to wp-config.php:
    define('GRAPHQL_ENABLED', true);
    define('GRAPHQL_PUBLIC', false); // Require auth
    

Then in Silex, authenticate with WordPress credentials.

Personal data protection (GDPR)

If querying user data, ensure:

  1. Users opt-in to data exposure
  2. Queries don't include sensitive fields
  3. Privacy policy discloses data usage

Troubleshooting

GraphQL endpoint returns 404

Check:

  1. WPGraphQL plugin is activated
  2. URL is correct: https://your-wordpress.com/graphql
  3. Permalinks are set (WordPress Settings → Permalinks)

Try visiting /graphql directly in browser.

Pods fields not in GraphQL

Ensure:

  1. WPGraphQL for Pods plugin is installed and activated (if fields do not appear automatically)
  2. Show in GraphQL is enabled in the Pod settings for each pod and each field
  3. WPGraphQL is enabled for the post type

Go to Pods AdminEdit Pods, select the pod, and verify each field has "Show in GraphQL" enabled.

Queries return null or empty

Check:

  1. Posts exist: /wp-admin/edit.php?post_type=blog_post
  2. Pods fields are filled in
  3. GraphQL query syntax is correct (use GraphiQL to test)

Authentication errors in Silex

If queries fail with auth errors:

  1. Check if WPGraphQL is public: try querying without auth
  2. If auth is required, you may need to pass credentials to Silex (contact support)

Performance issues

WordPress can be slow with large datasets. Optimize:

  1. Paginate queries:

    query GetPosts($first: Int!, $after: String) {
      blogPosts(first: $first, after: $after) {
        pageInfo { endCursor hasNextPage }
        edges { node { id title } }
      }
    }
    

  2. Limit fields: Only query fields you need

  3. Cache results: Use WPGraphQL Smart Cache plugin
  4. Upgrade hosting: More CPU/RAM helps

Best practices

Naming conventions

  • Post type slug: lowercase with underscores (blog_post, team_member)
  • Field names: lowercase with underscores (featured_image, author_name)
  • Custom taxonomy: lowercase plural (blog_categories, tags)

Field organization

Group related fields in your Pod definition:

  • Content: title, content, excerpt
  • Media: featured image, gallery
  • Metadata: author, date, categories

Data validation

Use Pods field settings:

  • Required fields: Prevent incomplete posts
  • Field limits: Text area max length
  • Conditional logic: Show fields based on other fields

Documentation

Document your data contract:

## WordPress Data Structure

### BlogPost post type
- `title` (string): Post title
- `content` (HTML): Main content
- `featuredImage.sourceUrl` (URL): Hero image
- `authorName` (string): Author name
- `categories[].name` (array): Post categories

Using ACF instead

If you prefer ACF (Advanced Custom Fields), the setup is similar. Install ACF + WPGraphQL for ACF instead of Pods. ACF Pro is a commercial plugin (~$99/year) that also handles custom fields and post types. The GraphQL query structure differs slightly: ACF fields appear under an acfFields wrapper (e.g., acfFields.featuredImage.sourceUrl instead of featuredImage.sourceUrl).

See also

Edit this page on GitLab