Codegea

Development

Custom software developmentSystems, platforms and integrations built around your operationCorporate websitesProfessional, fast and built to inspire trustOnline storesCatalog, payments and shipping ready to sell 24/7WooCommerceFast WooCommerce stores with each country’s payments and invoicingLanding pagesA page focused on one goal: turning visitors into customersMobile appsCustom iOS and Android apps that put your business in your customers’ pockets

Integration and CMS

CMS integrationsWordPress, Strapi, Directus and Arc XP connected to your whole ecosystemArc XPSupport, implementation and integrations for the media platformMigrationsMigrate your site, platform or database without losing anything

Growth and infrastructure

AI automationTechnology does the repetitive work and your team focuses on what mattersOn-page SEOBe found and recommended by Google: technical and content optimizationServers & hostingFast, secure servers monitored 24/7
RetainerYour dev team, by the monthFrom 20h a month. Fixed fee.
An AI quoting tool to quote services in minutesProfessional quotes in minutes, with projects, sellers and payments tracked in one place.See the case

By type

EcommerceStores and catalogsCorporate sitesBrand and lead genPlatforms & appsCustom software

Explore

All projectsCases and resultsClientsWho trusts usRetainerMonthly dev team

Blog

All articlesGuides and opinionNewsletterOne email a monthContactWe reply in 24h

Latest articles

How codegea.com is built: Next.js, Payload, Turso and R2CMS · 2026-10-20Cloudflare Workers: what they are and when to use themNode.js · 2026-10-19Live Preview in Payload with Next.jsCMS · 2026-10-19
NewsletterJoin our newsletterPractical web, SEO and AI notes.
ServicesCustom software developmentCorporate websitesOnline storesWooCommerceLanding pagesMobile appsCMS integrationsArc XPMigrationsAI automationOn-page SEOServers & hostingYour dev team, by the month
ProjectsProfessional quotes in minutes, with projects, sellers and payments tracked in one place.EcommerceCorporate sitesPlatforms & appsAll projectsClientsRetainer
Retainer
BlogAll articlesNewsletterContactHow codegea.com is built: Next.js, Payload, Turso and R2Cloudflare Workers: what they are and when to use themLive Preview in Payload with Next.jsJoin our newsletter
ESEN
Let's talk

CMS

How to customize the Payload CMS admin with your brand

Logo, colors, tab title, welcome screen and text: how to give the Payload CMS admin your company's or your client's brand, with the example and screenshots from this site.

Derian Pinto · Founder & Full Stack Developer2026-10-194 min

When you hand a site over to a client, what the client sees every day is not the website: it is the panel where they edit. If that panel says Payload, with Payload's colors and logo, it feels like someone else's tool that somebody installed for them. If it carries their brand, or yours, it is their panel. Payload lets you change almost everything, and the license (MIT) allows it.

This is what we did with this site's panel. What you see in the screenshots is the real codegea.com admin, running locally.

What we changed

Five things, from most to least visible:

  1. The logo and the icon (top left, on the login and in the panel).
  2. The colors and the typography.
  3. The tab title, the favicon and the image shown when the link is shared.
  4. A welcome screen with shortcuts.
  5. The text of the menu and the interface.

This is the login screen:

How to customize the Payload CMS admin with your brand

And the panel, with the welcome block and the menu:

How to customize the Payload CMS admin with your brand

Step 1: the tab title and favicon

In payload.config.ts, inside admin.meta:

admin: {
  meta: {
    titleSuffix: '· Codegea CMS',
    description: 'Content panel for codegea.com',
    icons: [
      { rel: 'icon', url: '/favicon.ico' },
      { rel: 'icon', type: 'image/png', sizes: '32x32', url: '/favicon-32x32.png' },
      { rel: 'apple-touch-icon', url: '/apple-touch-icon.png' },
    ],
    openGraph: {
      title: 'Codegea CMS',
      siteName: 'Codegea CMS',
      images: [{ url: '/og-codegea-2026.jpg', width: 1200, height: 630 }],
    },
    twitter: { title: 'Codegea CMS' },
  },
},

titleSuffix is what appears at the end of every tab: "Posts · Codegea CMS". The openGraph part matters more than it seems: if someone pastes the panel's address into WhatsApp, your image shows up and not somebody else's.

Step 2: the logo and icon

Payload lets you replace two graphic components. You give it the path to your component, in the path#ExportedName format:

admin: {
  components: {
    graphics: {
      Logo: '/components/admin/logo#Logo',
      Icon: '/components/admin/icon#Icon',
    },
  },
},

The logo is a normal React component. Ours draws the isotype in SVG with the name beside it:

export const Logo = () => (
  <div className="cg-logo">
    <Isotype size={40} />
    <span>Codegea</span>
  </div>
);

The icon is the small version, the one that appears in the top bar next to the breadcrumbs. After adding any new component, you have to regenerate the panel's import map:

pnpm generate:importmap

If you forget, your component doesn't show up. It is the most common mistake.

Step 3: colors and typography

Payload exposes its look as CSS variables. The panel layout imports a custom.css file, and that is where yours goes. We override three groups of variables.

First, the typography and the brand palette:

:root {
  --font-body: 'Inter Tight', system-ui, sans-serif;
  --cg-cobalt: #1e3faa;
  --cg-cobalt-dark: #16317f;
  --cg-ink: #0b0f1a;
  --cg-paper: #eef1f7;
}

Then, the backgrounds and text of the light and dark themes, which Payload paints with the --theme-* variables:

html[data-theme='light'] {
  --theme-bg: var(--cg-paper);
  --theme-elevation-0: #fff;
  --theme-elevation-50: #f6f8fc;
  --theme-text: var(--cg-ink);
}

html[data-theme='dark'] {
  --theme-bg: var(--cg-ink);
  --theme-elevation-0: #0b0f1a;
  --theme-elevation-800: #eef1f7;
}

Finally, the color of primary buttons and links:

.btn--style-primary {
  --bg-color: var(--cg-cobalt);
  --color: #fff;
  --hover-bg: var(--cg-cobalt-dark);
}

a:not([class]) {
  color: var(--cg-cobalt);
}

It is the quickest part and the one that changes the look the most: with those few variables, the whole panel goes from the factory gray to the brand's paper and cobalt. Always define both variants, light and dark; if you only do one, whoever uses dark mode will see half the panel in one color and half in another.

Step 4: a welcome block with shortcuts

Payload lets you mount your own components before the dashboard. Ours is a header with a sentence and three links: view the site, create a post and create a project.

admin: {
  components: {
    beforeDashboard: ['/components/admin/welcome#Welcome'],
  },
},
'use client';

export const Welcome = () => {
  const { i18n } = useTranslation();
  const copy = i18n.language === 'en' ? COPY.en : COPY.es;
  return (
    <section className="cg-welcome">
      <h2>{copy.title}</h2>
      <p>{copy.text}</p>
      <nav>{/* the three links */}</nav>
    </section>
  );
};

The only special thing is useTranslation, from @payloadcms/ui: it tells you which language the panel is in, so you can show the text in Spanish or English. For someone who logs in now and then, those three links save hunting for where a post is created.

Step 5: the text

There are three levels of text:

  • Your own collections. You give them labels per language and a group to cluster them in the menu. "Social posts", "Networks" and "Settings" come from there.
  • Payload's own text. It can be overridden per language with i18n.translations. We changed one: the "Payload settings" text, which now says "Codegea CMS settings". It was the only text in the panel that named the base CMS.
  • The panel's languages. i18n.supportedLanguages defines which ones it offers. The panel works in Spanish and English, and each editor picks theirs.

What still shows

Having not a single mention of Payload was the rule, and we almost get there. But look at the side menu:

How to customize the Payload CMS admin with your brand

Notice Forms, Form Submissions, Search Results and API Keys. Those names come from the plugins (forms, search, MCP) and are neither translated nor renamed. They can be changed with each plugin's override options, and on this site it is a pending task. We leave it in the article because it happens in every project: white-labeling looks more like a to-do list than a switch.

What we learned

  • Start with the CSS. With a few variables it already looks like another product. The logo and welcome block polish it; the color convinces.
  • Test dark mode and the language you don't use. The bugs are there.
  • Check the browser tab, the password reset email and the share image. Those are the places where the original name sneaks in.
  • Write the rule down. We put it in the repository's CLAUDE.md: "don't reintroduce references to Payload in visible text". Without that, the next change puts them back.

When it isn't worth it

If only you use the panel, or the client barely logs in, the tab title and the colors are enough. White-labeling pays off when someone lives with the panel every day. And there is no need to redo anything Payload already does well: content editing, permissions or search.

To keep going with the CMS, see how we extended it with a whole feature in a studio for publishing to social networks, and why we chose it in Payload vs Strapi vs Directus.

Share this article?LinkedInWhatsAppX

Written by

Derian Pinto

Founder & Full Stack Developer

Founder of Codegea. Builds custom websites, stores and platforms, and integrates and supports Arc XP for media companies.

Join our newsletter

An email with news and practical web, SEO and AI notes. No spam, unsubscribe anytime.

Shall we build your project?

Need help? Chat with us