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 redirects from './redirects.js'
|
||||
|
||||
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 = `
|
||||
default-src 'self';
|
||||
script-src 'self' 'unsafe-inline' https://layerandmesh.lime-forms.com https://matomo.layermesh.se https://maps.googleapis.com;
|
||||
style-src 'self' 'unsafe-inline' https://layerandmesh.lime-forms.com https://fonts.googleapis.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;
|
||||
font-src 'self' https://fonts.gstatic.com;
|
||||
connect-src 'self' https://matomo.layermesh.se https://layerandmesh.lime-forms.com https://maps.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;
|
||||
script-src 'self' 'unsafe-inline'
|
||||
https://layerandmesh.lime-forms.com
|
||||
https://matomo.layermesh.se
|
||||
https://maps.googleapis.com
|
||||
https://maps.gstatic.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';
|
||||
base-uri 'self';
|
||||
form-action 'self' https://layerandmesh.lime-forms.com;
|
||||
@ -26,6 +46,10 @@ const securityHeaders = [
|
||||
key: 'Content-Security-Policy',
|
||||
value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
|
||||
},
|
||||
{
|
||||
key: 'Strict-Transport-Security',
|
||||
value: 'max-age=63072000; includeSubDomains',
|
||||
},
|
||||
{
|
||||
key: 'X-Frame-Options',
|
||||
value: 'SAMEORIGIN',
|
||||
@ -40,7 +64,7 @@ const securityHeaders = [
|
||||
},
|
||||
{
|
||||
key: 'Permissions-Policy',
|
||||
value: 'camera=(), microphone=(), geolocation=()',
|
||||
value: 'camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=()',
|
||||
},
|
||||
]
|
||||
|
||||
@ -52,9 +76,8 @@ const nextConfig = {
|
||||
},
|
||||
images: {
|
||||
remotePatterns: [
|
||||
...[NEXT_PUBLIC_SERVER_URL /* 'https://example.com' */].map((item) => {
|
||||
...[NEXT_PUBLIC_SERVER_URL].map((item) => {
|
||||
const url = new URL(item)
|
||||
|
||||
return {
|
||||
hostname: url.hostname,
|
||||
protocol: url.protocol.replace(':', ''),
|
||||
@ -68,7 +91,6 @@ const nextConfig = {
|
||||
'.js': ['.ts', '.tsx', '.js', '.jsx'],
|
||||
'.mjs': ['.mts', '.mjs'],
|
||||
}
|
||||
|
||||
return webpackConfig
|
||||
},
|
||||
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>
|
||||
|
||||
{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) => {
|
||||
const media = mark.image as Media | null | undefined
|
||||
if (!media) return null
|
||||
@ -71,7 +71,7 @@ export async function Footer() {
|
||||
<FDImage
|
||||
media={media}
|
||||
size="thumbnail"
|
||||
className="h-12 w-auto object-contain"
|
||||
className="h-16 w-auto object-contain"
|
||||
fallbackAlt={mark.alt || ''}
|
||||
/>
|
||||
)
|
||||
@ -81,14 +81,12 @@ export async function Footer() {
|
||||
href={mark.linkUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="opacity-80 hover:opacity-100 transition-opacity"
|
||||
className="transition-opacity hover:opacity-80"
|
||||
>
|
||||
{imgEl}
|
||||
</a>
|
||||
) : (
|
||||
<span key={i} className="opacity-80">
|
||||
{imgEl}
|
||||
</span>
|
||||
<span key={i}>{imgEl}</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
@ -125,7 +123,31 @@ export async function Footer() {
|
||||
|
||||
{/* 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">
|
||||
<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 && (
|
||||
<nav className="flex items-center gap-4 flex-wrap">
|
||||
{navItems.map(({ link }, i) => (
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user