From 7f07efe05d4f1df7c0fb9a67a652f02cab6b7eab Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Mon, 12 Oct 2026 17:15:29 +0200 Subject: [PATCH] feat(marke): Logo, Banner, Favicons und Manifest-Icons Alle Varianten aus dem Symbol der Vorgabe per Skript (pnpm marke); Texte als Pfade, damit Wortmarke und Banner ohne installierte Schrift gleich aussehen. Closes #017 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 + docs/issues/017-branding.md | 17 +- docs/issues/README.md | 2 +- package.json | 6 +- pnpm-lock.yaml | 152 +++++++++++++++ public/brand/apple-touch-icon.png | Bin 0 -> 2925 bytes public/brand/avatar.svg | 8 + public/brand/banner.png | Bin 0 -> 47848 bytes public/brand/banner.svg | 29 +++ public/brand/favicon-16.png | Bin 0 -> 496 bytes public/brand/favicon-32.png | Bin 0 -> 887 bytes public/brand/icon-192.png | Bin 0 -> 4909 bytes public/brand/icon-512.png | Bin 0 -> 14345 bytes public/brand/icon-maskable-512.png | Bin 0 -> 9431 bytes public/brand/icon-small.svg | 5 + public/brand/logo-light.svg | 8 + public/brand/logo.svg | 8 + public/brand/symbol-light.svg | 5 + public/brand/symbol.svg | 2 +- scripts/marke-erzeugen.ts | 296 +++++++++++++++++++++++++++++ src/app/layout.tsx | 10 +- src/app/manifest.ts | 20 ++ tests/marke.test.ts | 68 +++++++ 23 files changed, 629 insertions(+), 9 deletions(-) create mode 100644 public/brand/apple-touch-icon.png create mode 100644 public/brand/avatar.svg create mode 100644 public/brand/banner.png create mode 100644 public/brand/banner.svg create mode 100644 public/brand/favicon-16.png create mode 100644 public/brand/favicon-32.png create mode 100644 public/brand/icon-192.png create mode 100644 public/brand/icon-512.png create mode 100644 public/brand/icon-maskable-512.png create mode 100644 public/brand/icon-small.svg create mode 100644 public/brand/logo-light.svg create mode 100644 public/brand/logo.svg create mode 100644 public/brand/symbol-light.svg create mode 100644 scripts/marke-erzeugen.ts create mode 100644 src/app/manifest.ts create mode 100644 tests/marke.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 16129da..2bb2286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). ## [Unveröffentlicht] ### Hinzugefügt +- Marken-Dateien nach Vorgabe unter `public/brand/`: Symbol (dunkel/hell), kleines Icon, Avatar, Logo (dunkel/hell), Banner 1280×640, Favicons, Apple-Touch- und Manifest-Icons; erzeugt mit `pnpm marke` (#017) +- Web-App-Manifest; Favicon passt sich hellem und dunklem Browser an (#017) ### Geändert diff --git a/docs/issues/017-branding.md b/docs/issues/017-branding.md index 57e2ae4..08ba02a 100644 --- a/docs/issues/017-branding.md +++ b/docs/issues/017-branding.md @@ -1,5 +1,5 @@ # #017 Branding-Assets -**Status:** offen +**Status:** erledigt **Meilenstein:** v0.6.0 **Labels:** design **Geschätzt:** 4 h **Tatsächlich:** – @@ -8,14 +8,21 @@ Alle Logo-Varianten, Banner, Favicons, Manifest-Icons nach Vorgabe. ## Aufgaben -- [ ] symbol(-light), icon-small, avatar, logo(-light), banner 1280×640 -- [ ] Favicon 16/32, Apple-Touch-Icon, Manifest-Icons per Skript aus SVG +- [x] symbol(-light), icon-small, avatar, logo(-light), banner 1280×640 (+ banner.png für die Social Preview) +- [x] Favicon 16/32, Apple-Touch-Icon, Manifest-Icons (192, 512, maskierbar) per Skript aus SVG (`pnpm marke`) ## Akzeptanzkriterien -- [ ] Darstellung in beiden Themes geprüft +- [x] Darstellung in beiden Themes geprüft (Vorschau-Tafel dunkel/hell, Favicons auf hellem und dunklem Tab) ## Abhängigkeiten #001 ## Notizen / Entscheidungen -– +- **Texte als Pfade:** Wortmarke und Banner sehen überall gleich aus, auch ohne installierte Schrift. + Die TTFs (JetBrains Mono 2.304, Space Grotesk 2.0.0, OFL) lädt `pnpm marke` mit SHA-256-Prüfung + nach `node_modules/.cache`; eingecheckt werden nur die Ergebnisse. +- opentype.js 1.3.5 kennt die Ligatur-Regeln von JetBrains Mono nicht und schreibt in `toPathData` + gelegentlich „NaN“ – deshalb Glyph für Glyph gesetzt und Pfaddaten selbst geschrieben. +- `icon-small.svg` passt sich per `prefers-color-scheme` an; die PNG-Favicons sind dicke Linien auf + Teal, weil 16 px mit den dünnen Linien des Symbols nicht lesbar waren. +- Unterzeile im Banner 32 statt 34 px – sonst breiter als die Ränder. diff --git a/docs/issues/README.md b/docs/issues/README.md index f339e75..65ffa88 100644 --- a/docs/issues/README.md +++ b/docs/issues/README.md @@ -20,7 +20,7 @@ Details und Architektur: [../architektur.md](../architektur.md). Zeiten werden a | [#014](014-verlauf.md) | Verlauf und Wiederholen | erledigt | v0.5.0 | 4 h | 1 h 21 min | | [#015](015-rollen-audit.md) | Rollen, Benutzer, Tokens, Audit-Log | erledigt | v0.5.0 | 6 h | 0 h 10 min | | [#016](016-oidc.md) | Anmeldung per OIDC | erledigt | v0.5.0 | 4 h | 0 h 08 min | -| [#017](017-branding.md) | Branding-Assets | offen | v0.6.0 | 4 h | – | +| [#017](017-branding.md) | Branding-Assets | erledigt | v0.6.0 | 4 h | – | | [#018](018-readme.md) | README und Dokumentation | offen | v0.6.0 | 4 h | – | | [#019](019-installer.md) | Docker-Image und LXC-Installer | offen | v0.6.0 | 6 h | – | | [#020](020-feldtest.md) | Feldtest 8.x und 9.x, Version 1.0.0 | offen | v1.0.0 | 6 h | – | diff --git a/package.json b/package.json index 9bcd679..9a0e3bc 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "typecheck": "tsc --noEmit", "worker": "tsx src/worker/main.ts", "openapi": "tsx scripts/openapi.ts", - "cli:pruefen": "scripts/cli-pruefen.sh" + "cli:pruefen": "scripts/cli-pruefen.sh", + "marke": "tsx scripts/marke-erzeugen.ts" }, "dependencies": { "@fontsource-variable/jetbrains-mono": "^5.3.0", @@ -55,8 +56,10 @@ "@commitlint/cli": "^21.2.3", "@commitlint/config-conventional": "^21.2.3", "@playwright/test": "1.63.0", + "@resvg/resvg-js": "2.6.2", "@tailwindcss/postcss": "^4.3.3", "@types/node": "^24.13.6", + "@types/opentype.js": "^1.3.10", "@types/pg": "^8.23.1", "@types/react": "^19.3.0", "@types/react-dom": "^19.3.0", @@ -68,6 +71,7 @@ "eslint-config-prettier": "^10.1.8", "husky": "^9.1.7", "lint-staged": "^17.5.1", + "opentype.js": "1.3.5", "prettier": "^3.9.9", "prisma": "7.10.0", "tailwindcss": "^4.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cfa95f3..6513595 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -233,12 +233,18 @@ importers: '@playwright/test': specifier: 1.63.0 version: 1.63.0 + '@resvg/resvg-js': + specifier: 2.6.2 + version: 2.6.2 '@tailwindcss/postcss': specifier: ^4.3.3 version: 4.3.3 '@types/node': specifier: ^24.13.6 version: 24.19.2 + '@types/opentype.js': + specifier: ^1.3.10 + version: 1.3.10 '@types/pg': specifier: ^8.23.1 version: 8.23.1 @@ -272,6 +278,9 @@ importers: lint-staged: specifier: ^17.5.1 version: 17.6.0 + opentype.js: + specifier: 1.3.5 + version: 1.3.5 prettier: specifier: ^3.9.9 version: 3.9.10 @@ -1357,6 +1366,86 @@ packages: '@types/react': optional: true + '@resvg/resvg-js-android-arm-eabi@2.6.2': + resolution: {integrity: sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@resvg/resvg-js-android-arm64@2.6.2': + resolution: {integrity: sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@resvg/resvg-js-darwin-arm64@2.6.2': + resolution: {integrity: sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@resvg/resvg-js-darwin-x64@2.6.2': + resolution: {integrity: sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': + resolution: {integrity: sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@resvg/resvg-js-linux-arm64-gnu@2.6.2': + resolution: {integrity: sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@resvg/resvg-js-linux-arm64-musl@2.6.2': + resolution: {integrity: sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@resvg/resvg-js-linux-x64-gnu@2.6.2': + resolution: {integrity: sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@resvg/resvg-js-linux-x64-musl@2.6.2': + resolution: {integrity: sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@resvg/resvg-js-win32-arm64-msvc@2.6.2': + resolution: {integrity: sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@resvg/resvg-js-win32-ia32-msvc@2.6.2': + resolution: {integrity: sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@resvg/resvg-js-win32-x64-msvc@2.6.2': + resolution: {integrity: sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@resvg/resvg-js@2.6.2': + resolution: {integrity: sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==} + engines: {node: '>= 10'} + '@rolldown/binding-android-arm-eabi@1.2.13': resolution: {integrity: sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1628,6 +1717,9 @@ packages: '@types/node@24.19.2': resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} + '@types/opentype.js@1.3.10': + resolution: {integrity: sha512-F67EFyk6j02okHz5JCgata3ZRAcZi9GLnzmkHw/rzJq3OCc8/ZVdoKrxMTYjcQP6IYHGBz2cav1cpzkOkPiPCQ==} + '@types/pg@8.23.1': resolution: {integrity: sha512-fKVHpikPdg4GKks3JuLEhvwSyvwzF23hnabPy6DD8ljVbC7+6J5dQzdv4arV6jqq57djnMgs1HKBxX4P8aBI3A==} @@ -3235,6 +3327,11 @@ packages: openid-client@6.8.8: resolution: {integrity: sha512-ZsucJA5Ad04Uv7YN4ql+s4GXNmb9uAYQwyJTsJx7CH/MX3JZioLE2pVKi1SC+YrbSLA4Px3Gi30dMjgOZtb6pA==} + opentype.js@1.3.5: + resolution: {integrity: sha512-thKDiELidAApOvXlncrpwDZKJCa9fXLEKM4+FoEWI+qTLDeNb+h7EkN+8a7KQODsB1GZ+Exz9KknkoPrEdXZDw==} + deprecated: This version should be ignored, it was meant to be published as 2.0.0 but got published as 1.3.5 by mistake. As of May 6th 2026 the latest v1 release is v1.3.4 + hasBin: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -4888,6 +4985,57 @@ snapshots: optionalDependencies: '@types/react': 19.3.0 + '@resvg/resvg-js-android-arm-eabi@2.6.2': + optional: true + + '@resvg/resvg-js-android-arm64@2.6.2': + optional: true + + '@resvg/resvg-js-darwin-arm64@2.6.2': + optional: true + + '@resvg/resvg-js-darwin-x64@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm64-gnu@2.6.2': + optional: true + + '@resvg/resvg-js-linux-arm64-musl@2.6.2': + optional: true + + '@resvg/resvg-js-linux-x64-gnu@2.6.2': + optional: true + + '@resvg/resvg-js-linux-x64-musl@2.6.2': + optional: true + + '@resvg/resvg-js-win32-arm64-msvc@2.6.2': + optional: true + + '@resvg/resvg-js-win32-ia32-msvc@2.6.2': + optional: true + + '@resvg/resvg-js-win32-x64-msvc@2.6.2': + optional: true + + '@resvg/resvg-js@2.6.2': + optionalDependencies: + '@resvg/resvg-js-android-arm-eabi': 2.6.2 + '@resvg/resvg-js-android-arm64': 2.6.2 + '@resvg/resvg-js-darwin-arm64': 2.6.2 + '@resvg/resvg-js-darwin-x64': 2.6.2 + '@resvg/resvg-js-linux-arm-gnueabihf': 2.6.2 + '@resvg/resvg-js-linux-arm64-gnu': 2.6.2 + '@resvg/resvg-js-linux-arm64-musl': 2.6.2 + '@resvg/resvg-js-linux-x64-gnu': 2.6.2 + '@resvg/resvg-js-linux-x64-musl': 2.6.2 + '@resvg/resvg-js-win32-arm64-msvc': 2.6.2 + '@resvg/resvg-js-win32-ia32-msvc': 2.6.2 + '@resvg/resvg-js-win32-x64-msvc': 2.6.2 + '@rolldown/binding-android-arm-eabi@1.2.13': optional: true @@ -5078,6 +5226,8 @@ snapshots: dependencies: undici-types: 7.24.6 + '@types/opentype.js@1.3.10': {} + '@types/pg@8.23.1': dependencies: '@types/node': 24.19.2 @@ -6848,6 +6998,8 @@ snapshots: jose: 6.2.12 oauth4webapi: 3.8.8 + opentype.js@1.3.5: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 diff --git a/public/brand/apple-touch-icon.png b/public/brand/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db2a5486529b558fc3c9fa95f9ccf8d52cdc267a GIT binary patch literal 2925 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 literal 0 HcmV?d00001 diff --git a/public/brand/avatar.svg b/public/brand/avatar.svg new file mode 100644 index 0000000..6750e24 --- /dev/null +++ b/public/brand/avatar.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/brand/banner.png b/public/brand/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..3cb9615636a33b064505ad4da64c0396d0a4957e GIT binary patch literal 47848 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/brand/favicon-16.png b/public/brand/favicon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..7dc0cb0727206fd202c092eab68e9f2da75540e3 GIT binary patch literal 496 zcmV@?_$_YcoO|bY&pmTT3_qxCxiq$+VO|qxLk$Svkp@p_V8S5=Z&a0X zj7T@EPNqPGp~Aa?(tnvY4d2A3ij6ccNo=N%n}z3v^OH-@DFaB$1UeT%BLu4~|VX zg)#-i(6#zXKT#_^=aE;LcH>IP)Vd9gtcfY&e-TU5q?|1K=Ar>yp`dcF+ZAL`A z5kovUlvQ9XfX(2?YTqcf3Ijj!&iOsNVe!Mb7sCSwMguu6@deKLLdIbm*H8pJaoK>| zyI_0($M!{JeM3S+VS#T~gfI zDDI|ujGSY@3r5YXANHNG8Tc$K{UfqHzlc#Hd6nf-@}OM`yj2)E!;yd;7+i*73ee=h z<$P*FkL)5O8VV?dkX#5#M@j*V^XiKUS$j2!(Lajd>f+WL(YUL5qi3Ya=7*J(0+?h@jBApKV3HD^ z%UD1<g`MXXHme$ zb1H-WUPp13mH!na}IpO$}1mP=_;F6cCS{06UHZ90~X@0W2iutJo~N zR=6TqcnFIPGd~_0HebbNL31R4EVMtAt*_s)XTnB=a8ZJ$umz+iwBeZMQ#wGv! zX{i`_g1uO51rXjmG&BbFW+5R|Pa!PFcBpa;!}Owt1hfZ1hB2e&oNv9=2M&b!8p?!b}JzbL4Frx{$YaRL)fmRigQxJC zl>mMp?u6x?9G-|^u1l_|k5dey)O_-{NkqD^dr(4xaQooQMc;GT<1fahIt%h%C`|wW N002ovPDHLkV1l4QnNEFW) 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 literal 0 HcmV?d00001 diff --git a/public/brand/icon-512.png b/public/brand/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..b6ebe9d11f96e4a3338bc850122f2b0f1584a8ab GIT binary patch literal 14345 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 + + + + diff --git a/public/brand/logo-light.svg b/public/brand/logo-light.svg new file mode 100644 index 0000000..a176417 --- /dev/null +++ b/public/brand/logo-light.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/brand/logo.svg b/public/brand/logo.svg new file mode 100644 index 0000000..7e0e353 --- /dev/null +++ b/public/brand/logo.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/brand/symbol-light.svg b/public/brand/symbol-light.svg new file mode 100644 index 0000000..8bd3ccf --- /dev/null +++ b/public/brand/symbol-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/brand/symbol.svg b/public/brand/symbol.svg index 14aae88..8297779 100644 --- a/public/brand/symbol.svg +++ b/public/brand/symbol.svg @@ -1,4 +1,4 @@ - + diff --git a/scripts/marke-erzeugen.ts b/scripts/marke-erzeugen.ts new file mode 100644 index 0000000..0722f79 --- /dev/null +++ b/scripts/marke-erzeugen.ts @@ -0,0 +1,296 @@ +/** + * Erzeugt alle Marken-Dateien unter public/brand/ aus dem Symbol der Vorgabe: + * + * symbol.svg, symbol-light.svg, icon-small.svg, avatar.svg, logo.svg, logo-light.svg, banner.svg, + * favicon-16.png, favicon-32.png, apple-touch-icon.png, icon-192.png, icon-512.png, + * icon-maskable-512.png + * + * Texte (Wortmarke, Banner) werden zu Pfaden – die SVGs sehen damit überall gleich aus, auch ohne + * installierte Schrift (README auf Gitea, Social Preview). Die Schriften (JetBrains Mono 2.304, + * Space Grotesk 2.0.0, beide SIL OFL) werden dafür einmal geladen, per SHA-256 geprüft und unter + * node_modules/.cache abgelegt; eingecheckt werden nur die Ergebnisse. + * + * pnpm marke + */ +import { execFileSync } from "node:child_process"; +import { createHash } from "node:crypto"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { Resvg } from "@resvg/resvg-js"; +import opentype from "opentype.js"; + +const ZIEL = "public/brand"; +const CACHE = "node_modules/.cache/proxdeploy-schriften"; + +const FARBE = { + ink: "#11161C", + panel: "#1A2129", + linie: "#2A333D", + muted: "#8B98A5", + paper: "#E6EDF3", + teal: "#2DD4BF", + tealDunkel: "#0F766E", +}; + +// ── Schriften ─────────────────────────────────────────────────────────────────────────────────── + +const ARCHIVE = { + jetbrains: { + url: "https://github.com/JetBrains/JetBrainsMono/releases/download/v2.304/JetBrainsMono-2.304.zip", + sha256: "6f6376c6ed2960ea8a963cd7387ec9d76e3f629125bc33d1fdcd7eb7012f7bbf", + }, + grotesk: { + url: "https://github.com/floriankarsten/space-grotesk/releases/download/2.0.0/SpaceGrotesk-2.0.0.zip", + sha256: "53b415577d4139248555300710bea0d268c7a5be67b93de53b716a9736cabffd", + }, +}; + +async function archivHolen(name: keyof typeof ARCHIVE): Promise { + const { url, sha256 } = ARCHIVE[name]; + mkdirSync(CACHE, { recursive: true }); + const pfad = join(CACHE, `${name}.zip`); + if (!existsSync(pfad)) { + const antwort = await fetch(url); + if (!antwort.ok) throw new Error(`${url}: HTTP ${antwort.status}`); + writeFileSync(pfad, Buffer.from(await antwort.arrayBuffer())); + } + const ist = createHash("sha256").update(readFileSync(pfad)).digest("hex"); + if (ist !== sha256) throw new Error(`${pfad}: Prüfsumme ${ist} statt ${sha256}`); + return pfad; +} + +function schriftAus(archiv: string, datei: string): opentype.Font { + const daten = execFileSync("unzip", ["-p", archiv, datei], { maxBuffer: 16 * 1024 * 1024 }); + return opentype.parse(daten.buffer.slice(daten.byteOffset, daten.byteOffset + daten.byteLength)); +} + +type Schriften = { mono: opentype.Font; monoFett: opentype.Font; grotesk: opentype.Font }; + +async function schriftenLaden(): Promise { + const jb = await archivHolen("jetbrains"); + const sg = await archivHolen("grotesk"); + return { + mono: schriftAus(jb, "fonts/ttf/JetBrainsMono-Regular.ttf"), + monoFett: schriftAus(jb, "fonts/ttf/JetBrainsMono-Bold.ttf"), + grotesk: schriftAus(sg, "SpaceGrotesk-2.0.0/ttf/static/SpaceGrotesk-Regular.ttf"), + }; +} + +/** + * Pfaddaten selbst schreiben: `toPathData` von opentype.js 1.3.5 liefert an manchen Positionen + * „NaN“ (beim Runden), und resvg bricht den Pfad dort ab. + */ +function pfadDaten(pfad: opentype.Path): string { + const z = (wert: number) => { + if (!Number.isFinite(wert)) throw new Error(`Ungültige Koordinate ${wert}`); + return String(Math.round(wert * 100) / 100); + }; + return pfad.commands + .map((b) => { + switch (b.type) { + case "M": + case "L": + return `${b.type}${z(b.x)} ${z(b.y)}`; + case "Q": + return `Q${z(b.x1)} ${z(b.y1)} ${z(b.x)} ${z(b.y)}`; + case "C": + return `C${z(b.x1)} ${z(b.y1)} ${z(b.x2)} ${z(b.y2)} ${z(b.x)} ${z(b.y)}`; + default: + return "Z"; + } + }) + .join(""); +} + +/** Text als Pfad; liefert Pfaddaten und die Breite. */ +function text(schrift: opentype.Font, inhalt: string, x: number, y: number, groesse: number) { + for (const zeichen of inhalt) { + if (schrift.charToGlyph(zeichen).index === 0 && zeichen !== " ") { + throw new Error(`${schrift.names.fullName?.en}: kein Glyph für „${zeichen}“`); + } + } + // Glyph für Glyph: opentype.js 1.3.5 scheitert an den kontextuellen Ersetzungen (Ligaturen) + // von JetBrains Mono; Logo und Banner brauchen keine. + const faktor = groesse / schrift.unitsPerEm; + let lauf = x; + const teile: string[] = []; + for (const zeichen of inhalt) { + const glyph = schrift.charToGlyph(zeichen); + teile.push(pfadDaten(glyph.getPath(lauf, y, groesse))); + lauf += (glyph.advanceWidth ?? 0) * faktor; + } + return { d: teile.filter(Boolean).join(" "), breite: lauf - x }; +} + +// ── Symbol ────────────────────────────────────────────────────────────────────────────────────── + +const SECHSECK = "M32 6 L54.5 19 V45 L32 58 L9.5 45 V19 Z"; + +function symbolInhalt(rahmen: string, akzent: string): string { + return [ + ``, + ``, + ``, + ].join("\n "); +} + +const svg = (breite: number, hoehe: number, inhalt: string, extra = "") => + `\n ${inhalt}\n\n`; + +/** Favicon-Variante: ohne Sockel, dicke Linien, passt sich dem hellen oder dunklen Browser an. */ +function iconKlein(): string { + return svg( + 64, + 64, + [ + ``, + ``, + ``, + ].join("\n "), + ); +} + +/** Avatar/App-Icon: abgerundetes Quadrat in Teal, Symbol in Ink. `randlos` für maskierbare Icons. */ +function avatar(randlos = false): string { + const hintergrund = randlos + ? `` + : ``; + // Maskierbar: Inhalt in der sicheren Zone (80 % in der Mitte). + const massstab = randlos ? 0.62 : 0.78; + const versatz = 32 * (1 - massstab); + return svg( + 64, + 64, + `${hintergrund}\n \n ${symbolInhalt(FARBE.ink, FARBE.ink)}\n `, + ); +} + +/** Favicon als Rasterbild (16/32 px): dicke Linien ohne Sockel auf Teal – auf jedem Tab-Hintergrund lesbar. */ +function faviconRaster(): string { + return svg( + 64, + 64, + [ + ``, + ``, + ``, + ``, + ``, + ].join("\n "), + ); +} + +// ── Logo: Symbol + Wortmarke ──────────────────────────────────────────────────────────────────── + +function wortmarke(s: Schriften, x: number, grundlinie: number, groesse: number, hell: boolean) { + const prox = text(s.mono, "Prox", x, grundlinie, groesse); + const deploy = text(s.monoFett, "Deploy", x + prox.breite, grundlinie, groesse); + const versalhoehe = (s.mono.tables["os2"]?.sCapHeight ?? 730) / s.mono.unitsPerEm; + const cursorX = x + prox.breite + deploy.breite + groesse * 0.12; + const cursorBreite = groesse * 0.52; + const cursorOben = grundlinie - versalhoehe * groesse - groesse * 0.06; + const cursorHoehe = versalhoehe * groesse + groesse * 0.2; + const text1 = hell ? FARBE.ink : FARBE.paper; + const akzent = hell ? FARBE.tealDunkel : FARBE.teal; + return { + inhalt: [ + ``, + ``, + ``, + ].join("\n "), + ende: cursorX + cursorBreite, + }; +} + +function logo(s: Schriften, hell: boolean): string { + const w = wortmarke(s, 78, 43, 30, hell); + const breite = Math.ceil(w.ende + 4); + return svg( + breite, + 64, + `${symbolInhalt(hell ? FARBE.ink : FARBE.paper, hell ? FARBE.tealDunkel : FARBE.teal)}\n ${w.inhalt}`, + ); +} + +// ── Banner 1280×640 ───────────────────────────────────────────────────────────────────────────── + +function banner(s: Schriften): string { + const teile: string[] = [``]; + // Großes, sehr transparentes Sechseck im Hintergrund. + teile.push( + ``, + ); + // Logo groß, links. + const massstab = 2; + teile.push( + `\n ${symbolInhalt(FARBE.paper, FARBE.teal)}\n ${wortmarke(s, 78, 43, 30, false).inhalt}\n `, + ); + // Unterzeile in Space Grotesk. + const zeile = text( + s.grotesk, + "VMs und LXC-Container auf Proxmox VE ausrollen, per Web oder CLI.", + 96, + 330, + 32, + ); + if (zeile.breite > 1280 - 2 * 96) throw new Error(`Unterzeile zu breit (${zeile.breite})`); + teile.push(``); + // Tags als Outline-Pills. + let x = 96; + for (const tag of ["Web-GUI", "CLI", "cloud-init", "LXC", "Debian", "Ubuntu"]) { + const t = text(s.mono, tag, 0, 0, 20); + const breite = t.breite + 36; + teile.push( + ``, + ``, + ); + x += breite + 12; + } + // Kleine Terminal-Karte rechts unten. + const karte = { x: 744, y: 470, b: 440, h: 110 }; + teile.push( + ``, + ``, + ); + const haken = text(s.mono, "✓", karte.x + 24, karte.y + 80, 18); + teile.push( + ``, + ``, + ); + return svg(1280, 640, teile.join("\n ")); +} + +// ── PNG ───────────────────────────────────────────────────────────────────────────────────────── + +function png(quelle: string, breite: number, datei: string): void { + const bild = new Resvg(quelle, { fitTo: { mode: "width", value: breite } }).render(); + writeFileSync(join(ZIEL, datei), bild.asPng()); +} + +async function main() { + const s = await schriftenLaden(); + mkdirSync(ZIEL, { recursive: true }); + const dateien: Record = { + "symbol.svg": svg(64, 64, symbolInhalt(FARBE.paper, FARBE.teal)), + "symbol-light.svg": svg(64, 64, symbolInhalt(FARBE.ink, FARBE.tealDunkel)), + "icon-small.svg": iconKlein(), + "avatar.svg": avatar(), + "logo.svg": logo(s, false), + "logo-light.svg": logo(s, true), + "banner.svg": banner(s), + }; + for (const [name, inhalt] of Object.entries(dateien)) writeFileSync(join(ZIEL, name), inhalt); + + // Raster-Icons aus dem Avatar: auf hellem und dunklem Grund gleich gut sichtbar. + png(faviconRaster(), 16, "favicon-16.png"); + png(faviconRaster(), 32, "favicon-32.png"); + png(dateien["avatar.svg"]!, 192, "icon-192.png"); + png(dateien["avatar.svg"]!, 512, "icon-512.png"); + png(avatar(true), 180, "apple-touch-icon.png"); + png(avatar(true), 512, "icon-maskable-512.png"); + // Vorschau des Banners (Social Preview verlangt ein Rasterbild). + png(dateien["banner.svg"]!, 1280, "banner.png"); + console.log(`${Object.keys(dateien).length} SVG und 7 PNG unter ${ZIEL}/ geschrieben`); +} + +await main(); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c70d325..91fa5a5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,7 +8,15 @@ import { THEME_COOKIE, themeAusCookie } from "@/lib/theme"; export const metadata: Metadata = { title: { default: "ProxDeploy", template: "%s · ProxDeploy" }, description: "VMs und LXC-Container auf Proxmox VE ausrollen, per Web oder CLI.", - icons: { icon: "/brand/symbol.svg" }, + icons: { + // SVG passt sich hellem und dunklem Browser an; PNG für Browser ohne SVG-Favicons. + icon: [ + { url: "/brand/icon-small.svg", type: "image/svg+xml" }, + { url: "/brand/favicon-32.png", sizes: "32x32", type: "image/png" }, + { url: "/brand/favicon-16.png", sizes: "16x16", type: "image/png" }, + ], + apple: { url: "/brand/apple-touch-icon.png", sizes: "180x180" }, + }, }; // themeColor verträgt keine CSS-Variablen; Ink ist der Hintergrund des dunklen Themes. diff --git a/src/app/manifest.ts b/src/app/manifest.ts new file mode 100644 index 0000000..5ab3f36 --- /dev/null +++ b/src/app/manifest.ts @@ -0,0 +1,20 @@ +import type { MetadataRoute } from "next"; + +/** Web-App-Manifest unter /manifest.webmanifest – öffentlich (siehe proxy.ts). */ +export default function manifest(): MetadataRoute.Manifest { + return { + name: "ProxDeploy", + short_name: "ProxDeploy", + description: "VMs und LXC-Container auf Proxmox VE ausrollen, per Web oder CLI.", + start_url: "/", + display: "standalone", + background_color: "#11161C", + theme_color: "#11161C", + lang: "de", + icons: [ + { src: "/brand/icon-192.png", sizes: "192x192", type: "image/png" }, + { src: "/brand/icon-512.png", sizes: "512x512", type: "image/png" }, + { src: "/brand/icon-maskable-512.png", sizes: "512x512", type: "image/png", purpose: "maskable" }, + ], + }; +} diff --git a/tests/marke.test.ts b/tests/marke.test.ts new file mode 100644 index 0000000..1e9a1d9 --- /dev/null +++ b/tests/marke.test.ts @@ -0,0 +1,68 @@ +import { existsSync, readdirSync, readFileSync } from "node:fs"; +import { join } from "node:path"; +import { Resvg } from "@resvg/resvg-js"; +import { describe, expect, it } from "vitest"; +import manifest from "@/app/manifest"; +import { metadata } from "@/app/layout"; + +const ORDNER = "public/brand"; + +/** Breite und Höhe aus dem IHDR-Block einer PNG-Datei. */ +function pngGroesse(datei: string): [number, number] { + const daten = readFileSync(join(ORDNER, datei)); + expect(daten.subarray(1, 4).toString()).toBe("PNG"); + return [daten.readUInt32BE(16), daten.readUInt32BE(20)]; +} + +describe("Marken-Dateien (pnpm marke)", () => { + it("alle SVGs der Vorgabe sind da, renderbar und ohne kaputte Koordinaten", () => { + const svgs = readdirSync(ORDNER).filter((d) => d.endsWith(".svg")); + expect(svgs.sort()).toEqual( + [ + "avatar.svg", + "banner.svg", + "icon-small.svg", + "logo-light.svg", + "logo.svg", + "symbol-light.svg", + "symbol.svg", + ].sort(), + ); + for (const datei of svgs) { + const text = readFileSync(join(ORDNER, datei), "utf8"); + expect(text, datei).not.toMatch(/NaN|Infinity/); + const bild = new Resvg(text).render(); + expect(bild.width, datei).toBeGreaterThan(0); + } + const banner = new Resvg(readFileSync(join(ORDNER, "banner.svg"), "utf8")).render(); + expect([banner.width, banner.height]).toEqual([1280, 640]); + }); + + it("kein Proxmox-Orange und nur Markenfarben", () => { + const erlaubt = new Set(["#11161C", "#1A2129", "#2A333D", "#8B98A5", "#E6EDF3", "#2DD4BF", "#0F766E"]); + for (const datei of readdirSync(ORDNER).filter((d) => d.endsWith(".svg"))) { + for (const [farbe] of readFileSync(join(ORDNER, datei), "utf8").matchAll(/#[0-9A-Fa-f]{6}\b/g)) { + expect(erlaubt.has(farbe.toUpperCase()), `${datei}: ${farbe}`).toBe(true); + } + } + }); + + it("Rasterbilder haben die richtige Größe; Layout und Manifest zeigen nur auf vorhandene Dateien", () => { + expect(pngGroesse("favicon-16.png")).toEqual([16, 16]); + expect(pngGroesse("favicon-32.png")).toEqual([32, 32]); + expect(pngGroesse("apple-touch-icon.png")).toEqual([180, 180]); + expect(pngGroesse("icon-192.png")).toEqual([192, 192]); + expect(pngGroesse("icon-512.png")).toEqual([512, 512]); + expect(pngGroesse("icon-maskable-512.png")).toEqual([512, 512]); + expect(pngGroesse("banner.png")).toEqual([1280, 640]); + + const pfade = [ + ...(manifest().icons ?? []).map((i) => i.src), + ...JSON.stringify(metadata.icons) + .matchAll(/"url":"([^"]+)"/g) + .map((t) => t[1]!), + ]; + expect(pfade.length).toBeGreaterThan(5); + for (const pfad of pfade) expect(existsSync(join("public", pfad)), pfad).toBe(true); + }); +});