Three CI typecheck failures from the previous microformat patch:
- post.created is the only date field in the schema (no _created on the
generated PostEntry). Drop the _created fallback.
- postTag items can be a slug string OR a tag object. Type narrowing
with `'name' in tag` widened to `never`; pull the name through an
explicit `{ name?: string }` cast in @const so the iteration stays
honest about the runtime shape.
- author isn't on PostEntry either; cast at the use-site for the
hidden h-card author block.
Two changes:
- New POST /api/cache/clear (auth: REVALIDATE_TOKEN). Wipes the
TTL content cache, the image disk + memory cache, and forwards to
the RustyCMS /api/transform/cache/invalidate endpoint when an
API key is configured. Single trigger to flush everything.
- /api/revalidate now also calls clearImageCache() on asset.* events
so a re-upload (focal change, alt edit, replacement) doesn't keep
serving the previous transformed image from disk.
clearImageCache() in image-cache.server.ts wipes the in-memory map
and removes every file under IMAGE_CACHE_DIR.
Posts whose row*Content contains a `youtube_video` block now ship a
schema.org VideoObject per video alongside the existing BlogPosting /
Event JSON-LD. Lets Google attach a video rich-result to the post URL
(thumbnail, duration where available, embed/content URLs) instead of
treating the page as plain text whose body happens to be a single
iframe.
Thumbnail uses YouTube's predictable maxresdefault + hqdefault URLs;
upload date falls back to post.created when the embed has none.
Microformats:
- Wrap the post <article> in h-entry with p-name on the headline,
p-summary on the subheadline (or sr-only fallback from excerpt),
e-content on the rendered body, dt-published on the created date
(hidden time element) and an invisible p-author h-card. Tag names
are mirrored as hidden p-category entries so crawlers see them
even though the visual Tags component already links them.
- itemscope/itemtype maps to schema.org BlogPosting (or Event when
`isEvent`), aligning the invisible microdata with the existing
JSON-LD.
Keywords:
- When post.seoKeywords is empty, fall back to the comma-joined tag
names so <meta name="keywords"> still ships something meaningful.
The article template only rendered the H1 it could pluck from the
markdown body (`contentHeadlineHtml`). Posts whose body opens with H2
(or no heading) silently lost both the schema-level `headline` and
`subheadline` — they were used in SEO/JSON-LD/breadcrumb only.
Fall back to the structured fields when no inline H1 is present.
- Accept dpr query param (clamped 1..4) and include it in cache key so
each density gets its own cached file.
- Accept format=auto and negotiate locally from the client's Accept
header (avif > webp > jpeg) before building the cache key — concrete
formats in the cache avoid cross-client leaks.
- 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.
- Updated the list styling in FilesBlock component to remove default list styles and improve layout consistency.
- Adjusted list item classes for better alignment and visual clarity, enhancing the overall user experience.
- Introduced FilesBlockItem and FilesBlockData interfaces to support file handling in the CMS.
- Integrated FilesBlock component into ContentRows.svelte for rendering file blocks.
- Updated block type handling to include support for files, enhancing content versatility.
- Changed comment in app.css to reflect German terminology for quotes.
- Added Button component to OrganisationsBlock for improved call-to-action presentation.
- Adjusted button styling and layout in OrganisationsBlock for better responsiveness and visual consistency.
- Added `packageManager` field to package.json for Yarn versioning.
- Updated yarn.lock to include new dependencies for `@emnapi` and `@esbuild` packages, enhancing compatibility and performance.
- Adjusted styling in TopBanner.svelte for improved layout and responsiveness.
- Added `class-variance-authority` version 0.7.1 to both package-lock.json and yarn.lock for enhanced styling capabilities.
- Removed outdated entries from yarn.lock to streamline dependencies and improve project maintainability.
- Introduced `class-variance-authority` to manage card component styles, allowing for flexible variant and layout options.
- Added a new color palette for "Fire" to the CSS for improved theming.
- Updated `Card` and `PostCard` components to utilize the new styling system, enhancing visual consistency and responsiveness.
- Refined layout and styling in various components for better user experience.
- Extracted headline and body content from the post's HTML, allowing for distinct rendering of the headline and body in the post page.
- Updated the Svelte component to display the extracted headline and body content separately, enhancing the layout and readability of posts.
- Changed headline class from `line-clamp-2` to `truncate` and adjusted font size to `text-sm`, enhancing the visual presentation and readability of post headlines.
- Introduced `excludeTag` property in PostOverviewBlockData interface to allow exclusion of specific tag slugs.
- Implemented `excludePostsByTagSlugs` function to filter out posts containing specified tag slugs.
- Updated `resolvePostOverviewBlocks` function to utilize the new exclusion logic, enhancing post filtering capabilities.
- Modified cached function to bypass caching in development mode.
- Updated fetchOpenApi function to return cached data only if not in development mode, ensuring accurate API fetching during development.
- Added `executeScripts` function to handle script elements within the comment slot, ensuring proper execution of inline scripts.
- Updated the comment slot container to utilize the new script execution functionality, enhancing dynamic content handling.
- Added "carousel" option to the presentation property in OrganisationsBlockData for horizontal slider functionality.
- Updated OrganisationsBlock.svelte to support carousel layout with smooth scrolling feature.
- Refined Badge component styling for better visual consistency.
- Improved overall structure and responsiveness of the organisations display.
- Updated getCalendarItems function to include the _resolve parameter set to "all", ensuring all related data is fetched.
- Refined getHref function in DeadlineBannerBlock.svelte to simplify link handling by directly checking for the url property.
- Changed margin class from `my-6` to `mb-6` in ContentRows.svelte for consistent spacing.
- Updated PostCard.svelte to use `$derived` for post properties, enhancing reactivity.
- Refined DeadlineBannerBlock.svelte by removing unnecessary border classes and improving layout for better content alignment.
- Modified Button.svelte to support rendering children directly, enhancing flexibility.
- Added `tabindex="0"` to TabBar.svelte for improved accessibility.
- Fixed textarea closing tag in Textarea.svelte for proper HTML structure.
- Corrected span closing tag in Toggle.svelte for valid markup.
Skip container-custom py-8 wrapper for deadline_banner so the colored
bar spans the viewport. Banner ships its own inner container-custom
for content positioning.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ml-auto pushed the "Mehr" link to the right edge which cancelled
justify-center for the rest of the content. Remove it so the whole
row is centered when a link is present.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Auto-mode deadline_banner now resolves to the next future event across
all calendar_items in the CMS instead of requiring a manually-curated
items[] pool. Server load hooks (+page.server.ts for /, /[...slug],
/post/[slug]) call resolveDeadlineBannerBlocks which fetches the
global calendar_item list once and attaches it as items[] when mode
is "auto" and items[] is not already resolved. Component logic
unchanged — it still picks the soonest future entry.
Also:
- cms.ts: getCalendarItems() bulk list fetcher
- PostOverviewBlock.svelte: design defaults to "cards" when value is
empty string (not just null/undefined) so existing entries with
design: "" render
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Updated QuoteBlock to support a new "center" variant for text alignment.
- Modified QuoteCarouselBlock to include an option for displaying navigation arrows.
- Enhanced type definitions for quote-related data structures to accommodate new features.
- Improved styling and layout handling for better visual presentation of quotes.
- Introduced a new QuoteCarouselBlock component for displaying rotating quotes.
- Added QuoteCarouselBlockData interface to define the structure of the quote carousel data.
- Updated existing components and types to integrate the new quote carousel functionality.
- Enhanced blog-utils to support filtering posts by tags more effectively.
- Made various UI improvements in the Footer and PostCard components for better user experience.
- Updated the grep command in the deployment workflow to use a regex pattern for better matching of the windwiderstand.de domain in the Caddyfile.
- This change ensures that the domain is correctly identified even with variations in whitespace or formatting.
- 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.
- 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.
- Updated PostEntry type to include _rawImageUrl and _imageFocal for improved image management.
- Refactored image handling in various components to utilize the new properties, ensuring better focal point support and responsive image rendering.
- Introduced warmResponsiveImage function for pre-fetching image variants to optimize loading performance.
- Replaced CmsImage component with RustyImage in multiple blocks for consistent image processing.
- Added new dependencies: blurhash and sharp for enhanced image processing.
- Updated existing dependencies to their latest versions, including @emnapi/runtime and @emnapi/wasi-threads.
- Changed package resolution URLs to use npm registry for consistency across package management files.
- 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.
trailingSlash='always' caused [...slug] rest-param to capture with
trailing slash. normalizePageSlug/normalizePostSlug only stripped
leading slash, so fallback match failed and pages 404'd.
Strip both leading and trailing slashes; normalize once at entry of
getPageBySlug/getPostBySlug.
- Set trailingSlash='always' globally via root layout.
- Update postHref, pageHref, Pagination, tag/breadcrumb hrefs, blog→posts
redirects to emit trailing slash.
- Match old Astro canonical so indexed URLs hit 200 directly instead of
308-redirect.