Two ways to ask
Send anAccept header:
.md to the path:
/index.md.
What the response looks like
The runtime converts the rendered page and adds YAML frontmatter from the page’s own metadata:url field is the page’s metadata.canonical when it declares one, and the
request URL when it does not.
What the converter reads
The converter reads the page’s main landmark:<main>, if the page has one.- An element with
role="main". <body>.
<nav>, <footer>, <script>, <style>, <svg>, <noscript>,
<iframe>, and <canvas> wherever they are.
Give your layout a <main> element. The output is then exactly your page
content, with no menu or footer text in front of it.
app/layout.tsx
HTML stays the default
A browser sendstext/html,application/xhtml+xml,… and receives the page it
always received. Markdown wins only when the client scores it above HTML:
Every SSR response carries
Vary: Accept, so a cache cannot serve the HTML to a
client that asked for markdown. Each HTML page also carries a Link header that
names its markdown twin:
Opt a route out
Some routes are an interaction, not a document. A dashboard, an editor, or an app shell converts to a list of button labels. Turn the variant off for that route:app/dashboard/page.tsx
406 to a client
that accepts only markdown, and 404 at /dashboard.md.
Caching
A markdown response is cached like the page it came from. The runtime keys it apart from the HTML, so the two never collide. A cache hit skips both the render and the conversion. Markdown responses are never advertised as shared-cacheable at a CDN, because a CDN keys on the URL alone. The origin cache still serves them without a render.Missing pages
A markdown request for a URL that does not exist renders yournot-found.tsx
boundary as markdown, at HTTP 404. Put your site map links in that boundary. An
agent that guessed a URL wrong then reads where to go next, instead of an opaque
error.
app/llms.ts
llms.txt is the file an agent reads first to learn what your site is. Add
app/llms.ts and Pylon serves it at /llms.txt in
llmstxt.org format:
app/llms.ts
app/sitemap.ts and app/robots.ts.
Write the details block for an agent, not for a visitor. Name the jobs you are
right for and the call to make. Marketing copy does not read as guidance.
The element order is fixed by the format: an H1 title, a blockquote summary,
prose with no headings, then H2 sections of links. Pylon strips headings out
of
details for you, because a heading there ends the prose block and starts
a link section.Design mode
A design tool needs a static copy of a page that maps back to source.pylon dev provides one when PYLON_DESIGN_MODE=1 is set. All of it is dev-only and returns 404 in production.
Source stamps. The SSR runner adds data-pylon-src="app/pricing/page.tsx:12:8" to every DOM element written under app/, components/, and .design/. The value is the file, the 1-based line, and the column of the opening <. Components are not stamped; each DOM element inside a component carries its own stamp. Browser bundles are unchanged.
The design render. Send X-Pylon-Design: 1:
- no hydration tail (
__PYLON_DATA__, module script), no dev HUD, no live-reload script, - the route stylesheet inlined as
<style>with no size cap, <base href="http://127.0.0.1:4321/">first in<head>, so relative asset URLs resolve inside asrcdociframe,Cache-Control: no-store. The render is never written to the SSR cache.
app/ has no URL. GET /_pylon/dev/render renders it anyway:
component and layouts are project-relative module paths without extension. They must exist inside the project; anything else is a 400. path is the URL the page renders under (default /). The result is a design render. The bearer token is required when PYLON_DEV_FILE_API_TOKEN is set.
Viewer. A page that redirects anonymous visitors renders as a signed-in user with X-Pylon-Design-Viewer: <userId> (or anon). The auth context is built the way a session resolves: the user’s most recent session’s org, their org role, and the admin flag. This header works only on design renders, and only when PYLON_DEV_FILE_API_TOKEN is set and sent. Without the token the request is a 401.