Compare commits

...
10 Commits
Author SHA1 Message Date
libretech 3c938b4b1c rebrand: hdm slides → uni slides (dhbw + hdm), make-targets mit hdm-/dhbw- prefix, dhbw_deploy_path typo fix 2026-05-04 20:05:50 +02:00
libretech 841a7ced76 dhbw: neuer kurs technik I — 4 kapitel + demo assets 2026-05-04 20:05:46 +02:00
libretech 5c419c9ed1 gendering: fehlende person-substantive in beiden kursen
- Nutzer/User -> Nutzende
- Endnutzer -> Endnutzende
- Teilnehmer -> Teilnehmende
- Programmierer/Entwickler -> Programmierende/Entwickelnde
- Web-Entwickler -> Web-Entwickelnde
- Tastatur-Nutzer -> Tastatur-Nutzende
- Benutzer -> Nutzende
- Konsumenten -> KonsumentInnen
- Künstler -> KünstlerInnen
- Autor -> AutorIn
- Fotografen -> FotografInnen
- Kunde -> KundIn

ausgenommen: code-identifiers (User, type User, /users/),
Sender/Empfänger (network protocol), Sawyer (konkrete person),
Hersteller/Betreiber (organisations-rolle).
2026-04-27 17:27:19 +02:00
libretech a955a7636a selbstlernen hex links: absolute urls fuer PDF-klick
PDF rendert relative pfade als nicht-klickbar. absolute https-urls
zu librete.ch/hdm/223015b/materials/hex1-5 funktionieren beide
in HTML- und PDF-export.
2026-04-27 16:29:09 +02:00
libretech c978842812 c01 Web-Zugänglichkeit Vertiefung: keine klausur, kein bg
- _class: 'erklaerung klausur' -> _class: erklaerung
- _backgroundColor: #fce4ec entfernt

ist nur eine vertiefung, keine klausur-folie.
2026-04-27 16:10:01 +02:00
libretech 61468d2d3a erklaerung: bg entfernen — soll vertiefung sein, nicht klausur
bug: 'section.erklaerung' hatte '@media print { background }' rule (alle 5
files), was im PDF rosa/blau-klausur-bg setzte. HTML hatte (in c) keinen
bg oder (in b) gradient bg. ergebnis: HTML zeigt erklaerung anders als PDF
— PDF sah aus wie klausurfolie obwohl es nur eine vertiefung ist.

fix: erklaerung behaelt nur 'font-size: 1.1rem' + h1 color/size + table
font-size. KEIN background mehr — weder screen noch print. visuell
unterschieden durch h1-color und font-size, nicht durch bg-farbe.

betroffen: b01, b02, b03, c01, c02 (alle files mit section.erklaerung).
2026-04-27 15:04:45 +02:00
libretech a3c3e259b4 b01: kaputte html-comments fixen (_class directive nicht im comment-prefix)
L603/L850: '<!-- _class: erklaerung' ohne '-->' und ' _class:' ohne '<!--'
in proper '<!--\n_class:\n-->' form gebracht. inhalt bleibt versteckt
wie vorher beabsichtigt, syntax aber jetzt sauber.
2026-04-27 01:26:31 +02:00
libretech ac39f2b746 klausurfragen pdf fix: pre blocks waren schwarz auf schwarz
bug: 'pre code { color: inherit }' fiel auf section --color-foreground (#1a1a2e)
zurueck weil 'pre' selbst keine 'color' hatte. multi-line code-bloecke
unsichtbar (nur hljs-syntax-spans hatten farbe, rest = dark on dark).

fix: 'pre { color: #f8f8f8 }' setzen + inline 'code' und hljs/non-hljs
selectoren analog zu chapter-styles ergaenzt.

verified: c klausurfragen page 60 (G2 mobile-first CSS pre-block) jetzt
voll lesbar.
2026-04-27 00:53:48 +02:00
libretech 19ca5ad3e0 223015b selbstlernen hex files: 5 statt 3 dateien, link wtf->hex, pfad ./materials
- referenzen wtf1/2/3 -> hex1/2/3 (dateinamen tatsächlich)
- hex4 (DOCX) und hex5 (ZIP) ergänzt — alle 5 vorhandenen materialien sichtbar
- pfad ../materials -> ./materials (build/223015b/materials struktur)
2026-04-26 22:05:48 +02:00
libretech aea96edd09 bit/byte/hex folien sync beide kurse + neue viz embeds
223015c (internettechnik):
- byte-aufbau ausgebaut (build-up tabelle 0..127..255 wie b)
- neue slides: why-8-bit, byte-flow, three-views nach byte-nibble-hex/hex-dec-table

223015b (dateiformate):
- byte-nibble-hex slide eingebaut
- neue slides: why-8-bit (vor hex-lead), hex-dec-table, byte-flow, three-views
- wo-begegnet-hex tabelle (CSS, MAC, fehlercodes, speicher, unicode)
- bit-vs-byte verwirrung (Mbit/s vs MB/s)

konvention: 'Byte' und 'Bit' invariant, kein plural-s
2026-04-26 22:05:32 +02:00
31 changed files with 2427 additions and 235 deletions

No files matched your search

+18 -14
View File
@@ -1,11 +1,12 @@
# CLAUDE.md - Agent Guidelines for HdM Slides
# CLAUDE.md - Agent Guidelines for Uni Slides (DHBW + HdM)
This project builds presentation decks for Marp, supporting multiple courses.
## Courses
- **223015b** - Dateiformate, Schnittstellen, Speichermedien (6 Kapitel)
- **223015c** - Internettechnologien (3 Kapitel)
- **223015b** - Dateiformate, Schnittstellen, Speichermedien (HdM, 6 Kapitel)
- **223015c** - Internettechnologien (HdM, 3 Kapitel)
- **dhbw** - Technik I – Grundlagen IT (DHBW, 4 Kapitel)
## Agent Restrictions
@@ -25,8 +26,9 @@ Slide files in `slides/*/*.md` are main content files:
```
slides/
├── 223015b/ # Dateiformate course
└── 223015c/ # Internettechnik course
├── 223015b/ # HdM: Dateiformate
├── 223015c/ # HdM: Internettechnik
└── dhbw/ # DHBW: Technik I
scripts/ # Shared scripts
themes/ # Custom Marp themes
build/ # Generated output (gitignored)
@@ -35,15 +37,17 @@ build/ # Generated output (gitignored)
## Build Commands
```bash
make dev # Marp live server all courses (port 1312, HMR)
make dev-b # Marp live server 223015b (port 1313, HMR)
make dev-c # Marp live server 223015c (port 1314, HMR)
make build # Build all courses
make build-b # Build 223015b only
make build-c # Build 223015c only
make html # HTML only
make pdf # PDF only
make klausur # Extract klausur slides → slides/*/klausur.md
make hdm-dev # HdM live server all (port 1312)
make hdm-dev-b # HdM 223015b only (port 1313)
make hdm-dev-c # HdM 223015c only (port 1314)
make dhbw-dev # DHBW live server (port 1315)
make hdm-build # Build all HdM courses
make dhbw-build # Build DHBW course
make hdm-html # HTML only (HdM)
make hdm-pdf # PDF only (HdM)
make hdm-klausur # Extract klausur slides → slides/*/klausurfolien.md
make hdm-deploy # Deploy HdM (ASK FIRST!)
make dhbw-deploy # Deploy DHBW (ASK FIRST!)
make deploy # Deploy all (ASK FIRST!)
```
+139 -75
View File
@@ -1,70 +1,93 @@
# HdM Slides - Unified Makefile
# Supports multiple courses: 223015b (Dateiformate) and 223015c (Internettechnik)
# Uni Slides - Unified Makefile
# DHBW + HdM courses
.PHONY: help dev dev-b dev-c build build-b build-c pdf html klausur clean install deploy qr optimize-images
.PHONY: help dev hdm-dev hdm-dev-b hdm-dev-c dhbw-dev \
build hdm-build hdm-build-b hdm-build-c dhbw-build \
html hdm-html hdm-html-b hdm-html-c \
pdf hdm-pdf hdm-pdf-b hdm-pdf-c \
klausur hdm-klausur hdm-klausur-b hdm-klausur-c \
qr qr-slides optimize-images clean install deploy deploy-index
# Course configuration
COURSES = 223015b 223015c
COURSE_HDM = 223015b 223015c
COURSE_DHBW = dhbw
SLIDES_DIR = slides
# Course-specific settings
# HdM course settings
223015b_NAME = Dateiformate, Schnittstellen, Speichermedien
223015b_KAPITEL = 00-intro 01-grundlagen-text-audio 02-bild-audio-video 03-speichermedien-schnittstellen 04-distribution-apis-zukunft 05-vertiefung-offene-fragen klausurfolien klausurfragen
223015b_DEPLOY_PATH = /home/tengo/html/hdm/223015b
223015c_NAME = Internettechnologien
223015c_KAPITEL = 01-geschichte-grundlagen-html 02-netzwerke-protokolle-css 03-interaktivitaet-javascript klausurfolien klausurfragen
223015c_DEPLOY_PATH = /home/tengo/html/hdm/223015c
# DHBW course settings
dhbw_NAME = Technik I – Grundlagen IT
dhbw_KAPITEL = 01_web_eng 02_css_extended 03_nodejs_basics 04_nodejs_advanced
# Deploy paths
HDM_DEPLOY_PATH = /home/tengo/html/hdm
DHBW_DEPLOY_PATH = /home/tengo/html/dhbw
DEPLOY_HOST = tengo@tuttle.uberspace.de
# Default target
help:
@echo "HdM Slides - Unified Build System"
@echo "Uni Slides - DHBW + HdM Build System"
@echo ""
@echo "Courses:"
@echo "HdM Courses:"
@echo " 223015b - Dateiformate, Schnittstellen, Speichermedien"
@echo " 223015c - Internettechnologien"
@echo ""
@echo "Development:"
@echo " make dev - Marp live server all courses (port 1312, HMR)"
@echo " make dev-b - Marp live server 223015b (port 1313, HMR)"
@echo " make dev-c - Marp live server 223015c (port 1314, HMR)"
@echo "DHBW Courses:"
@echo " dhbw - Technik I – Grundlagen IT"
@echo ""
@echo "Build:"
@echo " make build - Build all courses"
@echo " make build-b - Build 223015b only"
@echo " make build-c - Build 223015c only"
@echo " make pdf - Export all to PDF"
@echo " make html - Export all to HTML"
@echo " make klausur - Extract klausurfolien slides"
@echo "Development:"
@echo " make hdm-dev - Live server all HdM courses (port 1312, HMR)"
@echo " make hdm-dev-b - 223015b only (port 1313, HMR)"
@echo " make hdm-dev-c - 223015c only (port 1314, HMR)"
@echo " make dhbw-dev - DHBW live server (port 1315, HMR)"
@echo ""
@echo "Build (HdM):"
@echo " make hdm-build - Build all HdM courses"
@echo " make hdm-build-b - Build 223015b only"
@echo " make hdm-build-c - Build 223015c only"
@echo " make hdm-html - HTML only all HdM"
@echo " make hdm-pdf - PDF only all HdM"
@echo ""
@echo "Build (DHBW):"
@echo " make dhbw-build - Build DHBW course"
@echo ""
@echo "Klausur (HdM):"
@echo " make hdm-klausur - Extract klausurfolien all HdM"
@echo " make hdm-klausur-b - 223015b only"
@echo " make hdm-klausur-c - 223015c only"
@echo ""
@echo "Tools:"
@echo " make qr URL=... - Generate QR code for URL"
@echo " make qr URL=... - Generate QR code"
@echo " make qr-slides COURSE=223015b - QR for course URL"
@echo " make optimize-images COURSE=223015b - Resize images"
@echo ""
@echo "Deploy:"
@echo " make deploy - Deploy all courses"
@echo " make deploy-b - Deploy 223015b only"
@echo " make deploy-c - Deploy 223015c only"
@echo " make hdm-deploy - Deploy all HdM courses"
@echo " make dhbw-deploy - Deploy DHBW course"
@echo ""
@echo "Other:"
@echo " make clean - Remove generated files"
@echo " make install - Install dependencies"
# Ensure build directories exist
build/.exists:
@mkdir -p build/223015b build/223015c
@mkdir -p build/223015b build/223015c build/dhbw
@touch $@
# Development server (Marp live server with HMR)
dev:
# Development servers (HdM)
hdm-dev:
@./scripts/dev-server.sh
dev-b:
hdm-dev-b:
@./scripts/dev-server.sh 223015b 1313
dev-c:
hdm-dev-c:
@./scripts/dev-server.sh 223015c 1314
dev-kill:
@@ -72,8 +95,12 @@ dev-kill:
@-fuser -k 1313/tcp 2>/dev/null || true
@-fuser -k 1314/tcp 2>/dev/null || true
# Build functions
define build_course
# DHBW dev (using HdM dev-server for now)
dhbw-dev:
@./scripts/dev-server.sh dhbw 1315
# HdM build functions
define hdm_build_course
@echo "Building $(1)..."
@mkdir -p build/$(1)
@cp -r $(SLIDES_DIR)/$(1)/assets build/$(1)/ 2>/dev/null || true
@@ -88,17 +115,35 @@ define build_course
@./scripts/generate-index.sh $(1) build/$(1)
endef
build-b: build/.exists
$(call build_course,223015b)
hdm-build-b: build/.exists
$(call hdm_build_course,223015b)
build-c: build/.exists
$(call build_course,223015c)
hdm-build-c: build/.exists
$(call hdm_build_course,223015c)
build: build-b build-c
@echo "All courses built!"
hdm-build: hdm-build-b hdm-build-c
@echo "All HdM courses built!"
# HTML only builds
define html_course
# DHBW build function
define dhbw_build_course
@echo "Building $(1)..."
@mkdir -p build/$(1)
@cp -r $(SLIDES_DIR)/$(1)/assets build/$(1)/ 2>/dev/null || true
@for f in $($(1)_KAPITEL); do \
if [ -f "$(SLIDES_DIR)/$(1)/$$f.md" ]; then \
echo " Building $$f..."; \
npx @marp-team/marp-cli $(SLIDES_DIR)/$(1)/$$f.md -o build/$(1)/$$f.html; \
npx @marp-team/marp-cli $(SLIDES_DIR)/$(1)/$$f.md --pdf --allow-local-files -o build/$(1)/$$f.pdf; \
fi \
done
@./scripts/generate-index.sh $(1) build/$(1)
endef
dhbw-build: build/.exists
$(call dhbw_build_course,dhbw)
# HdM HTML only
define hdm_html_course
@echo "Building HTML for $(1)..."
@mkdir -p build/$(1)
@cp -r $(SLIDES_DIR)/$(1)/assets build/$(1)/ 2>/dev/null || true
@@ -112,16 +157,16 @@ define html_course
@./scripts/generate-index.sh $(1) build/$(1)
endef
html-b: build/.exists
$(call html_course,223015b)
hdm-html-b: build/.exists
$(call hdm_html_course,223015b)
html-c: build/.exists
$(call html_course,223015c)
hdm-html-c: build/.exists
$(call hdm_html_course,223015c)
html: html-b html-c
hdm-html: hdm-html-b hdm-html-c
# PDF only builds
define pdf_course
# HdM PDF only
define hdm_pdf_course
@echo "Building PDFs for $(1)..."
@mkdir -p build/$(1)
@for f in $($(1)_KAPITEL); do \
@@ -132,25 +177,32 @@ define pdf_course
done
endef
pdf-b: build/.exists
$(call pdf_course,223015b)
hdm-pdf-b: build/.exists
$(call hdm_pdf_course,223015b)
pdf-c: build/.exists
$(call pdf_course,223015c)
hdm-pdf-c: build/.exists
$(call hdm_pdf_course,223015c)
pdf: pdf-b pdf-c
hdm-pdf: hdm-pdf-b hdm-pdf-c
# Klausur slide extraction
klausur-b:
# Legacy aliases (no prefix)
build: hdm-build
html: hdm-html
pdf: hdm-pdf
# Klausur extraction (HdM)
hdm-klausur-b:
@./scripts/extract-klausur.sh 223015b
klausur-c:
hdm-klausur-c:
@./scripts/extract-klausur.sh 223015c
klausur: klausur-b klausur-c
@echo "Klausurfolien slides extracted for all courses!"
hdm-klausur: hdm-klausur-b hdm-klausur-c
@echo "Klausurfolien slides extracted for all HdM courses!"
# QR Code generation (uses nix-shell)
klausur: hdm-klausur
# QR Code generation
qr:
ifndef URL
@echo "Usage: make qr URL=https://example.com"
@@ -160,7 +212,6 @@ else
@echo "Generated: $(or $(OUTPUT),qr-code.png)"
endif
# QR code for a slide deck URL
qr-slides:
ifndef COURSE
@echo "Usage: make qr-slides COURSE=223015b"
@@ -183,38 +234,51 @@ else
@echo "Done! Originals in assets-original/"
endif
# Root index for /hdm/
HDM_DEPLOY_PATH = /home/tengo/html/hdm
# Root index
build-index: build/.exists
@echo "Building root index..."
@mkdir -p build
@./scripts/generate-root-index.sh
# Deploy
define deploy_course
# Deploy (HdM)
define hdm_deploy_course
@echo "Deploying $(1)..."
scp build/$(1)/*.html $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/
scp build/$(1)/*.pdf $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/ 2>/dev/null || true
scp build/$(1)/*.svg $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/ 2>/dev/null || true
scp -r build/$(1)/assets/ $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/
scp -r build/$(1)/materials/ $(DEPLOY_HOST):$($(1)_DEPLOY_PATH)/ 2>/dev/null || true
scp build/$(1)/*.html $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/$(1)/
scp build/$(1)/*.pdf $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
scp build/$(1)/*.svg $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
scp -r build/$(1)/assets/ $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
scp -r build/$(1)/materials/ $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
@echo "$(1) deployed!"
endef
deploy-b: build-b
$(call deploy_course,223015b)
hdm-deploy-b: hdm-build-b
$(call hdm_deploy_course,223015b)
deploy-c: build-c
$(call deploy_course,223015c)
hdm-deploy-c: hdm-build-c
$(call hdm_deploy_course,223015c)
hdm-deploy: hdm-build hdm-deploy-b hdm-deploy-c
@echo "All HdM courses deployed!"
# Deploy (DHBW)
define dhbw_deploy_course
@echo "Deploying $(1)..."
scp build/$(1)/*.html $(DEPLOY_HOST):$(DHBW_DEPLOY_PATH)/$(1)/
scp build/$(1)/*.pdf $(DEPLOY_HOST):$(DHBW_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
scp build/$(1)/*.svg $(DEPLOY_HOST):$(DHBW_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
scp -r build/$(1)/assets/ $(DEPLOY_HOST):$(DHBW_DEPLOY_PATH)/$(1)/ 2>/dev/null || true
@echo "$(1) deployed!"
endef
dhbw-deploy: dhbw-build
$(call dhbw_deploy_course,dhbw)
deploy-index: build-index
@echo "Deploying root index..."
scp build/index.html $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/
scp build/qr-root.svg $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/ 2>/dev/null || true
scp build/index.html $(DEPLOY_HOST):$(HDM_DEPLOY_PATH)/ 2>/dev/null || true
@echo "Root index deployed!"
deploy: build-index deploy-b deploy-c deploy-index
deploy: build-index hdm-deploy dhbw-deploy deploy-index
@echo "All courses deployed!"
# Clean
+27 -35
View File
@@ -1,25 +1,22 @@
# HdM Slides
# Uni Slides - DHBW + HdM
Presentation slides for HdM Stuttgart courses, built with [Marp](https://marp.app/).
Combined presentation slides for DHBW and HdM Stuttgart courses, built with [Marp](https://marp.app/).
## Courses
| Code | Title | Kapitel |
|------|-------|---------|
| 223015b | Dateiformate, Schnittstellen, Speichermedien | 6 |
| 223015c | Internettechnologien | 3 |
| Code | Title | Origin |
|------|-------|--------|
| 223015b | Dateiformate, Schnittstellen, Speichermedien | HdM |
| 223015c | Internettechnologien | HdM |
| dhbw | Technik I – Grundlagen IT | DHBW |
## Project Structure
```
slides/
├── 223015b/ # Dateiformate course
│ ├── 00-intro.md
│ ├── 01-grundlagen-text-audio.md
│ └── ...
└── 223015c/ # Internettechnik course
├── 01-geschichte-grundlagen-html.md
└── ...
├── 223015b/ # HdM: Dateiformate
├── 223015c/ # HdM: Internettechnik
├── dhbw/ # DHBW slides (TBD)
scripts/ # Build scripts
build/ # Generated output (gitignored)
```
@@ -27,40 +24,34 @@ build/ # Generated output (gitignored)
## Development
```bash
# Start development server (hot reload)
make dev # Single server for all courses (port 3000)
# Access individual courses:
# 223015b: http://localhost:3000/223015b/
# 223015c: http://localhost:3000/223015c/
make hdm-dev # Live server all HdM courses (port 1312, HMR)
make hdm-dev-b # 223015b only (port 1313, HMR)
make hdm-dev-c # 223015c only (port 1314, HMR)
make dhbw-dev # DHBW (not yet configured)
```
## Build
```bash
make build # Build all (HTML + PDF)
make build-b # Build 223015b only
make build-c # Build 223015c only
make html # HTML only
make pdf # PDF only
make hdm-build # Build all HdM courses (HTML + PDF)
make hdm-build-b # 223015b only
make hdm-build-c # 223015c only
make hdm-html # HTML only all HdM
make hdm-pdf # PDF only all HdM
```
## Klausur Folien
Extract exam-relevant slides (marked with `<!-- _class: klausur -->`) into a single file:
Extract exam slides (`<!-- _class: klausur -->`) into single file:
```bash
make klausur # Extract all courses
make klausur-b # 223015b only
make klausur-c # 223015c only
make hdm-klausur # All HdM courses
make hdm-klausur-b # 223015b only
make hdm-klausur-c # 223015c only
```
Output: `slides/<course>/klausurfolien.md`
The generated file includes:
- A title slide per kapitel for orientation
- All slides marked with `<!-- _class: klausur -->`
## Tools
```bash
@@ -72,9 +63,10 @@ make optimize-images COURSE=223015b # Resize images
## Deploy
```bash
make deploy # Deploy all courses
make deploy-b # Deploy 223015b only
make deploy-c # Deploy 223015c only
make hdm-deploy # Deploy all HdM courses
make hdm-deploy-b # 223015b only
make hdm-deploy-c # 223015c only
make deploy # Full deploy (all courses)
```
## Marking Slides as Klausur-Relevant
+2 -2
View File
@@ -1,5 +1,5 @@
{
description = "HdM Slides - Marp presentation builder";
description = "Uni Slides - DHBW + HdM Marp presentation builder";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
@@ -19,7 +19,7 @@
];
shellHook = ''
echo "HdM Slides - run 'make' for available commands"
echo "Uni Slides - run 'make' for available commands"
'';
};
}
+142 -21
View File
@@ -75,11 +75,6 @@ section.erklaerung :not(footer)
{
font-size: 1.1rem;
}
@media print {
section.erklaerung {
background: #e3f2fd !important;
}
}
section.erklaerung h1 {
font-size: 1.5rem;
color: #1e5f8a;
@@ -353,7 +348,7 @@ dann **150 Mbit/s ÷ 8** = **18,75 MB/s**
**50 MB Upload bei 10 Mbit/s = ~40 Sekunden**
<!--
- ADSL (Asymmetric Digital Subscriber Line, ITU = International Telecommunication Union, Norm G.992.1, 1999): Upload bewusst begrenzt — Annahme war, Nutzer konsumieren mehr als sie produzieren
- ADSL (Asymmetric Digital Subscriber Line, ITU = International Telecommunication Union, Norm G.992.1, 1999): Upload bewusst begrenzt — Annahme war, Nutzende konsumieren mehr als sie produzieren
- FTTH = Fiber To The Home (Glasfaser bis in die Wohnung)
- Glasfaser (FTTH) symmetrisch: Upload = Download
- FTTH-Verfügbarkeit Deutschland Ende 2024: ~40% der Haushalte (Bundesnetzagentur, Breitbandatlas)
@@ -439,7 +434,7 @@ Jede Messung = ein Zahlenwert
<!--
- Dynamikumfang Formel: ~6 dB pro Bit
- 16 Bit reicht für menschliches Hören unter realen Bedingungen (~80–90 dB)
- 24 Bit im Studio: mehr Headroom für Bearbeitung, kein perzipieller Mehrwert für Endnutzer (Meyer & Moran, JAES 2007)
- 24 Bit im Studio: mehr Headroom für Bearbeitung, kein perzipieller Mehrwert für Endnutzende (Meyer & Moran, JAES 2007)
- dB = Dezibel: logarithmische Einheit für Lautstärke
-->
@@ -561,7 +556,7 @@ RECHNUNG:
- CD (1982, Sony/Philips): erstes massenmarktfähiges digitales Distributionsmedium für unkomprimiertes PCM-Audio
- PCM (Pulse-Code Modulation) existierte bereits vorher: NHK (Nippon Hōsō Kyōkai = japanische öffentlich-rechtliche Rundfunkanstalt)-Forschung ab 1960er, digitale Studiogeräte ab 1970er
- Die CD war nicht das erste digitale Audio — aber das erste das in Konsumentenhänden landete
- Die CD war nicht das erste digitale Audio — aber das erste das in KonsumentInnen-Hand landete
-->
---
@@ -600,11 +595,12 @@ RECHNUNG:
---
<!-- _class: erklaerung
<!--
_class: erklaerung
# CD-Audio – Vertiefung
Die CD (1982) war nicht das erste digitale Audiomedium — PCM-Aufnahmen existierten seit den späten 1960ern in Tonstudios (u.a. NHK, Nippon Columbia). Die CD war das erste **massenmarktfähige** digitale Distributionsmedium für unkomprimiertes Audio in Konsumentenhänden.
Die CD (1982) war nicht das erste digitale Audiomedium — PCM-Aufnahmen existierten seit den späten 1960ern in Tonstudios (u.a. NHK, Nippon Columbia). Die CD war das erste **massenmarktfähige** digitale Distributionsmedium für unkomprimiertes Audio in KonsumentInnen-Hand.
**Warum 44.100 Hz?**
Kombination aus Nyquist-Limit (2× 20 kHz = 40 kHz Minimum) und Kompatibilität mit Videobandgeräten, die in frühen digitalen Tonstudios als Speichermedium genutzt wurden. NTSC: 3 Samples × 245 Zeilen × 60 Felder = 44.100. PAL: 3 Samples × 294 Zeilen × 50 Felder = 44.100.
@@ -847,7 +843,7 @@ KLAUSURRELEVANT:
<!--
---
_class: erklaerung
_class: erklaerung
# Kompression – Vertiefung
@@ -1195,6 +1191,33 @@ Sog. RGB Tuple (geordnete endliche Liste)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-nibble-hex.png)
<!--
Kernidee: jedes Byte lässt sich sauber in zwei 4-Bit-Hälften (Nibbles) zerlegen. Jede Hälfte hat 2⁴ = 16 Zustände – und genau 16 Symbole hat Hex (0-F). Deshalb passt Hex perfekt: 1 Nibble = 1 Hex-Ziffer, 1 Byte = 2 Hex-Ziffern. Keine krumme Umrechnung.
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/why-8-bit.png)
<!--
Warum gerade 8 Bit?
- CPU adressiert byteweise — kleinste adressierbare Einheit
- Halbe Byte (z.B. 0x0000.5) existieren nicht
- Speichercontroller, Bus, CPU-Register alle auf 8-Bit-Häppchen ausgelegt
- Einzelne Bit lesen: erst Byte holen, dann mit Bitmaske isolieren (byte & 0b1000_0000)
- Hardware-Geschichte: IBM System/360 (1964) setzte 8-Bit-Standard, 7-Bit-ASCII + 1 Paritätsbit
-->
---
<!-- _class: lead -->
# Hexadezimal
@@ -1226,6 +1249,102 @@ Sog. RGB Tuple (geordnete endliche Liste)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/hex-dec-table.png)
<!--
Hex ↔ Dezimal Lookup-Tabelle: 0–F = 0–15
A=10, B=11, C=12, D=13, E=14, F=15
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-flow.png)
<!--
1 Byte = 8 Bit = 2 Hex-Ziffern = 1 ASCII-Zeichen
- Dieselbe Datei, drei Schreibweisen
- Jeder Rahmen = ein Byte
- Byte ändern sich nicht, nur unsere Anzeige
- ↵ (0x0A) = nicht druckbar → Hex-Editoren zeigen . als Platzhalter
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/three-views.png)
<!--
Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektiven:
1. Bitstream — was wirklich gespeichert wird (unleserlich)
2. Hex — gruppiert in 8-Bit-Häppchen (kompakt)
3. Bedeutung — was die Byte signalisieren:
- 89: Magic Byte (>127 → "ich bin Binärdatei")
- 50 4E 47: P N G (ASCII-Format-Kürzel)
- 0D 0A 1A 0A: CR LF EOF LF (erkennt kaputte Übertragung)
-->
---
# Wo begegnet Ihnen Hex-Code?
| Kontext | Beispiel |
|---------|----------|
| CSS-Farben | `#FF5733` |
| MAC-Adressen | `00:1A:2B:3C:4D:5E` |
| Fehlercodes | `0x80070005` |
| Speicheradressen | `0xA04F20` |
| Unicode | `U+00E4` (ä) |
| Datei-Signaturen | `89 50 4E 47` (PNG) |
<!--
Präfixe:
- 0x = "das ist Hexadezimal" (C, JavaScript, Python)
- U+ = Unicode-Codepoint (Standard für Zeichenkodierung)
- # = CSS-Konvention für Farben
ABKÜRZUNGEN:
- MAC = Media Access Control (eindeutige Hardware-Adresse einer Netzwerkkarte)
- Unicode = universeller Zeichensatz für alle Schriftsysteme
Speicheradressen erklärt:
- 64-Bit-System → Adresse hat 64 Bit = 16 Hex-Ziffern
- Beispiel vollständig: 0x0000000000A04F20 (führende Nullen weggelassen)
- "0x" = Präfix, sagt nur "jetzt kommt Hex"
Fehlercodes: Windows zeigt diese bei Bluescreens
-->
---
# Bit vs. Byte: Die Verwirrung
**1 Byte = 8 Bit** → Bit ÷ 8 = Byte
| Einheit (Bit) | Einheit (Byte) |
|---------------|----------------|
| 1 Kbit = 1.000 Bit | 1 KB = 1.000 Byte = 8.000 Bit |
| 1 Mbit = 1.000.000 Bit | 1 MB = 1.000.000 Byte = 8 Mbit |
| 1 Gbit = 1 Mrd. Bit | 1 GB = 1 Mrd. Byte = 8 Gbit |
100 Mbit/s Bandbreite = **12,5 MB/s** Downloadrate
<!--
Bits = kleines b, Bytes = großes B
Internetanbieter: Mbit/s (klingt größer!)
100 Mbit/s ÷ 8 = 12,5 MB/s
Marketing - 100 klingt besser als 12,5
-->
---
<!-- _class: lead -->
# ASCII
@@ -1691,7 +1810,7 @@ Fangfrage: "Wie hoch ist die Sample Rate von Vinyls?" -> Vinyl has no sample rat
<!--
- Dynamikumfang Formel: ~6 dB pro Bit
- 16 Bit reicht für menschliches Hören unter realen Bedingungen
- 24 Bit im Studio: mehr Headroom für Bearbeitung, kein perzipieller Mehrwert für Endnutzer (Meyer & Moran, JAES 2007)
- 24 Bit im Studio: mehr Headroom für Bearbeitung, kein perzipieller Mehrwert für Endnutzende (Meyer & Moran, JAES 2007)
-->
---
@@ -1896,7 +2015,7 @@ Ein Zusammenspiel aus vielen Faktoren:
**P2P-Filesharing für MP3s**
- Shawn Fanning, 19 Jahre alt
- 80 Millionen User in 2 Jahren
- 80 Millionen Nutzende in 2 Jahren
- Musikindustrie verklagt (2001)
- Pandora's Box: Nicht mehr aufzuhalten
@@ -1913,7 +2032,7 @@ Ein Zusammenspiel aus vielen Faktoren:
# Napster & Musikindustrie
**1999:** Napster startet
**2001:** 80 Millionen User
**2001:** 80 Millionen Nutzende
**Musikindustrie:**
- CDs kosten $15–20
@@ -2007,19 +2126,21 @@ Vollständige Lizenz: https://creativecommons.org/licenses/by-sa/4.0/
# Selbstlernen: HEX Files
1. Drei Dateien ohne Dateiendung:
<a href="../materials/wtf1"/>`hex1`</a> <a href="../materials/wtf2"/>`hex2`</a> <a href="../materials/wtf3"/>`hex3`</a>
3. Lies erste 16 Bytes aus und identifiziere Dateiformat (Magic Number)
5. *Optional: Datei umbenennen und korrekte Dateiendung anhängen (bspw. `.jpg`)*
1. Fünf Dateien ohne Dateiendung:
<a href="https://librete.ch/hdm/223015b/materials/hex1">`hex1`</a> · <a href="https://librete.ch/hdm/223015b/materials/hex2">`hex2`</a> · <a href="https://librete.ch/hdm/223015b/materials/hex3">`hex3`</a> · <a href="https://librete.ch/hdm/223015b/materials/hex4">`hex4`</a> · <a href="https://librete.ch/hdm/223015b/materials/hex5">`hex5`</a>
2. Lies erste 16 Byte aus und identifiziere Dateiformat (Magic Number)
3. *Optional: Datei umbenennen und korrekte Dateiendung anhängen (bspw. `.jpg`)*
**Tools:**
- Hex-Editor: [hexed.it](https://hexed.it)
- Magic Numbers: [en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures)
<!--
- wtf1: Plaintext (keine Magic Number)
- wtf2: PNG (89 50 4E 47)
- wtf3: JPEG (FF D8 FF)
- hex1: Plaintext (keine Magic Number)
- hex2: PNG (89 50 4E 47)
- hex3: JPEG (FF D8 FF)
- hex4: DOCX (50 4B 03 04 — ZIP-Container)
- hex5: ZIP (50 4B 03 04)
- Gruppenarbeit: 3-4 Personen
- Ziel: Hex-Dump lesen lernen, Dateiformate verstehen
-->
+6 -18
View File
@@ -72,18 +72,6 @@ section.aufgabe footer {
}
section.erklaerung {
font-size: 1.1rem;
background: repeating-linear-gradient(
135deg,
#e3f2fd,
#e3f2fd 40px,
#fff 40px,
#fff 80px
) !important;
}
@media print {
section.erklaerung {
background: #e3f2fd !important;
}
}
section.erklaerung h1 {
font-size: 1.5rem;
@@ -960,7 +948,7 @@ KLAUSURRELEVANT:
<!--
- Kompatibilität schlägt oft Effizienz
- TIFF für Archivierung: Unkomprimiert oder verlustfrei
- RAW für Fotografen: Maximale Bearbeitungsfreiheit
- RAW für FotografInnen: Maximale Bearbeitungsfreiheit
- Frage: "Was passiert, wenn ihr ein PNG auf Instagram hochladet?"
-->
@@ -996,8 +984,8 @@ KLAUSURRELEVANT:
- Instagram ist keine Kunstgalerie, sondern Massenplattform
- Optimiert für Geschwindigkeit, nicht Qualität
- Facebook, Twitter, TikTok – alle machen das
- Tipp für Fotografen: Portfolio auf eigener Website
- Diskussion: Ist das fair? Trade-off Nutzer vs. Plattform
- Tipp für FotografInnen: Portfolio auf eigener Website
- Diskussion: Ist das fair? Trade-off Nutzende vs. Plattform
-->
---
@@ -1074,7 +1062,7 @@ KLAUSURRELEVANT:
**Codec** (Coder-Decoder) definiert den Kompressionsalgorithmus. Derselbe Container kann verschiedene Codecs enthalten – die Dateiendung verrät den Codec nicht.
| Container | Entwickler | Typische Codecs | Besonderheit |
| Container | Entwicklung | Typische Codecs | Besonderheit |
|-----------|------------|-----------------|--------------|
| MP4 | ISO/MPEG | H.264, H.265, AAC | Web-Standard, DRM-fähig |
| MKV | Matroska | Alle | Beliebig viele Streams, Kapitel |
@@ -1338,7 +1326,7 @@ H.264 (2003) ermöglichte erst YouTube (2005), Netflix-Streaming (2007) und Blu-
**Hardware-Ubiquität:** Seit 2010 hat jedes Smartphone, jede GPU, jeder Smart-TV einen H.264-Hardware-Decoder. Encoding in Echtzeit braucht keine CPU – das ermöglichte erst mobiles Video-Streaming und Videotelefonie.
**Patent-Pool (MPEG-LA):** ~2.000 Patente von 30+ Unternehmen. Endnutzer-Streaming ist lizenzfrei; Hardware-Hersteller zahlen ~$0,20/Gerät.
**Patent-Pool (MPEG-LA):** ~2.000 Patente von 30+ Unternehmen. Endnutzungs-Streaming ist lizenzfrei; Hardware-Hersteller zahlen ~$0,20/Gerät.
---
@@ -1359,7 +1347,7 @@ H.264 (2003) ermöglichte erst YouTube (2005), Netflix-Streaming (2007) und Blu-
<!--
- MPEG-LA = Licensing Authority
- Firefox weigerte sich lange, H.264 zu unterstützen
- "Free to View" gilt nur für Endnutzer-Streaming
- "Free to View" gilt nur für Endnutzungs-Streaming
- Diskussion: Sollten Standards patent-frei sein?
-->
@@ -72,18 +72,6 @@ section.aufgabe footer {
}
section.erklaerung {
font-size: 1.1rem;
background: repeating-linear-gradient(
135deg,
#e3f2fd,
#e3f2fd 40px,
#fff 40px,
#fff 80px
) !important;
}
@media print {
section.erklaerung {
background: #e3f2fd !important;
}
}
section.erklaerung h1 {
font-size: 1.5rem;
@@ -166,7 +154,7 @@ Hersteller: Dezimal (SI-Präfix) - klingt mehr!
Betriebssysteme: Binär - aber zeigen "GB" statt "GiB"
Diskrepanz bei 1 TB: 1.000.000.000.000 vs. 1.099.511.627.776 Bytes
→ 10% Unterschied bei TB-Größen
Verwirrung für Konsumenten seit Jahrzehnten
Verwirrung für KonsumentInnen seit Jahrzehnten
ISO/IEC 80000-13: Definiert KiB, MiB, GiB, TiB (2008)
-->
@@ -604,7 +592,7 @@ Voll: Langsamstes Backup, schnellste Wiederherstellung
<!--
Time Machine: Stündliche Snapshots, APFS-Integration
Veeam: Enterprise-Level, kostenlose Endnutzer-Version
Veeam: Enterprise-Level, kostenlose Privatversion
rsync: Unix-Klassiker, extrem effizient
Borg: Deduplizierung + Verschlüsselung
-->
+14 -14
View File
@@ -160,7 +160,7 @@ AWS Snowmobile: 45-Fuß-Container auf LKW
**Prozess:**
1. AWS schickt verschlüsseltes Gerät
2. Kunde kopiert Daten lokal (schnell!)
2. KundIn kopiert Daten lokal (schnell!)
3. Gerät zurück an AWS
4. AWS lädt in S3 hoch
@@ -220,7 +220,7 @@ Server unter Last (symbolisch)
**Klassisches Modell:** Ein Server, viele Clients
**Problem:**
1 Million User wollen 1 GB-Datei
1 Million Nutzende wollen 1 GB-Datei
→ Server braucht **1 PB Bandbreite!**
→ Server überlastet → **"Hug of Death"**
@@ -252,7 +252,7 @@ Globale Verteilung
**Funktionsweise:**
1. **Origin Server** (Hauptquelle)
2. **Edge Servers** (geografisch verteilt)
3. User → nächster Edge Server
3. Nutzende → nächster Edge Server
4. Erste Anfrage: Edge holt von Origin, cached
5. Weitere Anfragen: Direkt vom Edge (schnell!)
@@ -277,7 +277,7 @@ Große CDN-Anbieter: Cloudflare, Akamai, Amazon CloudFront, Fastly
- Lange Cache-Zeit (TTL: Tage/Wochen)
**Dynamic Content:**
- User-spezifisch (Profil)
- Nutzungs-spezifisch (Profil)
- Kurze TTL oder nicht cachebar
**Cache Invalidation:**
@@ -349,14 +349,14 @@ Dezentral, jeder ist Client & Server
- IPFS (InterPlanetary File System)
- Blockchain (Bitcoin, Ethereum)
**Vorteil:** Skalierbar (mehr User = mehr Bandbreite!)
**Vorteil:** Skalierbar (mehr Nutzende = mehr Bandbreite!)
**Nachteil:** Langsam bei wenigen Peers, oft für Piraterie missbraucht
<!--
P2P vs. Client-Server: Kein zentraler Server
Last verteilt sich auf alle Teilnehmer
Je mehr User, desto schneller (umgekehrt zu Client-Server!)
Last verteilt sich auf alle Teilnehmenden
Je mehr Nutzende, desto schneller (umgekehrt zu Client-Server!)
Zensur-resistent: Kein Single Point of Failure
Rechtliche Grauzone: Technologie neutral, aber oft illegal genutzt
-->
@@ -1023,8 +1023,8 @@ Privacy-Albtraum
**Beispiele:**
- **Foto:** Kamera, Datum, GPS, Belichtung
- **MP3:** Künstler, Album, Jahr, Genre, Cover
- **PDF:** Autor, Datum, Software
- **MP3:** KünstlerInnen, Album, Jahr, Genre, Cover
- **PDF:** AutorIn, Datum, Software
- **E-Mail:** Absender, Empfänger, Zeitstempel
**Warum wichtig?**
@@ -1180,7 +1180,7 @@ Wikipedia für Musik-Metadaten
**Idee:** Wikipedia für Musik-Metadaten
**Community-gepflegt:**
- Künstler, Alben, Tracks
- KünstlerInnen, Alben, Tracks
- Relationships (Band-Mitglieder, Label...)
- Releases (verschiedene Editionen, Länder)
@@ -1239,7 +1239,7 @@ Versteckte Informationen sichtbar
**PDF-Metadaten (XMP):**
**Gespeichert:**
- Titel, Autor, Betreff, Keywords
- Titel, AutorIn, Betreff, Keywords
- Erstellungsdatum, Änderungsdatum
- Software, **Company** (aus Office-Lizenz!)
@@ -1600,7 +1600,7 @@ QKD: Abhör-sichere Kommunikation (Quantenmechanik garantiert)
**Filecoin (2017):**
- Blockchain-basiert
- User vermieten Festplatten-Platz
- Nutzende vermieten Festplatten-Platz
- Bezahlung in FIL (Kryptowährung)
**Arweave (2018):**
@@ -1638,7 +1638,7 @@ Legitime Use-Cases: NFT-Storage, Zensur-resistente Archivierung
- 5G + Edge Computing nötig
**Cloud Gaming:**
- Spiel im Rechenzentrum, Stream zu User
- Spiel im Rechenzentrum, Stream zu Nutzenden
- Input-Lag = Todfeind (<50ms)
**Problem:** Physik (Lichtgeschwindigkeit!)
@@ -1647,7 +1647,7 @@ Legitime Use-Cases: NFT-Storage, Zensur-resistente Archivierung
8K: YouTube unterstützt, aber wer hat 8K-Monitor?
VR: Meta Quest, Apple Vision Pro
Latenz: Lichtgeschwindigkeit ~300.000 km/s, aber Routing + Processing addiert sich
Edge Computing: Server näher an User (5G-Masten)
Edge Computing: Server näher an Nutzende (5G-Masten)
Cloud Gaming: Stadia gescheitert (2023 †), GeForce Now, Xbox Cloud
Input-Lag: Fiber ~5ms/1000km, aber Server-Processing + Encoding + Decoding
-->
+11 -2
View File
@@ -30,12 +30,21 @@ h2 {
}
pre {
background: #0f0f23;
color: #f8f8f8;
border-radius: 8px;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #0f0f23;
color: #5fb3e4;
padding: 0.15em 0.4em;
border-radius: 4px;
}
section code:not(.hljs) { color: #5fb3e4 !important; }
section code.hljs { color: #f8f8f8 !important; }
a {
color: var(--color-highlight);
}
@@ -442,9 +451,9 @@ Ordne jede Eigenschaft zu: Vorteil von Analog oder Vorteil von Digital?
**Punkte:** 3
**Typ:** `[ESSAY]`
Erklären Sie die drei digitalen Distributionswege **Download**, **Streaming** und **Peer-to-Peer (P2P)**. Beschreiben Sie für jeden Weg: (1) wie die Daten zum Nutzer gelangen, (2) ob der Nutzer eine dauerhafte Kopie erhält, und (3) nennen Sie je ein Beispiel.
Erklären Sie die drei digitalen Distributionswege **Download**, **Streaming** und **Peer-to-Peer (P2P)**. Beschreiben Sie für jeden Weg: (1) wie die Daten zu Nutzenden gelangen, (2) ob Nutzende eine dauerhafte Kopie erhalten, und (3) nennen Sie je ein Beispiel.
> **Musterlösung:** **Download:** Datei wird vollständig vom Server heruntergeladen und lokal gespeichert. Nutzer erhält dauerhafte Kopie. Beispiel: iTunes Store, Steam. **Streaming:** Daten werden während des Abspielens übertragen, keine dauerhafte lokale Kopie. Beispiel: Netflix, Spotify. **P2P:** Nutzer laden Teile der Datei gleichzeitig von vielen anderen Nutzern herunter (dezentral). Dauerhafte Kopie möglich. Beispiel: BitTorrent.
> **Musterlösung:** **Download:** Datei wird vollständig vom Server heruntergeladen und lokal gespeichert. Nutzende erhalten dauerhafte Kopie. Beispiel: iTunes Store, Steam. **Streaming:** Daten werden während des Abspielens übertragen, keine dauerhafte lokale Kopie. Beispiel: Netflix, Spotify. **P2P:** Nutzende laden Teile der Datei gleichzeitig von vielen anderen herunter (dezentral). Dauerhafte Kopie möglich. Beispiel: BitTorrent.
---
+88 -26
View File
@@ -72,18 +72,6 @@ section.aufgabe footer {
}
section.erklaerung {
font-size: 1.1rem;
/**background: repeating-linear-gradient(
135deg,
#fce4ec,
#fce4ec 40px,
#fff 40px,
#fff 80px
) !important;**/
}
@media print {
section.erklaerung {
background: #fce4ec !important;
}
}
section.erklaerung h1 {
font-size: 1.5rem;
@@ -642,7 +630,7 @@ KATHLEEN BOOTH (1922–2022):
Kathleen Hylda Valerie Booth (geb. Britten), BSc Mathematik (Royal Holloway, London), PhD Applied Mathematics (King's College London). Arbeitete ab 1946 mit Andrew Booth (später ihr Ehemann) am Birkbeck College – eines der kleinsten Computing-Teams Großbritanniens: nur Andrew, Kathleen und Xenia Sweeting.
WAS SIE TAT:
Kathleen baute die Hardware des ARC (Automatic Relay Calculator) mit auf und entwickelte dann die Programmierarchitektur. 1947 reiste sie mit Andrew nach Princeton, wo sie John von Neumann trafen und die Stored-Program-Architektur kennenlernten. Sie schrieb "Coding for A.R.C." – die erste veröffentlichte Beschreibung einer Assembly-Sprache. Statt roher Binärzahlen (z.B. 10011) konnten Programmierer nun mnemonische Kürzel verwenden (z.B. M -> cR). Ein konzeptioneller Sprung – die erste Abstraktionsschicht zwischen Mensch und Maschine.
Kathleen baute die Hardware des ARC (Automatic Relay Calculator) mit auf und entwickelte dann die Programmierarchitektur. 1947 reiste sie mit Andrew nach Princeton, wo sie John von Neumann trafen und die Stored-Program-Architektur kennenlernten. Sie schrieb "Coding for A.R.C." – die erste veröffentlichte Beschreibung einer Assembly-Sprache. Statt roher Binärzahlen (z.B. 10011) konnten Programmierende nun mnemonische Kürzel verwenden (z.B. M -> cR). Ein konzeptioneller Sprung – die erste Abstraktionsschicht zwischen Mensch und Maschine.
VOR ASSEMBLER:
ENIAC (1943–46) wurde durch physisches Umstecken von Kabeln programmiert – Programmwechsel dauerten Tage. Danach kamen Stored-Program-Computer, aber Programme mussten als rohe Binärzahlen eingegeben werden. Jeder Tippfehler in einer 0/1-Folge konnte den Befehl komplett verfälschen.
@@ -726,7 +714,7 @@ Cambridge Analytica (2018): Facebook-Daten von 87 Mio. Nutzern wurden für polit
China Social Credit System: Punktesystem für "gutes Verhalten". Wer zu oft bei Rot geht, bekommt keinen Kredit mehr.
Die Frage: Wer entscheidet, was mit Technologie gemacht wird? Die Entwickler? Die Firmen? Die Politik? Wir alle?
Die Frage: Wer entscheidet, was mit Technologie gemacht wird? Die Entwickelnden? Die Firmen? Die Politik? Wir alle?
-->
---
@@ -913,19 +901,46 @@ Shannon: Begründer der Informationstheorie
# Das Byte
**8 Bit = 1 Byte**
### Die kleinste *adressierbare* Informationseinheit
### 8 bit = 1 Byte
```
0 0 1 0 1 0 1 0
0 0 1 0 1 0 1 0 = 42
```
**Wie viele Kombinationen?**
2⁸ = 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 = **256 Möglichkeiten** (0-255)
<!--
BYTE = Wortspiel aus "Bit" + "Bite" (Bissen)
Warum 8 Bits? IBM System/360 (1964) setzte Standard
2×2×2×2×2×2×2×2 = 256
BYTE = Wortspiel aus "Bit" + "Bite" (Bissen) — Begriff geprägt von Werner Buchholz (IBM, 1956)
Schreibweise mit "y" statt "i": bewusste Änderung zur Vermeidung von Verwechslung mit "Bit"
binary 00101010 = decimal 42
-->
---
# Das Byte
### 8 bit = 1 Byte
```
0 0 0 0 0 0 0 0 = 0
0 0 0 0 0 0 0 1 = 1
0 0 0 0 0 0 1 0 = 2
0 0 0 0 0 0 1 1 = 3
0 0 0 0 0 1 0 0 = 4
0 1 0 0 0 0 0 0 = 64
0 1 1 1 1 1 1 1 = 127
1 1 1 1 1 1 1 1 = ?
```
2 × 2 × 2 × 2 × 2 × 2 × 2 × 2 = 2⁸ = **256 mögliche Zustände**
<!--
- 1964: IBM System/360 setzte den 8-Bit-Byte-Standard — vorher 6-Bit/7-Bit-Systeme
- ASCII (1963) brauchte 7 Bit für 128 Zeichen
- 8 Bit = praktisch für Hardware (Zweierpotenz: 2³ = 8)
- 8 Bit = 2 Hexadezimalziffern (elegante Darstellung)
- Kleinste adressierbare Einheit im Speicher: Prozessor kann nicht einzelne Bits direkt ansprechen, immer Bytes
-->
---
@@ -957,6 +972,22 @@ Farbbild: Rot + Grün + Blau
Kernidee: jedes Byte lässt sich sauber in zwei 4-Bit-Hälften (Nibbles) zerlegen. Jede Hälfte hat 2⁴ = 16 Zustände – und genau 16 Symbole hat Hex (0-F). Deshalb passt Hex perfekt: 1 Nibble = 1 Hex-Ziffer, 1 Byte = 2 Hex-Ziffern. Keine krumme Umrechnung.
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/why-8-bit.png)
<!--
Warum gerade 8 Bit?
- CPU adressiert byteweise — kleinste adressierbare Einheit
- Halbe Byte (z.B. 0x0000.5) existieren nicht
- Speichercontroller, Bus, CPU-Register sind alle auf 8-Bit-Häppchen ausgelegt
- Einzelne Bit lesen: erst Byte holen, dann mit Bitmaske isolieren (byte & 0b1000_0000)
- Hardware-Geschichte: IBM System/360 (1964) setzte 8-Bit-Standard, 7-Bit-ASCII + 1 Paritätsbit
-->
<!--
# Zahlensysteme
@@ -1013,6 +1044,38 @@ CSS (Cascading Style Sheets)-Farben nutzen Hex: #FF0000 = Rot
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-flow.png)
<!--
1 Byte = 8 Bit = 2 Hex-Ziffern = 1 ASCII-Zeichen
- Dieselbe Datei, drei Schreibweisen
- Jeder Rahmen = ein Byte
- Byte ändern sich nicht, nur unsere Anzeige
- ↵ (0x0A) = nicht druckbar → Hex-Editoren zeigen . als Platzhalter
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/three-views.png)
<!--
Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektiven:
1. Bitstream — was wirklich gespeichert wird (unleserlich)
2. Hex — gruppiert in 8-Bit-Häppchen (kompakt)
3. Bedeutung — was die Byte signalisieren:
- 89: Magic Byte (>127 → "ich bin Binärdatei")
- 50 4E 47: P N G (ASCII-Format-Kürzel)
- 0D 0A 1A 0A: CR LF EOF LF (erkennt kaputte Übertragung)
-->
---
# Wo begegnet Ihnen Hex-Code?
| Kontext | Beispiel |
@@ -1523,10 +1586,9 @@ PRÜFUNGSRELEVANT: Arten von Einschränkungen, Screenreader-Beispiele, WCAG
---
<!-- _class: "erklaerung klausur" -->
<!-- _class: erklaerung -->
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #fce4ec -->
# Web-Zugänglichkeit – Vertiefung
@@ -1686,7 +1748,7 @@ button:focus-visible {
border-radius: 4px;
}
/* Anti-Pattern: Tastatur-Nutzer sind "blind" */
/* Anti-Pattern: Tastatur-Nutzende sind "blind" */
button:focus { outline: none; }
```
@@ -1826,7 +1888,7 @@ Fokus-Indikator immer sichtbar? Logische Reihenfolge? Alle Elemente erreichbar?
<!--
WAVE Tab-Reihenfolge: visualisiert DOM-Reihenfolge als Tab-Pfad.
Wenn Pfad kreuz und quer → schlechte Struktur für Tastatur-/Screenreader-Nutzer.
Wenn Pfad kreuz und quer → schlechte Struktur für Tastatur-/Screenreader-Nutzende.
-->
---
+1 -13
View File
@@ -73,18 +73,6 @@ section.glossar {
}
section.erklaerung {
font-size: 1.1rem;
/**background: repeating-linear-gradient(
135deg,
#fce4ec,
#fce4ec 40px,
#fff 40px,
#fff 80px
) !important;**/
}
@media print {
section.erklaerung {
background: #fce4ec !important;
}
}
section.erklaerung h1 {
font-size: 1.5rem;
@@ -1620,7 +1608,7 @@ Wie Encapsulation funktioniert.
# Netzwerk-Grundlagen – Vertiefung
Die vier Kernkonzepte für Web-Entwickler:
Die vier Kernkonzepte für Web-Entwickelnde:
**1. DNS-Auflösung:**
- Browser fragt DNS-Resolver (z.B. 8.8.8.8)
+10 -1
View File
@@ -30,12 +30,21 @@ h2 {
}
pre {
background: #0f0f23;
color: #f8f8f8;
border-radius: 8px;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #0f0f23;
color: #d63384;
padding: 0.15em 0.4em;
border-radius: 4px;
}
section code:not(.hljs) { color: #d63384 !important; }
section code.hljs { color: #f8f8f8 !important; }
a {
color: var(--color-highlight);
}
@@ -610,7 +619,7 @@ Ordne jedem Szenario den passenden HTTP-Status-Code zu.
Erklären Sie die drei HTTP-Status-Code-Kategorien **2xx**, **4xx** und **5xx**. Beschreiben Sie für jede: (1) was sie bedeutet, (2) wer „schuld" ist (Client oder Server), (3) ein konkretes Beispiel mit Szenario.
> **Musterlösung:** **2xx (Erfolg):** Die Anfrage wurde erfolgreich verarbeitet. Niemand ist „schuld" – alles funktioniert. Beispiel: 200 OK – die Webseite wurde korrekt geladen. **4xx (Client-Fehler):** Die Anfrage war fehlerhaft. Der Client ist verantwortlich. Beispiel: 404 Not Found – der Benutzer hat eine URL eingetippt, die nicht existiert. **5xx (Server-Fehler):** Der Server hat ein Problem. Der Betreiber ist verantwortlich. Beispiel: 503 Service Unavailable – der Server ist überlastet oder in Wartung.
> **Musterlösung:** **2xx (Erfolg):** Die Anfrage wurde erfolgreich verarbeitet. Niemand ist „schuld" – alles funktioniert. Beispiel: 200 OK – die Webseite wurde korrekt geladen. **4xx (Client-Fehler):** Die Anfrage war fehlerhaft. Der Client ist verantwortlich. Beispiel: 404 Not Found – Nutzende haben eine URL eingetippt, die nicht existiert. **5xx (Server-Fehler):** Der Server hat ein Problem. Der Betreiber ist verantwortlich. Beispiel: 503 Service Unavailable – der Server ist überlastet oder in Wartung.
---
+418
View File
@@ -0,0 +1,418 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2025"
title: Web Engineering
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #005f8a;
--color-dimmed: #4a6a7a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.7rem;
}
h1 {
color: #005f8a;
}
section.invert h1 {
color: #fff;
}
pre {
background: #0f1e2e;
color: #00b4d8;
border-radius: 8px;
border-left: 3px solid #005f8a;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a3a4a;
color: #00b4d8;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2025**
---
<!-- _class: lead -->
# Willkommen!
## 1. Sitzung: 09.05.2025
---
# Wer bist du, was machst du?
- B.Sc. Wirtschaftsinformatik (Leibniz-FH Hannover)
- Angestellt bei PONS Langenscheidt GmbH in Stuttgart
- Honorardozent und Berater
**Bisherige Vorlesungen (DHBW/Leibniz-FH):**
- Social Engineering, Mobile Medien, Web Eng
---
# Vorlesungsplan
| Sitzung | Datum | Thema |
|---------|-------|-------|
| 1 | 09.05. | Formalia, Kennenlernen, Internet 101 |
| 2 | 16.05. | HTML und CSS (Frameworks) |
| 3 | 23.05. | JS (Frameworks) und npm |
| 4 | 30.05. | nodeJS: Scripting, Running and Building |
| 5 | 06.06. | Express API, CRUD und "Middlewares" |
| 6 | 13.06. | Testing (unit, integration, end-to-end) |
| 7 | 20.06. | TypeScript |
| 8 | 27.06. | Docker, Proxies and DBs |
| 9 | 04.07. | Präsentationen |
---
# Prüfungsleistung
**LN** – Lernnachweis (50%)
- Projekte / Hausaufgaben
- Präsentation
---
# Internet 101 – Zeitleiste
| Jahr | Ereignis |
|------|----------|
| 1966 | ARPANET |
| 1969 | RFCs |
| 1986 | IETF |
| 1992 | Internet Society |
| 1974 | TCP/IP und HTTP(S) |
| 1987 | Domain Names und DNS |
| 1993 | "Erster" Browser: Mosaic |
| 1994 | W3C (HTML, XML, CSS, SVG, WCAG etc.) |
| 1995 | ECMAScript (JS) |
| 2006/08 | V8 JS Runtime Engine |
| Heute | 1,3 Mio. km Unterseekabel |
---
# Internet 101 – Browser Request
```
Browser Server
| |
|-- GET /products -------------->|
|<-- HTTP 200 + index.html -----|
| |
|-- GET /script.js ------------->|
|<-- HTTP 200 + script.js ------|
| |
|-- GET /api/products ---------->|
|<-- HTTP 200 + JSON ------------|
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/browser-server-sequence.png)
---
# HTTP – Hypertext Transfer Protocol
**Request:**
```
GET /products HTTP/1.1
Host: localhost:8080
```
**Response:**
```
HTTP/1.1 200 OK
Content-Type: application/json
[{"id": 1, "name": "Produkt A"}, ...]
```
---
# Entwicklungsumgebung
**Tools:**
- Node.js + npm
- VS Code
- Git
- Chrome DevTools
---
# Versionierung mit Git
```bash
git init
git add .
git commit -m "initial commit"
git remote add origin https://github.com/user/repo.git
git push -u origin main
```
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# HTML – Hypertext Markup Language
---
# HTML Grundlagen
```html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Meine Seite</title>
</head>
<body>
<h1>Überschrift</h1>
<p>Textabsatz</p>
</body>
</html>
```
---
# Semantisches HTML
```html
<header>Navigationsbereich</header>
<nav>Navigation</nav>
<main>
<article>
<section>
<h2>Überschrift</h2>
<p>Inhalt</p>
</section>
</article>
</main>
<footer>Fußzeile</footer>
```
---
# HTML – Tabellen und Listen
```html
<table>
<thead>
<tr><th>Name</th><th>Preis</th></tr>
</thead>
<tbody>
<tr><td>Produkt A</td><td>29,99 €</td></tr>
</tbody>
</table>
<ul>
<li>Punkt 1</li>
<li>Punkt 2</li>
</ul>
```
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# CSS – Cascading Style Sheets
---
# CSS Grundlagen
```css
/* Element */
body { font-family: Arial, sans-serif; }
/* Klasse */
.button { background: #005f8a; color: white; }
/* ID */
#header { height: 60px; }
/* Attribut */
input[type="text"] { border: 1px solid #ccc; }
```
---
# CSS Layout – Flexbox
```css
.container {
display: flex;
justify-content: space-between;
align-items: center;
}
```
---
# CSS Layout – Grid
```css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
```
---
# CSS – Box Model
```css
.box {
margin: 10px;
border: 2px solid #005f8a;
padding: 20px;
width: 200px;
box-sizing: border-box;
}
```
---
# CSS Responsive
```css
@media (max-width: 768px) {
.grid {
grid-template-columns: 1fr;
}
}
```
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# JavaScript
---
# JavaScript Grundlagen
```javascript
// Variablen
let name = "Welt";
const alter = 25;
// Funktionen
function gruss(name) {
return `Hallo, ${name}!`;
}
// Arrow Functions
const add = (a, b) => a + b;
// Arrays
const arr = [1, 2, 3];
arr.map(x => x * 2); // [2, 4, 6]
```
---
# DOM Manipulation
```javascript
// Element auswählen
const title = document.querySelector('h1');
// Inhalt ändern
title.textContent = 'Neue Überschrift';
// Event Listener
button.addEventListener('click', () => {
alert('Geklickt!');
});
```
---
# Fetch API
```javascript
fetch('/api/products')
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
```
---
# Async/Await
```javascript
async function loadProducts() {
try {
const res = await fetch('/api/products');
const data = await res.json();
return data;
} catch (err) {
console.error('Fehler:', err);
}
}
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/web-ecosystem-rings.png)
---
# Fragen?
1. Was ist der Unterschied zwischen `let` und `const`?
2. Wie funktioniert `fetch()`?
3. Was macht `box-sizing: border-box`?
+266
View File
@@ -0,0 +1,266 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2025"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #005f8a;
--color-dimmed: #4a6a7a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.7rem;
}
h1 {
color: #005f8a;
}
section.invert h1 {
color: #fff;
}
pre {
background: #0f1e2e;
color: #00b4d8;
border-radius: 8px;
border-left: 3px solid #005f8a;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a3a4a;
color: #00b4d8;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# CSS: Extended
---
# CSS Selectors – Tag, Class, ID, Attribute
```css
/* Tag */
p { color: #333; }
/* Class */
.button { background: blue; }
/* ID */
#header { height: 60px; }
/* Attribute */
input[type="text"] { border: 1px solid #ccc; }
input[disabled] { background: #eee; }
```
---
# CSS Selectors – Attribut-Selektoren
```css
/* presence */
[disabled] { opacity: 0.5; }
/* exact value */
[type="email"] { border-color: blue; }
/* contains word */
[class~="btn"] { cursor: pointer; }
/* starts with */
[href^="https"] { color: green; }
/* ends with */
[src$=".png"] { border: 1px solid #ccc; }
/* contains substring */
[class*="icon"] { padding-left: 20px; }
```
---
# CSS Combinators
```css
/* Child (direkt) */
div > p { margin: 0; }
/* Descendant (Nachkomme) */
div p { margin: 0; }
/* Next Sibling */
h1 + p { font-size: 1.2em; }
/* Subsequent Sibling */
h1 ~ p { color: #666; }
/* Selector List */
h1, h2, h3 { font-weight: bold; }
```
---
# Pseudo Classes
```css
/* User Interaction */
:hover { color: red; }
:active { background: blue; }
:focus { outline: 2px solid orange; }
/* Structure */
:first-child { margin-left: 0; }
:last-child { margin-right: 0; }
:nth-child(odd) { background: #f9f9f9; }
/* Links */
:visited { color: purple; }
:link { color: blue; }
```
---
# Pseudo Classes – More
```css
/* Form States */
:valid { border-color: green; }
:invalid { border-color: red; }
:placeholder-shown { color: #999; }
/* Content */
:before { content: "→ "; }
:after { content: " [Wichtig]"; }
:first-letter { font-size: 2em; }
:first-line { font-weight: bold; }
/* NOT */
:not(.disabled) { pointer-events: auto; }
:not(:last-child) { border-bottom: 1px solid #ccc; }
```
---
# Shorthand Properties
```css
/* margin: top right bottom left */
margin: 10px 20px 10px 20px;
/* centering */
margin: 0 auto;
/* padding same */
padding: 20px;
/* border: width style color */
border: 1px solid #333;
/* background: color image position/size repeat */
background: #fff url(logo.png) 0 0 no-repeat;
/* font: style variant weight size/line-height family */
font: italic normal bold 16px/1.5 Arial, sans-serif;
```
---
# Flexbox Shorthands
```css
/* flex: grow shrink basis */
flex: 1 0 auto;
/* place-items: align-items justify-items */
place-items: center stretch;
/* place-content: align-content justify-content */
place-content: space-between center;
/* gap: row-gap column-gap */
gap: 20px 40px;
```
---
# CSS Custom Properties (Variables)
```css
:root {
--primary-color: #005f8a;
--spacing: 20px;
--radius: 8px;
}
.button {
background: var(--primary-color);
padding: var(--spacing);
border-radius: var(--radius);
}
```
---
# CSS Functions
```css
/* calc */
width: calc(100% - 40px);
/* min/max/clamp */
width: min(100%, 600px);
font-size: clamp(14px, 2vw, 20px);
/* var with fallback */
color: var(--text-color, #333);
/* rgb/rgba/hsl/hsla */
color: hsl(200, 100%, 50%);
background: rgba(0, 0, 0, 0.5);
```
---
# Transition & Animation
```css
/* transition: property duration timing-function */
transition: all 0.3s ease-in-out;
transition: background 0.2s, transform 0.1s;
/* animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-out;
}
```
---
# Fragen?
1. Was bedeutet `div > p` vs `div p`?
2. Wann nutzt du `nth-child(even)`?
3. Warum `--variable` statt direkt `#fff`?
+228
View File
@@ -0,0 +1,228 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2025"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #005f8a;
--color-dimmed: #4a6a7a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.7rem;
}
h1 {
color: #005f8a;
}
section.invert h1 {
color: #fff;
}
pre {
background: #0f1e2e;
color: #00b4d8;
border-radius: 8px;
border-left: 3px solid #005f8a;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a3a4a;
color: #00b4d8;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# Node.js – Scripting, Running and Building
---
# Node.js – Was ist das?
- JavaScript Runtime (V8 Engine)
- Server-side JavaScript
- npm Package Manager
- Ideal für: APIs, CLI Tools, Automation
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/nodejs-usecases.png)
---
# node --check und node -e
```bash
# Syntax check only
node --check script.js
# One-liner
node -e "console.log('Hallo Welt')"
```
---
# node -e Beispiele
```bash
# String
node -e "console.log('Hello ' + process.argv[2])" Welt
# File reading
node -e "console.log(require('fs').readFileSync('data.json'))"
# JSON parsen
node -e "console.log(JSON.parse(process.argv[1]))" '{"a":1}'
```
---
# require() – Module laden
```javascript
// Eigene Datei
const utils = require('./utils');
// npm Modul
const express = require('express');
// Built-in
const fs = require('fs');
const path = require('path');
```
---
# __dirname und __filename
```javascript
// Aktuelles Verzeichnis (Node.js)
console.log(__dirname); // /home/user/project/src
console.log(__filename); // /home/user/project/src/app.js
// Pfad joinen
const configPath = path.join(__dirname, '..', 'config.json');
```
---
# HTTP Server mit Node.js (Built-in)
```javascript
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Hallo Welt!</h1>');
});
server.listen(3000, () => {
console.log('Server läuft auf Port 3000');
});
```
---
# fs – Dateien lesen/schreiben
```javascript
const fs = require('fs');
// Async
fs.readFile('data.json', 'utf8', (err, data) => {
if (err) throw err;
console.log(JSON.parse(data));
});
// Sync
const content = fs.readFileSync('data.json', 'utf8');
// Write
fs.writeFile('output.txt', 'Hallo Welt', (err) => {
if (err) throw err;
});
```
---
# package.json – Das Herzstück
```json
{
"name": "mein-projekt",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js",
"test": "node --test"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"nodemon": "^3.0.0"
}
}
```
---
# npm Scripts
```bash
# npm run <script>
npm run start
npm run dev
# Mit Argumenten
npm run build -- --production
# Lifecycle scripts
npm install → postinstall
npm start → start (direkt)
```
---
# Node.js Module – exports
```javascript
// utils.js
module.exports = {
add: (a, b) => a + b,
greet: (name) => `Hallo ${name}!`
};
// Oder einzelne Exporte
module.exports.add = (a, b) => a + b;
```
---
# Fragen?
1. Wie startest du einen Node.js Server auf Port 8080?
2. Was macht `node --check`?
3. Wozu dient `package.json`?
+258
View File
@@ -0,0 +1,258 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2025"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #005f8a;
--color-dimmed: #4a6a7a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.7rem;
}
h1 {
color: #005f8a;
}
section.invert h1 {
color: #fff;
}
pre {
background: #0f1e2e;
color: #00b4d8;
border-radius: 8px;
border-left: 3px solid #005f8a;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a3a4a;
color: #00b4d8;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #001520 -->
# node.js – Advanced
---
# node.js – Fun Facts
- Entwickelt von Ryan Dahl in 2009
- Erste serverseitige Laufzeitumgebung in JavaScript (C++)
- Inspiriert von Nginx (Non-blocking I/O)
**Alternativen heute:**
- **Deno** (2020): Rust, Tokio
- **Bun** (2022): Zig
---
# process – Prozess-Steuerung
```javascript
process.on("SIGINT", () => {
console.log("Received SIGINT. Closing server...");
server.close(() => {
console.log("Server closed.");
process.exit(0);
});
});
// Signale
process.exit(0); // Erfolgreich
process.exit(1); // Fehler
```
---
# node.js Module System
```javascript
// ES Modules
import express from 'express';
import { port } from './src/config/constants.js';
// CommonJS
const fs = require('fs');
```
---
# HTTP Request mit node-fetch
```javascript
// Node.js 18+ hat fetch eingebaut
const res = await fetch('https://api.example.com/data');
const data = await res.json();
// Ältere Versionen: node-fetch
import fetch from 'node-fetch';
```
---
# Web Server, Builder, Bundler
```bash
# Boilerplates erstellen
npm create vite@latest my-app -- --template react
npm create svelte@latest
npm create astro@latest
# nuxt
npm install nuxt
npm run dev
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/js-frameworks-overview.png)
---
# Express – Grundlagen
```javascript
import express from 'express';
const app = express();
app.listen(port, () => {
console.log(`Server läuft auf Port ${port}`);
});
```
---
# Express – Middleware
```javascript
app.use(express.json());
app.use('/api', (req, res, next) => {
console.log('Time:', Date.now());
next();
});
app.use((req, res, next) => {
console.log('Middleware 2');
next();
});
```
---
# Express – CRUD Routes
```javascript
app.get('/api/:key', async (req, res) => {
const context = cache.get(req.params.key);
res.json({ context });
});
app.post('/api/:key', async (req, res) => {
const payload = req.body;
res.json({ created: cache.set(req.params.key, payload) });
});
app.put('/api/:key', async (req, res) => {
const payload = req.body;
res.json({ updated: cache.update(req.params.key, payload) });
});
app.delete('/api/:key', async (req, res) => {
cache.remove(req.params.key);
res.json({ deleted: req.params.key });
});
```
---
# Express – server.listen
```javascript
const server = app.listen(port, () => {
console.log(`Server läuft auf Port ${port}`);
});
server.on('error', (err) => {
console.error('Server error:', err);
});
server.close(() => {
console.log('Server geschlossen');
});
```
---
# WebSockets
```javascript
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
console.log('Client verbunden');
ws.on('message', (data) => {
console.log('Empfangen:', data.toString());
ws.send('Pong');
});
});
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/ts-js-compilation.png)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/docker-orchestration.png)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/test-automation-trophy.png)
---
# Fragen?
1. Wozu dient `process.on('SIGINT')`?
2. Was macht `app.use(express.json())`?
3. Wie erstellst du einen GET-Endpoint mit Express?
View File
Whitespace-only changes.
@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Browser–Server HTTP Sequenz</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--border: #cbd5e1;
--bg-soft: #f8fafc;
--hl: #005f8a;
--req: #2563eb;
--res: #16a34a;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 24px 32px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 24px; font-size: 0.88rem; text-align: center; }
.diagram { display: grid; grid-template-columns: 140px 1fr 140px; gap: 0; align-items: start; }
/* Actors */
.actor {
display: flex; flex-direction: column; align-items: center; gap: 6px;
font-weight: 700; font-size: 0.9rem;
}
.actor-box {
border: 2px solid var(--dark); border-radius: 8px;
padding: 8px 18px; background: var(--bg-soft);
white-space: nowrap;
}
.lifeline {
width: 2px; background: var(--border);
height: 100%; min-height: 280px;
margin: 0 auto;
}
/* Messages */
.messages { display: flex; flex-direction: column; gap: 0; padding-top: 48px; }
.msg { display: flex; flex-direction: column; margin-bottom: 6px; }
.msg-arrow {
display: flex; align-items: center; gap: 0; position: relative;
}
.msg-line {
flex: 1; height: 2px;
}
.msg-line.req { background: var(--req); }
.msg-line.res { background: var(--res); background: repeating-linear-gradient(90deg, var(--res) 0 8px, transparent 8px 13px); }
.arrowhead-r { width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid var(--req); }
.arrowhead-l { width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-right: 10px solid var(--res); }
.msg-label {
font-size: 0.75rem; font-family: ui-monospace, monospace;
padding: 2px 0 6px; text-align: center;
}
.msg-label.req { color: var(--req); }
.msg-label.res { color: var(--res); }
.gap { height: 10px; }
.legend {
margin-top: 20px; display: flex; gap: 24px; justify-content: center;
font-size: 0.82rem;
}
.leg { display: flex; align-items: center; gap: 8px; }
.leg-line { width: 28px; height: 2px; }
.leg-line.req { background: var(--req); }
.leg-line.res { background: repeating-linear-gradient(90deg, var(--res) 0 6px, transparent 6px 10px); }
</style>
</head>
<body>
<h1>Browser–Server: HTTP Kommunikation</h1>
<p class="sub">Jede Ressource = eigener Request — Browser blockiert nicht, lädt parallel</p>
<div class="diagram">
<!-- Browser actor -->
<div class="actor">
<div class="actor-box">🌐 Browser</div>
<div class="lifeline"></div>
</div>
<!-- Messages -->
<div class="messages">
<div class="msg">
<div class="msg-arrow"><div class="msg-line req"></div><div class="arrowhead-r"></div></div>
<div class="msg-label req">GET /products</div>
</div>
<div class="msg">
<div class="msg-arrow"><div class="arrowhead-l"></div><div class="msg-line res"></div></div>
<div class="msg-label res">HTTP 200 + index.html</div>
</div>
<div class="gap"></div>
<div class="msg">
<div class="msg-arrow"><div class="msg-line req"></div><div class="arrowhead-r"></div></div>
<div class="msg-label req">GET /style.css</div>
</div>
<div class="msg">
<div class="msg-arrow"><div class="arrowhead-l"></div><div class="msg-line res"></div></div>
<div class="msg-label res">HTTP 200 + style.css</div>
</div>
<div class="gap"></div>
<div class="msg">
<div class="msg-arrow"><div class="msg-line req"></div><div class="arrowhead-r"></div></div>
<div class="msg-label req">GET /script.js</div>
</div>
<div class="msg">
<div class="msg-arrow"><div class="arrowhead-l"></div><div class="msg-line res"></div></div>
<div class="msg-label res">HTTP 200 + script.js</div>
</div>
<div class="gap"></div>
<div class="msg">
<div class="msg-arrow"><div class="msg-line req"></div><div class="arrowhead-r"></div></div>
<div class="msg-label req">GET /api/products</div>
</div>
<div class="msg">
<div class="msg-arrow"><div class="arrowhead-l"></div><div class="msg-line res"></div></div>
<div class="msg-label res">HTTP 200 + JSON</div>
</div>
</div>
<!-- Server actor -->
<div class="actor">
<div class="actor-box">🖥️ Server</div>
<div class="lifeline"></div>
</div>
</div>
<div class="legend">
<div class="leg"><div class="leg-line req"></div><span style="color:var(--req)">Request (Browser → Server)</span></div>
<div class="leg"><div class="leg-line res"></div><span style="color:var(--res)">Response (Server → Browser)</span></div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Docker: Service Orchestration</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--border: #cbd5e1;
--bg-soft: #f8fafc;
--blue: #2563eb;
--red: #dc2626;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 36px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; }
.sub { color: var(--muted); margin-bottom: 28px; font-size: 0.88rem; }
.diagram { display: flex; align-items: center; gap: 0; }
.node {
display: flex; flex-direction: column; align-items: center; justify-content: center;
border: 2px solid var(--dark); border-radius: 8px;
padding: 12px 16px; background: var(--bg-soft);
font-weight: 700; font-size: 0.9rem; text-align: center; min-width: 90px;
}
.node .sub-label { font-size: 0.72rem; font-weight: 400; color: var(--muted); margin-top: 3px; }
.client { border-radius: 50%; width: 72px; height: 72px; padding: 0; border-color: var(--red); }
.proxy { background: #eff6ff; border-color: var(--blue); min-width: 100px; }
.docker-box {
border: 2px dashed var(--blue); border-radius: 12px;
padding: 16px 20px; display: flex; align-items: center; gap: 0;
background: #f0f7ff;
position: relative;
}
.docker-label {
position: absolute; top: -11px; left: 14px;
background: #fff; padding: 0 6px;
font-size: 0.72rem; font-weight: 700; color: var(--blue);
text-transform: uppercase; letter-spacing: 0.06em;
}
.services { display: flex; flex-direction: column; gap: 12px; }
.db-col { display: flex; flex-direction: column; align-items: center; justify-content: center; }
/* arrows */
.arr { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 0 6px; }
.arr-h { display: flex; flex-direction: column; gap: 3px; align-items: center; }
.line { height: 2px; width: 44px; }
.line.blue { background: var(--blue); }
.line.red { background: var(--red); }
.line.dashed-blue { background: repeating-linear-gradient(90deg, var(--blue) 0 6px, transparent 6px 10px); }
.line.dashed-red { background: repeating-linear-gradient(90deg, var(--red) 0 6px, transparent 6px 10px); }
.arrowhead-r::after { content: '▶'; font-size: 0.65rem; color: inherit; }
.arrowhead-l::before { content: '◀'; font-size: 0.65rem; color: inherit; }
.arr-label { font-size: 0.65rem; color: var(--muted); white-space: nowrap; }
.arr-v { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 2px 0; }
.line-v { width: 2px; height: 28px; }
.line-v.blue { background: var(--blue); }
.line-v.dashed-blue { background: repeating-linear-gradient(180deg, var(--blue) 0 5px, transparent 5px 9px); }
.arr-v .arrowhead-d::after { content: '▼'; font-size: 0.65rem; color: var(--blue); }
.gap-col { display: flex; flex-direction: column; gap: 12px; align-items: center; justify-content: center; }
</style>
</head>
<body>
<h1>Docker: Service Orchestration</h1>
<p class="sub">Client kommuniziert nur mit dem Reverse Proxy — interne Services bleiben isoliert</p>
<div class="diagram">
<!-- Client -->
<div class="node client" style="color:var(--red); border-color:var(--red);">
Client
<div class="sub-label">Browser /<br>Web App</div>
</div>
<!-- arrows client → proxy -->
<div class="arr">
<div class="arr-h" style="color:var(--red)">
<div style="display:flex;align-items:center;gap:2px">
<div class="line red" style="width:36px"></div>
<span class="arrowhead-r" style="color:var(--red)"></span>
</div>
<div class="arr-label">localhost:10007</div>
</div>
<div style="height:8px"></div>
<div class="arr-h" style="color:var(--red)">
<div style="display:flex;align-items:center;gap:2px">
<span class="arrowhead-l" style="color:var(--red)"></span>
<div class="line dashed-red" style="width:36px"></div>
</div>
<div class="arr-label">response</div>
</div>
</div>
<!-- Docker compose boundary -->
<div class="docker-box">
<div class="docker-label">docker compose</div>
<!-- Reverse Proxy -->
<div class="node proxy">
Reverse<br>Proxy
<div class="sub-label">:10007</div>
</div>
<!-- arrows proxy → services -->
<div class="gap-col" style="padding: 0 8px;">
<div class="arr-h" style="color:var(--blue)">
<div style="display:flex;align-items:center;gap:2px">
<div class="line blue" style="width:28px"></div>
<span class="arrowhead-r" style="color:var(--blue)"></span>
</div>
<div class="arr-label">/api/*</div>
</div>
<div style="height:8px"></div>
<div class="arr-h" style="color:var(--blue)">
<div style="display:flex;align-items:center;gap:2px">
<div class="line blue" style="width:28px"></div>
<span class="arrowhead-r" style="color:var(--blue)"></span>
</div>
<div class="arr-label">/*</div>
</div>
</div>
<!-- Services column -->
<div class="services">
<div class="node" style="background:#dbeafe; border-color:var(--blue);">
Express API
<div class="sub-label">:3000</div>
</div>
<div class="node" style="background:#dcfce7; border-color:#16a34a;">
Web App
<div class="sub-label">:5173</div>
</div>
</div>
<!-- arrows → DB -->
<div class="gap-col" style="padding: 0 6px;">
<div class="arr-h" style="color:var(--blue)">
<div style="display:flex;align-items:center;gap:2px">
<div class="line dashed-blue" style="width:24px"></div>
<span class="arrowhead-r" style="color:var(--blue)"></span>
</div>
<div class="arr-label">:5432</div>
</div>
<div style="height:8px"></div>
<!-- web app does not connect to DB -->
<div style="width:48px"></div>
</div>
<!-- DB -->
<div class="db-col">
<div class="node" style="background:#fef9c3; border-color:#ca8a04; min-width:70px;">
DB
<div class="sub-label">PostgreSQL</div>
</div>
</div>
</div><!-- /docker-box -->
</div><!-- /diagram -->
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>JavaScript Frameworks – Übersicht</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 24px 28px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 24px; font-size: 0.88rem; text-align: center; }
.grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.col {
border-radius: 12px; padding: 18px 12px 16px;
display: flex; flex-direction: column; gap: 10px;
}
.col.active { outline: 2px solid var(--dark); outline-offset: 2px; }
.col-title {
font-size: 0.78rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em; color: var(--dark); text-align: center;
border-bottom: 1px solid rgba(0,0,0,0.12); padding-bottom: 8px; margin-bottom: 2px;
}
.items { display: flex; flex-direction: column; gap: 6px; }
.item {
display: flex; align-items: center; gap: 7px;
font-size: 0.82rem; font-weight: 600;
}
.item .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.item .note { font-size: 0.7rem; font-weight: 400; color: var(--muted); display: block; }
.css-col { background: #f1f5f9; }
.fe-col { background: #fce7f3; }
.render-col { background: #ede9fe; }
.build-col { background: #dbeafe; }
.be-col { background: #d1fae5; }
</style>
</head>
<body>
<h1>JavaScript Frameworks – Übersicht</h1>
<p class="sub">Kategorien des modernen JS-Ökosystems</p>
<div class="grid">
<div class="col css-col">
<div class="col-title">CSS Frameworks</div>
<div class="items">
<div class="item"><div class="dot" style="background:#38bdf8"></div><span>Tailwind CSS<span class="note">Utility-first</span></span></div>
<div class="item"><div class="dot" style="background:#7c3aed"></div><span>Bootstrap<span class="note">Komponenten</span></span></div>
<div class="item"><div class="dot" style="background:#e879f9"></div><span>Pico CSS<span class="note">Classless</span></span></div>
<div class="item"><div class="dot" style="background:#f97316"></div><span>UnoCSS<span class="note">Atomic</span></span></div>
</div>
</div>
<div class="col fe-col">
<div class="col-title">Frontend Frameworks</div>
<div class="items">
<div class="item"><div class="dot" style="background:#61dafb"></div><span>React<span class="note">Meta / Virtual DOM</span></span></div>
<div class="item"><div class="dot" style="background:#ff3e00"></div><span>Svelte<span class="note">Compiler-based</span></span></div>
<div class="item"><div class="dot" style="background:#42b883"></div><span>Vue<span class="note">Progressive</span></span></div>
<div class="item"><div class="dot" style="background:#dd0031"></div><span>Angular<span class="note">Google / Full</span></span></div>
</div>
</div>
<div class="col render-col">
<div class="col-title">Rendering Frameworks</div>
<div class="items">
<div class="item"><div class="dot" style="background:#000"></div><span>Next.js<span class="note">React / SSR</span></span></div>
<div class="item"><div class="dot" style="background:#ff3e00"></div><span>SvelteKit<span class="note">Svelte / SSR</span></span></div>
<div class="item"><div class="dot" style="background:#42b883"></div><span>Nuxt<span class="note">Vue / SSR</span></span></div>
<div class="item"><div class="dot" style="background:#ff5d01"></div><span>Astro<span class="note">Islands Arch.</span></span></div>
<div class="item"><div class="dot" style="background:#0ea5e9"></div><span>Gatsby<span class="note">React / SSG</span></span></div>
</div>
</div>
<div class="col build-col">
<div class="col-title">Build Tools &amp; Bundler</div>
<div class="items">
<div class="item"><div class="dot" style="background:#646cff"></div><span>Vite<span class="note">Dev-Server / HMR</span></span></div>
<div class="item"><div class="dot" style="background:#2b3a42"></div><span>Webpack<span class="note">Bundler</span></span></div>
<div class="item"><div class="dot" style="background:#f9b640"></div><span>esbuild<span class="note">Go / ultra-fast</span></span></div>
<div class="item"><div class="dot" style="background:#3178c6"></div><span>tsc<span class="note">TypeScript</span></span></div>
<div class="item"><div class="dot" style="background:#cc3534"></div><span>Rollup<span class="note">Libraries</span></span></div>
</div>
</div>
<div class="col be-col active">
<div class="col-title">Backend Frameworks</div>
<div class="items">
<div class="item"><div class="dot" style="background:#68a063"></div><span>Express<span class="note">Minimal / de-facto</span></span></div>
<div class="item"><div class="dot" style="background:#3178c6"></div><span>Fastify<span class="note">Performant</span></span></div>
<div class="item"><div class="dot" style="background:#5a45ff"></div><span>AdonisJS<span class="note">Full-stack</span></span></div>
<div class="item"><div class="dot" style="background:#e11d48"></div><span>NestJS<span class="note">Angular-style</span></span></div>
<div class="item"><div class="dot" style="background:#000"></div><span>Hono<span class="note">Edge-ready</span></span></div>
</div>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Node.js – Einsatzgebiete</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 32px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 28px; font-size: 0.88rem; text-align: center; }
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.card {
border-radius: 12px; padding: 28px 16px 24px;
display: flex; flex-direction: column; align-items: center; gap: 14px;
text-align: center;
}
.card .icon { font-size: 2rem; line-height: 1; }
.card .title { font-size: 1.1rem; font-weight: 700; }
.card .desc { font-size: 0.8rem; color: var(--muted); line-height: 1.5; }
.card .tags { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; margin-top: 4px; }
.tag { font-size: 0.72rem; background: rgba(0,0,0,0.07); border-radius: 99px; padding: 2px 9px; font-family: ui-monospace, monospace; }
.cli { background: #fce7f3; }
.api { background: #ede9fe; }
.web { background: #dbeafe; }
.ws { background: #d1fae5; }
</style>
</head>
<body>
<h1>Node.js – Einsatzgebiete</h1>
<p class="sub">Vier Hauptkategorien serverseitiger JavaScript-Anwendungen</p>
<div class="grid">
<div class="card cli">
<div class="icon">⌨️</div>
<div class="title">CLI</div>
<div class="desc">Kommandozeilen-Tools, Skripte, Build-Prozesse, Automatisierung</div>
<div class="tags">
<span class="tag">npm scripts</span>
<span class="tag">process.argv</span>
<span class="tag">fs</span>
</div>
</div>
<div class="card api">
<div class="icon">🔌</div>
<div class="title">API Server</div>
<div class="desc">REST- und GraphQL-APIs, JSON-Endpunkte, CRUD-Operationen</div>
<div class="tags">
<span class="tag">express</span>
<span class="tag">GET/POST</span>
<span class="tag">JSON</span>
</div>
</div>
<div class="card web">
<div class="icon">🌐</div>
<div class="title">Web Server</div>
<div class="desc">Statische Dateien ausliefern, Server-Side Rendering, Reverse Proxy</div>
<div class="tags">
<span class="tag">http</span>
<span class="tag">SSR</span>
<span class="tag">next.js</span>
</div>
</div>
<div class="card ws">
<div class="icon">⚡</div>
<div class="title">Web Sockets</div>
<div class="desc">Echtzeit-Kommunikation, Chat, Live-Updates, bidirektional</div>
<div class="tags">
<span class="tag">ws</span>
<span class="tag">socket.io</span>
<span class="tag">events</span>
</div>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Test Automation Trophy</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--border: #cbd5e1;
--bg-soft: #f8fafc;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 32px; display: flex; flex-direction: column; align-items: center; }
h1 { margin: 0 0 4px; font-size: 1.55rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 28px; font-size: 0.92rem; text-align: center; }
.trophy { display: flex; flex-direction: column; align-items: center; gap: 0; width: 480px; }
.layer {
display: flex; align-items: center; justify-content: center;
font-weight: 700; font-size: 1.05rem; color: var(--dark);
border-radius: 6px; transition: opacity 0.2s;
}
.layer .count {
font-size: 0.78rem; font-weight: 400; color: var(--muted);
margin-left: 8px;
}
.e2e { background: #fca5a5; width: 40%; height: 54px; clip-path: polygon(10% 100%, 90% 100%, 100% 0%, 0% 0%); }
.integration{ background: #60a5fa; width: 80%; height: 86px; }
.unit { background: #c4b5fd; width: 40%; height: 54px; clip-path: polygon(0% 100%, 100% 100%, 85% 0%, 15% 0%); }
.static { background: #fde68a; width: 28%; height: 60px; clip-path: polygon(0% 0%, 100% 0%, 80% 100%, 20% 100%); }
.legend {
margin-top: 28px; display: grid; grid-template-columns: 1fr 1fr;
gap: 8px 24px; font-size: 0.88rem; width: 480px;
}
.leg { display: flex; align-items: center; gap: 10px; }
.swatch { width: 16px; height: 16px; border-radius: 3px; flex-shrink: 0; }
.leg strong { display: block; }
.leg span { color: var(--muted); font-size: 0.82rem; }
</style>
</head>
<body>
<h1>Test Automation Trophy</h1>
<p class="sub">Schicht-Modell nach Kent C. Dodds — Breite = empfohlener Anteil</p>
<div class="trophy">
<div class="layer e2e">E2E</div>
<div class="layer integration">Integration</div>
<div class="layer unit">Unit</div>
<div class="layer static">Static</div>
</div>
<div class="legend">
<div class="leg"><div class="swatch" style="background:#fde68a"></div><div><strong>Static</strong><span>Linting, Type-Check, Format</span></div></div>
<div class="leg"><div class="swatch" style="background:#c4b5fd"></div><div><strong>Unit</strong><span>Einzelne Funktionen / Komponenten</span></div></div>
<div class="leg"><div class="swatch" style="background:#60a5fa"></div><div><strong>Integration</strong><span>Zusammenspiel mehrerer Teile ← Fokus</span></div></div>
<div class="leg"><div class="swatch" style="background:#fca5a5"></div><div><strong>End to End</strong><span>Ganzer User-Flow im Browser</span></div></div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>TypeScript → JavaScript Compilation</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--border: #cbd5e1;
--bg-soft: #f8fafc;
--ts: #3178c6;
--js: #f7df1e;
--remove: #dc2626;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 24px 28px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 24px; font-size: 0.88rem; text-align: center; }
.panels { display: grid; grid-template-columns: 1fr 48px 1fr 48px 1fr; align-items: start; gap: 0; }
.panel { border: 2px solid var(--border); border-radius: 10px; overflow: hidden; }
.panel-head {
padding: 8px 14px; font-size: 0.78rem; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.07em;
display: flex; align-items: center; gap: 8px;
}
.panel-body { padding: 14px; min-height: 100vh; display: flex; flex-direction: column; justify-content: center; }
.ts .panel-head { background: var(--ts); color: #fff; }
.strip .panel-head { background: #fee2e2; color: var(--remove); }
.js .panel-head { background: var(--js); color: var(--dark); }
pre {
margin: 0; font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 0.78rem; line-height: 1.65; white-space: pre;
}
.removed { color: var(--remove); text-decoration: line-through; background: #fee2e2; border-radius: 2px; }
.kept { color: #166534; }
.kw { color: var(--ts); }
.kw-js { color: #ca8a04; }
.type-ann{ color: #7c3aed; }
.str { color: #16a34a; }
.fn { color: #0369a1; }
.arrow-col {
display: flex; flex-direction: column; align-items: center;
justify-content: center; padding-top: 52px; gap: 4px;
}
.arrow-shaft { width: 2px; height: 32px; background: var(--muted); }
.arrow-head { width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 10px solid var(--muted); }
.arrow-label { font-size: 0.68rem; color: var(--muted); writing-mode: vertical-rl; text-orientation: mixed; letter-spacing: 0.05em; margin-top: 4px; white-space: nowrap; }
</style>
</head>
<body>
<h1>TypeScript → JavaScript Compilation</h1>
<p class="sub">Der TypeScript-Compiler entfernt alle Typ-Annotationen — nur JavaScript bleibt</p>
<div class="panels">
<!-- TypeScript -->
<div class="panel ts">
<div class="panel-head">📘 TypeScript-Datei</div>
<div class="panel-body">
<pre><span class="kw">type</span> <span class="type-ann">Result</span> = <span class="str">"pass"</span> | <span class="str">"fail"</span>;
<span class="kw">function</span> <span class="fn">verify</span>(result: <span class="type-ann">Result</span>) {
<span class="kw">if</span> (result === <span class="str">"pass"</span>) {
console.<span class="fn">log</span>(<span class="str">"Passed"</span>);
} <span class="kw">else</span> {
console.<span class="fn">log</span>(<span class="str">"Failed"</span>);
}
}</pre>
</div>
</div>
<!-- Arrow 1 -->
<div class="arrow-col">
<div class="arrow-shaft"></div>
<div class="arrow-head"></div>
<div class="arrow-label">tsc</div>
</div>
<!-- Strip phase -->
<div class="panel strip">
<div class="panel-head">✂️ Typen werden entfernt</div>
<div class="panel-body">
<pre><span class="removed">type Result = "pass" | "fail";</span>
<span class="kw">function</span> <span class="fn">verify</span>(result<span class="removed">: Result</span>) {
<span class="kw">if</span> (result === <span class="str">"pass"</span>) {
console.<span class="fn">log</span>(<span class="str">"Passed"</span>);
} <span class="kw">else</span> {
console.<span class="fn">log</span>(<span class="str">"Failed"</span>);
}
}</pre>
</div>
</div>
<!-- Arrow 2 -->
<div class="arrow-col">
<div class="arrow-shaft"></div>
<div class="arrow-head"></div>
<div class="arrow-label">output</div>
</div>
<!-- JavaScript -->
<div class="panel js">
<div class="panel-head">📄 JavaScript-Datei</div>
<div class="panel-body">
<pre><span class="kw-js">function</span> <span class="fn">verify</span>(result) {
<span class="kw-js">if</span> (result === <span class="str">"pass"</span>) {
console.<span class="fn">log</span>(<span class="str">"Passed"</span>);
} <span class="kw-js">else</span> {
console.<span class="fn">log</span>(<span class="str">"Failed"</span>);
}
}</pre>
</div>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

@@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Web Ecosystem – Schichten</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
}
html, body { margin: 0; padding: 0; background: #fff; min-height: 100vh; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 20px 28px; display: flex; flex-direction: column; align-items: center; }
h1 { margin: 0 0 4px; font-size: 1.45rem; text-align: center; }
.sub { color: var(--muted); margin-bottom: 20px; font-size: 0.88rem; text-align: center; }
.rings-wrap { position: relative; width: 520px; height: 520px; }
.ring {
position: absolute; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
top: 50%; left: 50%; transform: translate(-50%, -50%);
}
/* layers from outside in */
.r-css-libs { width: 520px; height: 520px; background: #f0fdf4; border: 2px solid #86efac; }
.r-frameworks{ width: 400px; height: 400px; background: #eff6ff; border: 2px solid #93c5fd; }
.r-bundlers { width: 290px; height: 290px; background: #fdf4ff; border: 2px solid #d8b4fe; }
.r-postcss { width: 196px; height: 196px; background: #fff7ed; border: 2px solid #fdba74; }
.r-core { width: 116px; height: 116px; background: var(--dark); border: none; color: #fff; flex-direction: column; gap: 2px; text-align: center; }
.r-core span { font-size: 0.72rem; font-weight: 700; line-height: 1.3; }
/* floating labels */
.label {
position: absolute; font-size: 0.72rem; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.06em;
background: rgba(255,255,255,0.85); padding: 2px 7px;
border-radius: 99px; white-space: nowrap;
}
/* ring label positions — top of each ring */
.lbl-css-libs { top: 12px; left: 50%; transform: translateX(-50%); color: #16a34a; }
.lbl-frameworks { top: 72px; left: 50%; transform: translateX(-50%); color: #2563eb; }
.lbl-bundlers { top: 128px; left: 50%; transform: translateX(-50%); color: #7c3aed; }
.lbl-postcss { top: 178px; left: 50%; transform: translateX(-50%); color: #ea580c; }
/* item pills scattered in each ring band */
.pill {
position: absolute; font-size: 0.7rem; font-weight: 600;
padding: 3px 9px; border-radius: 99px; white-space: nowrap;
background: rgba(255,255,255,0.9); border: 1px solid rgba(0,0,0,0.10);
}
</style>
</head>
<body>
<h1>Web Ecosystem – Schichten</h1>
<p class="sub">Von innen nach außen: Kern → Standards → Werkzeuge → Frameworks → CSS-Utilities</p>
<div class="rings-wrap">
<!-- Rings (painted back-to-front) -->
<div class="ring r-css-libs"></div>
<div class="ring r-frameworks"></div>
<div class="ring r-bundlers"></div>
<div class="ring r-postcss"></div>
<div class="ring r-core">
<span>JS</span>
<span>HTML</span>
<span>CSS</span>
</div>
<!-- Ring labels -->
<div class="label lbl-css-libs">CSS Utilities &amp; Libraries</div>
<div class="label lbl-frameworks">Frontend / Backend Frameworks</div>
<div class="label lbl-bundlers">Bundler &amp; Build Tools</div>
<div class="label lbl-postcss">PostCSS / Preprocessors</div>
<!-- CSS Libs band (outer ring) -->
<div class="pill" style="top:52px; left:30px; color:#16a34a;">Tailwind</div>
<div class="pill" style="top:60px; right:24px; color:#16a34a;">Bootstrap</div>
<div class="pill" style="bottom:52px;left:38px; color:#16a34a;">shadcn/ui</div>
<div class="pill" style="bottom:56px;right:28px;color:#16a34a;">Pico CSS</div>
<div class="pill" style="top:50%; left:4px; transform:translateY(-50%); color:#16a34a;">UnoCSS</div>
<div class="pill" style="top:50%; right:4px; transform:translateY(-50%); color:#16a34a;">DaisyUI</div>
<!-- Frameworks band -->
<div class="pill" style="top:88px; left:86px; color:#2563eb;">React</div>
<div class="pill" style="top:88px; right:72px; color:#2563eb;">Vue</div>
<div class="pill" style="bottom:88px;left:72px; color:#2563eb;">Svelte</div>
<div class="pill" style="bottom:88px;right:60px;color:#2563eb;">Angular</div>
<div class="pill" style="top:42%; left:60px; color:#2563eb;">Next.js</div>
<div class="pill" style="top:56%; left:60px; color:#2563eb;">Express</div>
<div class="pill" style="top:46%; right:54px; color:#2563eb;">Nuxt</div>
<div class="pill" style="top:58%; right:54px; color:#2563eb;">Fastify</div>
<!-- Bundlers band -->
<div class="pill" style="top:148px; left:145px; color:#7c3aed;">Vite</div>
<div class="pill" style="top:148px; right:132px;color:#7c3aed;">Webpack</div>
<div class="pill" style="bottom:145px;left:134px;color:#7c3aed;">esbuild</div>
<div class="pill" style="bottom:145px;right:120px;color:#7c3aed;">Rollup</div>
<!-- PostCSS band -->
<div class="pill" style="top:196px; left:50%; transform:translateX(-50%); color:#ea580c;">PostCSS</div>
<div class="pill" style="bottom:196px;left:50%;transform:translateX(-50%); color:#ea580c;">Sass / SCSS</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB