Server Hooks Setup

Server Hooks Setup

The Capyseo server hook provides runtime SEO analysis for SvelteKit.

Installation

npm install -D @capyseo/adapter-sveltekit

Basic Setup

Create or update src/hooks.server.ts:

import { createCapyseoHandle } from '@capyseo/adapter-sveltekit/hooks'; export const handle = createCapyseoHandle();

Configuration

export const handle = createCapyseoHandle({ // Enable (default: true in dev) enabled: process.env.NODE_ENV === 'development', // Logging level logLevel: 'issues', // 'none' | 'issues' | 'all' // Paths to exclude exclude: ['/admin/*', '/api/*'], // Gemini API key geminiApiKey: process.env.GEMINI_API_KEY, // Custom report handler onReport: (report) => { console.log(`${report.url}: ${report.score}/100`); }, });

Options

Option Type Default Description
enabled boolean true in dev Enable analysis
logLevel string 'issues' Logging verbosity
exclude string[] - Paths to skip
geminiApiKey string env var AI API key
onReport function - Custom handler

Log Levels

Level Behavior
'none' Silent
'issues' Log pages with problems
'all' Log every page

Combining with Other Hooks

Use sequence to combine hooks:

import { sequence } from '@sveltejs/kit/hooks'; import { createCapyseoHandle } from '@capyseo/adapter-sveltekit/hooks'; const capyseoHandle = createCapyseoHandle({ logLevel: 'issues', }); const authHandle = async ({ event, resolve }) => { // Your auth logic return resolve(event); }; export const handle = sequence(authHandle, capyseoHandle);

Custom Report Handler

Process reports programmatically:

import { createCapyseoHandle } from '@capyseo/adapter-sveltekit/hooks'; export const handle = createCapyseoHandle({ onReport: async (report) => { // Log to external service if (report.score < 80) { await fetch('https://monitoring.example.com/seo', { method: 'POST', body: JSON.stringify({ url: report.url, score: report.score, issues: report.issues.length, }), }); } // Store in database // await db.seoReports.create({ data: report }); // Alert on critical issues const errors = report.issues.filter(i => i.severity === 'error'); if (errors.length > 0) { console.error(`SEO errors on ${report.url}:`, errors); } }, });

Report Structure

interface SEOReport { url: string; timestamp: string; score: number; issues: Array<{ ruleId: string; severity: 'error' | 'warning' | 'info'; message: string; suggestion?: string; }>; }

Path Exclusion

createCapyseoHandle({ exclude: [ '/admin/*', // Admin pages '/api/*', // API routes '/auth/*', // Auth routes '/_app/*', // SvelteKit internals '/__data.json', // Data requests ], });

Production Usage

For production monitoring:

export const handle = createCapyseoHandle({ // Enable in production enabled: true, // Only log issues logLevel: 'issues', // Send to monitoring onReport: async (report) => { if (report.score < 70) { await sendAlert(`Low SEO score: ${report.url}`); } }, });

Performance

The hook is designed to be non-intrusive:

  1. Clones response - Original stream unaffected
  2. Async analysis - Doesn't block response
  3. No modification - Response unchanged
  4. Error resilient - Failures don't break app

Console Output

[capyseo] Analyzing /about... [capyseo] /about - Score: 85/100 x [meta-description] Missing meta description ! [heading-hierarchy] Skipped heading level [capyseo] Analyzing /blog... [capyseo] /blog - Score: 92/100 i [open-graph] Missing og:image

Development vs Production

const isDev = process.env.NODE_ENV === 'development'; export const handle = createCapyseoHandle({ // Verbose in dev, minimal in prod logLevel: isDev ? 'all' : 'none', // Custom handler for prod onReport: isDev ? undefined : sendToMonitoring, });

Troubleshooting

Hook Not Running

Check hooks.server.ts location (must be in src/).

No Output

Check logLevel:

createCapyseoHandle({ logLevel: 'all' })

Performance Issues

Exclude heavy paths:

createCapyseoHandle({ exclude: ['/api/*', '/large-page'], })