feat(payload-helper): Add SEO and footer components#406
Conversation
Adds SEO head meta rendering (Open Graph, Twitter Card, canonical URL, structured data, code injection) and footer code injection components for Payload CMS integration. Extracts serializeSchema as a generic utility under utils/seo. https://claude.ai/code/session_01ShF8qREiHw7gTnmaxSTk99
This comment has been minimized.
This comment has been minimized.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #406 +/- ##
==========================================
+ Coverage 64.59% 69.94% +5.35%
==========================================
Files 154 185 +31
Lines 6064 7394 +1330
==========================================
+ Hits 3917 5172 +1255
+ Misses 2064 2025 -39
- Partials 83 197 +114 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Remove unused serializeSchema import from PayloadFooter - Destructure props directly in PayloadFooter to match PayloadSEO pattern - Conditionally render og:url only when meta.canonical is present - Add minor changeset for sveltekit-helper https://claude.ai/code/session_01ShF8qREiHw7gTnmaxSTk99
Review summary
This PR adds comprehensive SEO and footer code injection components for Payload CMS integration. While the implementation is functional and well-structured, there is a critical XSS vulnerability from using Critical issues 🔴1. XSS vulnerability from unsanitised HTML injectionLocation: The components use <!-- Vulnerable code -->
{@html serializeSchema(meta.structuredData.settings)}
{@html codeInjectionSettings.head}
{@html siteCodeInjection}Impact: If an attacker gains access to Payload CMS admin (or if admin accounts are compromised), they could inject malicious JavaScript that executes on all pages, stealing user credentials, session tokens, or performing actions on behalf of users. Recommendation:
Example security documentation<!--
@component
PayloadSEO renders all head meta tags for a page.
⚠️ SECURITY WARNING: This component renders HTML from CMS settings without
sanitisation. Only grant Payload CMS admin access to trusted users.
Malicious code injection could lead to XSS attacks.
@example
```svelte
<PayloadSEO siteName="My Site" settings={globalSettings} pageMeta={page.meta} />--> The Recommendation: Define proper types for JSON-LD schemas or at least use a more descriptive type: // Option 1: Specific schemas
type StructuredData = WebSiteSchema | OrganizationSchema | BreadcrumbSchema | /* ... */;
// Option 2: Generic but documented
type StructuredData = Record<string, unknown> & {
'@context': string;
'@type': string;
};3. Potential runtime error from number to string conversionLocation: <meta property="og:image:width" content={meta.media.width.toString()} />
<meta property="og:image:height" content={meta.media.height.toString()} />If Recommendation: Add null checks or use optional chaining: {#if meta.media.width}
<meta property="og:image:width" content={meta.media.width.toString()} />
{/if}Suggestions 🟢1. Inconsistent British English usageLocation: The code uses "serialises" (British) in comments but the function name is 2. Missing JSDoc for exported utilitiesLocation: The 3. Component props could be more defensiveLocation: The component uses optional chaining but could handle edge cases more explicitly. For example, Recommendation: const site = $derived(settings.siteName?.trim() || siteName);Additional notes:
|
Summary
This PR adds comprehensive SEO support and footer code injection capabilities to the sveltekit-helper package through new Svelte components and utilities for Payload CMS integration.
Key Changes
New Components:
PayloadSEO.svelte: Renders complete SEO metadata including Open Graph, Twitter Card, canonical URLs, and structured data (JSON-LD)PayloadFooter.svelte: Handles footer code injection from both site-level settings and page-level overridesNew Utilities:
serializeSchema(): Converts structured data objects to JSON-LD script tagsresolveItems(): Helper to resolve Payload relationship fields to their populated objectsType Definitions:
PayloadSEOProps: Props for the SEO componentPayloadFooterProps: Props for the footer componentPayloadMeta: SEO metadata structurePayloadSettings: Site-level settings compatible with Payload CMSPayloadSocial: Social media links configurationPayloadCodeInjection: Header/footer script injection structurePackage Configuration:
./utils/seoexport to package.json for public API accessImplementation Details
PayloadSEOcomponent intelligently merges page-level and site-level metadata with proper fallback chainsserializeSchemautility function$props,$derived) for reactive state managementhttps://claude.ai/code/session_01ShF8qREiHw7gTnmaxSTk99