Commit Graph

20 Commits

Author SHA1 Message Date
Peter Meier 57f4b226f9 feat(footer,org): Footer-Redesign + OrganisationCard auf InfoCard-Basis
Footer:
- Newsletter 2-spaltig (Titel/Desc links, Formular rechts), Desc als
  Translation-Key newsletter_inline_desc
- Link-Spalten-Überschriften als kleine Label-Kappen, Links ohne Unterstrich
- Bottom-Bar: Logo + Site-Name (data.siteName) links, Copyright/Lizenz rechts
- Site-Name-Default "Windwiderstand Thüringen" (constants.ts)

OrganisationCard:
- Neue Komponente auf InfoCard-Basis; InfoCard um href/media/badge/footer-Slots
  erweitert
- OrganisationsBlock: 4 divergierende Kartenpfade → 1 OrganisationCard
- Story + CTA-Button (mitmachen) size md + Icon

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 11:59:36 +02:00
Peter Meier f77314dc49 feat(blocks): SectionGrid/InfoCard/ContactForm + Konsolidierung (Tier 1)
Deploy / verify (push) Successful in 1m31s
Deploy / deploy (push) Successful in 1m33s
Neue Komponenten: SectionGrid, InfoCard (tone/compact), ArrowLink, ContactFormBlock,
SectionGridBlock. CMS-Blöcke section_grid + contact_form (info_card-Collection).
OrganisationsBlock: presentation "grid" (SectionGrid + InfoCard-Tiles).
Kontaktformular-Submit: size md + Send-Icon.

Konsolidierung Tier 1:
- .card-surface + Card-Atom → rounded-lg, .chip → rounded-full, Input-Atome → rounded-md
- tote .btn-*-Klassen aus app.css entfernt (Atom nutzt --color-btn-*-Tokens)
- hardcoded Hex → stein-Tokens (InfoCard, ContactFormBlock)
- redundante rounded-sm auf card-surface-Nutzern entfernt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 10:49:54 +02:00
Peter Meier 84c41f80b1 feat(modal): route-targeted content modals on navigation
Deploy / verify (push) Successful in 1m12s
Deploy / deploy (push) Successful in 2m10s
Add a global modal/popup system driven entirely from the CMS. A new
`modal` config collection self-targets routes via a glob/regex urlPattern
(optional time window), and its `content` array of block references renders
through the existing BlockRenderer — so markdown, HTML and YouTube blocks
work exactly like a page row. A `modals` list collection holds the active
set behind an enable flag (analogous to `campaigns`).

- modal-match.ts: glob (`*`/`**`) + `~regex` pathname matcher, time window
  and modal selection helpers (+ unit tests)
- ContentModal.svelte: immediate/delay/scroll/exit_intent triggers, session
  vs. permanent dismiss (sessionStorage + localStorage, keyed by slug+version)
- +layout.server.ts: load `modals-global` in the bootstrap batch, resolve
  block images server-side
- +layout.svelte: mount on non-embed routes, match against the current path

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 09:47:49 +02:00
Peter Meier 7a490b1ae1 feat(frist): Deadline-Banner im AnnouncementBanner-Look (rot), nur ein Balken
Deploy / verify (push) Successful in 1m11s
Deploy / deploy (push) Successful in 1m29s
- Look wie AnnouncementBanner: kompakte zentrierte Leiste, weiße Schrift, 0.7rem,
  variant-Farbe (urgent=rot), flex-wrap → fließt/stackt sauber mobil
- Countdown als dunkles Badge (bg-black/20)
- Layout: aktive Frist verdrängt NEU-Banner → nie 2 Balken über der Navi

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 15:32:40 +02:00
Peter Meier f7529d3b47 feat(frist): Deadline-Countdown site-weit + variant-Styling (urgent=rot)
- DeadlineBannerBlock: Farbe nach variant (urgent rot / accent / info / default)
- Layout: deadline-banner-auslegung-2026 site-weit im Bootstrap geladen + oben
  gerendert (vorher nur auf /regionalplan)
- page-regionalplan: inline-Banner entfernt (kein Doppel), Content folgt separat

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 15:19:38 +02:00
Peter Meier d9519a867e perf: LCP-Fix, Banner-Crops, SSR-Cache, Bulk-Windkarte
Deploy / verify (push) Successful in 1m3s
Deploy / deploy (push) Successful in 1m47s
- TopBanner: JS-Fade-Gate entfernt (opacity-0 bis Hydration schob LCP
  von ~3s auf ~8.6s) — Bild malt jetzt progressiv über den LQIP
- buildBannerResponsive: Breakpoint-Varianten (1/1, 16/9, 24/9) mit
  media-Attributen, quality 60; CMS braucht explizites h neben ar,
  sonst kein Crop (Mobile bekam 1.92:1 unscharf hochskaliert)
- Layout-Preload: ein Link pro Breakpoint-Variante (WebP)
- Layout-Bootstrap-Batch + Logo-SVG-Fetch TTL-gecacht (liefen pro
  SSR-Request); invalidateCollection versteht CSV-Key-Heads
- WindkarteBlock: 40 Einzel-Fetches -> 1 List-Request mit Filter
- app.html: preconnect cms.pm86.de, api.iconify.design, analytics
- u-url Microformat: echte canonicalUrl statt href="#" (SEO-Audit)
- Icon-Subset: 'cloud' ergänzt (kein Runtime-Fetch an iconify mehr)
- StrommixBlock: nutzloses transition-colors entfernt (CLS-Audit)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:50:01 +02:00
Peter Meier a3f545d727 feat(windkarte): add per-area geo export + dynamic favicon
Deploy / verify (push) Successful in 1m1s
Deploy / deploy (push) Successful in 1m8s
- /api/vorranggebiete.geojson + .kml endpoints (filter via ?id=W-XX)
- Download-Buttons in WindAreaPanel pro selektiertes Gebiet
- Hover-Tooltip auf Polygon zeigt Fläche, geplante Anlagen, Höhe, Gemeinden
- Favicon + apple-touch-icon dynamisch aus data.logoUrl (CMS-Logo)
- alte windrad-PNGs in static/favicons/ entfernt
- WindkarteBlock list-fetch: _limit statt limit (RustyCMS-Param)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 12:14:58 +02:00
Peter Meier 44b991f7c1 Improve social media OG/Twitter meta for posts
Deploy / verify (push) Successful in 51s
Deploy / deploy (push) Successful in 1m2s
- Fix bug: post page was overriding og:image with 150x200 thumbnail
- og:type = "article" for posts (was always "website")
- article:published_time, article:modified_time, article:author, article:tag
- og:image:alt + twitter:image:alt (post headline)
- twitter:label1/data1 with reading time
- Remove thumbnail fallback from socialImage (falls back to site logo instead)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:35:32 +02:00
Peter Meier 4fc541acf9 perf: parallel block resolution, immutable asset caching, fewer favicons
Deploy / verify (push) Successful in 57s
Deploy / deploy (push) Successful in 59s
- +page.server.ts: resolveContentImages/Calendar/Deadline/SearchableText
  now run in parallel via Promise.all (after resolvePostOverviewBlocks)
- +page.server.ts: banner widths 5→3 [640,1024,1536]
- hooks.server.ts: /_app/immutable/** gets Cache-Control: max-age=31536000
- +layout.svelte: favicon tags 18→4 (ico, 32px png, 192px, apple-180px)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:00:07 +02:00
Peter Meier ef163fb336 feat(layout): add global announcement banner above nav
Deploy / verify (push) Successful in 1m12s
Deploy / deploy (push) Successful in 1m6s
Adds AnnouncementBanner component fed by a new top_banner CMS entry
(site-announcement). Extended top_banner schema and TS types with
optional link + linkLabel fields. Rendered inline-markdown text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 21:56:42 +02:00
Peter Meier 3f62473c32 fix(embed): skip site chrome on /widget routes via root layout
Deploy / verify (push) Successful in 50s
Deploy / deploy (push) Successful in 52s
(embed)/+layout@.svelte only resets intermediate layouts — root
+layout.svelte still wrapped every widget page with Header, Footer,
TopBanner, Breadcrumbs, Skip-Link, OG/JSON-LD/Analytics.

Root layout now derives isEmbed from $page.route.id (matches /(embed))
and renders just {@render children()} in that branch. svelte:head is
gated too: embed mode emits only the favicon, leaving the page free to
set its own <title> and noindex meta.

+layout.server.ts short-circuits the bootstrap batch (navigation,
footer, page_config, logo) for embed routes — saves one CMS roundtrip
+ logo transform per widget request, and avoids double-counting in
Umami/pm86 analytics when the widget is iframed elsewhere.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 10:04:01 +02:00
Peter Meier b7093b703a style(design): consistency sweep + UX upgrades
Deploy / verify (push) Successful in 49s
Deploy / deploy (push) Successful in 1m0s
- Palette: gray/zinc/slate/neutral → stein, red → fire, amber → erde,
  sky → himmel, green → wald
- Footer: replaced raw rgb with stein tokens
- Radius: unified to rounded-xs across cards, buttons, inputs, pagination
- Buttons: .btn-primary/.btn-secondary now font-medium; added secondary
- Card hover: -translate-y-0.5 + shadow + wald-300 border
- Header active link: wald border-bottom + wald-700 text
- Mobile nav: bigger touch targets + wald active accent
- Pagination: prev/next text labels + wald-500 active state with
  separated shape/color classes to avoid Tailwind conflicts
- Lead paragraph: scoped .markdown > p:first-child for top-level
  MarkdownBlock only via [data-block-type="markdown"]
- Section dividers: subtle wald-200 gradient between content rows
- Global focus-visible ring (wald-500)
- Inline hex → palette tokens (Badge amber, Tag custom-color contrast)
- Font weights snapped to design system (300/400/500/600/700)
- transition-all → transition-colors where only color changes
- Removed em-dashes from user-visible templates

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 01:06:22 +02:00
Peter Meier 00d42ebb42 feat(preview): consume rustycms live-preview drafts
Deploy / verify (push) Successful in 45s
Deploy / deploy (push) Successful in 1m1s
`?preview_draft=<sid>` on any page/post route forwards the signed
session id to the CMS, which renders the in-memory draft instead of
the persisted entry. Layout listens for `rustycms:reload` postMessages
from the admin iframe parent and re-runs `invalidateAll()` to pick up
fresh draft state. CSP `frame-ancestors` is set per-request when
`PUBLIC_PREVIEW_PARENT_ORIGIN` is configured so the admin iframe can
embed the response.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 09:24:05 +02:00
Peter Meier 3d343822e9 feat: print-friendly layout + comment count on every post overview
Deploy / verify (push) Successful in 42s
Deploy / deploy (push) Successful in 1m4s
- Hides Header / HeaderOverlay / Footer / TopBanner / Breadcrumbs and
  the comment accordion when printing. Action toolbar already had
  `print:hidden`.
- Adds @media print rules in app.css: 1.5cm page margins, 11pt body,
  forced black-on-white, expand link URLs after anchor text inside
  articles, keep images and headings together at page breaks.
- PostCard now renders the count pill whenever a value is known (incl.
  zero); previously hidden for `count === 0`, so posts whose comments
  are still pending always looked empty.
- Extracts the bulk-fetch helper to `lib/comment-counts.ts`
  (`fetchCommentCounts` + `postSlugForComments`) and uses it from both
  `BlogOverview` and `PostOverviewBlock`. Homepage / any page with a
  post_overview block now shows the badges too — previously only the
  paginated /posts/* routes did.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 15:29:15 +02:00
Peter Meier 50bb0ef398 feat(preview): implement preview mode for content management
Deploy / verify (push) Successful in 41s
Deploy / deploy (push) Successful in 1m3s
- Added support for a preview mode in the CMS, allowing draft content to be viewed without being indexed.
- Updated hooks and server logic to handle preview parameters, adjusting cache control and robots tags accordingly.
- Enhanced layout to display a preview notification when in preview mode, improving user experience for content editors.
2026-04-23 11:11:27 +02:00
Peter Meier b08c64eb38 feat(seo): add keywords meta tag support for improved SEO
Deploy / verify (push) Successful in 37s
Deploy / deploy (push) Failing after 58s
- Introduced keywords property in layout and page server files to enhance SEO capabilities.
- Updated relevant components to include keywords in meta tags for better search engine visibility.
2026-04-18 12:28:13 +02:00
Peter Meier da294010c8 feat: update site URLs and enhance image handling
Deploy / verify (push) Successful in 50s
Deploy / deploy (push) Failing after 1m3s
- Changed site URLs in docker-compose and deployment configurations to remove "www" prefix for consistency.
- Improved image handling by introducing warmPostCardImages function for pre-fetching images in posts and tags.
- Enhanced PostCard component with responsive image sizes for better performance.
- Updated layout to include robots meta tag and JSON-LD structured data for improved SEO.
- Added loading state for images in TopBanner component to enhance user experience.
2026-04-18 12:25:45 +02:00
Peter Meier a139372ce2 feat(image): enhance image handling with focal points and responsive support
Deploy / verify (push) Failing after 14s
Deploy / deploy (push) Has been skipped
- Added support for extracting focal points and alt text from CMS image fields.
- Introduced responsive image handling in TopBanner component, allowing for AVIF/WebP sources and LQIP placeholders.
- Updated image transformation functions to accommodate focal point parameters for better cropping.
- Refactored image URL resolution logic across various components and routes to utilize new image field structure.
2026-04-18 00:42:33 +02:00
Peter Meier da340530ee feat(analytics): pull pm86 site-id from CMS page_config, drop env var
Deploy / verify (push) Successful in 39s
Deploy / deploy (push) Successful in 54s
- +layout.server: expose pageConfig.analyticsPm86SiteId on layout data
- +layout.svelte: inject analytics.pm86.de script when CMS value present
- +error.svelte: light 404 page with wald-700 accent, dropped dark gradient
- .env.example + deploy.yml: remove PUBLIC_ANALYTICS_PM86_SITE_ID
2026-04-17 23:21:45 +02:00
Peter Meier 2fef91a548 Initial SvelteKit frontend port of windwiderstand.de
Deploy / verify (push) Failing after 32s
Deploy / deploy (push) Has been skipped
Full parity with Astro site: content rows, post/tag routes, pagination,
event badges + OSM map, comments, Live-Search via /api/search-index,
CMS image proxy, RSS, sitemap.

Deploy: Dockerfile + docker-compose.prod.yml + Gitea Actions workflow
to build + push to git.pm86.de registry and ssh-deploy to Contabo.
2026-04-17 22:01:30 +02:00