How to create dynamic customer branding in Appfarm: From static themes to smart colors

When you build apps that serve multiple organisations in Appfarm, branding gets personal. Each customer wants their own look — their logo, their colors, their vibe.

And that’s fair. But if you’ve ever tried to maintain separate themes per customer, you already know the pain: endless duplication, manual updates, and confusion over which theme applies where.

There’s a cleaner way to do this: one base color per customer, dynamic palette generation, and automatic application across the whole app.


Why separate themes don’t scale

It sounds reasonable at first:

“We’ll just make a theme for every customer and apply it when they log in.”

That works when you have two customers. Maybe five.

But once you get to dozens, it turns into chaos:

  • Every minor style change means editing every theme.
  • Forget one update, and your customers start seeing mismatched components.
  • You can’t easily add or remove palette variables without updating all themes.

Your design system turns into technical debt.


A better approach: dynamic theming from a single base color

Instead of maintaining a pile of static themes, make your theme data-driven.

Each customer object simply stores one property — let’s call it color — containing their brand’s main color in hex (e.g. #3498db).

When the customer logs in, a coded component in your app:

  1. Reads that color from the database (appfarm.data.color.get()).
  2. Calculates light, dark, and contrast variants automatically.
  3. Optionally derives a complementary secondary color or uses one if defined.
  4. Applies the new palette across the app using CSS variables — no theme swapping required.

From that moment, every Appfarm and Material UI component that uses color="primary" automatically respects the customer’s brand identity.


How it works under the hood

Appfarm’s design system (based on Material UI) relies heavily on CSS variables for its palette, such as:

--palette-primary-main
--palette-primary-light
--palette-primary-dark
--palette-primary-contrastText

By dynamically setting those variables from your coded component, you effectively override the current theme colors at runtime.

If your color field is empty or invalid, you can safely fall back to your default brand color — for example #034966.

You can even go a step further: if your app stores both a primary and a secondary color per customer, the same approach applies — the coded component updates both sets of variables to match.


Why this approach wins

  • Scales infinitely: one code path, unlimited customer variations.
  • Easy to maintain: no more editing dozens of themes for one style change.
  • Consistent: all components automatically use the right colors everywhere*.
  • Fast to brand: a single hex field in your customer object defines their whole look.

*Some of the built-in components, like buttons, don't respond to the palette variables, but with custom components, you can easily work around it.


For even more flexibility

You can easily extend this pattern:

  • Store both primary and secondary colors in the customer record (and override the --palette-secondary-... variables as well).
  • Add automatic accessibility checks for contrast.
  • Provide a color preview in your admin dashboard so users can tweak branding themselves.
  • Combine it with dark/light mode logic without breaking customer-specific branding.

⚠ A quick word of caution

This setup works because Appfarm (and Material UI under the hood) exposes its palette through CSS variables. The moment those variable names or structures change in a future update, your overrides could break.

That’s the trade-off when you bring custom code into the mix: you’re taking ownership of dependencies, updates, and maintenance. It’s not a reason not to do it — just something to be aware of. If you choose this approach, you’re stepping a bit outside the low-code comfort zone and into the world of version management. But for most projects, the flexibility you gain is well worth that responsibility.


Wrapping up

Appfarm’s theming engine gives you structure, but that doesn’t mean it has to lock you in. By calculating palettes on the fly, you get the best of both worlds — consistency for the platform and individuality for every customer. It’s a small technical tweak that delivers a big visual impact — and saves you from maintaining a library of nearly identical themes.