A modern, production-ready desktop application template combining the best of web technologies. Build cross-platform desktop apps with the developer experience of web development.
- Electron 40 - Latest stable version for cross-platform desktop apps
- React 18 - Latest React with concurrent features
- TypeScript 5 - Strict mode enabled for type safety
- Vite 6 - Lightning fast HMR and optimized builds
- HeroUI v2 - Beautiful, accessible React components
- Tailwind CSS v4 - Utility-first CSS with latest features
- Hot Module Replacement - Instant updates during development
- Type Safety - Full TypeScript support with strict mode
- Modern Tooling - ESLint, Prettier configured out of the box
- Path Aliases - Clean imports with
@/prefix - Error Boundaries - Graceful error handling
- Dark Mode - Built-in theme switching support
- Responsive Design - Works on all screen sizes
- Smooth Animations - Framer Motion integration
- Accessible - WCAG compliant components
- Customizable - Easy theming with Tailwind CSS
- Installer Generation - Build for Windows, macOS, and Linux
- Cross-Platform - Single codebase for all major desktop platforms
Before you begin, ensure you have met the following requirements:
- Node.js >= 18.0.0
- Yarn >= 1.22.0 (recommended) or npm/pnpm
- Git
Note: If you're building native dependencies (optional), you may need platform-specific build tools (Visual Studio Build Tools for Windows, or Xcode Command Line Tools for macOS).
git clone https://github.com/LingChen-tsjmdlc/electron-vite-heroui-template.git my-electron-app
cd my-electron-appyarn install# Run in Electron with hot reload
yarn dev
# Or just the web preview (browser)
yarn dev:web# Build for current platform
yarn build
# Build for specific platforms
yarn build:win # Windows
yarn build:mac # macOS
yarn build:linux # Linux
yarn build:all # All platformsmy-electron-app/
βββ electron/ # Electron main process
β βββ main.ts # Main process entry
β βββ preload.ts # Preload script for IPC
βββ src/
β βββ components/ # Reusable React components
β βββ config/ # Configuration files
β βββ layouts/ # Page layouts
β βββ pages/ # Application pages
β βββ styles/ # Global styles
β βββ types/ # TypeScript types
βββ build/ # Build configuration
βββ release/ # Generated installers
βββ package.json
βββ vite.config.ts
βββ tsconfig.json
βββ tailwind.config.js
Edit the build section in package.json:
{
"build": {
"appId": "com.yourcompany.yourapp",
"productName": "Your App Name",
"directories": {
"output": "release"
}
}
}- Create a new file in
src/pages/:
// src/pages/my-page.tsx
export default function MyPage() {
return <div>My New Page</div>;
}- Add route in
src/App.tsx:
import MyPage from "./pages/my-page";
<Route path="/my-page" element={<MyPage />} />Use Tailwind utility classes directly:
<div className="flex flex-col items-center justify-center min-h-screen bg-gradient-to-br from-primary-500 to-secondary-500">
<h1 className="text-4xl font-bold text-white">Hello World</h1>
</div>Customize in src/tailwind.config.js:
module.exports = {
theme: {
extend: {
colors: {
brand: {
DEFAULT: "#0070f3",
dark: "#0056cc",
},
},
},
},
};import { Button, Card, CardBody } from "@heroui/react";
<Card>
<CardBody>
<Button color="primary" size="lg">
Click Me
</Button>
</CardBody>
</Card>;When using links in this template, you must distinguish between internal navigation and external links:
For internal navigation (React Router):
import { Link } from "react-router-dom";
// β
Correct - No page refresh
<Link to="/docs">Documentation</Link>
<Link to="/about">About</Link>For external websites:
import { Link } from "@heroui/link";
// β
Correct - Opens in browser
<Link href="https://github.com" isExternal>
GitHub
</Link>;β Common Mistake:
import { Link } from "@heroui/link";
// Wrong! This causes page refresh and breaks routing
<Link href="/docs">Documentation</Link>;Why this matters:
- HeroUI's
Linkuses<a>tags which trigger page reloads - In Electron with HashRouter, page reloads lose the route state β white screen
- Always use
react-router-dom'sLinkfor internal navigation
Preload Script (electron/preload.ts):
contextBridge.exposeInMainWorld("electronAPI", {
sendMessage: (channel: string, data: any) => {
ipcRenderer.send(channel, data);
},
onMessage: (channel: string, callback: Function) => {
ipcRenderer.on(channel, (event, ...args) => callback(...args));
},
});Usage in React:
window.electronAPI.sendMessage("custom-event", { data: "value" });White screen after build?
- Ensure you're using
HashRouterfor Electron (already configured) - Check that all assets are included in the
filesarray inpackage.json
Hot reload not working?
- Make sure you're running
yarn devnotyarn build - Check that vite.config.ts has HMR enabled
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Electron for the cross-platform framework
- HeroUI for the beautiful component library
- Vite for the blazing fast build tool
- Tailwind CSS for the utility-first CSS
- React for the UI library
If you found this template helpful, please consider giving it a β on GitHub!
For questions or issues:
- Open an Issue
- Start a Discussion
Built with β€οΈ using Electron, React, Vite, and HeroUI
