Sitemap

How to Add Shadcn/UI to an Electron-Vite App in 5 Easy Steps

5 min readMay 3, 2025

--

In this easy-to-follow guide, I’ll show you how to set up Shadcn/UI in an Electron-Vite project from scratch, in 5 simple steps.

Photo by Desola Lanre-Ologun on Unsplash

If you’re building cross-platform desktop apps using JavaScript, React, or TypeScript, chances are you’ve tried Electron. But setting it up from scratch can be complex, especially when you want a fast, modern developer experience.

That’s where Electron-Vite comes in — a powerful boilerplate that combines the simplicity of Vite with the power of Electron. It makes development lightning-fast and much easier to configure. I use it in most of my projects because:

  • It’s fast (thanks to Vite)
  • It supports TypeScript and React out of the box
  • It has a clean, modern structure with separate folders for main, preload, and renderer processes
  • It’s easy to extend with things like Tailwind and UI libraries (like I’ll do today)

What is Shadcn and Why Use It?

Photo by Kelly Sikkema on Unsplash

Shadcn/UI is a modern component library for React built using Radix UI, Tailwind CSS, and other open-source tools.

Here’s why it’s fantastic:

  • It gives you beautiful, accessible UI components out of the box
  • It’s customizable — everything is just React + Tailwind
  • You own the code — Shadcn copies components into your project, not a package dependency

Shadcn works great in React and Vite projects. However, setting it up in an Electron-Vite app isn’t entirely straightforward, and that’s precisely why I’m writing this guide.

Setting Up Shadcn in an Electron-Vite Project (From Scratch)

Let’s start from zero. You’ll have a working Electron desktop app styled with Tailwind CSS and Shadcn/UI by the end.

Step 1: Create a New Electron Project

I’ll use the official quick-start template from @quick-start/electron.

npm create @quick-start/electron

Follow the prompts (I usually go with the default settings). Then run:

cd <project_name>
npm install
npm run dev

This will launch a basic Electron app using Vite. You’re now ready to customize it.

Step 2: Add Tailwind CSS

Tailwind is a utility-first CSS framework required for Shadcn components to work.

Install Tailwind dependencies:

npm install -D tailwindcss @tailwindcss/vite

Then, update your electron.vite.config.ts to include Tailwind in the renderer process:

// electron.vite.config.ts
import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()]
},
preload: {
plugins: [externalizeDepsPlugin()]
},
renderer: {
resolve: {
alias: {
'@renderer': resolve('src/renderer/src')
}
},
plugins: [react(), tailwindcss()]
}
})

Update the file src/renderer/src/assets/main.css by adding at the top:

@import "tailwindcss";

Make sure this file is imported into your main renderer entry file (src/renderer/src/main.tsx). If you are using a different CSS file in your project, update that one instead.

Step 3: Prepare for Shadcn Setup

Before initializing Shadcn, we need to adjust the TypeScript and Vite configs to avoid path errors.

Update tsconfig.node.json to look like this:

{
"extends": "@electron-toolkit/tsconfig/tsconfig.node.json",
"include": ["electron.vite.config.*", "src/main/**/*", "src/preload/**/*"],
"compilerOptions": {
"composite": true,
"types": ["electron-vite/node"],
"baseUrl": ".",
"paths": {
"@/*": ["./src/renderer/src/*"]
},
"moduleResolution": "bundler"
}
}

Create the file vite.config.ts. Shadcn expects a vite.config.ts file, so copy the contents of your electron.vite.config.ts into a new file called vite.config.ts in the project root.

Now, update tsconfig.json to make sure the main config also includes path aliases:

{
"files": [],
"references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }],
"compilerOptions": {
"composite": true,
"types": ["electron-vite/node"],
"baseUrl": ".",
"paths": {
"@/*": ["./src/renderer/src/*"]
}
}
}

Step 4: Initialize Shadcn

Now you’re ready to install Shadcn!

npx shadcn@latest init

Follow the prompts. It will ask about your preferred style (the default is default). Take a look at the options on the official Shadcn style page.

This will create some files. Edit the created components.json file so that the aliases part looks like:

  "aliases": {
"components": "@/components",
"utils": "@renderer/lib/utils",
"ui": "@/components/ui",
"lib": "@renderer/lib",
"hooks": "@renderer/hooks"
},

Step 5: Add Your First Shadcn Component

Let’s test everything by adding a button:

npx shadcn@latest add button

This will create a file like src/renderer/src/components/ui/button.tsx. You can now use it in your React components.

Note: Make sure the utility function cn is correctly imported from @renderer/lib/utils

You’re Done!

Now run your app:

npm run dev

You can now edit your App.tsx file, adding a button, like this:

import { Button } from '@renderer/components/ui/button'

function App(): React.JSX.Element {
return (
<div className="flex flex-col items-center justify-center min-h-svh">
<Button variant="default" size="lg">
ShadCN Button
</Button>
</div>
)
}

export default App

And you’ll see a beautiful red button in the middle of the screen!

Note: not seeing the cursor as a pointer when hovering over the button? This is because of Tailwind v4 updates, as explained here: https://ui.shadcn.com/docs/tailwind-v4 (Buttons now use the default cursor). Also, take a look at this issue, https://github.com/shadcn-ui/ui/issues/6843

Pro Tip: Avoid Duplicating Vite Configs

If you’ve been following along, you probably noticed you ended up with two config files for Vite: electron.vite.config.ts and vite.config.ts. We could use only vite.config.ts and tell electron-vite to use that as the main config file. This will require some changes:

Update the package.json scripts to tell Electron Vite to use the custom config file. Add --config ./vite.config.ts to all relevant scripts:

"scripts": {
"format": "prettier --write .",
"lint": "eslint --cache .",
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
"typecheck": "npm run typecheck:node && npm run typecheck:web",
"start": "electron-vite --config ./vite.config.ts preview",
"dev": "electron-vite --config ./vite.config.ts dev",
"build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
"build:mac": "electron-vite --config ./vite.config.ts build && electron-builder --mac",
"build:linux": "electron-vite --config ./vite.config.ts build && electron-builder --linux"
}

Now, update the electron-builder.yml file to make sure to omit the now-unused electron.vite.config.ts in the packaged app. So, in the electron-builder.yml, remove this line:

- '!electron.vite.config.{js,ts,mjs,cjs}'

And replace it with this:

- '!vite.config.{js,ts,mjs,cjs}'

So it’ll look something like this:

files:
- '!**/.vscode/*'
- '!src/*'
- '!vite.config.{js,ts,mjs,cjs}' # This is the one you want now
- '!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'

And finally, fix the tsconfig.node.json to tell TypeScript to include the new config file instead of the old one.

"include": ["vite.config.ts", "src/main/**/*", "src/preload/**/*"]

We can now safely delete electron.vite.config.ts (or archive it, just in case). The whole app will use vite.config.ts, and we’ll never have to deal with duplicated config again.

Final Thoughts

Getting Shadcn/UI working in an Electron-Vite app isn’t too hard, but there are a few extra steps beyond a typical React/Vite project.

Photo by Tran Mau Tri Tam ✪ on Unsplash

This guide walks you through everything step-by-step to:

  • Set up Electron-Vite
  • Add Tailwind CSS
  • Configure TypeScript correctly
  • Initialize Shadcn/UI
  • Use your first component

Now you can build great-looking desktop apps with powerful UI and modern dev tools.

--

--

Responses (1)