CMS for Fresh (Deno): Headless Content with Native Fetch

Web-standard fetch, no Node-centric SDK

July 30, 2026 · 4 min read

Fresh is Deno's full-stack web framework — island-based, no build step, server-rendered by default, running on the Deno runtime and Deno Deploy at the edge. It's fast and modern. What it doesn't give you is a place to store content. For a Fresh site with a blog, docs, or marketing pages, you need a CMS feeding it data. This post covers how to connect a headless CMS to Fresh, using Deno's built-in fetch, and why a self-hosted content layer suits the Deno philosophy of owning your runtime.

How a CMS plugs into Fresh

Fresh renders routes on the server (with islands for interactivity). A headless CMS becomes the data source: your route handler calls the CMS API, gets JSON, and Fresh renders it. Deno has fetch built in globally, so there's no import, no client library — the integration is one call in a handler.

// routes/blog/index.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

export const handler: Handlers = {
  async GET(_req, ctx) {
    const res = await fetch("https://cms.yoursite.com/api/v1/posts?per_page=20");
    const json = await res.json();
    return ctx.render(json.data);
  },
};

export default function BlogPage({ data }: PageProps) {
  return (
    <ul>
      {data.map((p) => <li><a href={`/blog/${p.slug}`}>{p.title}</a></li>)}
    </ul>
  );
}

The CMS never touches your Deno runtime or your islands. It's a JSON source your handler reads.

Why self-hosted headless fits Deno/Fresh

Deno developers value a clean runtime, web-standard APIs, and control. A SaaS CMS with a Node-shaped SDK and vendor-owned data cuts against that. A self-hosted CMS with a plain REST API fits: web-standard fetch, JSON, no SDK.

UnfoldCMS is one option. It's a self-hosted CMS on Laravel with a REST API at /api/v1/*. There's no npm/SDK to import — which matters in Deno, where you'd rather not pull a Node-centric client. You use the global fetch Deno already provides.

Key fits:

  • Web-standard fetch — no SDK, no npm compatibility shim, just the global Deno API.
  • REST + JSON — clean response shapes; no GraphQL client to import.
  • Self-hosted, pay once — your server, your data, no per-request metering.

Server-rendered vs. edge caching on Deno Deploy

Fresh renders on the server by default, often on Deno Deploy at the edge. Two ways to handle CMS content:

Approach How it works When
Fetch per request Handler calls CMS on each request Content changes often; simplest
Cache at the edge Cache CMS responses on Deno Deploy High traffic; reduce API calls

For a content site, edge-cache the CMS responses with a short TTL, and bust the cache when content changes.

Cache busting with webhooks

If you cache CMS data, clear it on publish. UnfoldCMS fires outgoing, HMAC-signed webhooks on publish/update/delete. Point one at a Fresh route that verifies the signature and clears the relevant cache:

Editor publishes
  → CMS sends signed webhook
  → Fresh route verifies HMAC, clears cached posts
  → Next request serves fresh content

The signature ensures only your CMS can trigger the bust.

Tradeoffs to know

  • Preview needs wiring. Drafts 404 on the public API; previewing unpublished content means a token-authed route you build.
  • No revision history. UnfoldCMS doesn't keep past versions of posts.
  • You run two runtimes. Fresh is Deno; the CMS is a PHP app you host separately. You don't write PHP, but you operate the CMS box.
  • REST only, no GraphQL. For Fresh handlers, REST + fetch is the natural fit.

FAQ

Does UnfoldCMS work with Deno's Fresh framework? Yes. Fresh route handlers use Deno's global fetch to call the CMS REST API and render the JSON. No SDK or npm import needed.

Do I need a special SDK for Deno? No. There's no client library for any framework. You use the web-standard fetch that Deno provides globally — ideal for avoiding Node-centric dependencies.

Can I cache CMS content on Deno Deploy? Yes. Cache API responses at the edge with a short TTL and bust the cache via a webhook when content changes.

REST or GraphQL? REST only. For Fresh's server handlers, REST plus fetch is the simplest integration.

Bottom line

Fresh gives you a modern, build-step-free Deno framework; a self-hosted headless CMS gives it content over a plain REST API. No SDK, no npm import — just Deno's global fetch in a route handler. Cache at the edge on Deno Deploy, bust it with a webhook on publish, and you have a content workflow that fits Deno's web-standard, own-your-runtime approach.

See the API in the demo or read the headless CMS complete guide.

Related: What is a content API · Headless CMS for Jamstack · CMS with API: REST vs GraphQL

Free & Open Source

Own your CMS. No subscriptions.

Unfold CMS is free to download and self-host. Built on Laravel + React, full source code included.

Share this post:

Discussion

Comments (0)

Leave a Comment

Please log in to leave a comment.

Don't have an account? Register here

No comments yet. Be the first to share your thoughts!

Keep Reading

Related Posts

Back to all posts
Powered by UnfoldCMS