dav.one

Setting up Astro project with Tailwind CSS V4 and daisyUI V5

Created on January 20, 2025 by Dawid WasowskiUpdated on September 10, 2026

1. Initialize your new Astro project

Initialize new Astro project by running the following command in your terminal.
Command will launch a CLI wizard to setup your project.
Setup a project as you like. Just don’t install dependencies during the setup process. You will do that later.

bunx create-astro@latest

2. Install Dependencies

bun i vite@latest tailwindcss @tailwindcss/vite
bun i -D daisyui

3. Configure Astro

Open project in your favorite editor. If it’s VSCode, you can also install official Astro extension.

Edit the astro.config.mjs file, located in the root of your project. You need to add Tailwind CSS as a Vite plugin.

import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  vite: {
    plugins: [
      tailwindcss()
    ],
  },
});

4. Add Tailwind CSS and daisyUI to your CSS

To make Tailwind CSS and daisyUI available in your project, you need to add them to your CSS file. You can make it available globally or locally. Everything depends on your needs. In following examples, we will make them available globally.

Assume your global CSS file is in src/styles/global.css

@import "tailwindcss";
@plugin "daisyui";

Then, import CSS file in the .astro component or layout. Remember to set the proper path to your CSS file.

---
import '../src/styles/global.css';
---

Another way to import the CSS file in the .astro component:

<style is:global>
  @import '../src/styles/global.css';
</style>

If you are not planning to use CSS files at all, you can import them in .astro component like this:

<style is:global>
  @import "tailwindcss";
  @plugin "daisyui";
</style>
YOU DID IT!

At this point, you should be able to use Tailwind CSS and daisyUI in your project.
Run the following command in your terminal to start Development Mode.

bun run dev

If you want, you can take a few additional steps that might be useful to you.

5. Configure Tailwind CSS

If you are not planning to use default color palette, you can disable it.
This will reduce the size of your CSS file by about 3kB (gzipped).

@theme {
  --color-*: initial;
}

6. Configure daisyUI

By default, daisyUI has two themes: light and dark and you don’t need to configure anything to make it work. They adjust according to the user’s settings (browser/system). However, you can customize it as you like. Check config and themes pages for more information. In this example, four themes are specified. Cupcake is the default theme. Forest will be used if the user has dark mode enabled. Light and Dark are also available for manual switching.

@plugin "daisyui" {
  themes: light, dark, cupcake --default, forest --prefersdark;
}

7. Add Typography plugin

By default, Tailwind CSS resets all text styles (headings lose their size, margins disappear, lists lose bullets, etc.). If you’re planning to create a blog or render Markdown content, the easiest way to restore beautiful text formatting - without writing custom CSS for every HTML tag - is by using a typography plugin.

There are two great options for this, depending on whether you prefer standard breakpoint-based scaling or modern fluid scaling.

Option 1: The official Tailwind Typography plugin

The official @tailwindcss/typography plugin is the industry standard. It’s incredibly robust, highly customizable, and tested across thousands of projects. To handle different screen sizes, it relies on utility classes like prose-sm for mobile and prose-lg for desktop, meaning your text size “snaps” at specific CSS breakpoints.

To make it available in your project, first install the package.

bun i -D @tailwindcss/typography

Add the plugin to your CSS file.

@import "tailwindcss";
@plugin "@tailwindcss/typography";

Finally, add the prose class somewhere in your project, for example, to your <article> tag. This will apply the typography styles to all text inside this element.

<article class="prose lg:prose-xl">
  <slot />
</article>

I recommend reading the official documentation and this page of daisyUI to learn more.

Option 2: Fluid scaling with Clampography

I created Clampography as a modern alternative to the official plugin. Instead of relying on rigid CSS breakpoints (prose-sm, prose-lg), it uses the CSS clamp() function. This means your text and margins scale smoothly and automatically between mobile and desktop sizes. No snapping, no media queries, just perfectly fluid typography everywhere.

To install it in your project, run the following command in your terminal.

bun i clampography

Then, add it to your CSS file. We use the typography option to scope the styles (similar to prose) to prevent it from accidentally styling UI components like daisyUI buttons.

@import "tailwindcss";
@plugin "clampography" {
  typography: ".clampography";
}
@plugin "daisyui";

Finally, to apply the styles, simply add the clampography class to the element that wraps your content.

<article class="clampography">
  <slot />
</article>

For full documentation and customization options, check out the usage guide.

8. Add custom fonts

You can use the Astro Fonts API to easily add custom fonts to your project. This allows you to integrate external providers or local files by simply defining their names and configuring the sources.

To get started, configure your fonts in the astro.config.mjs config file.

import { defineConfig, fontProviders } from 'astro/config';

export default defineConfig({
  fonts: [
    {
      name: 'Fira Mono',
      cssVariable: '--font-fira-mono',
      provider: fontProviders.google(),
      weights: [400],
    },
    {
      name: 'Roboto',
      cssVariable: '--font-roboto',
      provider: fontProviders.google(),
      weights: [200, 400, 700],
      subsets: ["latin", "latin-ext"],
    },
  ],
});

Now you can use these fonts in CSS for specific Themes.
Fonts will be loaded and available under the specified CSS variables.

[data-theme="dark"] {
  font-family: var(--font-fira-mono);
}

Or you can use them in classic way.

body {
  font-family: var(--font-roboto);
}

9. Add SVG Icons

There are two great ways to add SVG icons from Iconify (a massive catalog of over 300,000 open-source vector icons) to your Astro project. The choice depends on your project’s specific needs.

Option 1: The official astro-icon plugin

For most complex projects, the official astro-icon package is the standard choice. It’s incredibly powerful and optimizes your HTML by generating SVG sprites. This means if you render the exact same icon dozens of times on a single page (like an edit icon in a long data table), it only outputs the SVG code once and references it, saving significant bandwidth.

To use it, you install the package by running the following command in your terminal.

bun i -D astro-icon

Then, register the integration in your astro.config.mjs.

import { defineConfig } from "astro/config";
import icon from "astro-icon";

export default defineConfig({
  integrations: [
    icon()
  ],
});

Finally, you can use the component in your .astro files.

---
import { Icon } from 'astro-icon/components';
---

<Icon name="mdi:home" class="w-6 h-6 text-blue-500" />

Check out official documentation for more information.

Option 2: Zero-config with astro-iconify-component

I created my own package called astro-iconify-component as a completely hassle-free alternative. Instead of using sprites, it relies purely on generating inline SVG code.

It requires zero configuration, no Vite plugins, and provides immediate access to the entire Iconify catalog right out of the box. It also provides native components for React, Vue, and Svelte out of the box, making it exceptionally easy to use inside MDX files or static islands.

To install it in your project, run the following command in your terminal.

bun add astro-iconify-component

Then you will be able to use icons in .astro files like:

---
import Icon from "astro-iconify-component";
---

<Icon name="mdi:home" />
<Icon name="mdi:home" class="w-6 h-6 text-blue-500" />
<Icon name="mdi:alert" title="Warning" />

Or seamlessly in your UI framework islands and MDX files:

{/* In MDX or React */}
import Icon from 'astro-iconify-component/react';

<Icon name="game-icons:balloon-dog" class="h-42 w-42" />

To search for icons, I recommend using the official Iconify website or the great alternative Icônes.

10. Add JavaScript Frameworks

Astro lets you use popular frameworks, such as React, Vue or Svelte (even in the same time!).
To add them, you should follow integration guides and daisyUI guides.

For this tutorial, we will add React and Vue to our project. The process is very similar for both frameworks.

React

To install React in your project, run the following command in your terminal.

bun i @astrojs/react react react-dom @types/react @types/react-dom

Edit the astro.config.mjs configuration file again. Add React to the integrations list.

import { defineConfig } from "astro/config";
import react from "@astrojs/react";

export default defineConfig({
  integrations: [
    react()
  ],
});

If you are using TypeScript in your project, then you need to edit the tsconfig.json file located in the root of your project.
Add the following lines to compilerOptions section.

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "react"
  }
}

To see React in action, you can add a very simple component and render it inside an Astro file. For example, create a component at src/components/Counter.tsx like this:

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}

Then use it in an Astro component with a hydration directive:

---
import Counter from '../components/Counter';
---

<Counter client:load />

This will make the button interactive in the browser.

Vue

You can also add Vue to your Astro project. The process is very similar to React.
To install it in your project, run the following command in your terminal.

bun i @astrojs/vue vue

Edit the astro.config.mjs configuration file again. Add Vue to the integrations list.

import { defineConfig } from "astro/config";
import vue from "@astrojs/vue";

export default defineConfig({
  integrations: [
    vue()
  ],
});

To see Vue in action, you can add a simple component and render it inside an Astro file. For example, create a component at src/components/Counter.vue like this:

<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0);
</script>

<template>
  <button @click="count++">
    Clicked {{ count }} times
  </button>
</template>

Then use it in an Astro component with a hydration directive:

---
import Counter from '../components/Counter.vue';
---

<Counter client:load />

This will make the button interactive in the browser.

11. MDX

MDX allows you to use JavaScript expressions, variables, and imported components directly inside your Markdown content. It’s a great choice if you plan to write blog posts and want more flexibility than plain Markdown offers - for example, embedding a React or Vue component inside an article.

To install it in your project, run the following command in your terminal.

bun i @astrojs/mdx

Edit the astro.config.mjs configuration file again. Add MDX to the integrations list.

import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";

export default defineConfig({
  integrations: [
    mdx()
  ],
});

That’s it - no extra configuration is required to start using .mdx files. Any file placed inside src/pages/ with the .mdx extension will now be treated as a page. For example, create src/pages/hello.mdx:

---
title: My first MDX page
---

import Counter from '../components/Counter';

# Hello, MDX!

This is regular Markdown, but I can also use **imported components** here.

<Counter client:load />

You can also use inline JavaScript expressions directly in the text! 
For example: 2 + 2 = {2 + 2}, or the current year is {new Date().getFullYear()}.

12. Sitemap

Sitemap automatically generates a sitemap-index.xml file (and one or more numbered sitemap-N.xml files) based on the pages in your project. This helps search engines discover and index your content more effectively. To install it in your project, run the following command in your terminal.

bun i @astrojs/sitemap

Edit the astro.config.mjs configuration file again. Add sitemap to the integrations list. Unlike MDX, the sitemap integration also requires you to set the site option - your deployed site’s URL - since sitemap entries need absolute URLs.

import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";

export default defineConfig({
  site: "https://dav.one",
  integrations: [
    sitemap()
  ],
});

After building your site, you’ll find sitemap-index.xml and sitemap-0.xml in your output directory.

Finally, it’s a good idea to point crawlers to your sitemap by adding a line to your public/robots.txt file:

User-agent: *
Allow: /

Sitemap: https://dav.one/sitemap-index.xml

12. Finish

Are you having fun writing code in your new project, and is everything working as expected?
Do you have any issues or need some help? Perhaps you want to showcase your project or ask for feedback? Visit the daisyUI Discord server and say hello! 🖐