Skip to content
Agentside
Esc
↑↓navigate↵open⌘Jpreview
On this page

Quickstart

Install Agentside, describe your markdown twins and mount the handler in front of your app.

Install

npm install @usenotra/agentside

Agentside ships ESM with TypeScript types and depends on effect.

Describe your twins

Create one module that owns the config. Each key in routes is a page path and each value is the source of its markdown twin.

import { agentside, remote } from "@usenotra/agentside";

export const twins = agentside({
  routes: {
    "/": "# Acme\n\nAcme sends invoices your customers actually pay.",
    "/pricing": () => renderPricingMarkdown(),
    "/blog/[slug]": ({ params }) => getPost(params.slug)?.markdown ?? null,
    "/docs/[...path]": remote(({ params }) => `https://cms.acme.dev/docs/${params.path}.md`),
  },
  skip: ["/api", "/assets"],
});

agentside() validates the routes and builds the cache synchronously, so create it once at module scope and reuse it for every request.

Mount the handler

handle(request, next) takes a fetch Request and a function that renders your page. It returns the markdown twin when the request asks for one and otherwise calls next() and decorates the HTML response.

const response = await twins.handle(request, () => renderPage(request));

The framework guides show where this line goes in each framework.

Try it

curl -i http://localhost:3000/pricing.md
curl -i -H "Accept: text/markdown" http://localhost:3000/pricing
curl -i -A "GPTBot/1.2" http://localhost:3000/pricing
curl -I http://localhost:3000/pricing

The first three return Content-Type: text/markdown with an X-Agentside-Variant header. The last returns your HTML page with Link: </pricing.md>; rel="alternate"; type="text/markdown".

Serve a twin directly

When you already route .md URLs yourself, call serve instead. It always treats the request as an explicit markdown request and answers with the twin, a markdown 404 or a 503.

export const GET = (request: Request) => twins.serve(request);

Pass a pathname as the second argument when the request URL differs from the page path, for example twins.serve(request, "/pricing").

Was this page helpful?