Skip to content

Server-rendered sites

If the blog pages are made on request (Next.js on a server, Remix, Nuxt, PHP, Laravel, Rails, Django, a Cloudflare Worker or Pages Function), read the feed when /blog is visited and keep it a few minutes. There is no build hook and nothing to rebuild: a new article appears within your cache time.

  1. Add JOOGOOS_FEED_URL and, as a secret, JOOGOOS_FEED_KEY to the server’s environment.
  2. Add a route for the blog path and its articles (examples below). Cache the feed for about five minutes; the feed allows 60 reads an hour per key, and answers 304 to If-None-Match with its ETag.
  3. Deploy, and open /blog. The owner’s card in Joogoos turns green after the first read with the key: Joogoos remembers when a site last read its feed, and counts a read in the last seven days as connected.

Leave the Build hook box in Joogoos empty.

let cache = { at: 0, feed: null, etag: null };
async function feed() {
if (Date.now() - cache.at < 5 * 60_000 && cache.feed) return cache.feed;
const res = await fetch(process.env.JOOGOOS_FEED_URL, {
headers: {
authorization: `Bearer ${process.env.JOOGOOS_FEED_KEY}`,
...(cache.etag ? { 'if-none-match': cache.etag } : {}),
},
});
if (res.status === 200) cache = { at: Date.now(), feed: await res.json(), etag: res.headers.get('etag') };
else if (res.status === 304) cache.at = Date.now();
return cache.feed ?? { entries: [], redirects: [], gone: [] };
}
app.get(['/blog', '/blog/*'], async (req, res) => {
const f = await feed();
const path = req.path.replace(/\/+$/, '');
const moved = f.redirects.find((r) => r.from === path);
if (moved) return res.redirect(301, moved.to);
if (path === '/blog') return res.send(renderList(f.entries));
const entry = f.entries.find((e) => e.path === path);
if (entry) return res.send(renderArticle(entry));
res.status(f.gone.some((g) => g.path === path) ? 410 : 404).send('Not found');
});
$feed = apcu_fetch('joogoos_feed');
if ($feed === false) {
$ctx = stream_context_create(['http' => ['header' => 'Authorization: Bearer ' . getenv('JOOGOOS_FEED_KEY')]]);
$feed = json_decode(file_get_contents(getenv('JOOGOOS_FEED_URL'), false, $ctx), true);
apcu_store('joogoos_feed', $feed, 300);
}

Escape every field when you render it, and render entry.body with a Markdown library.