feat: Vue 3 Basis mit TailwindCSS, PrimeVue, i18n und Dark/Light Mode

- Vue 3 + Vite Setup
- TailwindCSS mit Dark Mode Support
- PrimeVue 4 mit Aura Theme
- vue-i18n (Deutsch/Englisch)
- Vue Router + Pinia
- Responsive Navbar mit Theme Toggle & Language Switcher
This commit is contained in:
2026-02-10 22:23:30 +00:00
parent 48fd98b0dc
commit 46b6a87505
16 changed files with 389 additions and 2 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
node_modules
dist
.DS_Store
*.local

View File

@@ -1,3 +1,41 @@
# vue3-basis
# Vue3 Basis
Vue 3 Basis mit TailwindCSS, PrimeVUE, i18n und Dark/Light Mode
Eine moderne Vue 3 Starter-Vorlage mit allen wichtigen Features.
## Features
-**Vite** - Blitzschneller Build
- 🎨 **TailwindCSS** - Utility-first CSS
- 🌙 **Dark/Light Mode** - Automatischer Theme-Switch
- 🌍 **i18n** - Deutsch & Englisch
- 💎 **PrimeVue 4** - UI-Komponenten
- 📦 **Pinia** - State Management
- 🛣️ **Vue Router** - SPA Navigation
## Installation
```bash
npm install
npm run dev
```
## Build
```bash
npm run build
```
## Struktur
```
src/
├── components/ # Wiederverwendbare Komponenten
├── views/ # Seiten-Komponenten
├── locales/ # Sprachdateien (de, en)
├── router/ # Vue Router Konfiguration
├── stores/ # Pinia Stores
└── composables/ # Composition API Funktionen
```
---
Erstellt von OpenClaw 🤖

13
index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue3 Basis</title>
<link rel="icon" href="/favicon.ico">
</head>
<body class="antialiased">
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

27
package.json Normal file
View File

@@ -0,0 +1,27 @@
{
"name": "vue3-basis",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.4.0",
"vue-router": "^4.2.0",
"vue-i18n": "^9.9.0",
"pinia": "^2.1.0",
"primevue": "^4.0.0",
"@primevue/themes": "^4.0.0",
"primeicons": "^7.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.0",
"vite": "^5.0.0",
"tailwindcss": "^3.4.0",
"postcss": "^8.4.0",
"autoprefixer": "^10.4.0"
}
}

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

13
src/App.vue Normal file
View File

@@ -0,0 +1,13 @@
<script setup>
import { RouterView } from 'vue-router'
import Navbar from './components/Navbar.vue'
</script>
<template>
<div class="min-h-screen">
<Navbar />
<main class="container mx-auto px-4 py-8">
<RouterView />
</main>
</div>
</template>

77
src/components/Navbar.vue Normal file
View File

@@ -0,0 +1,77 @@
<script setup>
import { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from 'primevue/button'
import Select from 'primevue/select'
const { locale, t } = useI18n()
const isDark = ref(false)
const languages = [
{ code: 'de', name: 'Deutsch' },
{ code: 'en', name: 'English' }
]
onMounted(() => {
isDark.value = document.documentElement.classList.contains('dark') ||
localStorage.getItem('theme') === 'dark' ||
(!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)
updateTheme()
})
function toggleTheme() {
isDark.value = !isDark.value
updateTheme()
}
function updateTheme() {
if (isDark.value) {
document.documentElement.classList.add('dark')
localStorage.setItem('theme', 'dark')
} else {
document.documentElement.classList.remove('dark')
localStorage.setItem('theme', 'light')
}
}
function changeLocale(event) {
locale.value = event.value
localStorage.setItem('locale', event.value)
}
</script>
<template>
<nav class="bg-white dark:bg-gray-800 shadow-md">
<div class="container mx-auto px-4">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<span class="text-xl font-bold text-primary-600 dark:text-primary-400">
Vue3 Basis
</span>
</div>
<div class="flex items-center gap-4">
<!-- Language Switcher -->
<Select
:modelValue="locale"
:options="languages"
optionLabel="name"
optionValue="code"
@update:modelValue="changeLocale"
class="w-32"
/>
<!-- Theme Toggle -->
<Button
:icon="isDark ? 'pi pi-sun' : 'pi pi-moon'"
severity="secondary"
text
rounded
@click="toggleTheme"
:aria-label="t('nav.toggleTheme')"
/>
</div>
</div>
</div>
</nav>
</template>

27
src/locales/de.json Normal file
View File

@@ -0,0 +1,27 @@
{
"nav": {
"toggleTheme": "Theme wechseln"
},
"home": {
"title": "Willkommen bei Vue3 Basis",
"getStarted": "Loslegen",
"features": {
"fast": {
"title": "Blitzschnell",
"desc": "Mit Vite und Vue 3 für optimale Performance gebaut."
},
"themes": {
"title": "Dark & Light Mode",
"desc": "Nahtloser Wechsel zwischen hellem und dunklem Design."
},
"i18n": {
"title": "Mehrsprachig",
"desc": "Vollständige Internationalisierung mit vue-i18n."
}
}
},
"about": {
"title": "Über uns",
"content": "Vue3 Basis ist eine moderne Starter-Vorlage mit TailwindCSS, PrimeVue und i18n."
}
}

27
src/locales/en.json Normal file
View File

@@ -0,0 +1,27 @@
{
"nav": {
"toggleTheme": "Toggle theme"
},
"home": {
"title": "Welcome to Vue3 Basis",
"getStarted": "Get Started",
"features": {
"fast": {
"title": "Lightning Fast",
"desc": "Built with Vite and Vue 3 for optimal performance."
},
"themes": {
"title": "Dark & Light Mode",
"desc": "Seamless switching between light and dark themes."
},
"i18n": {
"title": "Multilingual",
"desc": "Full internationalization support with vue-i18n."
}
}
},
"about": {
"title": "About",
"content": "Vue3 Basis is a modern starter template with TailwindCSS, PrimeVue and i18n."
}
}

34
src/main.js Normal file
View File

@@ -0,0 +1,34 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import PrimeVue from 'primevue/config'
import Aura from '@primevue/themes/aura'
import 'primeicons/primeicons.css'
import './style.css'
import App from './App.vue'
import router from './router'
import de from './locales/de.json'
import en from './locales/en.json'
const i18n = createI18n({
legacy: false,
locale: localStorage.getItem('locale') || 'de',
fallbackLocale: 'en',
messages: { de, en }
})
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(i18n)
app.use(PrimeVue, {
theme: {
preset: Aura,
options: {
darkModeSelector: '.dark'
}
}
})
app.mount('#app')

20
src/router/index.js Normal file
View File

@@ -0,0 +1,20 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]
})
export default router

15
src/style.css Normal file
View File

@@ -0,0 +1,15 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
}
body {
@apply bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100;
min-height: 100vh;
transition: background-color 0.3s, color 0.3s;
}

12
src/views/AboutView.vue Normal file
View File

@@ -0,0 +1,12 @@
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>
<template>
<div class="max-w-2xl mx-auto">
<h1 class="text-3xl font-bold mb-4">{{ t('about.title') }}</h1>
<p class="text-gray-600 dark:text-gray-400">{{ t('about.content') }}</p>
</div>
</template>

51
src/views/HomeView.vue Normal file
View File

@@ -0,0 +1,51 @@
<script setup>
import { useI18n } from 'vue-i18n'
import Card from 'primevue/card'
import Button from 'primevue/button'
const { t } = useI18n()
</script>
<template>
<div class="space-y-8">
<h1 class="text-4xl font-bold text-center">
{{ t('home.title') }}
</h1>
<div class="grid md:grid-cols-3 gap-6">
<Card>
<template #title>
<i class="pi pi-bolt text-primary-500 mr-2"></i>
{{ t('home.features.fast.title') }}
</template>
<template #content>
{{ t('home.features.fast.desc') }}
</template>
</Card>
<Card>
<template #title>
<i class="pi pi-palette text-primary-500 mr-2"></i>
{{ t('home.features.themes.title') }}
</template>
<template #content>
{{ t('home.features.themes.desc') }}
</template>
</Card>
<Card>
<template #title>
<i class="pi pi-globe text-primary-500 mr-2"></i>
{{ t('home.features.i18n.title') }}
</template>
<template #content>
{{ t('home.features.i18n.desc') }}
</template>
</Card>
</div>
<div class="text-center">
<Button :label="t('home.getStarted')" icon="pi pi-arrow-right" iconPos="right" />
</div>
</div>
</template>

12
tailwind.config.js Normal file
View File

@@ -0,0 +1,12 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
darkMode: 'class',
theme: {
extend: {},
},
plugins: [],
}

11
vite.config.js Normal file
View File

@@ -0,0 +1,11 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': '/src'
}
}
})