Other GraphQL APIs and backends¶
Use Strapi, Directus, Supabase, Squidex, or any GraphQL API as a CMS for Silex.
Overview¶
Silex connects to any GraphQL API. While WordPress is the primary CMS, you can use:
- Strapi — Headless CMS (open source)
- Directus — Database management interface (open source)
- Supabase — PostgreSQL with auto-generated API (open source)
- Squidex — Headless CMS (open source and hosted)
- Contentful — Hosted headless CMS
- Shopify — E-commerce platform
- Custom GraphQL — Any GraphQL API
This page covers setup for popular options and how to adapt for others.
Prerequisites¶
- GraphQL API endpoint (with HTTP access)
- Understanding of WordPress setup (concepts apply to all)
- Silex instance with CMS enabled
Strapi¶
Strapi is a self-hosted or hosted headless CMS with GraphQL support.
Installation¶
Self-hosted:
Hosted:
Go to Strapi Cloud and create a project.
Create content types¶
In Strapi admin (http://localhost:1337/admin):
- Go to Content Type Builder
- Click Create new single type or Create new collection type
- Add fields:
- title (Text)
- slug (UID, linked to title)
- description (Rich text)
- featuredImage (Media)
- Save
Example: Blog post type:
BlogPost (collection type)
├── title (String, required)
├── slug (UID, linked to title)
├── content (Rich text)
├── description (String, 160 chars)
├── featuredImage (Media, single media)
└── author (Relation to Author type)
Enable GraphQL¶
Install GraphQL plugin:
- Go to Plugins
- Search for GraphQL
- Install and enable
Access GraphQL at: http://localhost:1337/graphql
Query data¶
query GetBlogPosts {
blogPosts {
data {
id
attributes {
title
slug
description
content
featuredImage {
data {
attributes {
url
}
}
}
author {
data {
attributes {
name
}
}
}
}
}
}
}
Configure in Silex¶
In Silex settings:
config.cmsConfig.dataSources = [
{
id: 'strapi',
type: 'graphql',
url: 'https://my-strapi.example.com/graphql',
backend: 'strapi', // or use 'generic'
},
]
Directus¶
Directus provides a database UI and auto-generated API.
Installation¶
Self-hosted:
Hosted:
Go to Directus Cloud and create a project.
Create collections¶
In Directus admin (http://localhost:8055):
- Go to Data Model
- Click Create Collection
- Name:
blog_posts - Add fields:
- id (auto)
- title (String)
- slug (String, Slug from title)
- content (Text)
- featured_image (Image)
- Save
Enable GraphQL¶
GraphQL is enabled by default. Access at: http://localhost:8055/graphql
Query data¶
query GetBlogPosts {
blog_posts {
id
title
slug
content
featured_image {
id
filename_disk
filename_download
}
}
}
Configure in Silex¶
config.cmsConfig.dataSources = [
{
id: 'directus',
type: 'graphql',
url: 'https://my-directus.example.com/graphql',
backend: 'directus', // or 'generic'
},
]
Supabase¶
Supabase is PostgreSQL with auto-generated APIs (REST and GraphQL).
Setup¶
- Go to supabase.com
- Create new project
- Set up PostgreSQL database
Create tables¶
In Supabase SQL editor:
CREATE TABLE blog_posts (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
title TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
content TEXT,
excerpt TEXT,
featured_image_url TEXT,
author_name TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE authors (
id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
name TEXT NOT NULL,
bio TEXT,
avatar_url TEXT
);
ALTER TABLE blog_posts ADD COLUMN author_id BIGINT REFERENCES authors(id);
Enable GraphQL¶
GraphQL is available at: https://YOUR_PROJECT.supabase.co/graphql/v1
Query data¶
query GetBlogPosts {
blog_postsCollection(first: 10) {
edges {
node {
id
title
slug
content
excerpt
featuredImageUrl
author {
name
bio
}
}
}
}
}
Configure in Silex¶
Add a header with your Supabase API key:
config.cmsConfig.dataSources = [
{
id: 'supabase',
type: 'graphql',
url: 'https://YOUR_PROJECT.supabase.co/graphql/v1',
headers: {
'apikey': process.env.SUPABASE_API_KEY,
'Authorization': `Bearer ${process.env.SUPABASE_API_KEY}`,
},
},
]
Squidex¶
Squidex is a self-hosted or managed headless CMS with GraphQL.
Setup¶
Managed (easiest):
Go to squidex.io and create an account.
Self-hosted:
Create schema¶
In Squidex admin:
- Create new app
- Go to Schemas
- Create schema:
blog-post - Add fields:
- title (String)
- slug (String)
- content (Text)
- featuredImage (Assets)
- Publish
Query via GraphQL¶
query GetBlogPosts {
queryBlogPostsContents(first: 10) {
items {
id
data {
title
slug
content
featuredImage {
assetUrl
assetId
}
}
}
}
}
Configure in Silex¶
config.cmsConfig.dataSources = [
{
id: 'squidex',
type: 'graphql',
url: 'https://YOUR_INSTANCE.squidex.io/api/graphql',
backend: 'squidex', // or 'generic'
},
]
KeystoneJS¶
KeystoneJS is a Node.js headless CMS with built-in GraphQL. After setup, the GraphQL endpoint is typically at http://localhost:3000/api/graphql. Use backend type generic in the data source settings.
GetCockpit¶
Cockpit is a self-hosted headless CMS. Enable the GraphQL addon and find the endpoint at /api/graphql. Use backend type generic.
Sanity¶
Sanity provides a hosted GraphQL API. Deploy a GraphQL API from your Sanity project, then use the endpoint URL. Use backend type generic. Note: Sanity's default API is GROQ-based — you must explicitly deploy the GraphQL endpoint.
Saleor¶
Saleor is an open-source e-commerce platform with a GraphQL API. The endpoint is typically at /graphql/. Use backend type generic.
Prismic¶
Prismic offers a GraphQL API at https://your-repo.prismic.io/graphql. Add your access token as an Authorization header. Use backend type generic.
Nhost¶
Nhost provides a Hasura-based GraphQL API. Find your endpoint in the Nhost dashboard under GraphQL. Use backend type generic.
Hashnode¶
Hashnode exposes a public GraphQL API at https://gql.hashnode.com. No authentication needed for public content. Use backend type generic.
Hygraph (not compatible)¶
Warning: Hygraph (formerly GraphCMS) has known compatibility issues with Silex due to its GraphQL schema structure. It is not currently supported.
Using GraphQL Mesh for REST APIs¶
If your backend only has REST API (no GraphQL), use GraphQL Mesh to create a GraphQL layer.
Example: Add GraphQL to a REST API¶
Create a mesh configuration:
# .meshrc.yaml
sources:
- name: MyRestAPI
handler:
openapi:
source: https://api.example.com/openapi.json
# Or for any REST API:
- name: MyApi
handler:
rest:
endpoint: https://api.example.com
operations:
- type: Query
field: posts
path: /posts
method: GET
- type: Query
field: post
path: /posts/{id}
method: GET
argTypeMap:
id: String
Then expose via GraphQL:
Access at: http://localhost:4000/graphql
Authentication and headers¶
Some APIs require authentication. Configure in client config:
config.cmsConfig.dataSources = [
{
id: 'my-api',
type: 'graphql',
url: 'https://api.example.com/graphql',
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`,
'X-Custom-Header': 'value',
},
},
]
Or use Silex's built-in authentication (varies by backend).
Comparing backends¶
| Backend | Type | GraphQL | Open source | Pricing | Ease |
|---|---|---|---|---|---|
| WordPress | Relational | Via plugin | Yes | Free | Medium |
| Strapi | Headless CMS | Native | Yes | Free/paid | Medium |
| Directus | Database UI | Native | Yes | Free/paid | Easy |
| Supabase | PostgreSQL + API | Native | Yes | Free/paid | Easy |
| Squidex | Headless CMS | Native | Yes | Free/paid | Medium |
| Contentful | Hosted CMS | Native | No | Paid | Easy |
| Shopify | E-commerce | Native | No | Paid | Medium |
Data shape considerations¶
Different backends return data in different shapes. Normalize queries for consistency:
WordPress¶
Strapi¶
Directus¶
Use aliases to normalize:
Common patterns¶
Pagination¶
All backends support pagination. Common patterns:
# Offset-based (WordPress, Directus)
query GetPosts($offset: Int, $limit: Int) {
posts(offset: $offset, limit: $limit) { ... }
}
# Cursor-based (Strapi, Supabase)
query GetPosts($first: Int, $after: String) {
posts(first: $first, after: $after) {
pageInfo { hasNextPage endCursor }
edges { ... }
}
}
Filtering¶
# Filter by field
query GetPostsByAuthor($author: String) {
posts(filter: { author: { name: $author } }) { ... }
}
Sorting¶
query GetLatestPosts {
posts(sort: "-createdAt") { ... } # Or sort: [{field: "createdAt", direction: DESC}]
}
Troubleshooting¶
GraphQL endpoint returns 401 Unauthorized¶
Add authentication:
config.cmsConfig.dataSources = [
{
id: 'api',
type: 'graphql',
url: 'https://api.example.com/graphql',
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`,
},
},
]
Query returns null or empty¶
Check:
- Data exists in backend
- Query syntax is correct (test in GraphiQL)
- Filtering/pagination logic is right
Introspection disabled (can't browse schema)¶
Some APIs disable introspection for security. Ask provider for schema docs or:
See also¶
- WordPress setup
- Client configuration and plugins — Client config CMS settings
- How CMS works — CMS concepts for designers
- Official backend docs — Each backend's GraphQL docs
- Strapi Integration — vote for dedicated Strapi support