Skip to content

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:

npm install -g @strapi/cli
strapi new my-strapi-api --quickstart
cd my-strapi-api
npm run develop

Hosted:

Go to Strapi Cloud and create a project.

Create content types

In Strapi admin (http://localhost:1337/admin):

  1. Go to Content Type Builder
  2. Click Create new single type or Create new collection type
  3. Add fields:
  4. title (Text)
  5. slug (UID, linked to title)
  6. description (Rich text)
  7. featuredImage (Media)
  8. 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:

  1. Go to Plugins
  2. Search for GraphQL
  3. 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:

npm install -g @directus/cli
directus bootstrap
directus start

Hosted:

Go to Directus Cloud and create a project.

Create collections

In Directus admin (http://localhost:8055):

  1. Go to Data Model
  2. Click Create Collection
  3. Name: blog_posts
  4. Add fields:
  5. id (auto)
  6. title (String)
  7. slug (String, Slug from title)
  8. content (Text)
  9. featured_image (Image)
  10. 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

  1. Go to supabase.com
  2. Create new project
  3. 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:

docker-compose up -d squidex
# Access at http://localhost:80

Create schema

In Squidex admin:

  1. Create new app
  2. Go to Schemas
  3. Create schema: blog-post
  4. Add fields:
  5. title (String)
  6. slug (String)
  7. content (Text)
  8. featuredImage (Assets)
  9. 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:

npx graphql-mesh serve

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

{
  blogPosts {
    edges {
      node { id title }
    }
  }
}

Strapi

{
  blogPosts {
    data {
      id
      attributes { title }
    }
  }
}

Directus

{
  blog_posts {
    id
    title
  }
}

Use aliases to normalize:

query {
  posts: blogPosts {
    edges {
      node { id title }
    }
  }
}

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:

  1. Data exists in backend
  2. Query syntax is correct (test in GraphiQL)
  3. Filtering/pagination logic is right

Introspection disabled (can't browse schema)

Some APIs disable introspection for security. Ask provider for schema docs or:

query IntrospectionQuery {
  __schema {
    types {
      name
      fields {
        name
        type { name }
      }
    }
  }
}

See also

Edit this page on GitLab