Official documentation

SEO and sitemap

Technical reference for SEO and sitemap — Joss language and Joss Red ecosystem.

SEO and Sitemap

Index · Before: web project · Native classes

SEO prepares tags for search engines and networks. A sitemap lists URLs that a search engine can visit; it does not by itself improve the quality or authorization of a page.

SEO::title("Productos")
SEO::description("Catálogo")
SEO::keywords(["joss", "productos"])
SEO::canonical("https://example.com/products")
SEO::og("image", "https://example.com/cover.png")
$tags = SEO::render()

There is also SEO::meta($name, $content). The output escapes HTML attributes and adds a default Twitter card.

Dynamic Sitemap Generation (/sitemap.xml)

/sitemap.xml is generated live on every request with a beautiful interactive XSL interface (/sitemap.xsl). Does not write physical files to disk.

1. Manual Static Entries

Sitemap::add("/docs", "2026-07-15", "weekly", 0.8)

// O con mapas/arrays asociativos:
Sitemap::add({
    "url": "/contacto",
    "changefreq": "monthly",
    "priority": 0.6
})

2. Dynamic providers

Sitemap::provider accepts a closure or function that returns a list of sitemap entries, dynamically adding records from the database:

Sitemap::provider(func() {
    return [
        {"url": "/blog/mi-post", "changefreq": "daily", "priority": 0.9}
    ]
})

3. Route Exclusions

Sitemap::exclude([
    "/api/*",
    "/admin/*",
    "/checkout/*"
])

The base URL uses the current request, then APP_URL and finally http://localhost. Behind a proxy correctly configure Host and X-Forwarded-Proto.

SEO::twitter is not registered. SEO::render already adds a default card; use SEO::meta("twitter:...", valor) for additional metadata.

IndexNow (Instant Indexing)

IndexNow allows notifying search engines (Bing, Yandex, Seznam, Naver) in real time about changes or new pages without waiting for a crawler to crawl the sitemap.

// Generar la clave con CLI: joss indexnow generate
// O enviar URLs a IndexNow directamente:
IndexNow::submit("/blog/mi-nuevo-articulo")

// Notificar múltiples URLs por lote:
IndexNow::submit([
    "/blog/post-1",
    "/blog/post-2"
])

When starting the server (joss server start, joss program start, etc.), the runtime detects INDEXNOW_KEY in .env and the Joss HTTP server automatically responds internally on GET /{key}.txt with the key in plain text, validating your domain ownership instantly. You do not need to create physical files on disk or define routes in routes.joss.