more pagespeed fixes

This commit is contained in:
Evan Jarrett
2026-01-17 15:48:40 -06:00
parent b7ed0e7d5b
commit d0843323fe
16 changed files with 71 additions and 42 deletions
+2 -1
View File
@@ -352,7 +352,8 @@ func serveRegistry(cmd *cobra.Command, args []string) error {
// Mount static files if UI is enabled
if uiSessionStore != nil && uiTemplates != nil {
// Register dynamic routes for root-level files (favicons, manifests, etc.)
publicHandler := appview.PublicHandler()
// Wrap with cache middleware for 1 year (cache busting via query string hashes in templates)
publicHandler := appview.CacheMiddleware(appview.PublicHandler(), 31536000)
rootFiles, err := appview.PublicRootFiles()
if err != nil {
slog.Warn("Failed to scan static root files", "error", err)
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-6
View File
@@ -9,12 +9,6 @@
@plugin "@tailwindcss/typography";
/*@layer base {
.container {
max-width: 1920px;
}
}*/
@plugin "daisyui" {
themes:
light --default,
+46 -10
View File
@@ -518,7 +518,8 @@ document.addEventListener('DOMContentLoaded', () => {
});
// Featured carousel - scroll-based with proper wrap-around
document.addEventListener('DOMContentLoaded', () => {
// Deferred initialization to avoid blocking main thread during page load
function initFeaturedCarousel() {
const carousel = document.getElementById('featured-carousel');
const prevBtn = document.getElementById('carousel-prev');
const nextBtn = document.getElementById('carousel-next');
@@ -530,23 +531,50 @@ document.addEventListener('DOMContentLoaded', () => {
let intervalId = null;
const intervalMs = 5000;
function getItemWidth() {
// Cache dimensions to avoid forced reflow on every navigation
let cachedItemWidth = 0;
let cachedContainerWidth = 0;
let cachedScrollWidth = 0;
function updateCachedDimensions() {
const item = items[0];
if (!item) return 0;
if (!item) return;
// Batch all geometric reads together to minimize reflow
const style = getComputedStyle(carousel);
const gap = parseFloat(style.gap) || 24;
return item.offsetWidth + gap;
cachedItemWidth = item.offsetWidth + gap;
cachedContainerWidth = carousel.offsetWidth;
cachedScrollWidth = carousel.scrollWidth;
}
// Initial measurement after layout is stable (double-rAF)
requestAnimationFrame(() => {
requestAnimationFrame(() => {
updateCachedDimensions();
startInterval();
});
});
// Update on resize (debounced to avoid excessive recalculation)
let resizeTimeout;
window.addEventListener('resize', () => {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(updateCachedDimensions, 150);
});
function getItemWidth() {
if (!cachedItemWidth) updateCachedDimensions();
return cachedItemWidth;
}
function getVisibleCount() {
const containerWidth = carousel.offsetWidth;
const itemWidth = getItemWidth();
if (itemWidth === 0) return 1;
return Math.round(containerWidth / itemWidth);
if (!cachedContainerWidth || !cachedItemWidth) updateCachedDimensions();
return Math.round(cachedContainerWidth / cachedItemWidth) || 1;
}
function getMaxScroll() {
return carousel.scrollWidth - carousel.offsetWidth;
if (!cachedScrollWidth || !cachedContainerWidth) updateCachedDimensions();
return cachedScrollWidth - cachedContainerWidth;
}
function advance() {
@@ -587,9 +615,17 @@ document.addEventListener('DOMContentLoaded', () => {
if (intervalId) { clearInterval(intervalId); intervalId = null; }
}
startInterval();
carousel.addEventListener('mouseenter', stopInterval);
carousel.addEventListener('mouseleave', startInterval);
}
// Defer carousel setup to after critical path
document.addEventListener('DOMContentLoaded', () => {
if ('requestIdleCallback' in window) {
requestIdleCallback(initFeaturedCarousel, { timeout: 2000 });
} else {
setTimeout(initFeaturedCarousel, 100);
}
});
// Export functions that are called from templates via onclick handlers
+3 -2
View File
@@ -6,7 +6,8 @@
<section class="hero bg-base-200 min-h-[60vh] py-16 pb-24 relative overflow-hidden">
<!-- Background mascot -->
<picture>
<source srcset="/amathea_manatee-576w.webp 576w,
<source srcset="/amathea_manatee-384w.webp 384w,
/amathea_manatee-576w.webp 576w,
/amathea_manatee-768w.webp 768w,
/amathea_manatee-1152w.webp 1152w"
sizes="(max-width: 640px) 384px, (max-width: 1024px) 448px, 576px"
@@ -32,7 +33,7 @@
<div class="flex items-center justify-center gap-4 mt-8">
<a href="/auth/oauth/login?return_to=/" class="btn btn-primary btn-lg">Get Started</a>
<a href="/learn-more" class="btn btn-ghost btn-lg">Learn More</a>
<a href="/learn-more" class="btn btn-ghost btn-lg" aria-label="Learn more about the ATCR container registry">Learn More</a>
</div>
<!-- Benefit Cards -->
+1 -1
View File
@@ -1,7 +1,7 @@
{{ define "manifest-modal" }}
<dialog class="modal modal-open" onclick="if(event.target===this)this.remove()">
<div class="modal-box">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" onclick="this.closest('dialog').remove()" aria-label="Close dialog"></button>
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" onclick="this.closest('dialog').remove()" aria-label="Close manifest details"></button>
<h2 class="text-xl font-semibold mb-4">Manifest Details</h2>
@@ -20,9 +20,9 @@
<div class="card card-interactive bg-base-200 border-2 border-base-300 p-6 flex flex-col justify-between min-h-60 w-full" onclick="window.location='/r/{{ .OwnerHandle }}/{{ .Repository }}'">
<div class="flex gap-4 items-start">
{{ if .IconURL }}
<img src="{{ resizeImage .IconURL 96 }}" alt="{{ .Repository }}" loading="lazy" class="w-12 rounded-lg object-cover shrink-0">
<img src="{{ resizeImage .IconURL 96 }}" alt="{{ .Repository }}" loading="lazy" width="48" height="48" class="w-12 rounded-lg object-cover shrink-0">
{{ else if .OwnerAvatarURL }}
<img src="{{ resizeImage .OwnerAvatarURL 96 }}" alt="{{ .OwnerHandle }}" loading="lazy" class="w-12 rounded-lg object-cover shrink-0">
<img src="{{ resizeImage .OwnerAvatarURL 96 }}" alt="{{ .OwnerHandle }}" loading="lazy" width="48" height="48" class="w-12 rounded-lg object-cover shrink-0">
{{ else }}
<div class="avatar avatar-placeholder">
<div class="bg-neutral text-neutral-content w-12 rounded-lg shadow-sm uppercase">
+2 -1
View File
@@ -17,7 +17,8 @@
{{ end }}
hx-swap="outerHTML"
hx-on::before-request="this.disabled=true"
hx-on::after-request="if(event.detail.xhr.status===401) window.location='/auth/oauth/login'">
hx-on::after-request="if(event.detail.xhr.status===401) window.location='/auth/oauth/login'"
aria-label="{{ if .IsStarred }}Unstar{{ else }}Star{{ end }} {{ .Handle }}/{{ .Repository }}">
<i data-lucide="star" class="size-4 text-amber-400 stroke-amber-400 transition-transform group-hover:scale-110{{ if .IsStarred }} fill-amber-400{{ end }}" id="star-icon"></i>
<span id="star-count">{{ .StarCount }}</span>
</button>
+1 -1
View File
@@ -59,7 +59,7 @@
<p class="text-center text-base-content/60 mt-6">
Don't have an account? Create one at
<a href="https://bsky.app" target="_blank" class="link link-primary">bsky.app</a>
<a href="https://bsky.app" target="_blank" rel="noopener noreferrer" class="link link-primary" aria-label="Create an account on bsky.app (opens in new tab)">bsky.app</a>
</p>
</div>
</main>
+6 -6
View File
@@ -93,12 +93,12 @@
{{ end }}
{{ end }}
{{ if .Repository.SourceURL }}
<a href="{{ .Repository.SourceURL }}" target="_blank" class="link link-primary text-sm">
<a href="{{ .Repository.SourceURL }}" target="_blank" rel="noopener noreferrer" class="link link-primary text-sm" aria-label="View source code (opens in new tab)">
Source
</a>
{{ end }}
{{ if .Repository.DocumentationURL }}
<a href="{{ .Repository.DocumentationURL }}" target="_blank" class="link link-primary text-sm">
<a href="{{ .Repository.DocumentationURL }}" target="_blank" rel="noopener noreferrer" class="link link-primary text-sm" aria-label="View documentation (opens in new tab)">
Documentation
</a>
{{ end }}
@@ -174,7 +174,7 @@
hx-confirm="Delete tag {{ .Tag.Tag }}?"
hx-target="#tag-{{ sanitizeID .Tag.Tag }}"
hx-swap="outerHTML"
aria-label="Delete tag">
aria-label="Delete tag {{ .Tag.Tag }}">
<i data-lucide="trash-2" class="size-4"></i>
</button>
{{ end }}
@@ -184,7 +184,7 @@
<div class="flex flex-wrap justify-between items-center gap-2">
<div class="flex items-center gap-2">
<code class="font-mono text-xs text-base-content/60 truncate max-w-40" title="{{ .Tag.Digest }}">{{ .Tag.Digest }}</code>
<button class="btn btn-ghost btn-xs" onclick="copyToClipboard('{{ .Tag.Digest }}')" aria-label="Copy digest to clipboard"><i data-lucide="copy" class="size-3"></i></button>
<button class="btn btn-ghost btn-xs" onclick="copyToClipboard('{{ .Tag.Digest }}')" aria-label="Copy tag digest to clipboard"><i data-lucide="copy" class="size-3"></i></button>
</div>
{{ if .Platforms }}
<div class="flex flex-wrap gap-1">
@@ -247,7 +247,7 @@
</div>
<div class="flex items-center gap-2">
<code class="font-mono text-xs text-base-content/60 truncate max-w-40" title="{{ .Manifest.Digest }}">{{ .Manifest.Digest }}</code>
<button class="btn btn-ghost btn-xs" onclick="copyToClipboard('{{ .Manifest.Digest }}')" aria-label="Copy digest to clipboard"><i data-lucide="copy" class="size-3"></i></button>
<button class="btn btn-ghost btn-xs" onclick="copyToClipboard('{{ .Manifest.Digest }}')" aria-label="Copy manifest digest to clipboard"><i data-lucide="copy" class="size-3"></i></button>
</div>
</div>
<div class="flex items-center gap-2">
@@ -257,7 +257,7 @@
{{ if $.IsOwner }}
<button class="btn btn-ghost btn-sm text-error"
onclick="deleteManifest('{{ $.Repository.Name }}', '{{ .Manifest.Digest }}', '{{ sanitizeID .Manifest.Digest }}')"
aria-label="Delete manifest">
aria-label="Delete manifest {{ .Manifest.Digest | truncateDigest }}">
<i data-lucide="trash-2" class="size-4"></i>
</button>
{{ end }}
+1 -1
View File
@@ -337,7 +337,7 @@
<td class="font-mono text-sm">${escapeHtml(device.ip_address || 'Unknown')}</td>
<td>${createdDate}</td>
<td>${lastUsed}</td>
<td><button class="btn btn-error btn-xs" onclick="revokeDevice('${device.id}')">Revoke</button></td>
<td><button class="btn btn-error btn-xs" onclick="revokeDevice('${device.id}')" aria-label="Revoke access for device ${escapeHtml(device.name)}">Revoke</button></td>
</tr>
`;
}).join('');
+2 -2
View File
@@ -59,10 +59,10 @@
</td>
<td class="date-cell">{{formatTime .AddedAt}}</td>
<td class="actions">
<a href="/admin/crew/{{.RKey}}" class="btn btn-icon" title="Edit">
<a href="/admin/crew/{{.RKey}}" class="btn btn-icon" title="Edit" aria-label="Edit crew member {{if .Handle}}{{.Handle}}{{else}}{{.DID}}{{end}}">
<i data-lucide="pencil"></i>
</a>
<button class="btn btn-icon btn-danger" title="Delete" hx-post="/admin/crew/{{.RKey}}/delete" hx-confirm="Remove this crew member?" hx-target="#crew-{{.RKey}}" hx-swap="outerHTML">
<button class="btn btn-icon btn-danger" title="Delete" aria-label="Remove crew member {{if .Handle}}{{.Handle}}{{else}}{{.DID}}{{end}}" hx-post="/admin/crew/{{.RKey}}/delete" hx-confirm="Remove this crew member?" hx-target="#crew-{{.RKey}}" hx-swap="outerHTML">
<i data-lucide="trash-2"></i>
</button>
</td>
+1 -1
View File
@@ -30,7 +30,7 @@
<label for="did">DID</label>
<div class="input-with-lookup">
<input type="text" id="did" name="did" placeholder="did:plc:..." required>
<button type="button" id="lookup-btn" class="btn btn-sm" title="Lookup handle">
<button type="button" id="lookup-btn" class="btn btn-sm" title="Lookup handle" aria-label="Lookup handle from DID">
<i data-lucide="search"></i>
</button>
</div>
-4
View File
@@ -8,10 +8,6 @@ module.exports = {
darkMode: 'class',
theme: {
extend: {
// Only keep custom extensions not covered by DaisyUI
colors: {
star: 'var(--star)',
},
fontFamily: {
mono: ['Monaco', 'Menlo', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace'],
},