create-tauri-app-project-wind 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +170 -0
  2. package/index.js +283 -0
  3. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # create-tauri-app-project-wind
2
+
3
+ A modern, professional desktop application starter template built with Tauri, React 18, TypeScript, and Shadcn UI. Features a custom title bar, responsive navigation, and comprehensive UI component showcase.
4
+
5
+ ## 🚀 Quick Start
6
+
7
+ ### Interactive Installation (Recommended)
8
+
9
+ The CLI will guide you through configuration with interactive prompts:
10
+
11
+ ```bash
12
+ npm create tauri-app-project-wind@latest
13
+ ```
14
+
15
+ You'll be prompted for:
16
+ - 📁 **Project folder name** – Name for your project directory (lowercase, dashes/underscores allowed)
17
+ - 🏷️ **App display name** – How your app will be labeled in the window/titlebar
18
+ - 👤 **Author name** – Your name or organization (used in metadata)
19
+ - 📦 **Bundle identifier** – Reverse domain (e.g., com.company.app) for Tauri packaging
20
+ - 📦 **Package manager** – Choose npm, yarn, pnpm, or bun
21
+ - ⚡ **Auto-install** – Automatically install dependencies after setup
22
+
23
+ ### Quick Install with Defaults
24
+
25
+ Provide the project name as an argument to skip the first prompt:
26
+
27
+ ```bash
28
+ npm create tauri-app-project-wind@latest my-app
29
+ ```
30
+
31
+ ### Package Manager Specific
32
+
33
+ #### npm
34
+ ```bash
35
+ npm create tauri-app-project-wind@latest my-app
36
+ ```
37
+
38
+ #### yarn
39
+ ```bash
40
+ yarn create tauri-app-project-wind my-app
41
+ ```
42
+
43
+ #### pnpm
44
+ ```bash
45
+ pnpm create tauri-app-project-wind my-app
46
+ ```
47
+
48
+ #### bun
49
+ ```bash
50
+ bun create tauri-app-project-wind my-app
51
+ ```
52
+
53
+ ## ✨ What's Included
54
+
55
+ ### Core Technologies
56
+ - ⚡ **Tauri** - Build smaller, faster, more secure desktop applications
57
+ - ⚛️ **React 18** - Modern React with hooks and concurrent features
58
+ - 📘 **TypeScript** - Full type safety across the entire application
59
+ - 🎨 **Shadcn UI** - 52+ beautiful, accessible UI components
60
+ - 🎯 **Vite** - Lightning-fast development with HMR
61
+ - 💅 **TailwindCSS** - Utility-first CSS framework
62
+
63
+ ### Custom Features
64
+ - 🪟 **Custom Title Bar** - Native-like window controls (minimize, maximize, close)
65
+ - 🎨 **Theme System** - Light/Dark/System modes with live switching
66
+ - 📱 **Responsive Design** - Mobile-first approach with breakpoint handling
67
+ - 🍔 **Smart Navigation** - Hamburger menu on mobile, menubar on desktop
68
+ - 🎭 **Modern Animations** - Smooth transitions and interactive elements
69
+ - 🏗️ **Clean Architecture** - Pages, layouts, and components separation
70
+
71
+ ## 🎨 UI Components
72
+
73
+ ### Custom Components
74
+ - **TitleBar** - Custom window controls with draggable area
75
+ - Minimize, Maximize/Restore, Close buttons
76
+ - Integrated theme toggle with Sun/Moon icons
77
+ - Responsive hamburger menu (mobile)
78
+ - Desktop menubar (File, Edit, View, Help)
79
+ - About and Keyboard Shortcuts dialogs
80
+
81
+ ### Shadcn UI Components (52+)
82
+ **Form & Input**: Button, Input, Textarea, Checkbox, Switch, Radio Group, Select, Input OTP, Form, Field, Input Group
83
+
84
+ **Navigation**: Menubar, Navigation Menu, Breadcrumb, Tabs, Pagination, Command
85
+
86
+ **Feedback**: Alert, Alert Dialog, Dialog, Toast/Sonner, Progress, Spinner, Skeleton, Badge
87
+
88
+ **Layout**: Card, Separator, Scroll Area, Resizable Panels, Aspect Ratio, Sheet
89
+
90
+ **Overlay**: Dropdown Menu, Context Menu, Popover, Hover Card, Tooltip, Drawer
91
+
92
+ **Data Display**: Table, Avatar, Calendar, Carousel, Accordion, Collapsible, Toggle, Toggle Group
93
+
94
+ ## 🛠️ Project Structure
95
+
96
+ ```
97
+ my-app/
98
+ ├── src/
99
+ │ ├── components/
100
+ │ │ ├── ui/ # 52+ Shadcn UI components
101
+ │ │ ├── demo/ # Component showcase
102
+ │ │ ├── TitleBar.tsx # Custom window controls
103
+ │ │ └── theme-provider.tsx # Theme context
104
+ │ ├── layouts/
105
+ │ │ └── MainLayout.tsx # Main app layout wrapper
106
+ │ ├── pages/
107
+ │ │ └── Welcome.tsx # Welcome/demo page
108
+ │ └── lib/
109
+ │ └── utils.ts # Utility functions
110
+ ├── src-tauri/
111
+ │ ├── src/main.rs # Rust backend
112
+ │ └── tauri.conf.json # Tauri configuration
113
+ └── package.json # Node dependencies
114
+ ```
115
+
116
+ ## 📝 Available Scripts
117
+
118
+ ```bash
119
+ # Development
120
+ npm run dev # Start Vite dev server (web preview)
121
+ npm run tauri dev # Run Tauri app in development mode
122
+
123
+ # Build
124
+ npm run build # Build frontend for production
125
+ npm run tauri build # Build complete desktop application
126
+ ```
127
+
128
+ ## 🎯 Key Features
129
+
130
+ ### Custom Title Bar
131
+ - Native-like window controls (minimize, maximize, close)
132
+ - Draggable area - Click and drag to move window
133
+ - Double-click to maximize
134
+ - Integrated theme toggle with Sun/Moon icons
135
+ - Responsive menu that adapts to screen size
136
+
137
+ ### Responsive Navigation
138
+ **Desktop (≥768px)**: Traditional menubar with File, Edit, View, Help menus
139
+
140
+ **Mobile (<768px)**: Modern hamburger icon with smooth animation and slide-out navigation
141
+
142
+ ### Theme System
143
+ - **Light Mode** - Clean, bright interface
144
+ - **Dark Mode** - Easy on the eyes
145
+ - **System Mode** - Auto-detects OS preference and updates live
146
+
147
+ ## 📚 Documentation
148
+
149
+ For full documentation, examples, and advanced usage, visit:
150
+
151
+ 🔗 [GitHub Repository](https://github.com/ssanaullahrais/project-wind-tauri-js-starter-kit)
152
+
153
+ ## 🤝 Contributing
154
+
155
+ Contributions are welcome! Feel free to:
156
+ - Report bugs
157
+ - Suggest features
158
+ - Submit pull requests
159
+
160
+ ## 📄 License
161
+
162
+ MIT License
163
+
164
+ ## 🙏 Credits
165
+
166
+ Built with [Tauri](https://tauri.app/), [React](https://react.dev/), [Vite](https://vitejs.dev/), and [Shadcn UI](https://ui.shadcn.com/)
167
+
168
+ ---
169
+
170
+ **Happy coding! 🚀**
package/index.js ADDED
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require('child_process');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+ const readline = require('readline');
7
+
8
+ // ANSI color codes for better CLI experience
9
+ const colors = {
10
+ reset: '\x1b[0m',
11
+ bright: '\x1b[1m',
12
+ dim: '\x1b[2m',
13
+ cyan: '\x1b[36m',
14
+ green: '\x1b[32m',
15
+ yellow: '\x1b[33m',
16
+ blue: '\x1b[34m',
17
+ magenta: '\x1b[35m',
18
+ };
19
+
20
+ // Readline interface for user input
21
+ const rl = readline.createInterface({
22
+ input: process.stdin,
23
+ output: process.stdout
24
+ });
25
+
26
+ // Utility to ask questions
27
+ function question(query) {
28
+ return new Promise(resolve => rl.question(query, resolve));
29
+ }
30
+
31
+ // Validate project name
32
+ function validateProjectName(name) {
33
+ if (!name) return false;
34
+ if (!/^[a-z0-9-_]+$/i.test(name)) {
35
+ console.log(`${colors.yellow}⚠️ Project name can only contain letters, numbers, hyphens, and underscores${colors.reset}`);
36
+ return false;
37
+ }
38
+ return true;
39
+ }
40
+
41
+ // Validate bundle identifier
42
+ function validateBundleId(id) {
43
+ if (!id) return false;
44
+ if (!/^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$/i.test(id)) {
45
+ console.log(`${colors.yellow}⚠️ Bundle ID should be in reverse domain format (e.g., com.company.app)${colors.reset}`);
46
+ return false;
47
+ }
48
+ return true;
49
+ }
50
+
51
+ // Main function
52
+ async function main() {
53
+ console.log(`${colors.bright}${colors.cyan}`);
54
+ console.log('╔══════════════════════════════════════════════════════════╗');
55
+ console.log('║ ║');
56
+ console.log('║ 🌬️ Project Wind CLI Installer 🌬️ ║');
57
+ console.log('║ ║');
58
+ console.log('║ Modern Tauri + React + TypeScript + Shadcn/UI ║');
59
+ console.log('║ ║');
60
+ console.log('╚══════════════════════════════════════════════════════════╝');
61
+ console.log(colors.reset);
62
+ console.log(`${colors.dim}Let's set up your new desktop application!${colors.reset}\n`);
63
+
64
+ let config = {};
65
+
66
+ // 1. Project folder name
67
+ console.log(`${colors.cyan}📁 Project folder name:${colors.reset}`);
68
+ console.log(` ${colors.dim}This will be your project directory name${colors.reset}`);
69
+ console.log(` ${colors.dim}Use lowercase with dashes (e.g., my-awesome-app)${colors.reset}`);
70
+ let projectName = process.argv[2];
71
+ while (!validateProjectName(projectName)) {
72
+ projectName = await question(` > `);
73
+ }
74
+ config.projectName = projectName.trim();
75
+
76
+ // 2. App display name
77
+ const autoDisplayName = config.projectName.split('-').map(word =>
78
+ word.charAt(0).toUpperCase() + word.slice(1)
79
+ ).join(' ');
80
+ console.log(`\n${colors.cyan}🏷️ App display name:${colors.reset}`);
81
+ console.log(` ${colors.dim}This is the name shown in your app's titlebar and windows${colors.reset}`);
82
+ console.log(` ${colors.dim}Can use spaces and capitals (e.g., My Awesome App)${colors.reset}`);
83
+ console.log(` ${colors.dim}Press Enter to use: "${autoDisplayName}"${colors.reset}`);
84
+ let appName = await question(` > `);
85
+ config.appName = appName.trim() || autoDisplayName;
86
+
87
+ // 3. Author name
88
+ let author = await question(`\n${colors.cyan}👤 Author name:${colors.reset} ${colors.dim}(your name or company)${colors.reset}\n > `);
89
+ config.author = author.trim() || 'Your Name';
90
+
91
+ // 4. Bundle identifier
92
+ let bundleId = '';
93
+ const defaultBundleId = `com.${config.author.toLowerCase().replace(/\s+/g, '')}.${config.projectName.replace(/[^a-z0-9]/gi, '')}`;
94
+ while (!validateBundleId(bundleId)) {
95
+ bundleId = await question(`\n${colors.cyan}📦 Bundle identifier:${colors.reset} ${colors.dim}(defaults to "${defaultBundleId}")${colors.reset}\n > `);
96
+ if (!bundleId.trim()) {
97
+ bundleId = defaultBundleId;
98
+ }
99
+ }
100
+ config.bundleId = bundleId.trim();
101
+
102
+ // 5. Package manager
103
+ console.log(`\n${colors.cyan}📦 Package manager:${colors.reset}`);
104
+ console.log(` ${colors.dim}1) npm${colors.reset}`);
105
+ console.log(` ${colors.dim}2) yarn${colors.reset}`);
106
+ console.log(` ${colors.dim}3) pnpm${colors.reset}`);
107
+ console.log(` ${colors.dim}4) bun${colors.reset}`);
108
+ let pmChoice = await question(` > `);
109
+ config.packageManager = ['npm', 'yarn', 'pnpm', 'bun'][parseInt(pmChoice) - 1] || 'npm';
110
+
111
+ // 6. Auto install dependencies
112
+ let autoInstall = await question(`\n${colors.cyan}⚡ Install dependencies automatically?${colors.reset} ${colors.dim}(y/n, default: y)${colors.reset}\n > `);
113
+ config.autoInstall = autoInstall.trim().toLowerCase() !== 'n';
114
+
115
+ // Set defaults for non-prompted options
116
+ config.description = `A modern desktop application built with Tauri and React`;
117
+ config.theme = 'system';
118
+ config.initGit = false;
119
+ config.includeDemo = true;
120
+
121
+ rl.close();
122
+
123
+ // Display configuration summary
124
+ console.log(`\n${colors.bright}${colors.magenta}📋 Configuration Summary:${colors.reset}`);
125
+ console.log(`${colors.dim}${'─'.repeat(60)}${colors.reset}`);
126
+ console.log(` Project Name: ${colors.green}${config.projectName}${colors.reset}`);
127
+ console.log(` App Name: ${colors.green}${config.appName}${colors.reset}`);
128
+ console.log(` Author: ${colors.green}${config.author}${colors.reset}`);
129
+ console.log(` Bundle ID: ${colors.green}${config.bundleId}${colors.reset}`);
130
+ console.log(` Package Manager: ${colors.green}${config.packageManager}${colors.reset}`);
131
+ console.log(`${colors.dim}${'─'.repeat(60)}${colors.reset}\n`);
132
+
133
+ // Clone the repository
134
+ console.log(`${colors.blue}📦 Cloning template...${colors.reset}`);
135
+ try {
136
+ execSync(
137
+ `git clone --depth 1 https://github.com/ssanaullahrais/project-wind-tauri-js-starter-kit.git ${config.projectName}`,
138
+ { stdio: 'inherit' }
139
+ );
140
+ } catch (error) {
141
+ console.error(`${colors.yellow}⚠️ Failed to clone repository. Make sure git is installed.${colors.reset}`);
142
+ process.exit(1);
143
+ }
144
+
145
+ const projectPath = path.join(process.cwd(), config.projectName);
146
+
147
+ // Remove .git directory
148
+ console.log(`${colors.blue}🧹 Cleaning up...${colors.reset}`);
149
+ const gitDir = path.join(projectPath, '.git');
150
+ if (fs.existsSync(gitDir)) {
151
+ fs.rmSync(gitDir, { recursive: true, force: true });
152
+ }
153
+
154
+ // Remove cli directory from cloned project
155
+ const cliDir = path.join(projectPath, 'cli');
156
+ if (fs.existsSync(cliDir)) {
157
+ fs.rmSync(cliDir, { recursive: true, force: true });
158
+ }
159
+
160
+ // Remove demo components if not wanted
161
+ if (!config.includeDemo) {
162
+ console.log(`${colors.blue}🗑️ Removing demo components...${colors.reset}`);
163
+ const demoComponentPath = path.join(projectPath, 'src', 'components', 'demo');
164
+ if (fs.existsSync(demoComponentPath)) {
165
+ fs.rmSync(demoComponentPath, { recursive: true, force: true });
166
+ }
167
+ }
168
+
169
+ // Update configuration files
170
+ console.log(`${colors.blue}⚙️ Configuring project...${colors.reset}`);
171
+
172
+ // Update package.json
173
+ const packageJsonPath = path.join(projectPath, 'package.json');
174
+ if (fs.existsSync(packageJsonPath)) {
175
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
176
+ packageJson.name = config.projectName;
177
+ packageJson.description = config.description;
178
+ packageJson.author = config.author;
179
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
180
+ }
181
+
182
+ // Update tauri.conf.json
183
+ const tauriConfPath = path.join(projectPath, 'src-tauri', 'tauri.conf.json');
184
+ if (fs.existsSync(tauriConfPath)) {
185
+ const tauriConf = JSON.parse(fs.readFileSync(tauriConfPath, 'utf8'));
186
+ tauriConf.package.productName = config.appName;
187
+ tauriConf.tauri.windows[0].title = config.appName;
188
+ tauriConf.tauri.bundle.identifier = config.bundleId;
189
+ fs.writeFileSync(tauriConfPath, JSON.stringify(tauriConf, null, 2));
190
+ }
191
+
192
+ // Update index.html
193
+ const indexHtmlPath = path.join(projectPath, 'index.html');
194
+ if (fs.existsSync(indexHtmlPath)) {
195
+ let indexHtml = fs.readFileSync(indexHtmlPath, 'utf8');
196
+ indexHtml = indexHtml.replace(/<title>.*?<\/title>/, `<title>${config.appName}</title>`);
197
+ fs.writeFileSync(indexHtmlPath, indexHtml);
198
+ }
199
+
200
+ // Update TitleBar.tsx
201
+ const titleBarPath = path.join(projectPath, 'src', 'components', 'TitleBar.tsx');
202
+ if (fs.existsSync(titleBarPath)) {
203
+ let titleBar = fs.readFileSync(titleBarPath, 'utf8');
204
+ // Replace all instances of "Project Wind" with the app name
205
+ titleBar = titleBar.replace(/Project Wind/g, config.appName);
206
+ // Update copyright year and author
207
+ const currentYear = new Date().getFullYear();
208
+ titleBar = titleBar.replace(/© \d{4} .*?\. All rights reserved\./, `© ${currentYear} ${config.author}. All rights reserved.`);
209
+ // Update created by
210
+ titleBar = titleBar.replace(/<span className="font-medium">Sunny<\/span>/, `<span className="font-medium">${config.author}</span>`);
211
+ fs.writeFileSync(titleBarPath, titleBar);
212
+ }
213
+
214
+ // Update theme-provider.tsx if theme is not system
215
+ if (config.theme !== 'system') {
216
+ const themeProviderPath = path.join(projectPath, 'src', 'components', 'theme-provider.tsx');
217
+ if (fs.existsSync(themeProviderPath)) {
218
+ let themeProvider = fs.readFileSync(themeProviderPath, 'utf8');
219
+ themeProvider = themeProvider.replace(/defaultTheme="system"/, `defaultTheme="${config.theme}"`);
220
+ fs.writeFileSync(themeProviderPath, themeProvider);
221
+ }
222
+ }
223
+
224
+ // Update DemoComponents.tsx if it exists
225
+ if (config.includeDemo) {
226
+ const demoComponentsPath = path.join(projectPath, 'src', 'components', 'demo', 'DemoComponents.tsx');
227
+ if (fs.existsSync(demoComponentsPath)) {
228
+ let demoComponents = fs.readFileSync(demoComponentsPath, 'utf8');
229
+ demoComponents = demoComponents.replace(/Project Wind/g, config.appName);
230
+ fs.writeFileSync(demoComponentsPath, demoComponents);
231
+ }
232
+ }
233
+
234
+ // Initialize git if requested
235
+ if (config.initGit) {
236
+ console.log(`${colors.blue}🔧 Initializing git repository...${colors.reset}`);
237
+ try {
238
+ execSync('git init', { cwd: projectPath, stdio: 'ignore' });
239
+ execSync('git add .', { cwd: projectPath, stdio: 'ignore' });
240
+ execSync(`git commit -m "Initial commit: ${config.appName}"`, { cwd: projectPath, stdio: 'ignore' });
241
+ } catch (error) {
242
+ console.log(`${colors.yellow}⚠️ Git initialization failed (git may not be installed)${colors.reset}`);
243
+ }
244
+ }
245
+
246
+ // Install dependencies if requested
247
+ if (config.autoInstall) {
248
+ console.log(`\n${colors.blue}📥 Installing dependencies with ${config.packageManager}...${colors.reset}`);
249
+ console.log(`${colors.dim}This may take a few minutes...${colors.reset}\n`);
250
+ try {
251
+ const installCmd = config.packageManager === 'npm' ? 'npm install' :
252
+ config.packageManager === 'yarn' ? 'yarn' :
253
+ config.packageManager === 'pnpm' ? 'pnpm install' :
254
+ 'bun install';
255
+ execSync(installCmd, { cwd: projectPath, stdio: 'inherit' });
256
+ } catch (error) {
257
+ console.log(`${colors.yellow}⚠️ Dependency installation failed. You can install them manually later.${colors.reset}`);
258
+ }
259
+ }
260
+
261
+ // Success message
262
+ console.log(`\n${colors.bright}${colors.green}✅ Project created successfully!${colors.reset}\n`);
263
+ console.log(`${colors.bright}📝 Next steps:${colors.reset}\n`);
264
+ console.log(` ${colors.cyan}cd ${config.projectName}${colors.reset}`);
265
+
266
+ if (!config.autoInstall) {
267
+ console.log(` ${colors.cyan}${config.packageManager} install${colors.reset}`);
268
+ }
269
+
270
+ const devCmd = config.packageManager === 'npm' ? 'npm run tauri dev' :
271
+ config.packageManager === 'yarn' ? 'yarn tauri dev' :
272
+ config.packageManager === 'pnpm' ? 'pnpm tauri dev' :
273
+ 'bun run tauri dev';
274
+ console.log(` ${colors.cyan}${devCmd}${colors.reset}\n`);
275
+
276
+ console.log(`${colors.bright}${colors.magenta}🚀 Happy coding!${colors.reset}\n`);
277
+ }
278
+
279
+ // Run the main function
280
+ main().catch(error => {
281
+ console.error(`${colors.yellow}❌ An error occurred:${colors.reset}`, error.message);
282
+ process.exit(1);
283
+ });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "create-tauri-app-project-wind",
3
+ "version": "2.0.0",
4
+ "description": "Interactive CLI to create a customized Tauri + React + TypeScript desktop application",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "create-tauri-app-project-wind": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "README.md"
12
+ ],
13
+ "keywords": [
14
+ "tauri",
15
+ "react",
16
+ "typescript",
17
+ "shadcn",
18
+ "desktop",
19
+ "starter",
20
+ "template",
21
+ "project-wind",
22
+ "cli",
23
+ "create",
24
+ "scaffolding",
25
+ "boilerplate"
26
+ ],
27
+ "author": "Sunny",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/ssanaullahrais/project-wind-tauri-js-starter-kit.git",
32
+ "directory": "cli"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/ssanaullahrais/project-wind-tauri-js-starter-kit/issues"
36
+ },
37
+ "homepage": "https://github.com/ssanaullahrais/project-wind-tauri-js-starter-kit#readme",
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "preferGlobal": true
45
+ }