Skip to content

Guide

Publishing a syndication manifest

Four steps to add a Syndication Manifest document to your site so feed readers can discover your public feeds in one request.

1. Write the document

The minimum viable manifest names your publication and lists one feed. For most blogs that is enough.

/.well-known/syndication
{
  "version": "0.1",
  "publication": {
    "name": "Example Publication",
    "uri": "https://example.com/"
  },
  "feeds": [
    {
      "uri": "https://example.com/feed.xml",
      "mime_type": "application/rss+xml",
      "rel": ["primary", "subscribe"],
      "title": "All posts"
    }
  ]
}

Larger publications should group feeds into collections and defer detailed feed lists with feeds_uri.

2. Host it at /.well-known/syndication

Serve the document at the literal path /.well-known/syndication on the publication's origin. /.well-known/syndication.json is an optional alias.

Astro

src/pages/.well-known/syndication.ts
import type { APIRoute } from "astro";

export const GET: APIRoute = () =>
  new Response(JSON.stringify(manifest, null, 2), {
    headers: {
      "Content-Type": "application/syndication+json; charset=utf-8",
      "Access-Control-Allow-Origin": "*",
      "Cache-Control": "public, max-age=3600"
    }
  });

Next.js (App Router)

app/.well-known/syndication/route.ts
export const dynamic = "force-static";

export function GET() {
  return Response.json(manifest, {
    headers: {
      "Content-Type": "application/syndication+json; charset=utf-8",
      "Access-Control-Allow-Origin": "*",
      "Cache-Control": "public, max-age=3600"
    }
  });
}

Hugo

Add a content file at content/.well-known/syndication.md with custom output formats, or generate the JSON via a data file and template. Hugo serves the file at the configured path.

Jekyll

Place a file at .well-known/syndication.json with front matter permalink: /.well-known/syndication. Jekyll renders Liquid in the file before writing it.

WordPress

Add a rewrite rule in a small plugin that maps /.well-known/syndication to a template generating the JSON from your feed list. Set the content type header from the template.

nginx

nginx site config
location = /.well-known/syndication {
  default_type application/syndication+json;
  add_header Access-Control-Allow-Origin *;
  add_header Cache-Control "public, max-age=3600";
  alias /var/www/example.com/syndication.json;
}

Apache

.htaccess
<Files "syndication">
  ForceType application/syndication+json
  Header set Access-Control-Allow-Origin "*"
  Header set Cache-Control "public, max-age=3600"
</Files>

3. Set the right HTTP headers

The discovery endpoint should respond with:

  • Content-Type: application/syndication+json; charset=utf-8
  • Access-Control-Allow-Origin: *. Browser-based readers cannot discover feeds without this header.
  • Cache-Control: public, max-age=…. Match the document's advertised poll_interval_seconds when present.
  • Conditional caching: send ETag or Last-Modified and respond 304 to matching conditional requests.

4. Advertise it (optional)

Older readers can find the manifest from any HTML page if you advertise it in the head or as a Link header.

HTML
<link rel="syndication"
      type="application/syndication+json"
      href="/.well-known/syndication">
HTTP
Link: </.well-known/syndication>; rel="syndication"; type="application/syndication+json"

Verify

Use the validator to check your document against the 0.1 schema and confirm the headers your origin returns.