Field Forge + WPGraphQL — Headless WordPress
Field Forge ships with native WPGraphQL integration. When both plugins are active, Field Forge auto-registers GraphQL types for every field group on activation — no configuration, no separate add-on plugin, no manual schema registration. Your custom fields are immediately queryable via GraphQL.
What WPGraphQL is
WPGraphQL is the GraphQL API layer for WordPress. It exposes WordPress posts, pages, taxonomies, and users as a GraphQL schema that JavaScript frontends (Next.js, Astro, Nuxt, SvelteKit, etc.) can query efficiently. It’s the standard way to build headless WordPress with a JavaScript frontend.
WPGraphQL’s gap has always been custom fields. It doesn’t know about ACF, Meta Box, CMB2, or any other plugin’s fields — you need add-on plugins like WPGraphQL for ACF to bridge the gap.
Field Forge fills this gap natively. When Field Forge and WPGraphQL are both active, Field Forge’s custom fields appear in the GraphQL schema automatically.
How auto-registration works
On plugin activation
When Field Forge is activated (or WPGraphQL is activated after Field Forge), Field Forge:
- Detects WPGraphQL via
function_exists('register_graphql_object_type') - Reads all field groups from the database
- Generates GraphQL types for each field group — with nested types for repeaters, groups, and flexible content
- Registers types with WPGraphQL via the official WPGraphQL type registration API
- Adds a
fieldforgefield to every queryable post type - Registers resolvers that fetch field values from Field Forge’s custom table storage
All of this happens automatically, in the background, during plugin activation.
On field group changes
When you add, edit, or delete a field group in Field Forge’s visual builder, the GraphQL schema updates automatically. WPGraphQL’s schema cache is flushed and Field Forge re-registers the updated types on the next request.
You don’t need to manually regenerate anything.
Example GraphQL query
With Field Forge and WPGraphQL both active, you can query custom fields like this:
query GetHomepage {
page(id: "home", idType: URI) {
title
fieldforge {
heroSection {
title
subtitle
backgroundImage {
sourceUrl
altText
mediaDetails {
width
height
}
}
ctaButton {
text
url
openInNewTab
}
}
featuresSection {
sectionTitle
features {
icon
title
description
}
}
}
}
}
The fieldforge key exposes all field groups assigned to the page via location rules. Each field group is a typed object with its own fields.
Nested types
Repeater fields, groups, and flexible content all produce proper nested GraphQL types:
Repeater → array type
type TeamPageFieldforge {
teamMembers: [TeamMemberRow]
}
type TeamMemberRow {
name: String
photo: MediaItem
bio: String
socialLinks: [SocialLinkRow] # Nested repeater
}
Flexible content → union type
type LandingPageFieldforge {
pageSections: [PageSectionLayout]
}
union PageSectionLayout = HeroLayout | FeaturesLayout | CTALayout
Query union types with inline fragments:
query GetLandingPage {
page(id: "landing", idType: URI) {
fieldforge {
pageSections {
__typename
... on HeroLayout {
title
backgroundImage { sourceUrl }
}
... on FeaturesLayout {
sectionTitle
features {
title
description
}
}
}
}
}
}
Relational fields
Relational fields (Post Object, Relationship, User, Taxonomy) resolve to WPGraphQL’s native types:
type ProductFieldforge {
relatedProducts: [Post] # WPGraphQL's Post type
author: User # WPGraphQL's User type
categories: [Category] # WPGraphQL's Category type
}
This means you can chain queries through relationships:
query GetProduct {
post(id: "product-a", idType: URI) {
fieldforge {
productDetails {
relatedProducts {
title
slug
featuredImage {
node {
sourceUrl
}
}
fieldforge {
productDetails {
price
}
}
}
}
}
}
}
Options pages in GraphQL
Options page field values are exposed as root-level GraphQL types:
type FieldforgeOptions {
siteSettings: SiteSettingsFields
headerSettings: HeaderSettingsFields
footerSettings: FooterSettingsFields
}
type Query {
fieldforgeOptions: FieldforgeOptions
}
Query them without a specific post context:
query GetGlobalSettings {
fieldforgeOptions {
siteSettings {
companyName
phone
email
}
footerSettings {
copyright
socialLinks {
platform
url
}
}
}
}
Combining with TypeScript generation
Field Forge also generates TypeScript definitions for the same field groups. Use both:
- GraphQL for runtime data fetching with efficient queries
- TypeScript for compile-time type safety in your frontend code
The two feed different pipelines but represent the same underlying field group data. Update a field group in Field Forge and both the GraphQL schema and TypeScript definitions update together.
For teams using GraphQL Code Generator, you can introspect the Field Forge-augmented WPGraphQL schema and auto-generate typed query hooks:
# codegen.yml
schema: https://wp.example.com/graphql
documents: './src/**/*.graphql'
generates:
./src/gql/:
preset: client
plugins: []
Run graphql-codegen and your frontend has fully-typed GraphQL queries for all Field Forge fields.
vs WPGraphQL for ACF
WPGraphQL for ACF is a separate plugin from the WPGraphQL team that bridges ACF field groups into the GraphQL schema. It works with both ACF and SCF (since SCF is a fork of ACF).
Differences vs Field Forge’s native integration:
| Field Forge + WPGraphQL | WPGraphQL for ACF | |
|---|---|---|
| Installation | Auto-registers on Field Forge activation | Separate plugin to install and configure |
| Maintenance | Part of Field Forge release cycle | Independent release cycle |
| Custom fields source | Field Forge | ACF or SCF |
| Type mapping | Field Forge-specific | ACF-specific |
| Performance | Built-in batch loading with Field Forge custom table | Depends on wp_postmeta storage |
If you’re on ACF/SCF and need GraphQL, WPGraphQL for ACF is the path. If you’re considering modernizing the custom fields layer, Field Forge + WPGraphQL replaces both plugins with a more integrated experience.
Ready for GraphQL custom fields?
WPGraphQL integration is included in every paid plan. Auto-registers on activation, zero configuration.