Appearance
Kapitel 12: Praxisprojekt - Unternehmenswebsite
In diesem Kapitel bauen wir eine professionelle Unternehmenswebsite mit Nuxt 3.
12.1 Projektarchitektur designen
Funktionen:
- ✅ Responsive Design (Mobile-First)
- ✅ SEO-optimiert (SSR)
- ✅ Kontaktformular
- ✅ Animieren (Scroll-Animationen)
- ✅ Performance-optimiert (Lazy Loading)
Verzeichnisstruktur:
meine-firma/
├── components/
│ ├── AppHeader.vue
│ ├── AppFooter.vue
│ ├── HeroSection.vue
│ ├── ServicesSection.vue
│ ├── PortfolioSection.vue
│ └── ContactForm.vue
├── pages/
│ ├── index.vue → Startseite
│ ├── about.vue → Über uns
│ ├── services.vue → Leistungen
│ ├── portfolio.vue → Referenzen
│ └── contact.vue → Kontakt
├── public/
│ ├── images/
│ │ ├── hero-bg.jpg
│ │ ├── logo.png
│ │ └── ...
│ └── favicon.ico
├── assets/
│ └── scss/
│ ├── main.scss
│ └── _variables.scss
├── layouts/
│ └── default.vue
├── app.vue
├── nuxt.config.ts
└── package.json12.2 Layout erstellen (layouts/default.vue)
vue
<template>
<div class="default-layout">
<!-- Header -->
<AppHeader />
<!-- Hauptinhalt -->
<main>
<slot />
</main>
<!-- Footer -->
<AppFooter />
</div>
</template>
<script setup>
// Keine Imports nötig (Auto-Import!)
</script>
<style scoped>
.default-layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
</style>12.3 Header-Komponente (components/AppHeader.vue)
vue
<script setup>
const isMenuOpen = ref(false)
const navigation = [
{ name: 'Startseite', to: '/' },
{ name: 'Über uns', to: '/about' },
{ name: 'Leistungen', to: '/services' },
{ name: 'Portfolio', to: '/portfolio' },
{ name: 'Kontakt', to: '/contact' }
]
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value
}
</script>
<template>
<header class="app-header">
<div class="header-container">
<!-- Logo -->
<NuxtLink to="/" class="logo">
<img src="/images/logo.png" alt="Firmenlogo" />
<span>Meine Firma</span>
</NuxtLink>
<!-- Desktop-Navigation -->
<nav class="desktop-nav">
<NuxtLink
v-for="item in navigation"
:key="item.to"
:to="item.to"
class="nav-link"
>
{{ item.name }}
</NuxtLink>
</nav>
<!-- Mobile Menu Button -->
<button class="mobile-menu-btn" @click="toggleMenu">
<span></span>
<span></span>
<span></span>
</button>
</div>
<!-- Mobile Navigation -->
<nav v-if="isMenuOpen" class="mobile-nav">
<NuxtLink
v-for="item in navigation"
:key="item.to"
:to="item.to"
class="nav-link"
@click="isMenuOpen = false"
>
{{ item.name }}
</NuxtLink>
</nav>
</header>
</template>
<style scoped>
.app-header {
background: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
height: 70px;
}
.logo {
display: flex;
align-items: center;
gap: 10px;
text-decoration: none;
color: #333;
font-weight: bold;
font-size: 1.2em;
}
.logo img {
height: 40px;
}
.desktop-nav {
display: flex;
gap: 30px;
}
.nav-link {
text-decoration: none;
color: #333;
font-weight: 500;
transition: color 0.3s;
}
.nav-link:hover {
color: #00dc82;
}
.mobile-menu-btn {
display: none;
flex-direction: column;
gap: 5px;
background: none;
border: none;
cursor: pointer;
}
.mobile-menu-btn span {
width: 25px;
height: 3px;
background: #333;
}
.mobile-nav {
display: none;
flex-direction: column;
padding: 20px;
gap: 15px;
}
@media (max-width: 768px) {
.desktop-nav {
display: none;
}
.mobile-menu-btn {
display: flex;
}
.mobile-nav {
display: flex;
}
}
</style>12.4 Hero-Sektion (components/HeroSection.vue)
vue
<template>
<section class="hero-section">
<div class="hero-container">
<div class="hero-content">
<h1 class="hero-title">
Willkommen bei <span class="highlight">Meine Firma</span>
</h1>
<p class="hero-subtitle">
Wir bieten erstklassige Webentwicklungsdienstleistungen
</p>
<div class="hero-buttons">
<NuxtLink to="/services" class="btn-primary">
Unsere Leistungen
</NuxtLink>
<NuxtLink to="/contact" class="btn-secondary">
Kontakt aufnehmen
</NuxtLink>
</div>
</div>
<div class="hero-image">
<img src="/images/hero-bg.jpg" alt="Hero Bild" />
</div>
</div>
</section>
</template>
<style scoped>
.hero-section {
background: linear-gradient(135deg, #00dc82, #007aff);
color: white;
padding: 100px 20px;
}
.hero-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 50px;
}
.hero-content {
flex: 1;
}
.hero-title {
font-size: 3em;
margin-bottom: 20px;
line-height: 1.2;
}
.highlight {
color: #ffd700;
}
.hero-subtitle {
font-size: 1.2em;
margin-bottom: 30px;
opacity: 0.9;
}
.hero-buttons {
display: flex;
gap: 20px;
}
.btn-primary {
background: white;
color: #00dc82;
padding: 12px 30px;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
transition: transform 0.3s;
}
.btn-primary:hover {
transform: translateY(-2px);
}
.btn-secondary {
background: transparent;
color: white;
padding: 12px 30px;
border: 2px solid white;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
transition: all 0.3s;
}
.btn-secondary:hover {
background: white;
color: #00dc82;
}
.hero-image {
flex: 1;
text-align: center;
}
.hero-image img {
max-width: 100%;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
@media (max-width: 768px) {
.hero-container {
flex-direction: column;
text-align: center;
}
.hero-title {
font-size: 2em;
}
.hero-buttons {
justify-content: center;
}
}
</style>12.5 Startseite (pages/index.vue)
vue
<script setup>
// SEO-Konfiguration
useSeoMeta({
title: 'Startseite',
description: 'Willkommen bei Meine Firma - Ihr Partner für Webentwicklung',
ogTitle: 'Meine Firma - Webentwicklung',
ogDescription: 'Professionelle Webentwicklungsdienstleistungen',
ogImage: 'https://meine-firma.de/images/og-image.jpg'
})
</script>
<template>
<div class="home-page">
<!-- Hero-Sektion -->
<HeroSection />
<!-- Leistungen -->
<ServicesSection />
<!-- Portfolio -->
<PortfolioSection />
<!-- Kontakt CTA -->
<section class="cta-section">
<div class="cta-container">
<h2>Bereit für Ihr nächstes Projekt?</h2>
<p>Kontaktieren Sie uns noch heute!</p>
<NuxtLink to="/contact" class="cta-button">
Jetzt anfragen
</NuxtLink>
</div>
</section>
</div>
</template>
<style scoped>
.cta-section {
background: #f5f5f5;
padding: 80px 20px;
text-align: center;
}
.cta-container {
max-width: 800px;
margin: 0 auto;
}
.cta-container h2 {
font-size: 2.5em;
margin-bottom: 20px;
color: #333;
}
.cta-container p {
font-size: 1.2em;
margin-bottom: 30px;
color: #666;
}
.cta-button {
display: inline-block;
background: #00dc82;
color: white;
padding: 15px 40px;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
font-size: 1.1em;
transition: all 0.3s;
}
.cta-button:hover {
background: #00c476;
transform: translateY(-2px);
}
</style>12.6 SEO-Optimierung
Globale Meta-Konfiguration (app.vue):
vue
<script setup>
useHead({
titleTemplate: '%s - Meine Firma',
meta: [
{ name: 'description', content: 'Professionelle Webentwicklungsdienstleistungen' },
{ name: 'keywords', content: 'Webentwicklung, Vue.js, Nuxt 3, SEO' },
{ property: 'og:type', content: 'website' },
{ property: 'og:site_name', content: 'Meine Firma' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'canonical', href: 'https://meine-firma.de' }
],
script: [
{
type: 'application/ld+json',
children: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Meine Firma',
url: 'https://meine-firma.de',
logo: 'https://meine-firma.de/images/logo.png'
})
}
]
})
</script>
<template>
<NuxtPage />
</template>12.7 Performance-Optimierung
Bild-Optimierung mit <NuxtImg>:
bash
# Modul installieren
pnpm add @nuxt/imageIn nuxt.config.ts:
typescript
export default defineNuxtConfig({
modules: [
'@nuxt/image'
],
image: {
screens: {
sm: 640,
md: 768,
lg: 1024
}
}
})Verwendung:
vue
<template>
<NuxtImg
src="/images/hero.jpg"
alt="Hero Bild"
format="webp"
quality="80"
loading="lazy"
sizes="sm:100px md:500px lg:1000px"
/>
</template>12.8 Zusammenfassung
In diesem Kapitel haben Sie gelernt:
- ✅ Eine Unternehmenswebsite mit Nuxt 3 zu bauen
- ✅ Layouts & Komponenten zu strukturieren
- ✅ Responsive Header & Hero-Sektion zu erstellen
- ✅ SEO mit
useSeoMeta()zu optimieren - ✅ Performance-Optimierung (Bild-Optimierung)
Nächste Schritte: Im nächsten Kapitel lernen wir erweiterte Konfiguration & Optimierung für Nuxt 3.
📚 Weiterführende Ressourcen
Nächstes Kapitel: Kapitel 13: Erweiterte Konfiguration & Optimierung →
