feat: serve responsive WebP srcsets for faster mobile browsing

On-demand ?w= resize with a disk cache under webcache/; downloads stay full-resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Frank Schwenk
2026-08-01 13:04:33 +02:00
parent b09f90bfcc
commit dec74a46d7
9 changed files with 217 additions and 12 deletions
+2 -1
View File
@@ -44,7 +44,8 @@
if (!target.classList.contains("lightboxable")) return;
e.preventDefault();
e.stopPropagation();
openLightbox(target.currentSrc || target.src, target.alt);
var full = target.getAttribute("data-full-src");
openLightbox(full || target.currentSrc || target.src, target.alt);
});
box.addEventListener("click", function (e) {
+9 -1
View File
@@ -9,7 +9,15 @@
<li class="job-card">
<a href="/jobs/{{ job.job_id }}">
{% if job.thumbnail %}
<img class="thumb lightboxable" src="/jobs/{{ job.job_id }}/files/{{ job.thumbnail }}" alt="Variante von Job {{ job.job_id }}" loading="lazy">
{% set img = img_attrs(job.job_id, job.thumbnail) %}
<img class="thumb lightboxable"
src="{{ img.src }}"
srcset="{{ img.srcset }}"
sizes="{{ img.sizes }}"
data-full-src="{{ img.full_src }}"
alt="Variante von Job {{ job.job_id }}"
loading="lazy"
decoding="async">
{% else %}
<span class="thumb thumb-placeholder status-{{ job.status }}">{{ job.status }}</span>
{% endif %}
+36 -4
View File
@@ -13,8 +13,16 @@
<h2>Original &amp; Rembg</h2>
<div class="pair-grid">
{% if original_name %}
{% set img = img_attrs(job_id, original_name, sizes=PAIR_SIZES) %}
<figure>
<img class="lightboxable" src="/jobs/{{ job_id }}/files/{{ original_name }}" alt="Original" loading="lazy">
<img class="lightboxable"
src="{{ img.src }}"
srcset="{{ img.srcset }}"
sizes="{{ img.sizes }}"
data-full-src="{{ img.full_src }}"
alt="Original"
loading="lazy"
decoding="async">
<figcaption>
Original &middot;
<a href="/jobs/{{ job_id }}/files/{{ original_name }}" download>Download</a>
@@ -22,8 +30,16 @@
</figure>
{% endif %}
{% if has_rembg and rembg_name %}
{% set img = img_attrs(job_id, rembg_name, sizes=PAIR_SIZES) %}
<figure>
<img class="lightboxable" src="/jobs/{{ job_id }}/files/{{ rembg_name }}" alt="Freigestellt (rembg)" loading="lazy">
<img class="lightboxable"
src="{{ img.src }}"
srcset="{{ img.srcset }}"
sizes="{{ img.sizes }}"
data-full-src="{{ img.full_src }}"
alt="Freigestellt (rembg)"
loading="lazy"
decoding="async">
<figcaption>
Rembg &middot;
<a href="/jobs/{{ job_id }}/files/{{ rembg_name }}" download>Download</a>
@@ -45,8 +61,16 @@
{% else %}
<ul class="variant-grid">
{% for v in manifest.variants %}
{% set img = img_attrs(job_id, v.file) %}
<li class="variant-card">
<img class="lightboxable" src="/jobs/{{ job_id }}/files/{{ v.file }}" alt="Variante {{ v.id }}" loading="lazy">
<img class="lightboxable"
src="{{ img.src }}"
srcset="{{ img.srcset }}"
sizes="{{ img.sizes }}"
data-full-src="{{ img.full_src }}"
alt="Variante {{ v.id }}"
loading="lazy"
decoding="async">
<div class="variant-meta">
<strong>{{ v.id }}</strong> <span class="tag">{{ v.source }}</span>
<dl>
@@ -72,8 +96,16 @@
<h2>Zwischenschritte</h2>
<ul class="intermediate-grid">
{% for name in intermediates %}
{% set img = img_attrs(job_id, name) %}
<li>
<img class="lightboxable" src="/jobs/{{ job_id }}/files/{{ name }}" alt="{{ name }}" loading="lazy">
<img class="lightboxable"
src="{{ img.src }}"
srcset="{{ img.srcset }}"
sizes="{{ img.sizes }}"
data-full-src="{{ img.full_src }}"
alt="{{ name }}"
loading="lazy"
decoding="async">
<span>{{ name }}</span>
</li>
{% endfor %}