Switching Theme Dynamically in a Multi-tenant Next.js + Tailwind App

I'm currently developing a Next.js + Tailwind application that supports multiple tenants and allows each tenant to easily switch styles or themes.

I've been struggling with the idea of how to implement this feature without requiring a rebuild of the entire application every time a style is changed. Is there a way to dynamically update the style for one specific tenant without having to rebuild the whole app?

My goal is to have tenants change a style parameter, which would then update a database. When the tenant's web app is refreshed, the new style should be applied instantly without any delay or need for a full rebuild.

Answer №1

Implement React's Context feature to dynamically display styles such as light or dark mode.

Alternatively,

Utilize a state management tool or the browser's localStorage to control styles and toggle classes for HTML elements within a Tailwind CSS setup.

Answer №2

My solution involved a combination of analyzing URLs and passing server props to the client side.

For instance, I made sure my backend sent certain styles like primaryColor.

Here is a functional example:

  1. Before rendering in your page.tsx file, extract the tenantId from the URL and use it to fetch styles from the backend.
async function retrieveQueryParams() {
  const headersInstance = headers();
  const pathname = headersInstance.get("referer");
  if (!pathname) return new URLSearchParams();

  const urlSearchParams = new URLSearchParams(pathname.split("?")[1]);
  return urlSearchParams;
}

async function fetchStyles(tenantId: string) {
  try {
    const response = await fetch(`http://localhost:3000/themes/${tenantId}`);
    return response.json();
  } catch (error) {
    return {};
  }
}
  1. Access this data in your server component and pass it to your client component
export default async function Main({searchParams){
  const tenantId = searchParams?.tenantId || "";
  const styles = await fetchStyles(tenantId);

  return (
    <div>
      <ClientComponent styles={styles} />
    </div>
  )
}
  1. In your client component, dynamically update the global CSS variables
const ClientComponent = ({styles}) => {
  useEffect(() => {
    document.documentElement.style.setProperty("--primary-color", primaryColor);
  }, [primaryColor]);

return (
<div className="bg-primary w-100 h-100">
my colour has been changed
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Which rxjs operator should be used when dealing with nested subscriptions in the presence of an if statement?

In my Angular/Typescript project, I am dealing with 2 subscriptions. Each subscription is subscribing to its own observable A and B, which are located outside the component in the service file. Sometimes, when A changes, B may or may not change based on c ...

Tips for creating a Next.js "Link" component with an optional "href" property

I've created a custom React function using typescript for the Next.js Link component. The "href" property is necessary for the "Link" to be used anywhere, so it couldn't be utilized as a button that functions as a submit button in forms. import N ...

Encountering challenges with the search and filtering features

I'm having some trouble with the search and filter features I'm creating. They work fine initially, but once I enter a search query in the input field, the results show up as expected. However, if I delete the query or enter a different one, the ...

What is the best way to verify the presence of a value in an SQL column?

I need to check if a value exists in a column. If the value already exists, I do not want to insert it into the table. However, if it does not exist, then I want to add new data. Unfortunately, my attempted solution hasn't been successful. You can fi ...

A guide on converting TypeScript to JavaScript while utilizing top-level await

Exploring the capabilities of top-level await introduced with TypeScript 3.8 in a NodeJS setting. Here's an example of TypeScript code utilizing this feature: import { getDoctorsPage } from "./utils/axios.provider"; const page = await getDo ...

What is the method for determining the type of search results returned by Algolia?

My connection between firestore and algoliasearch is working well. I am implementing it with the help of typescript in nextjs. I am attempting to fetch the results using the following code snippet products = index.search(name).then(({hits}) => { ret ...

Retrieve data from a URL using Angular 6's HTTP POST method

UPDATE: Replaced res.json(data) with res.send(data) I am currently working on a web application using Angular 6 and NodeJS. My goal is to download a file through an HTTP POST request. The process involves sending a request to the server by calling a func ...

Utilizing AWS Amplify with TypeScript and TypeScript Lambdas for powerful web development

Currently, I am working on a project that involves a nextjs frontend with TypeScript and AWS Amplify for the backend. My intention is to write my Lambda functions in TypeScript as well. However, I have encountered an issue where I have one tsconfig.json fi ...

What could be causing the global npm package to not be utilized for module dependencies?

My typescript and ts-node are already installed globally. In my package.json file, I have the necessary configurations to run tests with npm test. Everything works fine since ts-node and typescript are installed as local modules. { "name": "two_sum", ...

When a MatFormFieldControl both implements ControlValueAccessor and Validator, it can potentially lead to a cyclic

I am attempting to develop a custom form control by implementing MatFormFieldControl, ControlValueAccessor, and Validator interfaces. However, I encounter issues when including NG_VALUE_ACCESSOR or NG_VALIDATORS. @Component({ selector: 'fe-phone-n ...

The initial processing step for the export namespace is to utilize the `@babel/plugin-proposal-export-namespace-from` plugin. Previous attempts to resolve this issue have been

I encountered a problem with my application and found two related questions on the same topic. However, due to a lack of reputation, I am unable to comment or ask questions there. That's why I'm reaching out here... Recently, I integrated Redux ...

Encountering the "encoding" Module Error when Implementing Nextjs-13 with Supabase

I encountered an issue while trying to utilize Supabase for handling data insertion/retrieval from my form. Upon compilation, I received an error stating that the encoding module was not found. Despite attempting cache cleaning and re-installation of npm m ...

What is the process for creating a clickable file upload in Angular?

Currently, I am utilizing the instructions found in this guide to implement a file upload feature in my project. The code provided works perfectly: <input type="file" class="file-input (change)="onFileSelected($event)" #fileUplo ...

Redirecting users to a different URL on my website using Firebase

My website was originally hosted on firebase at this URL: , but that version is now outdated. I recently updated the application and decided to switch to Vercel, hosting a new instance of my website at this URL: Now, I want to ensure that users don' ...

Building a hybrid application in Angular using UpgradeModule to manage controllers

I am currently in the process of upgrading a large AngularJS application using UpgradeModule to enable running AngularJS and Angular 6 simultaneously without going through the preparation phase, which typically involves following the AngularJS style guide. ...

Generate a commitment from the function

I know the basics of JavaScript Promise and promise chain, but I'm looking to deepen my understanding. For example, take a look at the method provided below. It's in TypeScript, but can be adjusted for JavaScript ES6. private InsertPersonInDB(p ...

Utilizing NextJS to efficiently route requests directly to the backend and send the responses back to the client within the

In the technology stack for my project, I am using a Next.js server for the front end and a separate back-end server to handle user data storage. When a client needs to send a request to the back end, they first make an API request to the Next.js server, ...

I'm having trouble with VSCode deleting my TypeScript code. Is there a way to disable this feature

My code keeps getting removed and I can't figure out how to stop it. Does anyone know which setting I need to adjust? Watch the video here: This issue occurs in all instances, not just with imports. ...

Angular service is able to return an Observable after using the .then method

I am currently facing an issue with retrieving the authentication status in a service method. Everything seems to be working fine except for the return statement. I am struggling with the usage of .then inside .map and I am unable to figure out how to retu ...

Stringified HTML code showcased

When working with Angular, I have encountered an issue where I am calling a function inside an .html file that returns a string containing a table element. My goal is to convert this string into HTML code. I attempted to use [innerHtml]: <p [innerHtml ...