Skip to main content
RapidDev - Software Development Agency
lovable-issues

Adding Custom Fonts to Lovable Without Conflicts

Load custom fonts in Lovable by adding a Google Fonts link tag in index.html or placing local font files in /public/fonts/ with @font-face declarations. Then extend the fontFamily in tailwind.config.ts so you can use font-[name] classes. Conflicts with shadcn/ui defaults are resolved by overriding the sans key to set your font as the global default.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read~10 minAll Lovable projectsMarch 2026RapidDev Engineering Team
TL;DR

Load custom fonts in Lovable by adding a Google Fonts link tag in index.html or placing local font files in /public/fonts/ with @font-face declarations. Then extend the fontFamily in tailwind.config.ts so you can use font-[name] classes. Conflicts with shadcn/ui defaults are resolved by overriding the sans key to set your font as the global default.

Why custom fonts conflict with default styles in Lovable projects

Lovable projects use Tailwind CSS with shadcn/ui, which sets a default font stack (typically Inter or the system sans-serif). When you add a custom font, three things can go wrong: the font loads but Tailwind does not know about it so no CSS class exists to apply it, the font's @font-face conflicts with existing declarations, or shadcn/ui component styles override your font setting with higher CSS specificity. Local fonts (files you upload to /public/fonts/) require an @font-face declaration that tells the browser the font family name, the file location, the weight, and the style. If any of these values are wrong, the browser silently falls back to the default font. The most common mistake is getting the src URL wrong — files in /public are served at the root, so /public/fonts/MyFont.woff2 becomes /fonts/MyFont.woff2 in the URL. Font conflicts with shadcn/ui happen because shadcn components inherit their font from the Tailwind theme. If you add a custom font to specific elements but do not update the Tailwind config, shadcn components continue using the default font, creating an inconsistent look throughout the app.

  • Font loaded but not added to tailwind.config.ts — no CSS class exists to apply the font
  • Wrong @font-face src path — /public/fonts/ files are served at /fonts/ not /public/fonts/
  • CSS specificity conflict — shadcn/ui inherits from the Tailwind sans font, not your custom font
  • Multiple @font-face declarations for the same family name with conflicting weights or styles
  • Font file format not supported — some browsers need WOFF2, older ones need WOFF or TTF

Error messages you might see

Failed to decode downloaded font: /fonts/CustomFont.woff2

The font file at this path is corrupted, the path is wrong (returning HTML instead of the font), or the file format is unsupported. Verify the file exists in /public/fonts/ and test the URL directly in the browser.

Font 'CustomFont' was not found

The @font-face rule references a font family name that does not match any loaded font. Check the font-family value in your @font-face rule and make sure it matches exactly what you use in CSS.

The font 'CustomFont' does not have a valid src descriptor

The src path in your @font-face rule is incorrect. For files in /public/fonts/, use url('/fonts/CustomFont.woff2') with a leading slash.

Before you start

  • A Lovable project open in the editor
  • Your custom font files (WOFF2 format recommended) or the Google Fonts URL
  • Access to Dev Mode to edit index.html and tailwind.config.ts

How to fix it

1

Add local font files to /public/fonts/

Vite serves files from /public at the root URL, making them available to @font-face rules

If you have font files (.woff2 is the best format for web), create a fonts folder inside /public. Upload your font files there using GitHub or Dev Mode. You need one file per weight and style combination — for example, Roboto-Regular.woff2, Roboto-Bold.woff2, and Roboto-Italic.woff2. WOFF2 has the best compression and is supported by all modern browsers.

Expected result: Font files are accessible at /fonts/FontName.woff2 when you visit the URL in the browser.

2

Declare the font with @font-face in index.html

The @font-face rule tells the browser the name, location, weight, and display strategy for each font file

Open index.html in the project root. Add a style tag in the head section with @font-face declarations for each font file. Each declaration maps a specific weight and style to a file. Use font-display: swap to show fallback text immediately while the font loads.

Before
typescript
<head>
<meta charset="UTF-8" />
<title>My App</title>
</head>
After
typescript
<head>
<meta charset="UTF-8" />
<title>My App</title>
<style>
@font-face {
font-family: 'BrandFont';
src: url('/fonts/BrandFont-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap; /* Show fallback text while font loads */
}
@font-face {
font-family: 'BrandFont';
src: url('/fonts/BrandFont-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
</style>
</head>

Expected result: The browser downloads the font files when the page loads. You can verify in the Network tab by filtering for 'font'.

3

Extend Tailwind configuration to include the custom font

Tailwind generates CSS classes based on the fontFamily config — without this, you cannot use font-brand in your components

Open tailwind.config.ts and add your font to the fontFamily section. If you want the font as the global default, override the sans key. If you want it available as an optional class, create a new key. Include fallback fonts in case the custom font fails to load.

Before
typescript
export default {
theme: {
extend: {},
},
};
After
typescript
export default {
theme: {
extend: {
fontFamily: {
// Makes font-brand available as a class
brand: ['BrandFont', 'Inter', 'sans-serif'],
// Override sans to make BrandFont the global default
sans: ['BrandFont', 'Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
},
},
},
};

Expected result: The class font-brand applies your custom font. If you override sans, all text uses the custom font by default.

4

Resolve conflicts with shadcn/ui component fonts

shadcn/ui components inherit the Tailwind sans font — if you do not override sans, they use the default font instead of yours

If you override the sans key in tailwind.config.ts, shadcn/ui components automatically use your custom font because they inherit from the Tailwind sans family. If you only added a custom key (like font-brand), shadcn/ui components still use the default font. To make everything consistent, either override sans globally or add the font-brand class to the body tag in index.html. If resolving font conflicts across many shadcn/ui components requires changes to the theme configuration, RapidDev's engineers have configured custom typography across 600+ Lovable projects.

Before
typescript
<body>
<div id="root"></div>
</body>
After
typescript
<body class="font-brand antialiased">
<div id="root"></div>
</body>

Expected result: All text in the app, including shadcn/ui components, uses your custom font consistently.

Complete code example

tailwind.config.ts
1import type { Config } from "tailwindcss";
2
3export default {
4 darkMode: ["class"],
5 content: ["./index.html", "./src/**/*.{ts,tsx}"],
6 theme: {
7 extend: {
8 fontFamily: {
9 // Custom brand font loaded via @font-face in index.html
10 brand: ['BrandFont', 'Inter', 'sans-serif'],
11 // Heading font from Google Fonts
12 heading: ['Playfair Display', 'Georgia', 'serif'],
13 // Override default sans-serif to use brand font globally
14 sans: ['BrandFont', 'Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
15 },
16 // Ensure custom font classes survive Tailwind's purge
17 // by using them in templates (not dynamically)
18 },
19 },
20 plugins: [require("tailwindcss-animate")],
21} satisfies Config;

Best practices to prevent this

  • Use WOFF2 format for all custom fonts — it has the best compression and is supported by all modern browsers
  • Always include font-display: swap in @font-face rules to prevent invisible text while the font loads
  • Override the Tailwind sans key if you want your font as the global default — this ensures shadcn/ui components also use it
  • Include fallback fonts in your fontFamily arrays so text remains readable if the custom font fails to load
  • Place font files in /public/fonts/ and reference them with a leading slash in the URL: url('/fonts/file.woff2')
  • Load only the weights you need — each weight adds 20-50KB to the page load time
  • Add font-preload link tags in index.html for critical fonts to speed up initial rendering

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I have a Lovable.dev project and I want to add a custom font. My project uses Tailwind CSS + shadcn/ui. Font details: - Font name: [name] - Source: [Google Fonts URL or local files] - Weights needed: [400, 700, etc.] - Should this be the global default? [yes/no] Please help me: 1. Create the @font-face declarations (or Google Fonts link tag) 2. Update tailwind.config.ts with the font 3. Apply it globally or to specific elements 4. Resolve any conflicts with shadcn/ui default fonts

Lovable Prompt

Add the custom font BrandFont to my project. I have uploaded BrandFont-Regular.woff2 and BrandFont-Bold.woff2 to /public/fonts/. Add @font-face declarations in @index.html for both weights with font-display: swap. Update @tailwind.config.ts to override the sans font family with BrandFont as the primary font and Inter as the fallback. Add the antialiased class to the body tag.

Frequently asked questions

How do I add a custom font to a Lovable project?

For Google Fonts, add a link tag in index.html. For local fonts, place WOFF2 files in /public/fonts/ and add @font-face rules in index.html. Then extend fontFamily in tailwind.config.ts and apply the font class to your elements or override the sans key for global usage.

Why does my custom font not appear on shadcn/ui components?

shadcn/ui components inherit the Tailwind sans font family. If you added your font as a separate key (like font-brand) instead of overriding sans, shadcn/ui still uses the default font. Override the sans key in tailwind.config.ts to make your font the global default.

What font file format should I use?

Use WOFF2. It has the best compression (30-50% smaller than WOFF), is supported by all modern browsers, and loads faster. Include a WOFF fallback only if you need to support very old browsers.

Where do I put local font files in a Lovable project?

Place them in /public/fonts/. Vite serves /public contents at the root, so /public/fonts/MyFont.woff2 is accessible at /fonts/MyFont.woff2 in your browser. Reference this path in your @font-face src rules.

How do I use different fonts for headings and body text?

Add both fonts to tailwind.config.ts with different keys (e.g., font-heading and font-body). Apply font-heading to your h1-h6 elements and font-body to paragraph text. You can also override the sans key for body and create a separate heading key.

What if I can't fix this myself?

If your font setup involves complex typography hierarchies, variable fonts, or conflicts with the shadcn/ui theme system across many components, RapidDev's engineers have configured custom font systems across 600+ Lovable projects.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.