fix: footer icons and sections, updated content security policy
This commit is contained in:
parent
b42d1729be
commit
b1abf9209f
BIN
media/based-in-sweden-logo.png
Normal file
BIN
media/based-in-sweden-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
BIN
media/iso_sbcert.png
Normal file
BIN
media/iso_sbcert.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
media/uc-sigill-lm-1200x1452.webp
Normal file
BIN
media/uc-sigill-lm-1200x1452.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
media/uc-sigill-lm-400x484.webp
Normal file
BIN
media/uc-sigill-lm-400x484.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
media/uc-sigill-lm-800x968.webp
Normal file
BIN
media/uc-sigill-lm-800x968.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
media/uc-sigill-lm.png
Normal file
BIN
media/uc-sigill-lm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 366 KiB |
@ -1,5 +1,4 @@
|
|||||||
import { withPayload } from '@payloadcms/next/withPayload'
|
import { withPayload } from '@payloadcms/next/withPayload'
|
||||||
|
|
||||||
import redirects from './redirects.js'
|
import redirects from './redirects.js'
|
||||||
|
|
||||||
const NEXT_PUBLIC_SERVER_URL = process.env.VERCEL_PROJECT_PRODUCTION_URL
|
const NEXT_PUBLIC_SERVER_URL = process.env.VERCEL_PROJECT_PRODUCTION_URL
|
||||||
@ -8,12 +7,33 @@ const NEXT_PUBLIC_SERVER_URL = process.env.VERCEL_PROJECT_PRODUCTION_URL
|
|||||||
|
|
||||||
const ContentSecurityPolicy = `
|
const ContentSecurityPolicy = `
|
||||||
default-src 'self';
|
default-src 'self';
|
||||||
script-src 'self' 'unsafe-inline' https://layerandmesh.lime-forms.com https://matomo.layermesh.se https://maps.googleapis.com;
|
script-src 'self' 'unsafe-inline'
|
||||||
style-src 'self' 'unsafe-inline' https://layerandmesh.lime-forms.com https://fonts.googleapis.com;
|
https://layerandmesh.lime-forms.com
|
||||||
img-src 'self' data: blob: https://matomo.layermesh.se https://img.youtube.com https://i.vimeocdn.com https://maps.googleapis.com https://maps.gstatic.com;
|
https://matomo.layermesh.se
|
||||||
font-src 'self' https://fonts.gstatic.com;
|
https://maps.googleapis.com
|
||||||
connect-src 'self' https://matomo.layermesh.se https://layerandmesh.lime-forms.com https://maps.googleapis.com;
|
https://maps.gstatic.com;
|
||||||
frame-src 'self' https://www.youtube.com https://www.youtube-nocookie.com https://player.vimeo.com https://www.google.com https://maps.google.com;
|
style-src 'self' 'unsafe-inline'
|
||||||
|
https://layerandmesh.lime-forms.com;
|
||||||
|
img-src 'self' data: blob:
|
||||||
|
https://matomo.layermesh.se
|
||||||
|
https://img.youtube.com
|
||||||
|
https://*.vimeocdn.com
|
||||||
|
https://maps.googleapis.com
|
||||||
|
https://maps.gstatic.com;
|
||||||
|
font-src 'self';
|
||||||
|
connect-src 'self'
|
||||||
|
https://matomo.layermesh.se
|
||||||
|
https://layerandmesh.lime-forms.com
|
||||||
|
https://maps.googleapis.com
|
||||||
|
https://*.googleapis.com;
|
||||||
|
frame-src 'self'
|
||||||
|
https://www.youtube.com
|
||||||
|
https://www.youtube-nocookie.com
|
||||||
|
https://player.vimeo.com
|
||||||
|
https://www.google.com
|
||||||
|
https://maps.google.com;
|
||||||
|
worker-src 'self';
|
||||||
|
media-src 'self' https://player.vimeo.com;
|
||||||
object-src 'none';
|
object-src 'none';
|
||||||
base-uri 'self';
|
base-uri 'self';
|
||||||
form-action 'self' https://layerandmesh.lime-forms.com;
|
form-action 'self' https://layerandmesh.lime-forms.com;
|
||||||
@ -26,6 +46,10 @@ const securityHeaders = [
|
|||||||
key: 'Content-Security-Policy',
|
key: 'Content-Security-Policy',
|
||||||
value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
|
value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'Strict-Transport-Security',
|
||||||
|
value: 'max-age=63072000; includeSubDomains',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'X-Frame-Options',
|
key: 'X-Frame-Options',
|
||||||
value: 'SAMEORIGIN',
|
value: 'SAMEORIGIN',
|
||||||
@ -40,7 +64,7 @@ const securityHeaders = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Permissions-Policy',
|
key: 'Permissions-Policy',
|
||||||
value: 'camera=(), microphone=(), geolocation=()',
|
value: 'camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=()',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -52,9 +76,8 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
...[NEXT_PUBLIC_SERVER_URL /* 'https://example.com' */].map((item) => {
|
...[NEXT_PUBLIC_SERVER_URL].map((item) => {
|
||||||
const url = new URL(item)
|
const url = new URL(item)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: url.hostname,
|
hostname: url.hostname,
|
||||||
protocol: url.protocol.replace(':', ''),
|
protocol: url.protocol.replace(':', ''),
|
||||||
@ -68,7 +91,6 @@ const nextConfig = {
|
|||||||
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||||
'.mjs': ['.mts', '.mjs'],
|
'.mjs': ['.mts', '.mjs'],
|
||||||
}
|
}
|
||||||
|
|
||||||
return webpackConfig
|
return webpackConfig
|
||||||
},
|
},
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
@ -83,4 +105,4 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||||
@ -63,7 +63,7 @@ export async function Footer() {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{certMarks.length > 0 && (
|
{certMarks.length > 0 && (
|
||||||
<div className="flex items-center gap-4 flex-wrap">
|
<div className="hidden sm:flex items-center gap-5 flex-wrap">
|
||||||
{certMarks.map((mark, i) => {
|
{certMarks.map((mark, i) => {
|
||||||
const media = mark.image as Media | null | undefined
|
const media = mark.image as Media | null | undefined
|
||||||
if (!media) return null
|
if (!media) return null
|
||||||
@ -71,7 +71,7 @@ export async function Footer() {
|
|||||||
<FDImage
|
<FDImage
|
||||||
media={media}
|
media={media}
|
||||||
size="thumbnail"
|
size="thumbnail"
|
||||||
className="h-12 w-auto object-contain"
|
className="h-16 w-auto object-contain"
|
||||||
fallbackAlt={mark.alt || ''}
|
fallbackAlt={mark.alt || ''}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -81,14 +81,12 @@ export async function Footer() {
|
|||||||
href={mark.linkUrl}
|
href={mark.linkUrl}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="opacity-80 hover:opacity-100 transition-opacity"
|
className="transition-opacity hover:opacity-80"
|
||||||
>
|
>
|
||||||
{imgEl}
|
{imgEl}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<span key={i} className="opacity-80">
|
<span key={i}>{imgEl}</span>
|
||||||
{imgEl}
|
|
||||||
</span>
|
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@ -125,7 +123,31 @@ export async function Footer() {
|
|||||||
|
|
||||||
{/* Left + center: copyright text and legal nav links */}
|
{/* Left + center: copyright text and legal nav links */}
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-6 flex-wrap">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-6 flex-wrap">
|
||||||
<p className="font-joey text-white/60 text-sm whitespace-nowrap">{bottomLeft}</p>
|
{/* Mobile-only cert marks — shown above copyright, hidden on sm+ (handled in top bar) */}
|
||||||
|
{certMarks.length > 0 && (
|
||||||
|
<div className="flex sm:hidden items-center gap-4 flex-wrap mb-1">
|
||||||
|
{certMarks.map((mark, i) => {
|
||||||
|
const media = mark.image as Media | null | undefined
|
||||||
|
if (!media) return null
|
||||||
|
const imgEl = (
|
||||||
|
<FDImage
|
||||||
|
media={media}
|
||||||
|
size="thumbnail"
|
||||||
|
className="h-14 w-auto object-contain"
|
||||||
|
fallbackAlt={mark.alt || ''}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
return mark.linkUrl ? (
|
||||||
|
<a key={i} href={mark.linkUrl} target="_blank" rel="noopener noreferrer">
|
||||||
|
{imgEl}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span key={i}>{imgEl}</span>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<p className="font-joey text-white/60 text-base whitespace-nowrap">{bottomLeft}</p>
|
||||||
{navItems.length > 0 && (
|
{navItems.length > 0 && (
|
||||||
<nav className="flex items-center gap-4 flex-wrap">
|
<nav className="flex items-center gap-4 flex-wrap">
|
||||||
{navItems.map(({ link }, i) => (
|
{navItems.map(({ link }, i) => (
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user