Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CMS Connector — Integration Guide

This document explains how to integrate the CMS Connector into a TypeScript project, with a example on Next.js with Directus. The pattern is simple: create a single shared instance (e.g., cmsInstance.ts) and reuse it across your application.

What you get

  • A typed interface to read and (optionally) write content to your CMS.
  • First-class Directus support via cmsType: "directus".
  • Strong TypeScript types for resources, dictionaries, and configuration.

Quick start (create a shared instance)

Create a file such as src/lib/cms/cmsInstance.ts and export a single shared instance. This instance can be imported wherever you need to access the CMS.

import { CmsFactory } from "cms-connector";

const cmsInstance = CmsFactory.createResource({
  cmsType: "directus",
  configuration: {
    languages: ["it"],
    url: process.env.FRONTEND_CMS_URL as string,
    // staticToken: process.env.DIRECTUS_STATIC_TOKEN, // optional; required only for write operations
  },
});

export default cmsInstance;

Environment variables (example for Next.js .env):

FRONTEND_CMS_URL=https://your-directus.example.com
# DIRECTUS_STATIC_TOKEN=your-static-token  # optional, only if you need write/patch/upload

Keep tokens server-side only; never expose them to the browser.


Using the instance in Next.js (App Router)

You can import the shared instance into Server Components, Route Handlers, and Server Actions.

Example: Server Component

// app/(site)/page.tsx
import cms from "@/lib/cms/cmsInstance";

export default async function HomePage() {
  const page = await cms.getResource({
    entityName: "page",
    language: "it",
    queryParameters: {
      filter: { slug: { _eq: "home" } },
      limit: 1,
    },
    includeDraft: false,
  });

  if (!page) return <div>Not found</div>;
  return <main>{page.title}</main>;
}

Example: Route Handler

// app/api/pages/[slug]/route.ts
import cms from "@/lib/cms/cmsInstance";
import { NextResponse } from "next/server";

export async function GET(_: Request, { params }: { params: { slug: string } }) {
  const page = await cms.getResource({
    entityName: "page",
    language: "it",
    queryParameters: { filter: { slug: { _eq: params.slug } }, limit: 1 },
    includeDraft: false,
    // Pass Next.js caching hints if needed via fetchOptions (see below)
  });

  return NextResponse.json(page ?? null);
}

Caching with fetchOptions

All read methods accept an optional fetchOptions?: RequestInit, which Next.js understands for caching and revalidation:

await cms.getResources({
  entityName: "page",
  language: "it",
  queryParameters: { limit: 10 },
  includeDraft: false,
  fetchOptions: { next: { revalidate: 60 } }, // ISR every 60 seconds
});

Using the instance in any TypeScript project

The same instance pattern works in any Node/TypeScript setup (e.g., Express, server-side scripts):

import cms from "./cmsInstance";

async function main() {
  const dictionary = await cms.getDictionary({ language: "it" });
  console.log(dictionary);
}

main().catch(console.error);

Read API overview

These are the main read methods you will use (types are strongly inferred from the underlying Directus schema):

  • getResource({ entityName, language, queryParameters, includeDraft, fetchOptions })
  • getResources({ entityName, language, queryParameters, includeDraft, fetchOptions })
  • getResourceById({ entityName, id, language, queryParameters, fetchOptions })
  • getResourcesCount({ entityName, filterParameters, fetchOptions })
  • getDictionary({ language, fetchOptions })
  • getConfiguration({ language, fetchOptions })

Notes:

  • If you configured languages in the instance, passing a language that is not in the allowed list will throw an error.
  • includeDraft toggles draft-vs-published behavior where supported.
  • queryParameters and filterParameters mirror Directus query shapes.

Write API (optional, requires static token)

To use write operations, provide a staticToken in the configuration. Keep it server-side only.

  • uploadFile({ formData })
  • createResource({ entityName, item })
  • patchResource({ id, entityName, item })

Example (Server Action / Route Handler only):

import cms from "@/lib/cms/cmsInstance";

export async function createExample() {
  const id = await cms.createResource({
    entityName: "page",
    item: { title: "Hello" },
  });
  return id;
}

Configuration reference

When using Directus, the factory expects:

CmsFactory.createResource({
  cmsType: "directus",
  configuration: {
    url: string;                      // required
    staticToken?: string;             // optional (required for write ops)
    languages?: readonly string[];    // optional (enables language guard)
  },
});

Currently supported cmsType values:

  • "directus"

Project structure recommendation

  • Create a shared instance file, e.g. src/lib/cms/cmsInstance.ts.
  • Reuse the exported instance everywhere (Server Components, Route Handlers, services).
  • Keep CMS environment variables in .env.local (Next.js) or your server env.

Troubleshooting

  • “Unknown CMS type …”: Ensure cmsType is exactly "directus".
  • “Missing or invalid language”: If you configured languages, pass only those values to read methods.
  • Write methods throwing: Provide staticToken in configuration; use them only on the server.
  • Network issues: Verify FRONTEND_CMS_URL points to the correct Directus REST endpoint.

Example recap

Here is the minimal instance example again for quick copy–paste:

import { CmsFactory } from "cms-connector";

const cmsInstance = CmsFactory.createResource({
  cmsType: "directus",
  configuration: {
    languages: ["it"],
    url: process.env.FRONTEND_CMS_URL as string,
  },
});

export default cmsInstance;

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages