Headless blog (Content API)
Write in Stavo, publish on your own website with your own design. Your site reads posts from a small, read-only API.
Every Stavo blog already has its own pages at https://drive.example.com/b/weeknight-kitchen or on a custom domain, with built-in themes. If you'd rather keep your existing website and its design, use the blog "headless": write and publish in Stavo as usual, and let your site fetch the posts.
Built-in themes or headless?
- Built-in themes (or a theme plugin): nothing to build. Feeds, sitemap, previews in chats and search engines all work out of the box. Best for most blogs.
- Headless: your site, your framework, your design. You render the pages, so you also own what search engines and link previews see. Best when the blog is one section of a bigger site.
You can do both: the blog keeps its own pages while your site shows the same posts.
Get a key
- Open the blog in Stavo, then Settings > Integrations. Only the blog's owner sees this.
- Give the key a name, like "Main website". Optionally list the sites allowed to use it from a browser, like
https://example.com. - Copy the key (it starts with
stc_) and the API address shown there:https://drive.example.com/api/content/v1/blogs/weeknight-kitchen.
Why a key in browser code is fine
Content API keys are read-only and only see what the blog already shows to everyone: published posts and pages, tags with published posts, the public authors and the blog's title and navigation. Drafts, posts waiting for review, scheduled posts before their time and private blogs never come out. Unlisted posts come out only when asked for by their exact address, never in lists. So a key in your site's JavaScript reveals nothing new. Revoke a key any time; make one per site so you can.
Allowed sites (CORS)
With no allowed sites, any website can use the key from a browser. With a list, browsers on other sites get a 403. Requests from servers (Next.js, Astro, a build script) don't send an origin and always work. Treat the list as a polite filter, not a secret: the key is public anyway.
Limits and caching
- 300 requests a minute per visitor address and 1,200 a minute per key. Over that you get a 429 with Retry-After.
- Answers carry an
ETagandCache-Control: public, max-age=60, stale-while-revalidate=300. Browsers and CDNs cache for a minute; sendIf-None-Matchto get a quick 304. - Fetch on your server or at build time when you can: it's faster for readers and kinder to your Stavo server.
Search engines and link previews
If your site fetches posts in the browser only, search engines may not index them well, and Discord, Slack and iMessage previews won't see the title or image (their crawlers don't run JavaScript). For anything you want found or shared, fetch on the server or at build time and render real HTML. Each post comes with a ready json_ld block, a canonical URL and its SEO fields, so you can put them in your page's head. The examples show how.