Shape published content with GraphQL, without guessing the schema.
Contoprix generates a tenant-aware GraphQL delivery schema from structured content models, then lets server-side applications query published site, page, navigation, component, and relation fields.
GraphQL is a delivery choice, not a universal REST replacement. Use it when a screen benefits from a deliberate query shape and your team can own the schema workflow.
What is a GraphQL CMS?
A GraphQL CMS exposes structured content through a typed graph so an application can select the published fields needed for a particular view.
The CMS still owns modeling, editorial workflow, localization, publication, permissions, and media. GraphQL is the delivery boundary between that governed content layer and an application. The frontend chooses fields, but it can only query types and relations present in the current schema.
This page focuses on that delivery contract. For the broader separation between content and presentation, start with the headless CMS architecture guide.
Contoprix also provides REST routes and framework SDK helpers. A team can use GraphQL for one complex server-rendered view and the standard SDK for routine page delivery without making one interface mandatory everywhere.
Delivery Flow
The content model becomes an application query contract
Stable website roots are combined with tenant-generated content types. Normal requests resolve only published data for the website associated with the credential.
Structured model
Enabled types, fields, components, and relations
Tenant schema
Stable roots plus generated model-specific fields
POST /graphql
Scoped, read-only published delivery
Application
Reviewed query, server cache, and rendered UI
Stable roots for websites, generated fields for content models
The public contract has a dependable system layer while allowing each tenant’s structured model to define its own content graph.
Stable system roots
Model-generated fields
Structured relations
Cursor pagination
A Stable Query
Query a page and navigation in one document
This example uses only stable fields defined by the current public schema. Variables carry the path and locale so the document remains reusable and reviewable.
Custom roots such as article depend on the tenant’s active model. Inspect or export the schema before selecting those fields.
query PageNavigation($path: String!, $locale: String) {
page(path: $path, locale: $locale) {
id
name
slug
locale
}
navigation(locale: $locale) {
id
name
url
openInNewTab
children {
id
name
url
}
}
}import { createContoprixGraphQLClient } from "@contoprix/graphql-client";
export const graph = createContoprixGraphQLClient({
endpoint: process.env.CONTOPRIX_BASE_URL!,
auth: {
type: "deliveryKey",
deliveryKey: process.env.CONTOPRIX_GRAPHQL_KEY!,
},
locale: "en",
timeout: 10_000,
});
const page = await graph.getPage({ path: "/about" });Frontend Integration
Keep GraphQL credentials and queries on the server
The current @contoprix/graphql-client package appends the endpoint path, sends delivery-key or bearer authentication, supports timeouts, and distinguishes transport failures from GraphQL response errors.
A GraphQL delivery key needs graphql:read. Use request() for strict error handling or requestWithErrors() only when the UI has a reviewed partial-data policy.
Choose the simpler contract for each screen
GraphQL can make complex response shapes explicit. REST often remains easier to cache, inspect, and operate for straightforward delivery requests.
| Decision area | REST and standard SDK | GraphQL |
|---|---|---|
| Simple page or entry lookup | Usually the shortest path | Useful, but may add query tooling without changing the result |
| One view combines several content shapes | May require multiple endpoints | Can select one reviewed response shape |
| Relations | Use delivered expansions or additional requests | Select relation fields exposed by the tenant schema |
| HTTP caching | Natural URL-based GET behavior | Requires a query-aware application or server cache policy |
| Errors | Primarily HTTP and endpoint response semantics | A response may contain both data and field-level errors |
| Schema tooling | SDK and endpoint DTOs | Schema export, generated types, and query maintenance |
Read the balanced technical comparison in REST vs GraphQL for Headless CMS Content Delivery.
Treat the schema and query as maintained application contracts
A durable GraphQL integration includes model review, generated types, bounded queries, explicit error behavior, and cache refresh after publication.
- 01
Model
Define and enable content types, component types, fields, and relations in Contoprix.
- 02
Inspect
Use Graph Playground in development or pull the protected schema export with the CLI.
- 03
Generate
Generate TypeScript output for the current tenant schema instead of guessing model fields.
- 04
Query
Write bounded documents with variables and request only the fields the server-rendered view needs.
- 05
Handle
Distinguish transport failures from GraphQL errors and decide whether partial data is safe.
- 06
Refresh
Connect publication to the application cache policy so new published content reaches visitors.
Inspect, do not assume
Generated content fields differ by tenant and model revision.
Separate scopes
GraphQL delivery and schema export use separate least-privilege scopes.
Bound the query
Use variables, cursor pagination, reviewed depth, and intentional error handling.
Build with the Current Contract
Inspect the schema, run a stable query, then integrate it at the server boundary.
Start in the GraphQL guide or Graph Playground. For conventional page and content requests, compare the REST delivery API and SDK first.