Comments (5)
I have theming implemented in my app. It's a multi-faceted approach that involves a combination of dynamically importing css and objects with tailwind classes.
Essentially all you need to do is get your subdomain or domain from next/headers at the root layout. Then use that to dynamically load your required theming info.
export default async function RootLayout(props: LayoutProps) {
const headersList = headers();
const host = headersList.get('host');
const site = await getSiteData(host);
...
In my case getSiteData() looks like this - I have my hostname parsing function here
// Extract subdomain helper
function extractSubdomain(domain: string) {
if (domain.endsWith(`.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`)) {
return domain.replace(`.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`, '');
} else if (domain.endsWith('.localhost:3000')) {
return domain.replace('.localhost:3000', '');
}
return null;
}
export async function getSiteData(domain: string | null) {
if (!domain) {
return console.log("No domain provided");;
}
const subdomain = extractSubdomain(domain);
return await unstable_cache(
async () => {
return prisma.site.findUnique({
where: subdomain ? { subdomain: subdomain } : { customDomain: domain },
include: {
user: true,
activeTheme: true,
},
});
},
[`${domain}-metadata`],
{
revalidate: 900,
tags: [`${domain}-metadata`],
},
)();
}
Colour and font tokens are set by CSS variables and called for at the root with a data attribute. Those CSS variables are also set into my tailwind.config, just like @rpfelgueiras has shown in the link he referenced.
Set your data attributes on your tag. This is where you want font definitions especially
<html
{ "data-color-theme": `theme-${themeName}-color` }
{ "data-font-theme": `theme-${themeName}-font` }
>
Define CSS variables
@layer base {
[data-color-theme='theme-themeName-color'] {
--background: 0 0% 99%;
--foreground: 45 25% 5%;
--primary: 45 25% 5%;
--primary-foreground: 45 25% 98%;
...
Then, tailwind classes are put into a theme-{themeName}.tsx file and applied in the site template code after dynamically importing the tailwind classes
Theme file
const themeName: Theme = {
name: "The Theme Name",
global: {
text: "text-primary font-light",
buttonRadius: "rounded-full"
},
...
Dynamic import. This depends on naming your files with the same values you're using in your database to identify a site's theme.
const themeData = await import(`@/styles/themes/theme-${themeName}/theme-${themeName}`);`
Applied in components
<div className={cn(theme.profile.container)}>
<p className={cn(theme.profile.name)}>{data?.displayName}</p>
<div className={cn(theme.profile.infoContainer)}>
...
In my case, I'm not swapping out large chunks of JSX (yet). I'm just changing style. But there's no stopping you from having entire components conditionally render this way. It's a bit tedious to set up initially. But once the architecture is done, creating new themes is a bit less work.
from platforms.
I currently have the same requirement and had no luck with radix-theme yet - see #379
from platforms.
@chrishoermann I was searching for a solution and I will probably go in this direction tailwindlabs/tailwindcss#11964
In build time generate the right theme configurations per tenant and place the output in the right server/folder.
from platforms.
I have a ServerSideThemeWrapper
wrapping everything in the [domain] route, which has access to the relevant Site, from which I pass the theme props.
Using shadcn/ui:
export function ServersideThemeWrapper({
children,
className,
color,
radius,
}: ServersideThemeWrapperProps) {
return (
<div
className={cn(`theme-${color}`, "w-full", className)}
style={
{
"--radius": `${radius ? radius : 0.5}rem`,
} as React.CSSProperties
}
>
{children}
</div>
);
}
from platforms.
Related Issues (20)
- Adding NextAuth
- Bug: Adding a custom domain with an initial misconfigured DNS config keeps staying in error mode forever
- request headers host unexpectedly changed
- Error when deploying Django App on Vercel
- how to invalidate all a pages of a [domain] route
- Title and description fields within the post editor do not trigger the save function as expected, also infinite loop on editor page related to nav.tsx HOT 4
- How to get this to work with next-auth v5? HOT 3
- Support for internationalization HOT 3
- When accessing blog created on localhost, it returns 404 how do I solve this HOT 2
- Edge function Error : ERR_MODULE_NOT_FOUND on an installed module HOT 1
- Errors are not showing on login page because of redirects in middleware HOT 1
- minor: (invalid?) use of promises HOT 1
- Stuck on "add your root domain & wildcard domain." from guide HOT 3
- Bug: able to create sites with blank site name & description HOT 1
- Use custom domain for Preview Deployments HOT 1
- can we use platforms without vercel HOT 2
- Adding custom domains without relying on subdomains
- Feature Request: "teams/orgs" support
- RFC: Revert all edge rendering back to Node.js
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from platforms.