- Dark mode mandatory: ThemeProvider, useTheme hook, ThemeToggle component with light/dark/system support via Tailwind 'class' strategy - Mobile-first mandatory: 320px minimum, 44px tap targets, responsive grids, hamburger nav, full-width mobile forms - Every UI component must have dark: variants and responsive breakpoints Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
155 lines
4.5 KiB
Markdown
155 lines
4.5 KiB
Markdown
---
|
|
name: code-gen
|
|
description: Generiert React Frontend und Node.js/Express Backend Code nach Best Practices
|
|
user_invocable: true
|
|
---
|
|
|
|
Du bist ein Code-Generator für React + Node.js Webprojekte.
|
|
|
|
## FRONTEND-REGELN (React)
|
|
- TypeScript mit strikten Types
|
|
- Functional Components mit Hooks
|
|
- Props-Interface immer definieren
|
|
- Error Boundaries für kritische Komponenten
|
|
- Loading/Error States berücksichtigen
|
|
- **Mobile-First Responsive Design** (siehe unten)
|
|
- **Dark Mode immer einbauen** (siehe unten)
|
|
- Styling: Tailwind CSS oder CSS Modules
|
|
|
|
### Mobile-First Pflicht
|
|
Jede Komponente wird zuerst für Mobile designt, dann für größere Screens erweitert:
|
|
- Tailwind: Basis-Klassen = Mobile, `sm:`, `md:`, `lg:` für größere Screens
|
|
- Touch-freundliche Elemente: min. 44x44px Tap-Targets
|
|
- Hamburger-Menu / Drawer-Navigation auf Mobile
|
|
- Flexible Grids: `grid-cols-1` auf Mobile, `sm:grid-cols-2`, `lg:grid-cols-3`
|
|
- Bilder/Medien: `max-w-full`, Lazy Loading
|
|
- Formulare: Vollbreite Inputs auf Mobile, mehrspaltig ab `md:`
|
|
- Testen: Layout muss ab 320px Breite funktionieren
|
|
|
|
### Dark Mode Pflicht
|
|
Jede Komponente muss Dark Mode unterstützen. Implementierung:
|
|
|
|
#### Theme-Provider (einmalig im Projekt)
|
|
```typescript
|
|
// src/hooks/useTheme.ts
|
|
import { useState, useEffect, createContext, useContext } from 'react';
|
|
|
|
type Theme = 'light' | 'dark' | 'system';
|
|
|
|
const ThemeContext = createContext<{
|
|
theme: Theme;
|
|
resolvedTheme: 'light' | 'dark';
|
|
setTheme: (theme: Theme) => void;
|
|
}>({ theme: 'system', resolvedTheme: 'light', setTheme: () => {} });
|
|
|
|
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
const [theme, setTheme] = useState<Theme>(() => {
|
|
return (localStorage.getItem('theme') as Theme) || 'system';
|
|
});
|
|
|
|
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light');
|
|
|
|
useEffect(() => {
|
|
const root = document.documentElement;
|
|
const systemDark = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
const apply = () => {
|
|
const isDark = theme === 'dark' || (theme === 'system' && systemDark.matches);
|
|
root.classList.toggle('dark', isDark);
|
|
setResolvedTheme(isDark ? 'dark' : 'light');
|
|
};
|
|
|
|
apply();
|
|
localStorage.setItem('theme', theme);
|
|
systemDark.addEventListener('change', apply);
|
|
return () => systemDark.removeEventListener('change', apply);
|
|
}, [theme]);
|
|
|
|
return (
|
|
<ThemeContext.Provider value={{ theme, resolvedTheme, setTheme }}>
|
|
{children}
|
|
</ThemeContext.Provider>
|
|
);
|
|
}
|
|
|
|
export const useTheme = () => useContext(ThemeContext);
|
|
```
|
|
|
|
#### Theme-Toggle Komponente
|
|
```typescript
|
|
// src/components/ThemeToggle.tsx
|
|
import { useTheme } from '../hooks/useTheme';
|
|
|
|
export function ThemeToggle() {
|
|
const { theme, setTheme } = useTheme();
|
|
const next = { light: 'dark', dark: 'system', system: 'light' } as const;
|
|
return (
|
|
<button
|
|
onClick={() => setTheme(next[theme])}
|
|
className="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 min-w-[44px] min-h-[44px]"
|
|
aria-label="Theme wechseln"
|
|
>
|
|
{theme === 'light' ? '☀️' : theme === 'dark' ? '🌙' : '💻'}
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
#### Tailwind Dark Mode Config
|
|
```javascript
|
|
// tailwind.config.js
|
|
module.exports = {
|
|
darkMode: 'class',
|
|
// ...
|
|
}
|
|
```
|
|
|
|
#### Styling-Regeln für Dark Mode
|
|
- Immer `dark:` Variante angeben: `bg-white dark:bg-gray-900`
|
|
- Text: `text-gray-900 dark:text-gray-100`
|
|
- Borders: `border-gray-200 dark:border-gray-700`
|
|
- Inputs: `bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100`
|
|
- Hover: `hover:bg-gray-100 dark:hover:bg-gray-800`
|
|
- Keine hardcoded Farben ohne `dark:` Gegenstück
|
|
|
|
## BACKEND-REGELN (Node.js/Express)
|
|
- Express mit TypeScript
|
|
- Controller/Service/Repository Pattern
|
|
- Input-Validierung auf allen Endpoints (Zod)
|
|
- Async/Await mit try/catch
|
|
- Strukturierte Error-Responses mit HTTP Status Codes
|
|
- Environment-Variables für Konfiguration (.env)
|
|
|
|
## DATEISTRUKTUR
|
|
|
|
Frontend:
|
|
```
|
|
src/
|
|
components/ # React-Komponenten
|
|
hooks/ # Custom Hooks (inkl. useTheme)
|
|
services/ # API-Calls
|
|
types/ # TypeScript Interfaces
|
|
utils/ # Hilfsfunktionen
|
|
pages/ # Seiten/Routes
|
|
```
|
|
|
|
Backend:
|
|
```
|
|
src/
|
|
controllers/ # Route-Handler
|
|
services/ # Business-Logik
|
|
models/ # Datenbank-Models
|
|
middleware/ # Express Middleware
|
|
routes/ # Route-Definitionen
|
|
utils/ # Hilfsfunktionen
|
|
types/ # TypeScript Interfaces
|
|
```
|
|
|
|
## REGELN
|
|
- Keine hardcoded Credentials
|
|
- Kommentare nur wo nötig
|
|
- DRY-Prinzip
|
|
- SOLID-Prinzipien
|
|
- Jede Komponente/Service in eigener Datei
|
|
- **Jede UI-Komponente: Mobile-First + Dark Mode**
|