SEO & Discoverability
Radish-generated apps include built-in SEO infrastructure: structured data (JSON-LD), sitemap, robots.txt, analytics integration, and AI discoverability (llms.txt).
JSON-LD Structured Data
Every generated app includes src/lib/seo/json-ld.ts with schema.org helpers for rich search results.
Usage
With <JsonLd> component (recommended):
<script>
import { JsonLd, productLd, breadcrumbLd } from '@radish/components';
let { data } = $props();
</script>
<JsonLd data={productLd(data.product)} />
<JsonLd data={breadcrumbLd([
{ name: 'Home', url: '/' },
{ name: 'Products', url: '/products' },
{ name: data.product.name, url: `/products/${data.product.id}` }
])} />
With toJsonLd() helper (manual):
<script>
import { toJsonLd, productLd } from '$lib/seo/json-ld';
// or: import { toJsonLd, productLd } from '@radish/components';
let { data } = $props();
</script>
<svelte:head>
{@html toJsonLd(productLd(data.product))}
</svelte:head>
Available Helpers
| Function | Schema Type | Use For |
|---|---|---|
productLd() | Product | E-commerce products with price, brand, availability |
articleLd() | Article | Blog posts, news articles |
courseLd() | Course | Educational content with instructor, pricing |
organizationLd() | Organization | Company/brand info with logo |
breadcrumbLd() | BreadcrumbList | Navigation path for breadcrumbs |
faqLd() | FAQPage | FAQ pages with Q&A pairs |
entityLd() | Any | Generic mapper for custom entity types |
Product Example
productLd({
name: 'Organic Coffee Beans',
description: 'Premium single-origin beans',
price: 24.99,
currency: 'USD',
brand: 'FairTrade',
sku: 'COF-001',
images: ['/images/coffee.jpg'],
availability: 'in_stock',
url: 'https://myshop.com/products/coffee'
})
Generic Entity Mapper
For entities without a specific helper, entityLd() auto-maps common field names:
import { toJsonLd, entityLd } from '$lib/seo/json-ld';
// Maps: name→name, description→description, price→price,
// imageUrl→image, createdAt→dateCreated, etc.
const ld = entityLd(data.course, 'Course');
| Entity Field | Schema.org Property |
|---|---|
name, title | name |
description | description |
price | price |
image, imageUrl, thumbnailUrl | image |
createdAt | dateCreated |
publishedAt | datePublished |
updatedAt | dateModified |
author, authorName | author |
Custom field mappings:
entityLd(record, 'Recipe', {
cookTime: 'cookTime',
ingredients: 'recipeIngredient'
})
Sitemap
Generated at /sitemap.xml as a dynamic SvelteKit endpoint. Edit src/routes/sitemap.xml/+server.ts to add pages:
const staticPages = [
{ path: '/', changefreq: 'daily', priority: '1.0' },
{ path: '/about', changefreq: 'monthly', priority: '0.5' },
];
// Add database-driven pages:
const products = await new ProductService(systemAuth()).list({ limit: 1000 });
for (const p of products.items) {
staticPages.push({ path: `/products/${p.id}`, changefreq: 'weekly', priority: '0.7' });
}
Robots.txt
Generated at /robots.txt as a dynamic endpoint. Includes sitemap reference. Edit src/routes/robots.txt/+server.ts to add rules.
Google Analytics
Set GOOGLE_ANALYTICS_ID in .env:
GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
Initialize in your root layout:
<script>
import { onMount } from 'svelte';
import { initAnalytics } from '$lib/analytics';
onMount(() => initAnalytics());
</script>
Track custom events:
import { trackEvent } from '$lib/analytics';
trackEvent('purchase', { value: 29.99, currency: 'USD' });
AI Discoverability (llms.txt)
Generated at /llms.txt — describes the app for AI assistants. Edit src/routes/llms.txt/+server.ts to customize.
See llmstxt.org for the specification.