diff --git a/.gitignore b/.gitignore index 5939e84..e6a51f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,42 +1,30 @@ -# Dependencies -node_modules/ -.pnp/ +# dependencies +node_modules +/node_modules +/.pnp .pnp.js -# Build -.next/ -out/ -build/ -dist/ +# testing +/coverage -# Environment -.env -.env.local -.env.development.local -.env.test.local -.env.production.local +# next.js +/.next/ +/out/ -# Debug +# production +/build + +# misc +.DS_Store +*.pem + +# debug npm-debug.log* yarn-debug.log* -yarn-error.log* +ts-debug.log* -# IDE -.idea/ -.vscode/ -*.swp -*.swo -.DS_Store +# local env files +.env*.local -# TypeScript -*.tsbuildinfo -next-env.d.ts - -# Testing -coverage/ - -# Misc -*.log -*.pid -*.seed -*.pid.lock +# vercel +.vercel diff --git a/README.md b/README.md index 77e96af..397203b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,10 @@ Es ist ein neutraler, stabiler Arbeitscontainer, mit dem KI individuelle Website ``` / ├── app/ # Next.js App Router -├── src/ # Source Code (Komponenten, Utils) +├── components/ # Fundament-Komponenten +│ ├── layout/ # Container, Section +│ └── ui/ # Button, Card +├── src/ # Projekt-spezifischer Code (Utils, Hooks) ├── skills/ # KI-Regeln und Guidelines ├── spec/ # Projektspezifikation & Design Tokens ├── theme/ # CSS Variables & Stylesheets @@ -121,6 +124,14 @@ docker run -p 3000:3000 website --- +## Entwicklungshinweise + +> **Build und Dev dürfen nicht gleichzeitig laufen.** +> Next.js kann CSS-Referenzen verlieren, wenn `npm run build` und `npm run dev` parallel ausgeführt werden. +> Nutze `npm run clean` um den `.next` Cache zu löschen, falls Styling-Probleme auftreten. + +--- + ## Wichtig - Dieses Skeleton erzwingt **kein Design** diff --git a/READ_FIRST.md b/READ_FIRST.md new file mode 100644 index 0000000..86fbddd --- /dev/null +++ b/READ_FIRST.md @@ -0,0 +1,56 @@ +# READ FIRST + +## Pflicht-Lesereihenfolge + +Bevor an diesem Projekt gearbeitet wird, müssen folgende Dateien gelesen und verstanden werden: + +1. `skills/SYSTEM_SKILLS.md` – Grundregeln und Verbote +2. `skills/UI_GUIDELINES.md` – Qualitätsstandards für UI +3. `skills/DEFINITION_OF_DONE.md` – Abnahmekriterien +4. `spec/ProjectSpec.json` – Projektspezifikation +5. `spec/design_tokens.json` – Design-Token-Definitionen +6. `prompts/master_prompt.md` – Workflow-Anleitung + +--- + +## Entwicklungswarnung + +> **Build und Dev dürfen NICHT gleichzeitig laufen.** +> +> Wenn `npm run build` und `npm run dev` parallel ausgeführt werden, verliert Next.js CSS-Referenzen. +> Das führt zu fehlendem Styling und instabilem Hot-Reload. +> +> **Lösung bei Problemen:** +> ```bash +> npm run clean +> ``` +> Dieser Befehl löscht den `.next` Cache und stellt einen sauberen Zustand her. + +--- + +## Inline-Styling ist verboten + +`style={{ ... }}` ist im gesamten Projekt verboten. Alle Styles müssen über: + +- `theme/globals.css` – CSS Variables (`:root`) +- `theme/stylesheet.css` – Typografie & strukturelle Regeln +- `spec/design_tokens.json` – Token-Definitionen + +gesteuert werden. + +--- + +## Architektur-Überblick + +``` +components/ +├── layout/ +│ ├── Container.tsx → Max-Width, horizontales Padding, responsive +│ └── Section.tsx → Vertikaler Rhythmus (Spacing) +└── ui/ + ├── Button.tsx → Varianten: primary / secondary / ghost + └── Card.tsx → Neutraler Wrapper (Radius, Border, Shadow) +``` + +Diese Komponenten verwenden ausschließlich CSS Variables aus `globals.css`. +Sie diktieren KEIN Design – sie erzwingen Struktur. diff --git a/app/page.tsx b/app/page.tsx index 80c7314..5499f9d 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,14 @@ +import { Container } from "@/components/layout/Container"; +import { Section } from "@/components/layout/Section"; + export default function Page() { return (
-

Ready

+
+ +

Ready

+
+
); } diff --git a/components/layout/Container.tsx b/components/layout/Container.tsx new file mode 100644 index 0000000..10e9149 --- /dev/null +++ b/components/layout/Container.tsx @@ -0,0 +1,21 @@ +import type { ElementType, ReactNode } from "react"; + +interface ContainerProps { + children: ReactNode; + className?: string; + as?: ElementType; +} + +export function Container({ + children, + className = "", + as: Tag = "div", +}: ContainerProps) { + return ( + + {children} + + ); +} diff --git a/components/layout/Section.tsx b/components/layout/Section.tsx new file mode 100644 index 0000000..65105a0 --- /dev/null +++ b/components/layout/Section.tsx @@ -0,0 +1,21 @@ +import type { ElementType, ReactNode } from "react"; + +interface SectionProps { + children: ReactNode; + className?: string; + as?: ElementType; +} + +export function Section({ + children, + className = "", + as: Tag = "section", +}: SectionProps) { + return ( + + {children} + + ); +} diff --git a/components/ui/Button.tsx b/components/ui/Button.tsx new file mode 100644 index 0000000..df2b95e --- /dev/null +++ b/components/ui/Button.tsx @@ -0,0 +1,45 @@ +import type { ButtonHTMLAttributes, ReactNode } from "react"; + +type ButtonVariant = "primary" | "secondary" | "ghost"; +type ButtonSize = "sm" | "md" | "lg"; + +interface ButtonProps extends ButtonHTMLAttributes { + children: ReactNode; + variant?: ButtonVariant; + size?: ButtonSize; +} + +const baseClasses = + "inline-flex items-center justify-center font-medium rounded-[var(--radius-md)] transition-all duration-[var(--duration-normal)] ease-[var(--easing-default)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-primary)] disabled:pointer-events-none disabled:opacity-50"; + +const variantClasses: Record = { + primary: + "bg-[var(--color-primary)] text-[color:var(--color-background)] hover:opacity-90", + secondary: + "bg-[var(--color-muted)] text-[color:var(--color-foreground)] border border-[color:var(--color-border)] hover:opacity-80", + ghost: + "bg-transparent text-[color:var(--color-foreground)] hover:bg-[var(--color-muted)]", +}; + +const sizeClasses: Record = { + sm: "px-[var(--spacing-sm)] py-[var(--spacing-xs)] text-[length:var(--font-size-sm)]", + md: "px-[var(--spacing-md)] py-[var(--spacing-sm)] text-[length:var(--font-size-base)]", + lg: "px-[var(--spacing-lg)] py-[var(--spacing-md)] text-[length:var(--font-size-lg)]", +}; + +export function Button({ + children, + variant = "primary", + size = "md", + className = "", + ...props +}: ButtonProps) { + return ( + + ); +} diff --git a/components/ui/Card.tsx b/components/ui/Card.tsx new file mode 100644 index 0000000..c8f64f7 --- /dev/null +++ b/components/ui/Card.tsx @@ -0,0 +1,21 @@ +import type { ElementType, ReactNode } from "react"; + +interface CardProps { + children: ReactNode; + className?: string; + as?: ElementType; +} + +export function Card({ + children, + className = "", + as: Tag = "div", +}: CardProps) { + return ( + + {children} + + ); +} diff --git a/package.json b/package.json index 50dfbf5..d3f5943 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "clean": "rm -rf .next" }, "dependencies": { "next": "^15.1.0", diff --git a/spec/design_tokens.json b/spec/design_tokens.json index 790851b..5430ac2 100644 --- a/spec/design_tokens.json +++ b/spec/design_tokens.json @@ -91,5 +91,15 @@ "modal": 400, "popover": 500, "tooltip": 600 + }, + "letterSpacing": { + "tight": "-0.01em", + "normal": "0em", + "wide": "0.05em" + }, + "layout": { + "containerMaxWidth": "80rem", + "containerPaddingX": "clamp(1rem, 5vw, 2rem)", + "sectionSpacingY": "4rem" } } diff --git a/theme/globals.css b/theme/globals.css index a04ef04..cd19145 100644 --- a/theme/globals.css +++ b/theme/globals.css @@ -43,6 +43,11 @@ --line-height-normal: 1.5; --line-height-relaxed: 1.75; + /* Letter Spacing - Placeholders */ + --letter-spacing-tight: -0.01em; + --letter-spacing-normal: 0em; + --letter-spacing-wide: 0.05em; + /* Spacing - Placeholders */ --spacing-xs: 0.25rem; --spacing-sm: 0.5rem; @@ -79,6 +84,11 @@ --z-modal: 400; --z-popover: 500; --z-tooltip: 600; + + /* Layout - Placeholders */ + --container-max-width: 80rem; + --container-padding-x: clamp(1rem, 5vw, 2rem); + --section-spacing-y: var(--spacing-3xl); } /* diff --git a/theme/stylesheet.css b/theme/stylesheet.css index f8f1c42..bc28019 100644 --- a/theme/stylesheet.css +++ b/theme/stylesheet.css @@ -1,37 +1,148 @@ /* * Stylesheet * - * Project-specific styles go here. + * Typography & structural rules only. + * NO component styles. NO layout sections. * This file is imported by globals.css. * * Structure: - * 1. Component Styles - * 2. Layout Styles - * 3. Page-specific Styles - * 4. Utility Classes - * 5. Animations + * 1. Typography + * 2. Structural Rules + * 3. Utility Classes + * 4. Animations */ /* ========================================================================== - 1. Component Styles + 1. Typography ========================================================================== */ -/* Components are added per project */ +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: var(--font-weight-bold); + line-height: var(--line-height-tight); + letter-spacing: var(--letter-spacing-tight); + margin-top: 0; + margin-bottom: var(--spacing-md); +} + +h1 { + font-size: var(--font-size-4xl); +} + +h2 { + font-size: var(--font-size-3xl); +} + +h3 { + font-size: var(--font-size-2xl); +} + +h4 { + font-size: var(--font-size-xl); +} + +h5 { + font-size: var(--font-size-lg); +} + +h6 { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); +} + +p { + margin-top: 0; + margin-bottom: var(--spacing-md); + line-height: var(--line-height-normal); +} + +small { + font-size: var(--font-size-sm); +} + +strong, +b { + font-weight: var(--font-weight-bold); +} + +/* Prevent orphans and widows in text blocks */ +p, +li, +dd { + orphans: 2; + widows: 2; +} + +/* Lists */ +ul, +ol { + margin-top: 0; + margin-bottom: var(--spacing-md); + padding-left: var(--spacing-lg); +} + +li { + margin-bottom: var(--spacing-xs); +} + +/* Blockquote */ +blockquote { + margin: 0 0 var(--spacing-md); + padding-left: var(--spacing-lg); + border-left: 3px solid var(--color-border); + font-style: italic; +} + +/* Code */ +code { + font-family: var(--font-mono); + font-size: var(--font-size-sm); +} + +pre { + margin-top: 0; + margin-bottom: var(--spacing-md); + overflow-x: auto; +} + +pre code { + font-size: var(--font-size-sm); +} /* ========================================================================== - 2. Layout Styles + 2. Structural Rules ========================================================================== */ -/* Layout styles are added per project */ +/* Focus styles for keyboard navigation */ +:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +/* Selection */ +::selection { + background-color: var(--color-primary); + color: var(--color-background); +} + +/* Reduced motion */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} /* ========================================================================== - 3. Page-specific Styles - ========================================================================== */ - -/* Page styles are added per project */ - -/* ========================================================================== - 4. Utility Classes + 3. Utility Classes ========================================================================== */ .visually-hidden { @@ -47,7 +158,7 @@ } /* ========================================================================== - 5. Animations + 4. Animations ========================================================================== */ /* Animations are added per project */