Opravit nezobrazování obrázků na webu
CI / test (push) Successful in 1m50s
CI / build-and-push (push) Successful in 2m27s

Payload skládá URL uploadů absolutně podle serverURL. next/image to
vyhodnotí jako externí zdroj a bez images.remotePatterns odmítne
s HTTP 400 "url parameter is not allowed" — samotný soubor se přitom
servíruje správně, takže se to projevilo až s nahraným obrázkem.

Do next/image proto posíláme jen cestu (helper cestaKSouboru). Soubor
leží na stejném originu jako web, takže je to korektní, a navíc na tom
nezávisí doména: remotePatterns se zapékají při buildu, ale tentýž image
běží na stagingu i v produkci pod jiným jménem.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 16:44:54 +02:00
co-authored by Claude Opus 5
parent 631d2ac2e3
commit 1c51034031
4 changed files with 26 additions and 4 deletions
+2 -2
View File
@@ -6,7 +6,7 @@ import React from 'react'
import config from '@/payload.config'
import type { Media, Product } from '@/payload-types'
import { formatujCenu, popisStavu } from '@/lib/format'
import { cestaKSouboru, formatujCenu, popisStavu } from '@/lib/format'
import '../../styles.css'
export const dynamic = 'force-dynamic'
@@ -59,7 +59,7 @@ export default async function DetailPolozky({ params }: Props) {
<Image
key={obrazek.id}
alt={obrazek.alt ?? polozka.nazev}
src={url}
src={cestaKSouboru(url)}
width={width}
height={height}
sizes="(max-width: 900px) 100vw, 800px"
+2 -2
View File
@@ -5,7 +5,7 @@ import React from 'react'
import config from '@/payload.config'
import type { Media, Product } from '@/payload-types'
import { formatujCenu, popisStavu } from '@/lib/format'
import { cestaKSouboru, formatujCenu, popisStavu } from '@/lib/format'
import './styles.css'
// Obsah se čte z CMS při každém požadavku — jinak by se úprava položky
@@ -86,5 +86,5 @@ function prvniObrazek(polozka: Product) {
if (!url || !width || !height) return null
return { url, width, height, alt: media.alt ?? polozka.nazev }
return { url: cestaKSouboru(url), width, height, alt: media.alt ?? polozka.nazev }
}
+17
View File
@@ -1,5 +1,22 @@
import type { Product } from '@/payload-types'
/**
* Payload skládá URL obrázků absolutně podle `serverURL`
* (`https://…/api/media/file/x.png`). `next/image` by to bral jako cizí zdroj
* a bez `remotePatterns` ho odmítne s „url parameter is not allowed".
*
* Doménu proto zahazujeme — soubor leží na stejném originu jako web. Navíc
* je tím stejný image použitelný na stagingu i v produkci, kde se domény liší;
* `remotePatterns` se zapékají při buildu, takže by to jinak nešlo.
*/
export function cestaKSouboru(url: string): string {
try {
return new URL(url).pathname
} catch {
return url // už je relativní
}
}
/** `28900` → `28 900 Kč` (pevná mezera, ať se cena nezalomí). */
export function formatujCenu(cena: number): string {
return `${cena.toLocaleString('cs-CZ').replace(/\s/g, ' ')} `