Skip to content
mbmsabithb
All work

Personal project

Live

Shabbu's Tasty Kitchen

A 3,200-post recipe blog, moved to Cloudflare Workers and tuned to stay inside free-plan limits.

Role
Designed and built
Period
Nov 2024 – present
Built with
Cloudflare WorkersR2D1Durable ObjectsOpenNextPostgreSQL (Supabase)Gemini 2.5 FlashNext.js 16React 19

Visit shabbustastykitchen.com

A recipe blog covering Indian, Kerala, Malabar, Arabic and international dishes. It started as a WordPress blog; the content now lives in Supabase and the site runs on Next.js on Cloudflare Workers, with a custom admin, a newsletter, ad slots and Gemini extracting structured recipe data from each post.

~3,200
published posts
493
commits since Nov 2024
3
cache layers before the database
~13k
lines of TypeScript

Designed so a page view costs almost nothing

A request passes through three cache layers before it can reach the database, so a typical page view uses no Worker CPU and no query.

  1. 1

    Workers Cache

    Sits in front of the Worker. A hit runs none of my code.

  2. 2

    OpenNext cache

    ISR output in R2, tag invalidation in D1, background revalidation through a Durable Object queue.

  3. 3

    Data cache

    Every Supabase read is wrapped and cached with tags.

  4. 4

    Supabase

    Reached only on a cold miss, under row-level security.

Engineering for a free plan

Daily revalidation, on purpose
Roughly 3,200 pages regenerating hourly would blow through R2's free write quota, so posts revalidate daily and render on their first visit.
Lists fetched from the browser
List queries run client-side with a plain fetch against the REST API, so they never touch the Worker and the Supabase client isn't bundled twice. The Worker bundle sits close to the plan's size limit.
Private routes are never cached
The worker forces no-store on admin, login and preview, because a cache hit would skip the login check.
The migration was a SEO job too
Old WordPress permalinks, tag and category URLs and .html paths are 301-redirected to the new routes, so existing search results keep working.

What it does

Reading
Browse by category, cuisine, tag and archive, with Recipe structured data on every post, an RSS feed and a dynamic sitemap.
Publishing
A custom admin with a rich-text editor, image upload and crop, recipe forms, categories and a subscribers list. Gemini turns a pasted post into structured recipe fields.
Growth
Ad slots, affiliate links on the recipe card, and a newsletter synced to Brevo that never blocks a signup if the sync fails.
Write access by allow-list
Being logged in isn't enough to edit content. Every write policy checks an admin allow-list through a security-definer function.