# SDK: @superduperseo/content

A typed client for the [Content API](https://superduperseo.com/docs/content-api). No dependencies; works in Node 18+, edge runtimes and Cloudflare Workers.

```bash
npm install @superduperseo/content
```

Set the site key in the **server** environment: `SUPERDUPERSEO_CONTENT_KEY=sds_live_...`.

```ts
import { createClient } from '@superduperseo/content'
const cms = createClient() // reads SUPERDUPERSEO_CONTENT_KEY; or createClient({ key })

const hit = await cms.resolve('/blog/my-post')
if (hit?.type === 'redirect') return Response.redirect(hit.to, 301)
if (hit?.type === 'gone') return new Response(null, { status: 410 })
if (hit?.type === 'post') render(hit.post) // seo.title, head_html, title as <h1>, html
// null: not a blog page: render your own page or a real 404
```

| Method | Returns |
|---|---|
| `resolve(path)` | `{ type: 'post', post }`, `{ type: 'redirect', to, status: 301 }`, `{ type: 'gone', status: 410 }` or `null` |
| `site()` | Site name, routes, feed URL, structured data |
| `posts(page)`, `allPosts()` | Post summaries, newest first |
| `post(slug)` | A full post |
| `author(slug)`, `authors()`, `topic(slug)`, `topics()` | Author and topic pages |
| `redirects()` | All 301s and 410s |
| `sitemapXml()`, `feedXml()`, `llmsTxt()` | Text to serve at /sitemap.xml, the feed URL, /llms.txt |
| `indexNowKey()` | Serve it as text at `/{key}.txt` |
| `search()`, `changes()` | Search entries; what changed (by cursor) |
| `clearCache(file?)` | Drop cached copies (call it from your webhook) |

Responses are cached in memory for 60 seconds and revalidated with ETags. If SuperDuperSEO cannot be reached, the last good copy is served.

## Next.js helpers

```ts
import { metadataFor, jsonLd, revalidateRoute } from '@superduperseo/content/next'

export async function generateMetadata({ params }) { return metadataFor(await cms.post((await params).slug)) }
// <script type="application/ld+json" dangerouslySetInnerHTML={jsonLd(post)} />
export const POST = revalidateRoute({ secret: process.env.SUPERDUPERSEO_WEBHOOK_SECRET!, revalidate: revalidatePath })
```

## Webhooks

`verifyWebhook(secret, rawBody, signatureHeader)` returns the event, or `null` when the signature is wrong or older than 5 minutes. See [Webhooks](https://superduperseo.com/docs/webhooks).

Complete examples: [Next.js starter](https://superduperseo.com/docs/starter-nextjs), [Cloudflare starter](https://superduperseo.com/docs/starter-cloudflare).
