Workspace Branding

Manage workspace branding assets (logo, favicon, brand name, Open Graph image) and fetch them in your Next.js app through the cmssy gateway.

July 14, 2026

Overview

cmssy is headless - your Next.js app owns all visual styling (colors, typography, dark mode) as standard Tailwind/CSS in your own repo. What cmssy stores per workspace is branding: a brand name and shared assets you fetch and apply in your site.


Workspace Branding

Branding lives on the workspace site config. Fetch it through the gateway with your own GraphQL query - createCmssyClient(cmssy).query(...). Site config is exposed under public.siteConfig, and the assets sit on its branding sub-object:

import { createCmssyClient, type CmssyBranding } from "@cmssy/core";
import { cmssy } from "@/cmssy.config";

const SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
  public {
    siteConfig(workspaceSlug: $workspaceSlug) {
      branding {
        brandName
        logoUrl
        faviconUrl
        ogImageUrl
      }
    }
  }
}`;

const data = await createCmssyClient(cmssy).query<{
  public: { siteConfig: { branding: CmssyBranding | null } };
}>(SITE_CONFIG_QUERY, { workspaceSlug: cmssy.workspaceSlug });

const branding = data.public.siteConfig.branding;
// CmssyBranding | null - brandName, logoUrl, faviconUrl, ogImageUrl (each nullable)
FieldWhat it isWhere to use
brandNameDisplay name of the site / brand.Page title, metadata, header
logoUrlLogo asset URL.Render in your header or footer
faviconUrlFavicon asset URL.Wire into your metadata icons
ogImageUrlDefault Open Graph / social-share image.Default OG image for pages without a custom image

Every field is nullable - render only what is set.

Using branding in your app

Favicon:

import { createCmssyClient } from "@cmssy/core";
import { cmssy } from "@/cmssy.config";

const SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
  public { siteConfig(workspaceSlug: $workspaceSlug) { branding { faviconUrl } } }
}`;

export async function generateMetadata() {
  const data = await createCmssyClient(cmssy).query<{
    public: { siteConfig: { branding: { faviconUrl: string | null } | null } };
  }>(SITE_CONFIG_QUERY, { workspaceSlug: cmssy.workspaceSlug });

  const faviconUrl = data.public.siteConfig.branding?.faviconUrl;
  return faviconUrl ? { icons: { icon: faviconUrl } } : {};
}

Logo in header:

import { createCmssyClient, type CmssyBranding } from "@cmssy/core";
import { cmssy } from "@/cmssy.config";

const SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
  public { siteConfig(workspaceSlug: $workspaceSlug) { branding { brandName logoUrl } } }
}`;

export default async function Header() {
  const data = await createCmssyClient(cmssy).query<{
    public: { siteConfig: { branding: CmssyBranding | null } };
  }>(SITE_CONFIG_QUERY, { workspaceSlug: cmssy.workspaceSlug });

  const branding = data.public.siteConfig.branding;
  return (
    <header>
      {branding?.logoUrl && <img src={branding.logoUrl} alt={branding.brandName ?? ""} />}
      {branding?.brandName && <h1>{branding.brandName}</h1>}
    </header>
  );
}