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.
Set it up
Section titled “Set it up”- Add
JOOGOOS_FEED_URLand, as a secret,JOOGOOS_FEED_KEYto the server’s environment. - 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
304toIf-None-Matchwith itsETag. - 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.
Node (Express)
Section titled “Node (Express)”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.